Module: wine Branch: master Commit: 6a9e19344dae44e97361041996f237f4bfd905c6 URL: https://source.winehq.org/git/wine.git/?a=commit;h=6a9e19344dae44e9736104199...
Author: Alexandre Julliard julliard@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@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 );