From: Jacek Caban jacek@codeweavers.com
NtSetInformationThread for i386 causes WOW64_CPURESERVED_FLAG_RESET_STATE to be set, which makes subsequent syscall to restore the state instead of returning its result. --- dlls/wow64/syscall.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index bc6d46258ed..73fb84c6d2e 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -865,13 +865,14 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, { case IMAGE_FILE_MACHINE_I386: { - I386_CONTEXT orig_ctx, ctx = { CONTEXT_I386_FULL }; + I386_CONTEXT orig_ctx, *ctx; void *args_data; ULONG *stack;
- NtQueryInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx), NULL ); + RtlWow64GetCurrentCpuArea( NULL, (void **)&ctx, NULL ); + orig_ctx = *ctx;
- stack = args_data = ULongToPtr( (ctx.Esp - len) & ~15 ); + stack = args_data = ULongToPtr( (ctx->Esp - len) & ~15 ); memcpy( args_data, args, len ); *(--stack) = 0; *(--stack) = len; @@ -879,16 +880,13 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, *(--stack) = id; *(--stack) = 0xdeadbabe;
- orig_ctx = ctx; - ctx.Esp = PtrToUlong( stack ); - ctx.Eip = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher; - NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, &ctx, sizeof(ctx) ); + ctx->Esp = PtrToUlong( stack ); + ctx->Eip = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher;
if (!__wine_setjmpex( &frame.jmpbuf, NULL )) cpu_simulate(); else - NtSetInformationThread( GetCurrentThread(), ThreadWow64Context, - &orig_ctx, sizeof(orig_ctx) ); + *ctx = orig_ctx; } break;
From: Jacek Caban jacek@codeweavers.com
--- dlls/wow64/syscall.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index 73fb84c6d2e..8cb5f92c245 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -850,6 +850,8 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, void **ret_ptr, ULONG *ret_len ) { + TEB32 *teb32 = (TEB32 *)((char *)NtCurrentTeb() + NtCurrentTeb()->WowTebOffset); + ULONG teb_frame = teb32->Tib.ExceptionList; struct user_callback_frame frame;
frame.prev_frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA]; @@ -916,6 +918,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, break; }
+ teb32->Tib.ExceptionList = teb_frame; NtCurrentTeb()->TlsSlots[WOW64_TLS_USERCALLBACKDATA] = frame.prev_frame; NtCurrentTeb()->TlsSlots[WOW64_TLS_TEMPLIST] = frame.temp_list; return frame.status;
From: Jacek Caban jacek@codeweavers.com
--- dlls/wow64win/syscall.c | 4 +- dlls/wow64win/user.c | 226 +++++++++++++++++++++++++++++++ dlls/wow64win/wow64win_private.h | 5 + include/ntuser.h | 2 +- 4 files changed, 235 insertions(+), 2 deletions(-)
diff --git a/dlls/wow64win/syscall.c b/dlls/wow64win/syscall.c index 0be70421b74..20ea054ff7c 100644 --- a/dlls/wow64win/syscall.c +++ b/dlls/wow64win/syscall.c @@ -53,6 +53,8 @@ SYSTEM_SERVICE_TABLE sdwhwin32 =
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved ) { - if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst ); + if (reason != DLL_PROCESS_ATTACH) return TRUE; + LdrDisableThreadCalloutsForDll( inst ); + NtCurrentTeb()->Peb->KernelCallbackTable = user_callbacks; return TRUE; } diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index c69c8fd6d6c..1f4acc04e2a 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -189,6 +189,232 @@ static struct client_menu_name32 *client_menu_name_64to32( const struct client_m return name32; }
+static NTSTATUS dispatch_callback( ULONG id, void *args, ULONG len ) +{ + void *ret_ptr; + ULONG ret_len; + NTSTATUS status = Wow64KiUserCallbackDispatcher( id, args, len, &ret_ptr, &ret_len ); + return NtCallbackReturn( ret_ptr, ret_len, status ); +} + +static NTSTATUS WINAPI wow64_NtUserCallEnumDisplayMonitor( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallSendAsyncCallback( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallWinEventHook( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallWindowsHook( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCopyImage( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserDrawScrollBar( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserDrawText( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserFreeCachedClipboardData( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserImmProcessKey( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserImmTranslateMessage( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserInitBuiltinClasses( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserInitBuiltinClasses, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserLoadDriver( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserLoadDriver, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserLoadImage( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserLoadSysMenu( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserLoadSysMenu, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserPostDDEMessage( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserRenderSynthesizedFormat( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserRenderSynthesizedFormat, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserUnpackDDEMessage( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallFreeIcon( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserCallFreeIcon, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserThunkLock( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserThunkLock, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserCallVulkanDebugReportCallback( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserCallVulkanDebugUtilsCallback( void *arg, ULONG size ) +{ + FIXME( "\n" ); + return 0; +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst0( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 0, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst1( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 1, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst2( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 2, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst3( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 3, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst4( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 4, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst5( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 5, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst6( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 6, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst7( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 7, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst8( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 8, arg, size ); +} + +static NTSTATUS WINAPI wow64_NtUserDriverCallbackFirst9( void *arg, ULONG size ) +{ + return dispatch_callback( NtUserDriverCallbackFirst + 9, arg, size ); +} + +user_callback user_callbacks[] = +{ + /* user32 callbacks */ + wow64_NtUserCallEnumDisplayMonitor, + wow64_NtUserCallSendAsyncCallback, + wow64_NtUserCallWinEventHook, + wow64_NtUserCallWinProc, + wow64_NtUserCallWindowsHook, + wow64_NtUserCopyImage, + wow64_NtUserDrawScrollBar, + wow64_NtUserDrawText, + wow64_NtUserFreeCachedClipboardData, + wow64_NtUserImmProcessKey, + wow64_NtUserImmTranslateMessage, + wow64_NtUserInitBuiltinClasses, + wow64_NtUserLoadDriver, + wow64_NtUserLoadImage, + wow64_NtUserLoadSysMenu, + wow64_NtUserPostDDEMessage, + wow64_NtUserRenderSynthesizedFormat, + wow64_NtUserUnpackDDEMessage, + /* win16 hooks */ + wow64_NtUserCallFreeIcon, + wow64_NtUserThunkLock, + /* Vulkan support */ + wow64_NtUserCallVulkanDebugReportCallback, + wow64_NtUserCallVulkanDebugUtilsCallback, + /* Driver-specific callbacks */ + wow64_NtUserDriverCallbackFirst0, + wow64_NtUserDriverCallbackFirst1, + wow64_NtUserDriverCallbackFirst2, + wow64_NtUserDriverCallbackFirst3, + wow64_NtUserDriverCallbackFirst4, + wow64_NtUserDriverCallbackFirst5, + wow64_NtUserDriverCallbackFirst6, + wow64_NtUserDriverCallbackFirst7, + wow64_NtUserDriverCallbackFirst8, + wow64_NtUserDriverCallbackFirst9, +}; + +C_ASSERT( ARRAYSIZE(user_callbacks) == NtUserCallCount ); + NTSTATUS WINAPI wow64_NtUserActivateKeyboardLayout( UINT *args ) { HKL layout = get_handle( &args ); diff --git a/dlls/wow64win/wow64win_private.h b/dlls/wow64win/wow64win_private.h index cf0b2b62e5f..643875c69ce 100644 --- a/dlls/wow64win/wow64win_private.h +++ b/dlls/wow64win/wow64win_private.h @@ -27,7 +27,12 @@ ALL_WIN32_SYSCALLS #undef SYSCALL_ENTRY
+typedef NTSTATUS (WINAPI *user_callback)( void *params, ULONG size ); +extern user_callback user_callbacks[] DECLSPEC_HIDDEN; + void * WINAPI Wow64AllocateTemp( SIZE_T size ); +NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, + void **ret_ptr, ULONG *ret_len );
struct object_attr64 { diff --git a/include/ntuser.h b/include/ntuser.h index 5b7d66a2a4e..f5555056078 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -54,7 +54,7 @@ enum NtUserCallVulkanDebugUtilsCallback, /* Driver-specific callbacks */ NtUserDriverCallbackFirst, - NtUserDriverCallbackLast = NtUserDriverCallbackFirst + 10, + NtUserDriverCallbackLast = NtUserDriverCallbackFirst + 9, NtUserCallCount };
This merge request was approved by Huw Davies.