ntdll: Add a helper to get the Wow64 TEB.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bab4f2939e
commit
7b4ca95ab6
|
@ -761,19 +761,14 @@ static SIZE_T get_machine_context_size( USHORT machine )
|
||||||
*/
|
*/
|
||||||
void set_thread_id( TEB *teb, DWORD pid, DWORD tid )
|
void set_thread_id( TEB *teb, DWORD pid, DWORD tid )
|
||||||
{
|
{
|
||||||
|
WOW_TEB *wow_teb = get_wow_teb( teb );
|
||||||
|
|
||||||
teb->ClientId.UniqueProcess = ULongToHandle( pid );
|
teb->ClientId.UniqueProcess = ULongToHandle( pid );
|
||||||
teb->ClientId.UniqueThread = ULongToHandle( tid );
|
teb->ClientId.UniqueThread = ULongToHandle( tid );
|
||||||
if (teb->WowTebOffset)
|
if (wow_teb)
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
wow_teb->ClientId.UniqueProcess = pid;
|
||||||
TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset);
|
wow_teb->ClientId.UniqueThread = tid;
|
||||||
teb32->ClientId.UniqueProcess = pid;
|
|
||||||
teb32->ClientId.UniqueThread = tid;
|
|
||||||
#else
|
|
||||||
TEB64 *teb64 = (TEB64 *)((char *)teb + teb->WowTebOffset);
|
|
||||||
teb64->ClientId.UniqueProcess = pid;
|
|
||||||
teb64->ClientId.UniqueThread = tid;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -784,24 +779,23 @@ void set_thread_id( TEB *teb, DWORD pid, DWORD tid )
|
||||||
NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size, SIZE_T commit_size )
|
NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size, SIZE_T commit_size )
|
||||||
{
|
{
|
||||||
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
|
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
|
||||||
|
WOW_TEB *wow_teb = get_wow_teb( teb );
|
||||||
INITIAL_TEB stack;
|
INITIAL_TEB stack;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
if (teb->WowTebOffset)
|
if (wow_teb)
|
||||||
{
|
{
|
||||||
WOW64_CPURESERVED *cpu;
|
WOW64_CPURESERVED *cpu;
|
||||||
SIZE_T cpusize = sizeof(WOW64_CPURESERVED) +
|
SIZE_T cpusize = sizeof(WOW64_CPURESERVED) +
|
||||||
((get_machine_context_size( main_image_info.Machine ) + 7) & ~7) + sizeof(ULONG64);
|
((get_machine_context_size( main_image_info.Machine ) + 7) & ~7) + sizeof(ULONG64);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset);
|
|
||||||
|
|
||||||
/* 32-bit stack */
|
/* 32-bit stack */
|
||||||
if ((status = virtual_alloc_thread_stack( &stack, zero_bits, reserve_size, commit_size, 0 )))
|
if ((status = virtual_alloc_thread_stack( &stack, zero_bits, reserve_size, commit_size, 0 )))
|
||||||
return status;
|
return status;
|
||||||
teb32->Tib.StackBase = PtrToUlong( stack.StackBase );
|
wow_teb->Tib.StackBase = PtrToUlong( stack.StackBase );
|
||||||
teb32->Tib.StackLimit = PtrToUlong( stack.StackLimit );
|
wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit );
|
||||||
teb32->DeallocationStack = PtrToUlong( stack.DeallocationStack );
|
wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack );
|
||||||
|
|
||||||
/* 64-bit stack */
|
/* 64-bit stack */
|
||||||
if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, kernel_stack_size )))
|
if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, kernel_stack_size )))
|
||||||
|
@ -814,16 +808,14 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size,
|
||||||
thread_data->kernel_stack = stack.StackBase;
|
thread_data->kernel_stack = stack.StackBase;
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
#else
|
#else
|
||||||
TEB64 *teb64 = (TEB64 *)((char *)teb + teb->WowTebOffset);
|
|
||||||
|
|
||||||
/* 64-bit stack */
|
/* 64-bit stack */
|
||||||
if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, 0 ))) return status;
|
if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, 0 ))) return status;
|
||||||
|
|
||||||
cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15);
|
cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15);
|
||||||
cpu->Machine = main_image_info.Machine;
|
cpu->Machine = main_image_info.Machine;
|
||||||
teb64->Tib.StackBase = teb64->TlsSlots[WOW64_TLS_CPURESERVED] = PtrToUlong( cpu );
|
wow_teb->Tib.StackBase = wow_teb->TlsSlots[WOW64_TLS_CPURESERVED] = PtrToUlong( cpu );
|
||||||
teb64->Tib.StackLimit = PtrToUlong( stack.StackLimit );
|
wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit );
|
||||||
teb64->DeallocationStack = PtrToUlong( stack.DeallocationStack );
|
wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -321,11 +321,18 @@ static inline void mutex_unlock( pthread_mutex_t *mutex )
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
|
typedef TEB32 WOW_TEB;
|
||||||
static inline TEB64 *NtCurrentTeb64(void) { return NULL; }
|
static inline TEB64 *NtCurrentTeb64(void) { return NULL; }
|
||||||
#else
|
#else
|
||||||
|
typedef TEB64 WOW_TEB;
|
||||||
static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; }
|
static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline WOW_TEB *get_wow_teb( TEB *teb )
|
||||||
|
{
|
||||||
|
return teb->WowTebOffset ? (WOW_TEB *)((char *)teb + teb->WowTebOffset) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
enum loadorder
|
enum loadorder
|
||||||
{
|
{
|
||||||
LO_INVALID,
|
LO_INVALID,
|
||||||
|
|
|
@ -2985,9 +2985,10 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
|
||||||
void virtual_free_teb( TEB *teb )
|
void virtual_free_teb( TEB *teb )
|
||||||
{
|
{
|
||||||
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
|
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
|
||||||
void *ptr = teb;
|
void *ptr;
|
||||||
SIZE_T size;
|
SIZE_T size;
|
||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
|
WOW_TEB *wow_teb = get_wow_teb( teb );
|
||||||
|
|
||||||
signal_free_thread( teb );
|
signal_free_thread( teb );
|
||||||
if (teb->DeallocationStack)
|
if (teb->DeallocationStack)
|
||||||
|
@ -3000,24 +3001,15 @@ void virtual_free_teb( TEB *teb )
|
||||||
size = 0;
|
size = 0;
|
||||||
NtFreeVirtualMemory( GetCurrentProcess(), &thread_data->kernel_stack, &size, MEM_RELEASE );
|
NtFreeVirtualMemory( GetCurrentProcess(), &thread_data->kernel_stack, &size, MEM_RELEASE );
|
||||||
}
|
}
|
||||||
if (teb->WowTebOffset)
|
if (wow_teb && (ptr = ULongToPtr( wow_teb->DeallocationStack )))
|
||||||
{
|
{
|
||||||
#ifdef _WIN64
|
size = 0;
|
||||||
TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset);
|
NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE );
|
||||||
void *addr = ULongToPtr( teb32->DeallocationStack );
|
|
||||||
#else
|
|
||||||
TEB64 *teb64 = (TEB64 *)((char *)teb + teb->WowTebOffset);
|
|
||||||
void *addr = ULongToPtr( teb64->DeallocationStack );
|
|
||||||
#endif
|
|
||||||
if (addr)
|
|
||||||
{
|
|
||||||
size = 0;
|
|
||||||
NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
|
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
|
||||||
list_remove( &thread_data->entry );
|
list_remove( &thread_data->entry );
|
||||||
|
ptr = teb;
|
||||||
if (!is_win64) ptr = (char *)ptr - teb_offset;
|
if (!is_win64) ptr = (char *)ptr - teb_offset;
|
||||||
*(void **)ptr = next_free_teb;
|
*(void **)ptr = next_free_teb;
|
||||||
next_free_teb = ptr;
|
next_free_teb = ptr;
|
||||||
|
|
Loading…
Reference in New Issue