Alexandre Julliard : ntdll: Always allocate space for both 32- and 64-bit TEB.

Alexandre Julliard julliard at winehq.org
Tue Apr 27 16:08:58 CDT 2021


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Apr 27 12:21:47 2021 +0200

ntdll: Always allocate space for both 32- and 64-bit TEB.

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

---

 dlls/ntdll/tests/info.c        |  4 ++++
 dlls/ntdll/unix/server.c       |  1 +
 dlls/ntdll/unix/unix_private.h | 12 +++---------
 dlls/ntdll/unix/virtual.c      | 37 +++++++++++++++++++++++++------------
 4 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 3a71a9f245c..b68edfa64dc 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -3096,6 +3096,10 @@ static void test_wow64(void)
             "wrong WowTebOffset %x (%p/%p)\n", NtCurrentTeb()->WowTebOffset, teb64, NtCurrentTeb() );
         ok( (char *)teb64 + 0x2000 == (char *)NtCurrentTeb(), "unexpected diff %p / %p\n",
             teb64, NtCurrentTeb() );
+        ok( (char *)teb64 + teb64->WowTebOffset == (char *)NtCurrentTeb() ||
+            broken( NtCurrentTeb()->WowTebOffset == 1 ),  /* vista */
+            "wrong WowTebOffset %x (%p/%p)\n", teb64->WowTebOffset, teb64, NtCurrentTeb() );
+        ok( !teb64->GdiBatchCount, "GdiBatchCount set %x\n", teb64->GdiBatchCount );
         ok( teb64->Tib.ExceptionList == PtrToUlong( NtCurrentTeb() ), "wrong Tib.ExceptionList %s / %p\n",
             wine_dbgstr_longlong(teb64->Tib.ExceptionList), NtCurrentTeb() );
         ok( teb64->Tib.Self == PtrToUlong( teb64 ), "wrong Tib.Self %s / %p\n",
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c
index 1ee903e1bf4..b13e2997962 100644
--- a/dlls/ntdll/unix/server.c
+++ b/dlls/ntdll/unix/server.c
@@ -1459,6 +1459,7 @@ static void init_teb64( TEB *teb )
     teb->WowTebOffset  = -teb_offset;
     teb64->ClientId.UniqueProcess = PtrToUlong( teb->ClientId.UniqueProcess );
     teb64->ClientId.UniqueThread  = PtrToUlong( teb->ClientId.UniqueThread );
+    teb64->WowTebOffset           = teb_offset;
 #endif
 }
 
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 9a7e9ca01d6..a5bade02b8a 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -70,16 +70,10 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
 }
 
 static const SIZE_T page_size = 0x1000;
+static const SIZE_T teb_size = 0x3000;  /* TEB64 + TEB32 */
 static const SIZE_T signal_stack_mask = 0xffff;
-#ifdef _WIN64
-static const SIZE_T teb_size = 0x2000;
-static const SIZE_T teb_offset = 0;
-static const SIZE_T signal_stack_size = 0x10000 - 0x2000;
-#else
-static const SIZE_T teb_size = 0x3000;  /* TEB64 + TEB */
-static const SIZE_T teb_offset = 0x2000;
 static const SIZE_T signal_stack_size = 0x10000 - 0x3000;
-#endif
+static const LONG teb_offset = 0x2000;
 
 /* callbacks to PE ntdll from the Unix side */
 extern void     (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN;
@@ -298,7 +292,7 @@ static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
 
 static inline void *get_signal_stack(void)
 {
-    return (char *)NtCurrentTeb() + teb_size - teb_offset;
+    return (void *)(((ULONG_PTR)NtCurrentTeb() & ~signal_stack_mask) + teb_size);
 }
 
 static inline void mutex_lock( pthread_mutex_t *mutex )
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index bb630765c3e..182f9089dbf 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2837,16 +2837,29 @@ static PEB *init_peb( void *ptr )
 
 
 /* set some initial values in a new TEB */
-static void init_teb( TEB *teb, PEB *peb )
+static TEB *init_teb( void *ptr, PEB *peb )
 {
-    struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
-
-#ifndef _WIN64
-    TEB64 *teb64 = (TEB64 *)((char *)teb - teb_offset);
+    struct ntdll_thread_data *thread_data;
+    TEB *teb;
+    TEB64 *teb64 = ptr;
+    TEB32 *teb32 = (TEB32 *)((char *)ptr + teb_offset);
 
+#ifdef _WIN64
+    teb = (TEB *)teb64;
+    teb32->Peb = PtrToUlong( (char *)peb - page_size );
+    teb32->Tib.Self = PtrToUlong( teb32 );
+    teb32->Tib.ExceptionList = ~0u;
+    teb32->ActivationContextStackPointer = PtrToUlong( &teb32->ActivationContextStack );
+    teb32->ActivationContextStack.FrameListCache.Flink =
+        teb32->ActivationContextStack.FrameListCache.Blink =
+            PtrToUlong( &teb32->ActivationContextStack.FrameListCache );
+    teb32->StaticUnicodeString.Buffer = PtrToUlong( teb32->StaticUnicodeBuffer );
+    teb32->StaticUnicodeString.MaximumLength = sizeof( teb32->StaticUnicodeBuffer );
+#else
+    teb = (TEB *)teb32;
     teb64->Peb = PtrToUlong( (char *)peb + page_size );
     teb64->Tib.Self = PtrToUlong( teb64 );
-    teb64->Tib.ExceptionList = PtrToUlong( teb );
+    teb64->Tib.ExceptionList = PtrToUlong( teb32 );
     teb64->ActivationContextStackPointer = PtrToUlong( &teb64->ActivationContextStack );
     teb64->ActivationContextStack.FrameListCache.Flink =
         teb64->ActivationContextStack.FrameListCache.Blink =
@@ -2862,11 +2875,13 @@ static void init_teb( TEB *teb, PEB *peb )
     InitializeListHead( &teb->ActivationContextStack.FrameListCache );
     teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
     teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
+    thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
     thread_data->request_fd = -1;
     thread_data->reply_fd   = -1;
     thread_data->wait_fd[0] = -1;
     thread_data->wait_fd[1] = -1;
     list_add_head( &teb_list, &thread_data->entry );
+    return teb;
 }
 
 
@@ -2896,11 +2911,10 @@ TEB *virtual_alloc_first_teb(void)
                              MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE );
     teb_block_pos = 30;
     ptr = (char *)teb_block + 30 * block_size;
-    teb = (TEB *)((char *)ptr + teb_offset);
     data_size = 2 * block_size;
     NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&ptr, 0, &data_size, MEM_COMMIT, PAGE_READWRITE );
     peb = init_peb( (char *)teb_block + 31 * block_size );
-    init_teb( teb, peb );
+    teb = init_teb( ptr, peb );
     *(ULONG_PTR *)&peb->CloudFileFlags = get_image_address();
     return teb;
 }
@@ -2943,8 +2957,7 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
         NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&ptr, 0, &block_size,
                                  MEM_COMMIT, PAGE_READWRITE );
     }
-    *ret_teb = teb = (TEB *)((char *)ptr + teb_offset);
-    init_teb( teb, NtCurrentTeb()->Peb );
+    *ret_teb = teb = init_teb( ptr, NtCurrentTeb()->Peb );
     server_leave_uninterrupted_section( &virtual_mutex, &sigset );
 
     if ((status = signal_alloc_thread( teb )))
@@ -2964,7 +2977,7 @@ 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;
+    void *ptr = teb;
     SIZE_T size;
     sigset_t sigset;
 
@@ -2982,7 +2995,7 @@ void virtual_free_teb( TEB *teb )
 
     server_enter_uninterrupted_section( &virtual_mutex, &sigset );
     list_remove( &thread_data->entry );
-    ptr = (char *)teb - teb_offset;
+    if (!is_win64) ptr = (char *)ptr - teb_offset;
     *(void **)ptr = next_free_teb;
     next_free_teb = ptr;
     server_leave_uninterrupted_section( &virtual_mutex, &sigset );




More information about the wine-cvs mailing list