Как использовать WriteProcessMemory в Delphi

Я не могу скомпилировать этот код. Могу ли я получить помощь? Благодарю.

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;

Он показывает "Типы фактических и формальных параметров var должны быть идентичны" в строке, где используется "WriteProcessMemory".

2 ответа

Решение

В вашем коде есть несколько митак.

  • вы передаете HWND в VirtualAllocEx(), но это ожидает THandle вместо открытого процесса. А ты звонишь VirtualAllocEx() прежде чем вы открыли дескриптор процесса. И вы не запрашиваете запись в выделенную память.

  • при звонке OpenProcess()вы не просите PROCESS_VM_WRITE разрешение, которое WriteProcessMemory() требует.

  • ваше использование WriteProcessMemory() не соответствует его объявлению. Вот почему вы получаете ошибку компилятора.

  • вы передаете HWNDИдентификатор процесса как LPARAM из DTM_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;

Типы фактических и формальных параметров var должны быть идентичны

Это ошибка компилятора E2003. Если вы столкнетесь с ошибкой компилятора, которую вы не понимаете, первым делом прочитайте документацию. Это говорит:

Для параметра переменной фактический аргумент должен иметь точный тип формального параметра.

Вызов функции, которая приводит к этой ошибке WriteProcessMemory, Давайте посмотрим на его объявление:

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

Здесь только один var параметр здесь, последний параметр. Передаваемая переменная должна иметь тип SIZE_T, но вы передали переменную типа DWORD, Это несоответствие.

Некоторые другие комментарии:

  • Призыв к VirtualAllocEx неизбежно потерпит неудачу, потому что вы передаете дескриптор окна, а не дескриптор процесса.
  • Семантически нет смысла проверять положительный идентификатор потока. Тест не равен нулю для успеха или иным образом.
  • Вы не проверяете OpenProcess возвращаемое значение Это может легко потерпеть неудачу.
  • Вы не открываете процесс с PROCESS_VM_WRITE право доступа, которое необходимо для WriteProcessMemory,
  • Вы пропустите ручку, если вызов WriteProcessMemory выходит из строя.
  • Тип возврата WriteProcessMemory является BOOL,
  • hDTP странное имя для идентификатора процесса. Это имя говорит о том, что вы думаете, что это дескриптор элемента управления выбора даты. Это не. Это идентификатор процесса.
  • Вы передаете этот идентификатор процесса в SendMessage звоните, а не адрес системного времени, которое вы только что написали.
Другие вопросы по тегам