Sebastian Lackner : ntdll: Add support for ATL thunk 'MOV this,ecx; MOV func,eax; JMP eax'.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Oct 21 09:49:44 CDT 2014


Module: wine
Branch: master
Commit: dcd2b0a36695d7b5f17b753f49f1032884677234
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dcd2b0a36695d7b5f17b753f49f1032884677234

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Tue Oct 21 06:02:02 2014 +0200

ntdll: Add support for ATL thunk 'MOV this,ecx; MOV func,eax; JMP eax'.

---

 dlls/kernel32/tests/virtual.c | 19 +++++++++++++++++++
 dlls/ntdll/signal_i386.c      | 19 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index a89f1e3..ae0ede5 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -1913,6 +1913,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
     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 cls_name[] = "atl_thunk_class";
     DWORD ret, size, old_prot;
     ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE;
@@ -2114,6 +2115,24 @@ static void test_atl_thunk_emulation( ULONG dep_flags )
     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)
+        ok( num_execute_fault_calls == 0 || broken(num_execute_fault_calls == 1) /* Windows XP */,
+            "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) );
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index e8c6a77..b315e55 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1640,6 +1640,14 @@ union atl_thunk
         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;
 };
 #include "poppack.h"
 
@@ -1689,6 +1697,17 @@ static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context )
                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;
+    }
 
     return FALSE;
 }




More information about the wine-cvs mailing list