我如何使用 Wow64GetThreadContext?
How can I use Wow64GetThreadContext?
如何在 x64 中正确使用 Wow64GetThreadContext
?在 DelphiXE7 中 Winapi.Windows.pas
中没有定义该函数。
不过我试过了。
program Project3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows;
const
WOW64_SIZE_OF_80387_REGISTERS = 80;
WOW64_MAXIMUM_SUPPORTED_EXTENSION = 512;
WOW64_CONTEXT_i386 = [==]010000; // this assumes that i386 and
WOW64_CONTEXT_i486 = [==]010000; // i486 have identical context records
WOW64_CONTEXT_CONTROL = LongInt(WOW64_CONTEXT_i386 or [==]000001); // SS:SP, CS:IP, FLAGS, BP
WOW64_CONTEXT_INTEGER = LongInt(WOW64_CONTEXT_i386 or [==]000002); // AX, BX, CX, DX, SI, DI
WOW64_CONTEXT_SEGMENTS = LongInt(WOW64_CONTEXT_i386 or [==]000004); // DS, ES, FS, GS
WOW64_CONTEXT_FLOATING_POINT = LongInt(WOW64_CONTEXT_i386 or [==]000008); // 387 state
WOW64_CONTEXT_DEBUG_REGISTERS = LongInt(WOW64_CONTEXT_i386 or [==]000010); // DB 0-3,6,7
WOW64_CONTEXT_EXTENDED_REGISTERS = LongInt(WOW64_CONTEXT_i386 or [==]000020); // cpu specific extensions
WOW64_CONTEXT_FULL = (WOW64_CONTEXT_CONTROL or WOW64_CONTEXT_INTEGER or WOW64_CONTEXT_SEGMENTS);
WOW64_CONTEXT_ALL = (WOW64_CONTEXT_CONTROL or WOW64_CONTEXT_INTEGER or WOW64_CONTEXT_SEGMENTS or WOW64_CONTEXT_FLOATING_POINT or WOW64_CONTEXT_DEBUG_REGISTERS or WOW64_CONTEXT_EXTENDED_REGISTERS);
WOW64_CONTEXT_XSTATE = LongInt(WOW64_CONTEXT_i386 or [==]000040);
WOW64_CONTEXT_EXCEPTION_ACTIVE = 000000;
WOW64_CONTEXT_SERVICE_ACTIVE = 000000;
WOW64_CONTEXT_EXCEPTION_REQUEST = 000000;
WOW64_CONTEXT_EXCEPTION_REPORTING = 000000;
type
PWOW64_FLOATING_SAVE_AREA = ^WOW64_FLOATING_SAVE_AREA;
WOW64_FLOATING_SAVE_AREA = record
ControlWord: DWORD;
StatusWord: DWORD;
TagWord: DWORD;
ErrorOffset: DWORD;
ErrorSelector: DWORD;
DataOffset: DWORD;
DataSelector: DWORD;
RegisterArea: Array[0..WOW64_SIZE_OF_80387_REGISTERS-1] of BYTE;
Cr0NpxState: DWORD;
end;
PWOW64_CONTEXT = ^WOW64_CONTEXT;
WOW64_CONTEXT = record
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
ContextFlags: DWORD ;
//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//
Dr0: DWORD;
Dr1: DWORD;
Dr2: DWORD;
Dr3: DWORD;
Dr6: DWORD;
Dr7: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//
FloatSave: WOW64_FLOATING_SAVE_AREA;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
SegGs: DWORD;
SegFs: DWORD;
SegEs: DWORD;
SegDs: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
Edi: DWORD;
Esi: DWORD;
Ebx: DWORD;
Edx: DWORD;
Ecx: DWORD;
Eax: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//
Ebp: DWORD;
Eip: DWORD;
SegCs: DWORD; // MUST BE SANITIZED
EFlags: DWORD; // MUST BE SANITIZED
Esp: DWORD;
SegSs: DWORD;
//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//
ExtendedRegisters: Array[0..WOW64_MAXIMUM_SUPPORTED_EXTENSION-1] of BYTE;
end;
function Wow64GetThreadContext(
{_In_} hThread: THandle;
{_Inout_} var lpContext: WOW64_CONTEXT
): BOOL; WINAPI; external Kernel32 delayed;
var
TargetContext: WOW64_CONTEXT;
begin
TargetContext.ContextFlags := WOW64_CONTEXT_FULL;
Wow64GetThreadContext(GetCurrentThread, TargetContext);
WriteLn(GetLastError); // 87 - ERROR_INVALID_PARAMETER
ReadLn;
end.
You cannot get a valid context for a running thread. Use the Wow64SuspendThread function to suspend the thread before calling Wow64GetThreadContext.
If you call Wow64GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid.
换句话说,您不能在执行线程上调用 Wow64GetThreadContext
。
从文档中进一步了解:
This function is intended for 64-bit applications. It is not supported on 32-bit Windows; such calls fail and set the last error code to ERROR_INVALID_FUNCTION. A 32-bit application can call this function on a WOW64 thread; the result is the same as calling the GetThreadContext function.
只有从传递 32 位线程句柄的 64 位进程调用此函数才有意义。换句话说,你传递的线程必须来自不同的进程。
因此,我认为您是从 64 位进程执行并指定 64 位线程。该函数失败,因为您指定的线程不是 32 位 WOW64 线程。
其他一些问题:
- 您需要使用
WOW64_CONTEXT
结构而不是 CONTEXT
。
- 如文档所述,您应该仅在函数失败时调用
GetLastError
,如 return 值所示。这是新手 Win32 程序员最常犯的错误。
如何在 x64 中正确使用 Wow64GetThreadContext
?在 DelphiXE7 中 Winapi.Windows.pas
中没有定义该函数。
不过我试过了。
program Project3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows;
const
WOW64_SIZE_OF_80387_REGISTERS = 80;
WOW64_MAXIMUM_SUPPORTED_EXTENSION = 512;
WOW64_CONTEXT_i386 = [==]010000; // this assumes that i386 and
WOW64_CONTEXT_i486 = [==]010000; // i486 have identical context records
WOW64_CONTEXT_CONTROL = LongInt(WOW64_CONTEXT_i386 or [==]000001); // SS:SP, CS:IP, FLAGS, BP
WOW64_CONTEXT_INTEGER = LongInt(WOW64_CONTEXT_i386 or [==]000002); // AX, BX, CX, DX, SI, DI
WOW64_CONTEXT_SEGMENTS = LongInt(WOW64_CONTEXT_i386 or [==]000004); // DS, ES, FS, GS
WOW64_CONTEXT_FLOATING_POINT = LongInt(WOW64_CONTEXT_i386 or [==]000008); // 387 state
WOW64_CONTEXT_DEBUG_REGISTERS = LongInt(WOW64_CONTEXT_i386 or [==]000010); // DB 0-3,6,7
WOW64_CONTEXT_EXTENDED_REGISTERS = LongInt(WOW64_CONTEXT_i386 or [==]000020); // cpu specific extensions
WOW64_CONTEXT_FULL = (WOW64_CONTEXT_CONTROL or WOW64_CONTEXT_INTEGER or WOW64_CONTEXT_SEGMENTS);
WOW64_CONTEXT_ALL = (WOW64_CONTEXT_CONTROL or WOW64_CONTEXT_INTEGER or WOW64_CONTEXT_SEGMENTS or WOW64_CONTEXT_FLOATING_POINT or WOW64_CONTEXT_DEBUG_REGISTERS or WOW64_CONTEXT_EXTENDED_REGISTERS);
WOW64_CONTEXT_XSTATE = LongInt(WOW64_CONTEXT_i386 or [==]000040);
WOW64_CONTEXT_EXCEPTION_ACTIVE = 000000;
WOW64_CONTEXT_SERVICE_ACTIVE = 000000;
WOW64_CONTEXT_EXCEPTION_REQUEST = 000000;
WOW64_CONTEXT_EXCEPTION_REPORTING = 000000;
type
PWOW64_FLOATING_SAVE_AREA = ^WOW64_FLOATING_SAVE_AREA;
WOW64_FLOATING_SAVE_AREA = record
ControlWord: DWORD;
StatusWord: DWORD;
TagWord: DWORD;
ErrorOffset: DWORD;
ErrorSelector: DWORD;
DataOffset: DWORD;
DataSelector: DWORD;
RegisterArea: Array[0..WOW64_SIZE_OF_80387_REGISTERS-1] of BYTE;
Cr0NpxState: DWORD;
end;
PWOW64_CONTEXT = ^WOW64_CONTEXT;
WOW64_CONTEXT = record
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
ContextFlags: DWORD ;
//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//
Dr0: DWORD;
Dr1: DWORD;
Dr2: DWORD;
Dr3: DWORD;
Dr6: DWORD;
Dr7: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//
FloatSave: WOW64_FLOATING_SAVE_AREA;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
SegGs: DWORD;
SegFs: DWORD;
SegEs: DWORD;
SegDs: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
Edi: DWORD;
Esi: DWORD;
Ebx: DWORD;
Edx: DWORD;
Ecx: DWORD;
Eax: DWORD;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//
Ebp: DWORD;
Eip: DWORD;
SegCs: DWORD; // MUST BE SANITIZED
EFlags: DWORD; // MUST BE SANITIZED
Esp: DWORD;
SegSs: DWORD;
//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//
ExtendedRegisters: Array[0..WOW64_MAXIMUM_SUPPORTED_EXTENSION-1] of BYTE;
end;
function Wow64GetThreadContext(
{_In_} hThread: THandle;
{_Inout_} var lpContext: WOW64_CONTEXT
): BOOL; WINAPI; external Kernel32 delayed;
var
TargetContext: WOW64_CONTEXT;
begin
TargetContext.ContextFlags := WOW64_CONTEXT_FULL;
Wow64GetThreadContext(GetCurrentThread, TargetContext);
WriteLn(GetLastError); // 87 - ERROR_INVALID_PARAMETER
ReadLn;
end.
You cannot get a valid context for a running thread. Use the Wow64SuspendThread function to suspend the thread before calling Wow64GetThreadContext.
If you call Wow64GetThreadContext for the current thread, the function returns successfully; however, the context returned is not valid.
换句话说,您不能在执行线程上调用 Wow64GetThreadContext
。
从文档中进一步了解:
This function is intended for 64-bit applications. It is not supported on 32-bit Windows; such calls fail and set the last error code to ERROR_INVALID_FUNCTION. A 32-bit application can call this function on a WOW64 thread; the result is the same as calling the GetThreadContext function.
只有从传递 32 位线程句柄的 64 位进程调用此函数才有意义。换句话说,你传递的线程必须来自不同的进程。
因此,我认为您是从 64 位进程执行并指定 64 位线程。该函数失败,因为您指定的线程不是 32 位 WOW64 线程。
其他一些问题:
- 您需要使用
WOW64_CONTEXT
结构而不是CONTEXT
。 - 如文档所述,您应该仅在函数失败时调用
GetLastError
,如 return 值所示。这是新手 Win32 程序员最常犯的错误。