ntdll: Always send the native TEB pointer to the server.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-05-13 15:43:16 +02:00
parent d743c1e6c3
commit 4dca2cc797
6 changed files with 65 additions and 18 deletions

View File

@ -2866,7 +2866,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
HANDLE mapping = 0;
SECTION_IMAGE_INFORMATION image_info;
NTSTATUS nts;
void *prev;
ULONG64 prev;
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
@ -2885,8 +2885,16 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
if (nts && nts != STATUS_INVALID_IMAGE_NOT_MZ) goto done;
prev = NtCurrentTeb()->Tib.ArbitraryUserPointer;
NtCurrentTeb()->Tib.ArbitraryUserPointer = nt_name.Buffer + 4;
if (NtCurrentTeb64())
{
prev = NtCurrentTeb64()->Tib.ArbitraryUserPointer;
NtCurrentTeb64()->Tib.ArbitraryUserPointer = (ULONG_PTR)(nt_name.Buffer + 4);
}
else
{
prev = (ULONG_PTR)NtCurrentTeb()->Tib.ArbitraryUserPointer;
NtCurrentTeb()->Tib.ArbitraryUserPointer = nt_name.Buffer + 4;
}
switch (nts)
{
@ -2898,7 +2906,11 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
break;
}
NtCurrentTeb()->Tib.ArbitraryUserPointer = prev;
if (NtCurrentTeb64())
NtCurrentTeb64()->Tib.ArbitraryUserPointer = prev;
else
NtCurrentTeb()->Tib.ArbitraryUserPointer = (void *)(ULONG_PTR)prev;
done:
if (nts == STATUS_SUCCESS)

View File

@ -3144,7 +3144,6 @@ static void test_wow64(void)
ok( !status, "ThreadBasicInformation failed %x\n", status );
if (!ReadProcessMemory( pi.hProcess, info.TebBaseAddress, &teb, sizeof(teb), &res )) res = 0;
ok( res == sizeof(teb), "wrong len %lx\n", res );
todo_wine_if( sizeof(void *) > sizeof(int) )
ok( teb.Tib.Self == info.TebBaseAddress, "wrong teb %p / %p\n", teb.Tib.Self, info.TebBaseAddress );
if (is_wow64)
{
@ -3156,11 +3155,9 @@ static void test_wow64(void)
else
{
ok( !teb.GdiBatchCount, "GdiBatchCount set\n" );
todo_wine
ok( teb.WowTebOffset == 0x2000 ||
broken( !teb.WowTebOffset || teb.WowTebOffset == 1 ), /* pre-win10 */
"wrong teb offset %d\n", teb.WowTebOffset );
todo_wine
ok( (char *)teb.Tib.ExceptionList == (char *)info.TebBaseAddress + 0x2000,
"wrong Tib.ExceptionList %p / %p\n",
(char *)teb.Tib.ExceptionList, (char *)info.TebBaseAddress + 0x2000 );
@ -3193,7 +3190,7 @@ static void test_wow64(void)
ok( !teb.WowTebOffset || broken( teb.WowTebOffset == 1 ), /* vista */
"wrong teb offset %d\n", teb.WowTebOffset );
}
else todo_wine ok( !info.TebBaseAddress, "got teb %p\n", info.TebBaseAddress );
else ok( !info.TebBaseAddress, "got teb %p\n", info.TebBaseAddress );
status = pNtQueryInformationProcess( pi.hProcess, ProcessBasicInformation,
&proc_info, sizeof(proc_info), NULL );

View File

@ -1457,11 +1457,8 @@ static void init_teb64( TEB *teb )
TEB64 *teb64 = (TEB64 *)((char *)teb - teb_offset);
if (!is_wow64) return;
teb->GdiBatchCount = PtrToUlong( teb64 );
teb->WowTebOffset = -teb_offset;
teb64->ClientId.UniqueProcess = PtrToUlong( teb->ClientId.UniqueProcess );
teb64->ClientId.UniqueThread = PtrToUlong( teb->ClientId.UniqueThread );
teb64->WowTebOffset = teb_offset;
#endif
}
@ -1584,6 +1581,8 @@ size_t server_init_process(void)
if (!is_win64)
{
is_wow64 = TRUE;
NtCurrentTeb()->GdiBatchCount = PtrToUlong( (char *)NtCurrentTeb() - teb_offset );
NtCurrentTeb()->WowTebOffset = -teb_offset;
init_teb64( NtCurrentTeb() );
}
}
@ -1608,7 +1607,7 @@ size_t server_init_process(void)
void server_init_process_done(void)
{
PEB *peb = NtCurrentTeb()->Peb;
void *entry;
void *entry, *teb;
NTSTATUS status;
int suspend, needs_close, unixdir;
@ -1632,10 +1631,13 @@ void server_init_process_done(void)
* is sent by init_process_done */
signal_init_process();
/* always send the native TEB */
if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb();
/* Signal the parent process to continue */
SERVER_START_REQ( init_process_done )
{
req->teb = wine_server_client_ptr( NtCurrentTeb() );
req->teb = wine_server_client_ptr( teb );
req->peb = wine_server_client_ptr( NtCurrentTeb()->Peb );
#ifdef __i386__
req->ldt_copy = wine_server_client_ptr( &__wine_ldt_copy );
@ -1658,12 +1660,16 @@ void server_init_process_done(void)
*/
void server_init_thread( void *entry_point, BOOL *suspend )
{
void *teb;
int reply_pipe = init_thread_pipe();
/* always send the native TEB */
if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb();
SERVER_START_REQ( init_thread )
{
req->unix_tid = get_unix_tid();
req->teb = wine_server_client_ptr( NtCurrentTeb() );
req->teb = wine_server_client_ptr( teb );
req->entry = wine_server_client_ptr( entry_point );
req->reply_fd = reply_pipe;
req->wait_fd = ntdll_get_thread_data()->wait_fd[1];

View File

@ -901,6 +901,22 @@ BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LA
#endif
}
static BOOL is_process_wow64( const CLIENT_ID *id )
{
HANDLE handle;
ULONG_PTR info;
BOOL ret = FALSE;
if (id->UniqueProcess == ULongToHandle(GetCurrentProcessId())) return is_wow64;
if (!NtOpenProcess( &handle, PROCESS_QUERY_LIMITED_INFORMATION, NULL, id ))
{
if (!NtQueryInformationProcess( handle, ProcessWow64Information, &info, sizeof(info), NULL ))
ret = !!info;
NtClose( handle );
}
return ret;
}
/******************************************************************************
* NtQueryInformationThread (NTDLL.@)
*/
@ -935,6 +951,13 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
SERVER_END_REQ;
if (status == STATUS_SUCCESS)
{
if (is_wow64)
{
if (is_process_wow64( &info.ClientId ))
info.TebBaseAddress = (char *)info.TebBaseAddress + teb_offset;
else
info.TebBaseAddress = NULL;
}
if (data) memcpy( data, &info, min( length, sizeof(info) ));
if (ret_len) *ret_len = min( length, sizeof(info) );
}

View File

@ -2830,7 +2830,7 @@ static PEB *init_peb( void *ptr )
/* set some initial values in a new TEB */
static TEB *init_teb( void *ptr, PEB *peb )
static TEB *init_teb( void *ptr, PEB *peb, BOOL is_wow )
{
struct ntdll_thread_data *thread_data;
TEB *teb;
@ -2848,6 +2848,9 @@ static TEB *init_teb( void *ptr, PEB *peb )
PtrToUlong( &teb32->ActivationContextStack.FrameListCache );
teb32->StaticUnicodeString.Buffer = PtrToUlong( teb32->StaticUnicodeBuffer );
teb32->StaticUnicodeString.MaximumLength = sizeof( teb32->StaticUnicodeBuffer );
teb32->GdiBatchCount = PtrToUlong( teb64 );
teb32->WowTebOffset = -teb_offset;
if (is_wow) teb64->WowTebOffset = teb_offset;
#else
teb = (TEB *)teb32;
teb64->Peb = PtrToUlong( (char *)peb + page_size );
@ -2859,6 +2862,12 @@ static TEB *init_teb( void *ptr, PEB *peb )
PtrToUlong( &teb64->ActivationContextStack.FrameListCache );
teb64->StaticUnicodeString.Buffer = PtrToUlong( teb64->StaticUnicodeBuffer );
teb64->StaticUnicodeString.MaximumLength = sizeof( teb64->StaticUnicodeBuffer );
teb64->WowTebOffset = teb_offset;
if (is_wow)
{
teb32->GdiBatchCount = PtrToUlong( teb64 );
teb32->WowTebOffset = -teb_offset;
}
#endif
teb->Peb = peb;
teb->Tib.Self = &teb->Tib;
@ -2908,7 +2917,7 @@ TEB *virtual_alloc_first_teb(void)
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 );
teb = init_teb( ptr, peb );
teb = init_teb( ptr, peb, FALSE );
*(ULONG_PTR *)&peb->CloudFileFlags = get_image_address();
thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
thread_data->debug_info = (struct debug_info *)((char *)teb_block + 31 * block_size + 2 * page_size);
@ -2953,7 +2962,7 @@ NTSTATUS virtual_alloc_teb( TEB **ret_teb )
NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&ptr, 0, &block_size,
MEM_COMMIT, PAGE_READWRITE );
}
*ret_teb = teb = init_teb( ptr, NtCurrentTeb()->Peb );
*ret_teb = teb = init_teb( ptr, NtCurrentTeb()->Peb, is_wow64 );
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
if ((status = signal_alloc_thread( teb )))

View File

@ -134,7 +134,7 @@ static const struct object_ops debug_obj_ops =
/* get a pointer to TEB->ArbitraryUserPointer in the client address space */
static client_ptr_t get_teb_user_ptr( struct thread *thread )
{
unsigned int ptr_size = is_machine_64bit( thread->process->machine ) ? 8 : 4;
unsigned int ptr_size = is_machine_64bit( supported_machines[0] ) ? 8 : 4;
return thread->teb + 5 * ptr_size;
}