ntdll: Always send the native TEB pointer to the server.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d743c1e6c3
commit
4dca2cc797
|
@ -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)
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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) );
|
||||
}
|
||||
|
|
|
@ -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 )))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue