简体   繁体   中英

How to use WriteProcessMemory in Delphi

I cannot compile this code. Could I have a help? Thanks.

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;

It shows "Types of actual and formal var parameters must be identical" at line where is using "WriteProcessMemory".

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.

Your code has several mitakes in it.

  • you are passing an HWND to VirtualAllocEx() , but it expects a THandle to an opened process instead. And you are calling VirtualAllocEx() before you have opened the process handle. And you are not requesting write acess to the allocated memory.

  • when calling OpenProcess() , you are not asking for PROCESS_VM_WRITE permission, which WriteProcessMemory() requires.

  • your use of WriteProcessMemory() does not match its declaration. That is why you are getting a compiler error.

  • you are passing the HWND 's process ID as the LPARAM of DTM_SETSYSTEMTIME , but it expects the allocated TSystemTime pointer instead.

Try something more like this:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM