diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 2f7c0b0f1e8..ec986df451a 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -59,8 +59,6 @@ extern NTSTATUS close_handle( HANDLE ) DECLSPEC_HIDDEN; /* exceptions */ extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) DECLSPEC_HIDDEN; extern void DECLSPEC_NORETURN raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ) DECLSPEC_HIDDEN; -extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN; -extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN; extern LONG WINAPI call_unhandled_exception_filter( PEXCEPTION_POINTERS eptr ) DECLSPEC_HIDDEN; #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7c477db7890..52f7b73f8bf 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1724,172 +1724,12 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context ) } -/*********************************************************************** - * wow64_get_server_context_flags - */ -static unsigned int wow64_get_server_context_flags( DWORD flags ) -{ - unsigned int ret = 0; - - flags &= ~WOW64_CONTEXT_i386; /* get rid of CPU id */ - if (flags & WOW64_CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; - if (flags & WOW64_CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; - if (flags & WOW64_CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; - if (flags & WOW64_CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; - if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; - if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; - return ret; -} - -/*********************************************************************** - * wow64_context_from_server - */ -static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *from ) -{ - if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; - - to->ContextFlags = WOW64_CONTEXT_i386; - if (from->flags & SERVER_CTX_CONTROL) - { - to->ContextFlags |= WOW64_CONTEXT_CONTROL; - to->Ebp = from->ctl.i386_regs.ebp; - to->Esp = from->ctl.i386_regs.esp; - to->Eip = from->ctl.i386_regs.eip; - to->SegCs = from->ctl.i386_regs.cs; - to->SegSs = from->ctl.i386_regs.ss; - to->EFlags = from->ctl.i386_regs.eflags; - } - if (from->flags & SERVER_CTX_INTEGER) - { - to->ContextFlags |= WOW64_CONTEXT_INTEGER; - to->Eax = from->integer.i386_regs.eax; - to->Ebx = from->integer.i386_regs.ebx; - to->Ecx = from->integer.i386_regs.ecx; - to->Edx = from->integer.i386_regs.edx; - to->Esi = from->integer.i386_regs.esi; - to->Edi = from->integer.i386_regs.edi; - } - if (from->flags & SERVER_CTX_SEGMENTS) - { - to->ContextFlags |= WOW64_CONTEXT_SEGMENTS; - to->SegDs = from->seg.i386_regs.ds; - to->SegEs = from->seg.i386_regs.es; - to->SegFs = from->seg.i386_regs.fs; - to->SegGs = from->seg.i386_regs.gs; - } - if (from->flags & SERVER_CTX_FLOATING_POINT) - { - to->ContextFlags |= WOW64_CONTEXT_FLOATING_POINT; - to->FloatSave.ControlWord = from->fp.i386_regs.ctrl; - to->FloatSave.StatusWord = from->fp.i386_regs.status; - to->FloatSave.TagWord = from->fp.i386_regs.tag; - to->FloatSave.ErrorOffset = from->fp.i386_regs.err_off; - to->FloatSave.ErrorSelector = from->fp.i386_regs.err_sel; - to->FloatSave.DataOffset = from->fp.i386_regs.data_off; - to->FloatSave.DataSelector = from->fp.i386_regs.data_sel; - to->FloatSave.Cr0NpxState = from->fp.i386_regs.cr0npx; - memcpy( to->FloatSave.RegisterArea, from->fp.i386_regs.regs, sizeof(to->FloatSave.RegisterArea) ); - } - if (from->flags & SERVER_CTX_DEBUG_REGISTERS) - { - to->ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS; - to->Dr0 = from->debug.i386_regs.dr0; - to->Dr1 = from->debug.i386_regs.dr1; - to->Dr2 = from->debug.i386_regs.dr2; - to->Dr3 = from->debug.i386_regs.dr3; - to->Dr6 = from->debug.i386_regs.dr6; - to->Dr7 = from->debug.i386_regs.dr7; - } - if (from->flags & SERVER_CTX_EXTENDED_REGISTERS) - { - to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS; - memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); - } - return STATUS_SUCCESS; -} - -/*********************************************************************** - * wow64_context_to_server - */ -static void wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from ) -{ - DWORD flags = from->ContextFlags & ~WOW64_CONTEXT_i386; /* get rid of CPU id */ - - memset( to, 0, sizeof(*to) ); - to->cpu = CPU_x86; - - if (flags & WOW64_CONTEXT_CONTROL) - { - to->flags |= SERVER_CTX_CONTROL; - to->ctl.i386_regs.ebp = from->Ebp; - to->ctl.i386_regs.esp = from->Esp; - to->ctl.i386_regs.eip = from->Eip; - to->ctl.i386_regs.cs = from->SegCs; - to->ctl.i386_regs.ss = from->SegSs; - to->ctl.i386_regs.eflags = from->EFlags; - } - if (flags & WOW64_CONTEXT_INTEGER) - { - to->flags |= SERVER_CTX_INTEGER; - to->integer.i386_regs.eax = from->Eax; - to->integer.i386_regs.ebx = from->Ebx; - to->integer.i386_regs.ecx = from->Ecx; - to->integer.i386_regs.edx = from->Edx; - to->integer.i386_regs.esi = from->Esi; - to->integer.i386_regs.edi = from->Edi; - } - if (flags & WOW64_CONTEXT_SEGMENTS) - { - to->flags |= SERVER_CTX_SEGMENTS; - to->seg.i386_regs.ds = from->SegDs; - to->seg.i386_regs.es = from->SegEs; - to->seg.i386_regs.fs = from->SegFs; - to->seg.i386_regs.gs = from->SegGs; - } - if (flags & WOW64_CONTEXT_FLOATING_POINT) - { - to->flags |= SERVER_CTX_FLOATING_POINT; - to->fp.i386_regs.ctrl = from->FloatSave.ControlWord; - to->fp.i386_regs.status = from->FloatSave.StatusWord; - to->fp.i386_regs.tag = from->FloatSave.TagWord; - to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset; - to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector; - to->fp.i386_regs.data_off = from->FloatSave.DataOffset; - to->fp.i386_regs.data_sel = from->FloatSave.DataSelector; - to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState; - memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) ); - } - if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) - { - to->flags |= SERVER_CTX_DEBUG_REGISTERS; - to->debug.i386_regs.dr0 = from->Dr0; - to->debug.i386_regs.dr1 = from->Dr1; - to->debug.i386_regs.dr2 = from->Dr2; - to->debug.i386_regs.dr3 = from->Dr3; - to->debug.i386_regs.dr6 = from->Dr6; - to->debug.i386_regs.dr7 = from->Dr7; - } - if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) - { - to->flags |= SERVER_CTX_EXTENDED_REGISTERS; - memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) ); - } -} - - /****************************************************************************** * RtlWow64GetThreadContext (NTDLL.@) */ NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context ) { - BOOL self; - NTSTATUS ret; - context_t server_context; - unsigned int server_flags = wow64_get_server_context_flags( context->ContextFlags ); - - if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret; - if (self) return STATUS_INVALID_PARAMETER; - return wow64_context_from_server( context, &server_context ); + return NtQueryInformationThread( handle, ThreadWow64Context, context, sizeof(*context), NULL ); } @@ -1898,11 +1738,7 @@ NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context */ NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context ) { - BOOL self; - context_t server_context; - - wow64_context_to_server( &server_context, context ); - return set_thread_context( handle, &server_context, &self ); + return NtSetInformationThread( handle, ThreadWow64Context, context, sizeof(*context) ); } diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 70546849d9a..e60018fb47d 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -467,66 +467,6 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void) } -/*********************************************************************** - * set_thread_context - */ -NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) -{ - NTSTATUS ret; - - SERVER_START_REQ( set_thread_context ) - { - req->handle = wine_server_obj_handle( handle ); - wine_server_add_data( req, context, sizeof(*context) ); - ret = wine_server_call( req ); - *self = reply->self; - } - SERVER_END_REQ; - - return ret; -} - - -/*********************************************************************** - * get_thread_context - */ -NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) -{ - NTSTATUS ret; - - SERVER_START_REQ( get_thread_context ) - { - req->handle = wine_server_obj_handle( handle ); - req->flags = flags; - wine_server_set_reply( req, context, sizeof(*context) ); - ret = wine_server_call( req ); - *self = reply->self; - handle = wine_server_ptr_handle( reply->handle ); - } - SERVER_END_REQ; - - if (ret == STATUS_PENDING) - { - LARGE_INTEGER timeout; - timeout.QuadPart = -1000000; - if (NtWaitForSingleObject( handle, FALSE, &timeout )) - { - NtClose( handle ); - return STATUS_ACCESS_DENIED; - } - SERVER_START_REQ( get_thread_context ) - { - req->handle = wine_server_obj_handle( handle ); - req->flags = flags; - wine_server_set_reply( req, context, sizeof(*context) ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - } - return ret; -} - - /*********************************************************************** * NtContinue (NTDLL.@) */ diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 35191d1d61e..d26e0a98cac 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -666,6 +666,163 @@ NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int fla } +#ifdef __x86_64__ + +/*********************************************************************** + * wow64_get_server_context_flags + */ +static unsigned int wow64_get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= ~WOW64_CONTEXT_i386; /* get rid of CPU id */ + if (flags & WOW64_CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & WOW64_CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & WOW64_CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; + if (flags & WOW64_CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; + return ret; +} + +/*********************************************************************** + * wow64_context_from_server + */ +static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *from ) +{ + if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; + + to->ContextFlags = WOW64_CONTEXT_i386; + if (from->flags & SERVER_CTX_CONTROL) + { + to->ContextFlags |= WOW64_CONTEXT_CONTROL; + to->Ebp = from->ctl.i386_regs.ebp; + to->Esp = from->ctl.i386_regs.esp; + to->Eip = from->ctl.i386_regs.eip; + to->SegCs = from->ctl.i386_regs.cs; + to->SegSs = from->ctl.i386_regs.ss; + to->EFlags = from->ctl.i386_regs.eflags; + } + if (from->flags & SERVER_CTX_INTEGER) + { + to->ContextFlags |= WOW64_CONTEXT_INTEGER; + to->Eax = from->integer.i386_regs.eax; + to->Ebx = from->integer.i386_regs.ebx; + to->Ecx = from->integer.i386_regs.ecx; + to->Edx = from->integer.i386_regs.edx; + to->Esi = from->integer.i386_regs.esi; + to->Edi = from->integer.i386_regs.edi; + } + if (from->flags & SERVER_CTX_SEGMENTS) + { + to->ContextFlags |= WOW64_CONTEXT_SEGMENTS; + to->SegDs = from->seg.i386_regs.ds; + to->SegEs = from->seg.i386_regs.es; + to->SegFs = from->seg.i386_regs.fs; + to->SegGs = from->seg.i386_regs.gs; + } + if (from->flags & SERVER_CTX_FLOATING_POINT) + { + to->ContextFlags |= WOW64_CONTEXT_FLOATING_POINT; + to->FloatSave.ControlWord = from->fp.i386_regs.ctrl; + to->FloatSave.StatusWord = from->fp.i386_regs.status; + to->FloatSave.TagWord = from->fp.i386_regs.tag; + to->FloatSave.ErrorOffset = from->fp.i386_regs.err_off; + to->FloatSave.ErrorSelector = from->fp.i386_regs.err_sel; + to->FloatSave.DataOffset = from->fp.i386_regs.data_off; + to->FloatSave.DataSelector = from->fp.i386_regs.data_sel; + to->FloatSave.Cr0NpxState = from->fp.i386_regs.cr0npx; + memcpy( to->FloatSave.RegisterArea, from->fp.i386_regs.regs, sizeof(to->FloatSave.RegisterArea) ); + } + if (from->flags & SERVER_CTX_DEBUG_REGISTERS) + { + to->ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS; + to->Dr0 = from->debug.i386_regs.dr0; + to->Dr1 = from->debug.i386_regs.dr1; + to->Dr2 = from->debug.i386_regs.dr2; + to->Dr3 = from->debug.i386_regs.dr3; + to->Dr6 = from->debug.i386_regs.dr6; + to->Dr7 = from->debug.i386_regs.dr7; + } + if (from->flags & SERVER_CTX_EXTENDED_REGISTERS) + { + to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS; + memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); + } + return STATUS_SUCCESS; +} + +/*********************************************************************** + * wow64_context_to_server + */ +static void wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from ) +{ + DWORD flags = from->ContextFlags & ~WOW64_CONTEXT_i386; /* get rid of CPU id */ + + memset( to, 0, sizeof(*to) ); + to->cpu = CPU_x86; + + if (flags & WOW64_CONTEXT_CONTROL) + { + to->flags |= SERVER_CTX_CONTROL; + to->ctl.i386_regs.ebp = from->Ebp; + to->ctl.i386_regs.esp = from->Esp; + to->ctl.i386_regs.eip = from->Eip; + to->ctl.i386_regs.cs = from->SegCs; + to->ctl.i386_regs.ss = from->SegSs; + to->ctl.i386_regs.eflags = from->EFlags; + } + if (flags & WOW64_CONTEXT_INTEGER) + { + to->flags |= SERVER_CTX_INTEGER; + to->integer.i386_regs.eax = from->Eax; + to->integer.i386_regs.ebx = from->Ebx; + to->integer.i386_regs.ecx = from->Ecx; + to->integer.i386_regs.edx = from->Edx; + to->integer.i386_regs.esi = from->Esi; + to->integer.i386_regs.edi = from->Edi; + } + if (flags & WOW64_CONTEXT_SEGMENTS) + { + to->flags |= SERVER_CTX_SEGMENTS; + to->seg.i386_regs.ds = from->SegDs; + to->seg.i386_regs.es = from->SegEs; + to->seg.i386_regs.fs = from->SegFs; + to->seg.i386_regs.gs = from->SegGs; + } + if (flags & WOW64_CONTEXT_FLOATING_POINT) + { + to->flags |= SERVER_CTX_FLOATING_POINT; + to->fp.i386_regs.ctrl = from->FloatSave.ControlWord; + to->fp.i386_regs.status = from->FloatSave.StatusWord; + to->fp.i386_regs.tag = from->FloatSave.TagWord; + to->fp.i386_regs.err_off = from->FloatSave.ErrorOffset; + to->fp.i386_regs.err_sel = from->FloatSave.ErrorSelector; + to->fp.i386_regs.data_off = from->FloatSave.DataOffset; + to->fp.i386_regs.data_sel = from->FloatSave.DataSelector; + to->fp.i386_regs.cr0npx = from->FloatSave.Cr0NpxState; + memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) ); + } + if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) + { + to->flags |= SERVER_CTX_DEBUG_REGISTERS; + to->debug.i386_regs.dr0 = from->Dr0; + to->debug.i386_regs.dr1 = from->Dr1; + to->debug.i386_regs.dr2 = from->Dr2; + to->debug.i386_regs.dr3 = from->Dr3; + to->debug.i386_regs.dr6 = from->Dr6; + to->debug.i386_regs.dr7 = from->Dr7; + } + if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) + { + to->flags |= SERVER_CTX_EXTENDED_REGISTERS; + memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) ); + } +} + +#endif /* __x86_64__ */ + + /****************************************************************************** * NtQueryInformationThread (NTDLL.@) */ @@ -886,6 +1043,26 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, return status; } + case ThreadWow64Context: + { +#ifdef __x86_64__ + BOOL self; + WOW64_CONTEXT *context = data; + context_t server_context; + unsigned int server_flags; + + if (length != sizeof(*context)) return STATUS_INFO_LENGTH_MISMATCH; + server_flags = wow64_get_server_context_flags( context->ContextFlags ); + if ((status = get_thread_context( handle, &server_context, server_flags, &self ))) return status; + if (self) return STATUS_INVALID_PARAMETER; + status = wow64_context_from_server( context, &server_context ); + if (ret_len && !status) *ret_len = sizeof(*context); + return status; +#else + return STATUS_INVALID_INFO_CLASS; +#endif + } + case ThreadPriority: case ThreadBasePriority: case ThreadImpersonationToken: @@ -1041,6 +1218,21 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class, return status; } + case ThreadWow64Context: + { +#ifdef __x86_64__ + BOOL self; + const WOW64_CONTEXT *context = data; + context_t server_context; + + if (length != sizeof(*context)) return STATUS_INFO_LENGTH_MISMATCH; + wow64_context_to_server( &server_context, context ); + return set_thread_context( handle, &server_context, &self ); +#else + return STATUS_INVALID_INFO_CLASS; +#endif + } + case ThreadBasicInformation: case ThreadTimes: case ThreadPriority: