mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 21:54:14 +00:00
wow64: Add support for user callbacks.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be6ccdf51c
commit
7165997036
|
@ -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.@)
|
||||
*/
|
||||
|
|
|
@ -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 ) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
|
Loading…
Reference in a new issue