From 500d83235b01e02fe5b5552961f48cf2e17a22a7 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sat, 18 Oct 2014 04:36:26 +0200 Subject: [PATCH] Added patch to implement support for additional ATL thunks. --- debian/changelog | 1 + patches/Makefile | 20 ++ ...dd-tests-for-additional-ATL-thunks-e.patch | 171 +++++++++++++++ ...dd-support-for-additional-ATL-thunks.patch | 204 ++++++++++++++++++ patches/ntdll-ATL_Thunk/definition | 4 + 5 files changed, 400 insertions(+) create mode 100644 patches/ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-additional-ATL-thunks-e.patch create mode 100644 patches/ntdll-ATL_Thunk/0002-ntdll-Add-support-for-additional-ATL-thunks.patch create mode 100644 patches/ntdll-ATL_Thunk/definition diff --git a/debian/changelog b/debian/changelog index 1876a202..6bb93c8a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ wine-compholio (1.7.29) UNRELEASED; urgency=low * Added patch to implement ID3DXSkinInfoImpl_UpdateSkinnedMesh. * Added patch for implementation of D3DXGetShaderInputSemantics. * Added patch to ensure tests check exact return value of ParseURLFromOutsideSourceX. + * Added patch for additional ATL thunks. * Removed patch to fix issues with drag image in ImageLists (accepted upstream). * Removed patch to set ldr.EntryPoint for main executable (accepted upstream). * Removed patch to implement stubs for [Get|Set]SystemFileCacheSize (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index 684646e5..9a2a6b05 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -41,6 +41,7 @@ PATCHLIST := \ kernel32-UTF7_Support.ok \ libs-Unicode_Collation.ok \ msvcp90-basic_string_wchar_dtor.ok \ + ntdll-ATL_Thunk.ok \ ntdll-DOS_Attributes.ok \ ntdll-Dynamic_DST.ok \ ntdll-Exception.ok \ @@ -578,6 +579,25 @@ msvcp90-basic_string_wchar_dtor.ok: echo '+ { "msvcp90-basic_string_wchar_dtor", "Michael Müller", "basic_string_wchar_dtor needs to return NULL." },'; \ ) > msvcp90-basic_string_wchar_dtor.ok +# Patchset ntdll-ATL_Thunk +# | +# | Included patches: +# | * Implement additional ATL Thunks. [by Sebastian Lackner] +# | +# | This patchset fixes the following Wine bugs: +# | * [#29903] Support for additional ATL Thunks +# | +# | Modified files: +# | * dlls/kernel32/tests/virtual.c, dlls/ntdll/signal_i386.c +# | +.INTERMEDIATE: ntdll-ATL_Thunk.ok +ntdll-ATL_Thunk.ok: + $(call APPLY_FILE,ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-additional-ATL-thunks-e.patch) + $(call APPLY_FILE,ntdll-ATL_Thunk/0002-ntdll-Add-support-for-additional-ATL-thunks.patch) + @( \ + echo '+ { "ntdll-ATL_Thunk", "Sebastian Lackner", "Implement additional ATL Thunks." },'; \ + ) > ntdll-ATL_Thunk.ok + # Patchset ntdll-DOS_Attributes # | # | Included patches: diff --git a/patches/ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-additional-ATL-thunks-e.patch b/patches/ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-additional-ATL-thunks-e.patch new file mode 100644 index 00000000..3f2bd693 --- /dev/null +++ b/patches/ntdll-ATL_Thunk/0001-kernel32-tests-Add-tests-for-additional-ATL-thunks-e.patch @@ -0,0 +1,171 @@ +From bec1fa5d3b8ccd21ec4be39980a06f37ab2a6bdc Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 18 Oct 2014 03:15:57 +0200 +Subject: kernel32/tests: Add tests for additional ATL thunks emulated on + Windows. + +--- + dlls/kernel32/tests/virtual.c | 113 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 108 insertions(+), 5 deletions(-) + +diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c +index 73b753e..6971144 100644 +--- a/dlls/kernel32/tests/virtual.c ++++ b/dlls/kernel32/tests/virtual.c +@@ -1882,7 +1882,24 @@ static inline DWORD send_message_excpt( HWND hWnd, UINT uMsg, WPARAM wParam, LPA + pNtCurrentTeb()->Tib.ExceptionList = &frame; + + num_guard_page_calls = num_execute_fault_calls = 0; +- ret = SendMessageA( hWnd, WM_USER, 0, 0 ); ++ ret = SendMessageA( hWnd, uMsg, wParam, lParam ); ++ ++ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev; ++ ++ return ret; ++} ++ ++static inline DWORD call_proc_excpt( DWORD (CALLBACK *code)(void *), void *arg ) ++{ ++ EXCEPTION_REGISTRATION_RECORD frame; ++ DWORD ret; ++ ++ frame.Handler = execute_fault_seh_handler; ++ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList; ++ pNtCurrentTeb()->Tib.ExceptionList = &frame; ++ ++ num_guard_page_calls = num_execute_fault_calls = 0; ++ ret = code( arg ); + + pNtCurrentTeb()->Tib.ExceptionList = frame.Prev; + +@@ -1900,14 +1917,26 @@ static LRESULT CALLBACK jmp_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR + static LRESULT CALLBACK atl_test_func( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) + { + DWORD arg = (DWORD)hWnd; +- ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg ); ++ if (uMsg == WM_USER) ++ ok( arg == 0x11223344, "arg is 0x%08x instead of 0x11223344\n", arg ); ++ else ++ ok( arg != 0x11223344, "arg is unexpectedly 0x11223344\n" ); + return 43; + } + ++static DWORD CALLBACK atl5_test_func( void ) ++{ ++ return 44; ++} ++ + static void test_atl_thunk_emulation( ULONG dep_flags ) + { + static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00}; +- static const char code_atl[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; ++ static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; ++ static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; ++ static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1}; ++ static const char code_atl4[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0}; ++ static const char code_atl5[] = {0x59, 0x58, 0x51, 0xFF, 0x60, 0x04}; + static const char cls_name[] = "atl_thunk_class"; + DWORD ret, size, old_prot; + ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE; +@@ -2008,7 +2037,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + + /* Now test with a proper ATL thunk instruction. */ + +- memcpy( base, code_atl, sizeof(code_atl) ); ++ memcpy( base, code_atl1, sizeof(code_atl1) ); + *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13); + + success = VirtualProtect( base, size, PAGE_EXECUTE_READWRITE, &old_prot ); +@@ -2077,6 +2106,80 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + win_skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n" ); + } + ++ /* Test alternative ATL thunk instructions. */ ++ ++ memcpy( base, code_atl2, sizeof(code_atl2) ); ++ *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 10); ++ ++ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); ++ ok( success, "VirtualProtect failed %u\n", GetLastError() ); ++ ++ ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); ++ /* FIXME: we don't check the content of the register ECX yet */ ++ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); ++ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); ++ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) ++ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) ++ todo_wine ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ ++ memcpy( base, code_atl3, sizeof(code_atl3) ); ++ *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func; ++ ++ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); ++ ok( success, "VirtualProtect failed %u\n", GetLastError() ); ++ ++ ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); ++ /* FIXME: we don't check the content of the registers ECX/EDX yet */ ++ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); ++ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); ++ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) ++ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) ++ todo_wine ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ ++ memcpy( base, code_atl4, sizeof(code_atl4) ); ++ *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func; ++ ++ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); ++ ok( success, "VirtualProtect failed %u\n", GetLastError() ); ++ ++ ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); ++ /* FIXME: We don't check the content of the registers EAX/ECX yet */ ++ ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); ++ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); ++ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) ++ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) ++ todo_wine ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ ++ memcpy( base, code_atl5, sizeof(code_atl5) ); ++ ++ success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); ++ ok( success, "VirtualProtect failed %u\n", GetLastError() ); ++ ++ ret = (DWORD_PTR)atl5_test_func; ++ ret = call_proc_excpt( (void *)base, &ret - 1 ); ++ /* FIXME: We don't check the content of the registers EAX/ECX yet */ ++ ok( ret == 44, "call returned wrong result, expected 44, got %d\n", ret ); ++ ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); ++ if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) ++ ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) ++ todo_wine ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ else ++ ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); ++ + /* Restore the JMP instruction, set to executable, and then destroy the Window */ + + memcpy( base, code_jmp, sizeof(code_jmp) ); +@@ -2194,7 +2297,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + + /* Now test with a proper ATL thunk instruction. */ + +- memcpy( base, code_atl, sizeof(code_atl) ); ++ memcpy( base, code_atl1, sizeof(code_atl1) ); + *(DWORD *)(base + 9) = (DWORD_PTR)atl_test_func - (DWORD_PTR)(base + 13); + + count = 64; +-- +2.1.2 + diff --git a/patches/ntdll-ATL_Thunk/0002-ntdll-Add-support-for-additional-ATL-thunks.patch b/patches/ntdll-ATL_Thunk/0002-ntdll-Add-support-for-additional-ATL-thunks.patch new file mode 100644 index 00000000..ca67e847 --- /dev/null +++ b/patches/ntdll-ATL_Thunk/0002-ntdll-Add-support-for-additional-ATL-thunks.patch @@ -0,0 +1,204 @@ +From 31046c5a489a1b646b6dfb94c8156b96bb40bd2e Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 18 Oct 2014 04:32:27 +0200 +Subject: ntdll: Add support for additional ATL thunks. + +--- + dlls/kernel32/tests/virtual.c | 12 ----- + dlls/ntdll/signal_i386.c | 120 ++++++++++++++++++++++++++++++++++++------ + 2 files changed, 103 insertions(+), 29 deletions(-) + +diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c +index 6971144..3be2977 100644 +--- a/dlls/kernel32/tests/virtual.c ++++ b/dlls/kernel32/tests/virtual.c +@@ -2120,9 +2120,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); + if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) + ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); +- else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) +- todo_wine +- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + else + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + +@@ -2138,9 +2135,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); + if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) + ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); +- else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) +- todo_wine +- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + else + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + +@@ -2156,9 +2150,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); + if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) + ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); +- else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) +- todo_wine +- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + else + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + +@@ -2174,9 +2165,6 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) + ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); + if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) + ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); +- else if (dep_flags & MEM_EXECUTE_OPTION_DISABLE) +- todo_wine +- ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + else + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index f97799c..b2a9cb0 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -1616,12 +1616,46 @@ static inline BOOL check_invalid_gs( CONTEXT *context ) + + + #include "pshpack1.h" +-struct atl_thunk ++union atl_thunk + { +- DWORD movl; /* movl this,4(%esp) */ +- DWORD this; +- BYTE jmp; /* jmp func */ +- int func; ++ struct ++ { ++ DWORD movl; /* movl this,4(%esp) */ ++ DWORD this; ++ BYTE jmp; /* jmp func */ ++ int func; ++ } t1; ++ struct ++ { ++ BYTE movl; /* movl this,ecx */ ++ DWORD this; ++ BYTE jmp; /* jmp func */ ++ int func; ++ } t2; ++ struct ++ { ++ BYTE movl1; /* movl this,edx */ ++ DWORD this; ++ BYTE movl2; /* movl func,ecx */ ++ DWORD func; ++ WORD jmp; /* jmp ecx */ ++ } t3; ++ struct ++ { ++ BYTE movl1; /* movl this,ecx */ ++ DWORD this; ++ BYTE movl2; /* movl func,eax */ ++ DWORD func; ++ WORD jmp; /* jmp eax */ ++ } t4; ++ struct ++ { ++ DWORD inst1; /* pop ecx ++ * pop eax ++ * push ecx ++ * jmp 4(%eax) */ ++ WORD inst2; ++ } t5; + }; + #include "poppack.h" + +@@ -1632,26 +1666,78 @@ struct atl_thunk + */ + static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context ) + { +- const struct atl_thunk *thunk = (const struct atl_thunk *)rec->ExceptionInformation[1]; +- struct atl_thunk thunk_copy; +- BOOL ret = FALSE; ++ const union atl_thunk *thunk = (const union atl_thunk *)rec->ExceptionInformation[1]; ++ union atl_thunk thunk_copy; ++ SIZE_T thunk_len; + +- if (virtual_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*thunk) ) != sizeof(*thunk)) +- return FALSE; ++ thunk_len = virtual_uninterrupted_read_memory( thunk, &thunk_copy, sizeof(*thunk) ); ++ if (!thunk_len) return FALSE; + +- if (thunk_copy.movl == 0x042444c7 && thunk_copy.jmp == 0xe9) ++ if (thunk_len >= sizeof(thunk_copy.t1) && thunk_copy.t1.movl == 0x042444c7 && ++ thunk_copy.t1.jmp == 0xe9) + { + if (virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, +- &thunk_copy.this, sizeof(DWORD) ) == sizeof(DWORD)) ++ &thunk_copy.t1.this, sizeof(DWORD) ) == sizeof(DWORD)) ++ { ++ context->Eip = (DWORD_PTR)(&thunk->t1.func + 1) + thunk_copy.t1.func; ++ TRACE( "emulating ATL thunk type 1 at %p, func=%08x arg=%08x\n", ++ thunk, context->Eip, thunk_copy.t1.this ); ++ return TRUE; ++ } ++ } ++ else if (thunk_len >= sizeof(thunk_copy.t2) && thunk_copy.t2.movl == 0xb9 && ++ thunk_copy.t2.jmp == 0xe9) ++ { ++ context->Ecx = thunk_copy.t2.this; ++ context->Eip = (DWORD_PTR)(&thunk->t2.func + 1) + thunk_copy.t2.func; ++ TRACE( "emulating ATL thunk type 2 at %p, func=%08x ecx=%08x\n", ++ thunk, context->Eip, context->Ecx ); ++ return TRUE; ++ } ++ else if (thunk_len >= sizeof(thunk_copy.t3) && thunk_copy.t3.movl1 == 0xba && ++ thunk_copy.t3.movl2 == 0xb9 && ++ thunk_copy.t3.jmp == 0xe1ff) ++ { ++ context->Edx = thunk_copy.t3.this; ++ context->Ecx = thunk_copy.t3.func; ++ context->Eip = thunk_copy.t3.func; ++ TRACE( "emulating ATL thunk type 3 at %p, func=%08x ecx=%08x edx=%08x\n", ++ thunk, context->Eip, context->Ecx, context->Edx ); ++ return TRUE; ++ } ++ else if (thunk_len >= sizeof(thunk_copy.t4) && thunk_copy.t4.movl1 == 0xb9 && ++ thunk_copy.t4.movl2 == 0xb8 && ++ thunk_copy.t4.jmp == 0xe0ff) ++ { ++ context->Ecx = thunk_copy.t4.this; ++ context->Eax = thunk_copy.t4.func; ++ context->Eip = thunk_copy.t4.func; ++ TRACE( "emulating ATL thunk type 4 at %p, func=%08x eax=%08x ecx=%08x\n", ++ thunk, context->Eip, context->Eax, context->Ecx ); ++ return TRUE; ++ } ++ else if (thunk_len >= sizeof(thunk_copy.t5) && thunk_copy.t5.inst1 == 0xff515859 && ++ thunk_copy.t5.inst2 == 0x0460) ++ { ++ DWORD func, stack[2]; ++ if (virtual_uninterrupted_read_memory( context->Esp, ++ stack, sizeof(stack) ) == sizeof(stack) && ++ virtual_uninterrupted_read_memory( (DWORD *)stack[1] + 1, ++ &func, sizeof(DWORD) ) == sizeof(DWORD) && ++ virtual_uninterrupted_write_memory( (DWORD *)context->Esp + 1, ++ &stack[0], sizeof(stack[0]) ) == sizeof(stack[0])) + { +- context->Eip = (DWORD_PTR)(&thunk->func + 1) + thunk_copy.func; +- TRACE( "emulating ATL thunk at %p, func=%08x arg=%08x\n", +- thunk, context->Eip, thunk_copy.this ); +- ret = TRUE; ++ context->Ecx = stack[0]; ++ context->Eax = stack[1]; ++ context->Esp = context->Esp + sizeof(DWORD); ++ context->Eip = func; ++ TRACE( "emulating ATL thunk type 5 at %p, func=%08x eax=%08x ecx=%08x esp=%08x\n", ++ thunk, context->Eip, context->Eax, context->Ecx, context->Esp ); ++ return TRUE; + } + } + +- return ret; ++ return FALSE; + } + + +-- +2.1.2 + diff --git a/patches/ntdll-ATL_Thunk/definition b/patches/ntdll-ATL_Thunk/definition new file mode 100644 index 00000000..d61a1d98 --- /dev/null +++ b/patches/ntdll-ATL_Thunk/definition @@ -0,0 +1,4 @@ +Author: Sebastian Lackner +Subject: Implement additional ATL Thunks. +Revision: 1 +Fixes: [29903] Support for additional ATL Thunks