Delphi 10.4编译错误:“实参和形参的类型必须相同”

9cbw7uwe  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(222)

我是编程新手。我使用的是 Delphi 10.4 Community Edition。我正在尝试运行BassPlayer演示项目,但在编译和运行时遇到错误。错误发生在名为wa_ipc.pas的文件的第1691行。我不知道如何修复此错误。

function SendMessageRetStr(wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): String;
var
  dwProcessId: DWORD;
  phandle: THandle;
  P: Pointer;
  C: Cardinal;
  PB: Pointer;
  B: Byte;
begin
  Result := '';
  GetWindowThreadProcessID(wnd, pointer(dwProcessId));
  phandle := OpenProcess(PROCESS_VM_READ, False, dwProcessId);
  if phandle = 0 then exit;
  P := Pointer(SendMessage(wnd, uMsg, wParam, lParam));
  PB := nil;
  B := 0;
  repeat
    if not ReadProcessMemory(phandle,P,@PB,1,C) then break; (*<-- Error message here*)
    B := Byte(PB);
    if B <> 0 then begin
      Result := Result + Chr(B);
    end;
    P := Pointer(DWord(P)+1);
  until (B=0);

  CloseHandle(phandle);
end;

我得到的错误是:
[dcc32错误] wa_ipc.pas(1691):E2033实参和形参的类型必须相同
Winapi.Windows.pas单元中,ReadProcessMemory()函数声明为:

function ReadProcessMemory(hProcess: THandle; const lpBaseAddress: Pointer; lpBuffer: Pointer; nSize: SIZE_T; var lpNumberOfBytesRead: SIZE_T): BOOL; stdcall;
hyrbngr7

hyrbngr71#

我发现这段代码有很多问题。

  • GetWindowThreadProcessId()的第二个参数中使用pointer(dwProcessId)是错误的。它在运行时 * 不会 * 按预期工作。您正在传递一个无效的内存地址供API写入,导致 * 未定义的行为 *。您需要改用@dwProcessId
  • 您在ReadProcessMemory()的第三个参数中使用@PB是错误的。您正在从远程进程阅读1个字节到Pointer变量中,然后您正在将该Pointer截断为Byte。虽然这在运行时 * 将 * 表现为预期的行为,但在 * 逻辑上 * 是错误的,您确实应该使用@B并完全删除PB
  • ReadProcessMemory()的第5个参数中使用C错误。这是导致编译器错误的原因。在Win32 API中,该参数需要指向SIZE_T的 * 指针 *(它是指针大小的无符号整数),不是Cardinal的 * 值 *(它是一个固定大小的32位无符号整数)。在 Delphi 的Winapi.Windows单元中,该参数被声明为对SIZE_T变量的var引用,而不是Cardinal变量的var引用,因此会出现编译器错误。您必须将变量声明为与var引用所需的完全相同的数据类型。
  • 所讨论的远程数据显然是一个8位的以空值结尾的ANSI字符串,但是您将8位字符按原样追加到16位的UnicodeString中。除非所讨论的字符是纯ASCII字符,否则结果将不是您所期望的。
  • Dword是一个32位整数,因此只有当您的应用被编译为32位可执行文件时,这种转换才能正常工作,因为32位可执行文件在运行时使用32位内存地址。但在64位可执行文件中,您可能会截断指针指向的内存地址。您需要使用DWORD_PTR(或等效的)来代替。

现在,说了这么多,试着做一些类似这样的事情:

function SendMessageRetStr(wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): String;
var
  dwProcessId: DWORD;
  hProcess: THandle;
  PCh: LRESULT;
  bytesRead: SIZE_T;
  Ch: AnsiChar;
  S: AnsiString;
begin
  Result := '';
  GetWindowThreadProcessID(wnd, @dwProcessId);
  hProcess := OpenProcess(PROCESS_VM_READ, False, dwProcessId);
  if hProcess = 0 then Exit;
  try
    PCh := SendMessage(wnd, uMsg, wParam, lParam);
    repeat
      if not ReadProcessMemory(hProcess, Pointer(PCh), @Ch, 1, bytesRead{or: PSize_t(nil)^}) then break;
      if Ch = #0 then break;
      S := S + Ch;
      Inc(PCh);
    until False;
  finally
    CloseHandle(hProcess);
  end;
  Result := string(S);
end;

相关问题