diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index c7b94eba923..f8ef274db0c 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -761,19 +761,14 @@ static SIZE_T get_machine_context_size( USHORT machine ) */ 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.UniqueThread = ULongToHandle( tid ); - if (teb->WowTebOffset) + if (wow_teb) { -#ifdef _WIN64 - TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset); - 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 + wow_teb->ClientId.UniqueProcess = pid; + wow_teb->ClientId.UniqueThread = tid; } } @@ -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 ) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; + WOW_TEB *wow_teb = get_wow_teb( teb ); INITIAL_TEB stack; NTSTATUS status; - if (teb->WowTebOffset) + if (wow_teb) { WOW64_CPURESERVED *cpu; SIZE_T cpusize = sizeof(WOW64_CPURESERVED) + ((get_machine_context_size( main_image_info.Machine ) + 7) & ~7) + sizeof(ULONG64); #ifdef _WIN64 - TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset); - /* 32-bit stack */ if ((status = virtual_alloc_thread_stack( &stack, zero_bits, reserve_size, commit_size, 0 ))) return status; - teb32->Tib.StackBase = PtrToUlong( stack.StackBase ); - teb32->Tib.StackLimit = PtrToUlong( stack.StackLimit ); - teb32->DeallocationStack = PtrToUlong( stack.DeallocationStack ); + wow_teb->Tib.StackBase = PtrToUlong( stack.StackBase ); + wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit ); + wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack ); /* 64-bit stack */ 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; return STATUS_SUCCESS; #else - TEB64 *teb64 = (TEB64 *)((char *)teb + teb->WowTebOffset); - /* 64-bit stack */ if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, 0 ))) return status; cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15); cpu->Machine = main_image_info.Machine; - teb64->Tib.StackBase = teb64->TlsSlots[WOW64_TLS_CPURESERVED] = PtrToUlong( cpu ); - teb64->Tib.StackLimit = PtrToUlong( stack.StackLimit ); - teb64->DeallocationStack = PtrToUlong( stack.DeallocationStack ); + wow_teb->Tib.StackBase = wow_teb->TlsSlots[WOW64_TLS_CPURESERVED] = PtrToUlong( cpu ); + wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit ); + wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack ); #endif } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index c8c959029d0..a864604377e 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -321,11 +321,18 @@ static inline void mutex_unlock( pthread_mutex_t *mutex ) } #ifdef _WIN64 +typedef TEB32 WOW_TEB; static inline TEB64 *NtCurrentTeb64(void) { return NULL; } #else +typedef TEB64 WOW_TEB; static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; } #endif +static inline WOW_TEB *get_wow_teb( TEB *teb ) +{ + return teb->WowTebOffset ? (WOW_TEB *)((char *)teb + teb->WowTebOffset) : NULL; +} + enum loadorder { LO_INVALID, diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 6c3bc04ace7..c268b66f50c 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2985,9 +2985,10 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb ) void virtual_free_teb( TEB *teb ) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - void *ptr = teb; + void *ptr; SIZE_T size; sigset_t sigset; + WOW_TEB *wow_teb = get_wow_teb( teb ); signal_free_thread( teb ); if (teb->DeallocationStack) @@ -3000,24 +3001,15 @@ void virtual_free_teb( TEB *teb ) size = 0; NtFreeVirtualMemory( GetCurrentProcess(), &thread_data->kernel_stack, &size, MEM_RELEASE ); } - if (teb->WowTebOffset) + if (wow_teb && (ptr = ULongToPtr( wow_teb->DeallocationStack ))) { -#ifdef _WIN64 - TEB32 *teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset); - 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 ); - } + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE ); } server_enter_uninterrupted_section( &virtual_mutex, &sigset ); list_remove( &thread_data->entry ); + ptr = teb; if (!is_win64) ptr = (char *)ptr - teb_offset; *(void **)ptr = next_free_teb; next_free_teb = ptr;