【问题标题】:How to use WriteProcessMemory in Delphi如何在 Delphi 中使用 WriteProcessMemory
【发布时间】:2017-11-13 02:04:55
【问题描述】:

我无法编译此代码。我可以帮忙吗?谢谢。

procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
var
  st: TSystemTime;
  pst: Pointer;
  hDTP: Cardinal;
  hProc: THandle;
  dwWrote: DWORD;
begin
  DateTimeToSystemTime(dt, st);
  pst:= VirtualAllocEx(h, nil, SizeOf(st), MEM_COMMIT, 0);
  if pst <> nil then begin
    if GetWindowThreadProcessId(h, hDTP) > 0 then begin
      hProc:= OpenProcess(PROCESS_VM_OPERATION, false, hDTP);
      if WriteProcessMemory(hProc, pst, @st, SizeOf(st), dwWrote) > 0 then begin
        SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, hDTP);
        CloseHandle(hProc);
      end;
    end;
    VirtualFreeEx(h, pst, 0, MEM_RELEASE);
  end;
end;

它在使用“WriteProcessMemory”的行显示“实际和正式 var 参数的类型必须相同”。

【问题讨论】:

    标签: delphi delphi-xe2


    【解决方案1】:

    实际和形式 var 参数的类型必须相同

    这是编译器错误 E2003。如果遇到不理解的编译器错误,首先要做的是阅读documentation。它说:

    对于可变参数,实际参数必须是形参的确切类型。

    导致此错误的函数调用是WriteProcessMemory。让我们看看它的声明:

    function WriteProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; 
      lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesWritten: SIZE_T): BOOL; stdcall;
    

    这里只有一个var参数,最后一个参数。您传递的变量必须是SIZE_T 类型,但您传递的是DWORD 类型的变量。这就是不匹配。

    其他一些cmets:

    • VirtualAllocEx 的调用必然会失败,因为您传递的是窗口句柄而不是进程句柄。
    • 从语义上讲,测试正线程 ID 是没有意义的。测试不等于 0 是否成功。
    • 您没有检查OpenProcess 返回值。那很容易失败。
    • 您没有打开具有PROCESS_VM_WRITE 访问权限的进程,这是WriteProcessMemory 所必需的。
    • 如果对 WriteProcessMemory 的调用失败,则会泄漏句柄。
    • WriteProcessMemory的返回类型为BOOL
    • hDTP 是一个奇怪的进程 ID 名称。该名称表明您认为它是日期时间选择器控件的句柄。它不是。这是进程ID。
    • 您在SendMessage 调用中传递了该进程ID,而不是您刚刚写入的系统时间的地址。

    【讨论】:

    • 您能否修改该程序作为您的评论?你做过测试吗?对于 BOOL,您可以获得 TRUE/FALSE 或 1/0。关于 SIZE_T,DWORD 或整数都一样。
    • 您询问了编译器错误,我对此进行了全面介绍。我要测试什么?我不明白?
    【解决方案2】:

    您的代码中有几个错误。

    • 您将 HWND 传递给 VirtualAllocEx(),但它希望将 THandle 传递给打开的进程。在您打开进程句柄之前,您正在调用VirtualAllocEx()。而且您没有请求对分配的内存进行写访问。

    • 在调用OpenProcess() 时,您不会请求PROCESS_VM_WRITE 权限,而WriteProcessMemory() 需要。

    • 您对WriteProcessMemory() 的使用与其声明不匹配。这就是您收到编译器错误的原因。

    • 您将 HWND 的进程 ID 作为 LPARAMDTM_SETSYSTEMTIME 传递,但它需要分配的 TSystemTime 指针。

    试试这样的:

    procedure ChangeOutsideDateTime(h: HWND; dt: TDateTime);
    var
      st: TSystemTime;
      PID: DWORD;
      hProc: THandle;
      pst: Pointer;
      NumWrote: SIZE_T;
    begin
      GetWindowThreadProcessId(h, PID);
      hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_WRITE, false, PID);
      if hProc <> 0 then
      try
        pst := VirtualAllocEx(hProc, nil, SizeOf(st), MEM_COMMIT, PAGE_READWRITE);
        if pst <> nil then
        try
          DateTimeToSystemTime(dt, st);
          if WriteProcessMemory(hProc, pst, @st, SizeOf(st), NumWrote) then begin
            SendMessage(h, DTM_SETSYSTEMTIME, GDT_VALID, LPARAM(pst));
          end;
        finally
          VirtualFreeEx(hProc, pst, 0, MEM_RELEASE);
        end;
      finally
        CloseHandle(hProc);
      end;
    end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-25
      • 2014-08-24
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多