我该如何使用Wow64GetThreadContext?

时间:2015-01-06 14:05:00

标签: delphi winapi delphi-xe7

如何在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 = $00010000;   // this assumes that i386 and
  WOW64_CONTEXT_i486 = $00010000;   // i486 have identical context records
  WOW64_CONTEXT_CONTROL = LongInt(WOW64_CONTEXT_i386 or $00000001); // SS:SP, CS:IP, FLAGS, BP
  WOW64_CONTEXT_INTEGER = LongInt(WOW64_CONTEXT_i386 or $00000002); // AX, BX, CX, DX, SI, DI
  WOW64_CONTEXT_SEGMENTS = LongInt(WOW64_CONTEXT_i386 or $00000004);    // DS, ES, FS, GS
  WOW64_CONTEXT_FLOATING_POINT = LongInt(WOW64_CONTEXT_i386 or $00000008);  // 387 state
  WOW64_CONTEXT_DEBUG_REGISTERS = LongInt(WOW64_CONTEXT_i386 or $00000010); // DB 0-3,6,7
  WOW64_CONTEXT_EXTENDED_REGISTERS = LongInt(WOW64_CONTEXT_i386 or $00000020);  // 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 $00000040);
  WOW64_CONTEXT_EXCEPTION_ACTIVE = $08000000;
  WOW64_CONTEXT_SERVICE_ACTIVE = $10000000;
  WOW64_CONTEXT_EXCEPTION_REQUEST = $40000000;
  WOW64_CONTEXT_EXCEPTION_REPORTING = $80000000;


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.

1 个答案:

答案 0 :(得分:3)

来自documentation

  

您无法获得正在运行的线程的有效上下文。在调用Wow64GetThreadContext之前,使用Wow64SuspendThread函数挂起线程。

     

如果为当前线程调用Wow64GetThreadContext,则函数返回成功;但是,返回的上下文无效。

换句话说,你不能在执行线程上调用Wow64GetThreadContext

还有文档:

  

此功能适用于64位应用程序。 32位Windows不支持它;此类调用失败,并将最后一个错误代码设置为ERROR_INVALID_FUNCTION。 32位应用程序可以在WOW64线程上调用此函数;结果与调用GetThreadContext函数相同。

仅通过传递32位线程句柄的64位进程调用此函数才有意义。换句话说,您传递的线程必须来自不同的进程。

所以,我的信念是你从64位进程执行并指定64位线程。该函数失败,因为您指定的线程不是32位WOW64线程。

其他一些问题:

  1. 您需要使用WOW64_CONTEXT结构而不是CONTEXT
  2. 如文档所述,您应该只在函数失败时调用GetLastError,如返回值所示。这是新手Win32程序员最常犯的错误。