Alexandre Julliard : wow64: Add support for user callbacks.

Alexandre Julliard julliard at winehq.org
Thu Dec 2 15:30:15 CST 2021


Module: wine
Branch: master
Commit: 716599703671fe0e003c022a21f39621fe064d67
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=716599703671fe0e003c022a21f39621fe064d67

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Dec  2 09:59:08 2021 +0100

wow64: Add support for user callbacks.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wow64/syscall.c  | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/wow64/syscall.h  |   1 +
 dlls/wow64/wow64.spec |   2 +-
 include/winternl.h    |   7 ++--
 4 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c
index bee186456cc..75a5df5c453 100644
--- a/dlls/wow64/syscall.c
+++ b/dlls/wow64/syscall.c
@@ -70,6 +70,18 @@ struct mem_header
     BYTE               data[1];
 };
 
+/* stack frame for user callbacks */
+struct user_callback_frame
+{
+    struct user_callback_frame *prev_frame;
+    struct mem_header          *temp_list;
+    void                      **ret_ptr;
+    ULONG                      *ret_len;
+    NTSTATUS                    status;
+    __wine_jmp_buf              jmpbuf;
+};
+
+
 SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
 
 /* wow64win syscall table */
@@ -143,6 +155,26 @@ NTSTATUS WINAPI wow64_NtAllocateUuids( UINT *args )
 }
 
 
+/***********************************************************************
+ *           wow64_NtCallbackReturn
+ */
+NTSTATUS WINAPI wow64_NtCallbackReturn( UINT *args )
+{
+    void *ret_ptr = get_ptr( &args );
+    ULONG ret_len = get_ulong( &args );
+    NTSTATUS status = get_ulong( &args );
+
+    struct user_callback_frame *frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA];
+
+    if (!frame) return STATUS_NO_CALLBACK_ACTIVE;
+
+    *frame->ret_ptr = ret_ptr;
+    *frame->ret_len = ret_len;
+    frame->status = status;
+    __wine_longjmp( &frame->jmpbuf, 1 );
+}
+
+
 /**********************************************************************
  *           wow64_NtClose
  */
@@ -793,6 +825,86 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON
 }
 
 
+/**********************************************************************
+ *           Wow64KiUserCallbackDispatcher  (wow64.@)
+ */
+NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len,
+                                               void **ret_ptr, ULONG *ret_len )
+{
+    struct user_callback_frame frame;
+
+    frame.prev_frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA];
+    frame.temp_list  = NtCurrentTeb()->TlsSlots[WOW64_TLS_TEMPLIST];
+    frame.ret_ptr    = ret_ptr;
+    frame.ret_len    = ret_len;
+
+    NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA] = &frame;
+    NtCurrentTeb()->TlsSlots[WOW64_TLS_TEMPLIST] = NULL;
+
+    /* cf. 32-bit KeUserModeCallback */
+    switch (current_machine)
+    {
+    case IMAGE_FILE_MACHINE_I386:
+        {
+            I386_CONTEXT orig_ctx, ctx = { CONTEXT_I386_FULL };
+            void *args_data;
+            ULONG *stack;
+
+            NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx), NULL );
+
+            stack = args_data = ULongToPtr( (ctx.Esp - len) & ~15 );
+            memcpy( args_data, args, len );
+            *(--stack) = 0;
+            *(--stack) = len;
+            *(--stack) = PtrToUlong( args_data );
+            *(--stack) = id;
+            *(--stack) = 0xdeadbabe;
+
+            orig_ctx = ctx;
+            ctx.Esp = PtrToUlong( stack );
+            ctx.Eip = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher;
+            NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx) );
+
+            if (!__wine_setjmpex( &frame.jmpbuf, NULL ))
+                cpu_simulate();
+            else
+                NtSetInformationThread( GetCurrentThread(), ThreadWow64Context,
+                                        &orig_ctx, sizeof(orig_ctx) );
+        }
+        break;
+
+    case IMAGE_FILE_MACHINE_ARMNT:
+        {
+            ARM_CONTEXT orig_ctx, ctx = { CONTEXT_ARM_FULL };
+            void *args_data;
+
+            NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx), NULL );
+
+            args_data = ULongToPtr( (ctx.Sp - len) & ~15 );
+            memcpy( args_data, args, len );
+
+            ctx.R0 = id;
+            ctx.R1 = PtrToUlong( args );
+            ctx.R2 = len;
+            ctx.Sp = PtrToUlong( args_data );
+            ctx.Pc = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher;
+            NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx) );
+
+            if (!__wine_setjmpex( &frame.jmpbuf, NULL ))
+                cpu_simulate();
+            else
+                NtSetInformationThread( GetCurrentThread(), ThreadWow64Context,
+                                        &orig_ctx, sizeof(orig_ctx) );
+        }
+        break;
+    }
+
+    NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA] = frame.prev_frame;
+    NtCurrentTeb()->TlsSlots[WOW64_TLS_TEMPLIST] = frame.temp_list;
+    return frame.status;
+}
+
+
 /**********************************************************************
  *           Wow64LdrpInitialize  (wow64.@)
  */
diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h
index cb8fed9b99c..1e122e97314 100644
--- a/dlls/wow64/syscall.h
+++ b/dlls/wow64/syscall.h
@@ -37,6 +37,7 @@
     SYSCALL_ENTRY( NtAllocateVirtualMemoryEx ) \
     SYSCALL_ENTRY( NtAreMappedFilesTheSame ) \
     SYSCALL_ENTRY( NtAssignProcessToJobObject ) \
+    SYSCALL_ENTRY( NtCallbackReturn ) \
     SYSCALL_ENTRY( NtCancelIoFile ) \
     SYSCALL_ENTRY( NtCancelIoFileEx ) \
     SYSCALL_ENTRY( NtCancelTimer ) \
diff --git a/dlls/wow64/wow64.spec b/dlls/wow64/wow64.spec
index 5c3f39c50f1..e05a608d319 100644
--- a/dlls/wow64/wow64.spec
+++ b/dlls/wow64/wow64.spec
@@ -9,7 +9,7 @@
 @ stub Wow64GetWow64ImageOption
 @ stub Wow64IsControlFlowGuardEnforced
 @ stub Wow64IsStackExtentsCheckEnforced
-@ stub Wow64KiUserCallbackDispatcher
+@ stdcall Wow64KiUserCallbackDispatcher(long ptr long ptr ptr)
 @ stdcall Wow64LdrpInitialize(ptr)
 @ stub Wow64LogPrint
 @ stub Wow64NotifyUnsimulateComplete
diff --git a/include/winternl.h b/include/winternl.h
index 5c2a1c07aeb..5b6ba98be42 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -1080,9 +1080,10 @@ typedef struct _TEB64
 } TEB64;
 
 /* reserved TEB64 TLS slots for Wow64 */
-#define WOW64_TLS_CPURESERVED  1
-#define WOW64_TLS_TEMPLIST     3
-#define WOW64_TLS_FILESYSREDIR 8
+#define WOW64_TLS_CPURESERVED      1
+#define WOW64_TLS_TEMPLIST         3
+#define WOW64_TLS_USERCALLBACKDATA 5
+#define WOW64_TLS_FILESYSREDIR     8
 
 
 /***********************************************************************




More information about the wine-cvs mailing list