如何在Delphi中使用WriteProcessMemory

时间:2017-11-13 02:04:56

标签: delphi delphi-xe2

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

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参数的类型必须相同”。

2 个答案:

答案 0 :(得分:6)

Types of actual and formal var parameters must be identical

This is compiler error E2003. If you encounter a compiler error that you don't understand, the first thing to do is read the documentation. It says:

For a variable parameter, the actual argument must be of the exact type of the formal parameter.

The function call which leads to this error is WriteProcessMemory. Let's look at its declaration:

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

There is only one var parameter here, the final parameter. The variable that you pass must be of type SIZE_T, but you passed a variable of type DWORD. That is the mismatch.

Some other comments:

  • The call to VirtualAllocEx is bound to fail because you pass a window handle rather than a process handle.
  • Semantically it makes no sense to test for positive thread ID. Test not equal to zero for success or otherwise.
  • You don't check the OpenProcess return value. That could readily fail.
  • You don't open the process with the PROCESS_VM_WRITE access right which is necessary for WriteProcessMemory.
  • You leak the handle if the call to WriteProcessMemory fails.
  • The return type of WriteProcessMemory is BOOL.
  • hDTP is a strange name for a process ID. That name suggests you think it is the handle of the date time picker control. It's not. It's the process ID.
  • You pass that process ID in the SendMessage call rather than the address of the system time that you just wrote.

答案 1 :(得分:2)

您的代码中有几个简化。

  • 您正在将HWND传递给VirtualAllocEx(),但它希望THandle代替已打开的流程。在打开流程句柄之前,您正在调用VirtualAllocEx()。并且您没有请求写入已分配的内存。

  • 在致电OpenProcess()时,您并未要求获得PROCESS_VM_WRITE WriteProcessMemory()所需的WriteProcessMemory()权限。

  • 您对HWND的使用与其声明不符。这就是您收到编译器错误的原因。

  • 您正在将LPARAM的进程ID作为DTM_SETSYSTEMTIME的{​​{1}}传递,但它需要使用已分配的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;