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