Alexandre Julliard : ntdll: Add a helper to get the Wow64 TEB.

Alexandre Julliard julliard at winehq.org
Thu Jun 17 15:38:06 CDT 2021


Module: wine
Branch: master
Commit: 7b4ca95ab63c86549bb6fd7a6acbe43b9b28c964
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=7b4ca95ab63c86549bb6fd7a6acbe43b9b28c964

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Jun 17 09:25:06 2021 +0200

ntdll: Add a helper to get the Wow64 TEB.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/thread.c       | 34 +++++++++++++---------------------
 dlls/ntdll/unix/unix_private.h |  7 +++++++
 dlls/ntdll/unix/virtual.c      | 20 ++++++--------------
 3 files changed, 26 insertions(+), 35 deletions(-)

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;




More information about the wine-cvs mailing list