繁体   English   中英

Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突

[英]Delphi XE2: Invoke WinAPI EnumResourceNames cause access violation in Win64 platform

在Delphi XE2 Win32平台上运行以下代码即可。 但是,如果在调试模式下运行,则在win64平台上编译的同一代码将导致“ EnumRCDataProc”中的访问冲突:

procedure TForm2.Button1Click(Sender: TObject);
  function EnumRCDataProc(hModule: THandle; lpszType, lpszName: PChar; lParam:
      NativeInt): Boolean; stdcall;
  begin
    TStrings(lParam).Add(lpszName);
    Result := True;
  end;

var k: NativeInt;
    L: TStringList;
    H: THandle;
begin
  H := LoadPackage('resource.bpl');
  L := TStringList.Create;
  try
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
    ShowMessage(L.Text);
  finally
    L.Free;
    UnloadPackage(H);
  end;
end;

在Win64平台上的Delphi XE2 IDE中调试代码时,我发现EnumRCDataProc中的hModule的值与变量H不匹配。我怀疑为EnumRCDataProc构造的参数可能有问题。 但是,我不知道如何。 有任何想法吗?

问题是您已经使EnumRCDataProc成为本地过程。 您需要将其移到方法之外。

function EnumRCDataProc(hModule: HMODULE; lpszType, lpszName: PChar; lParam:
    NativeInt): BOOL; stdcall;
begin
  TStrings(lParam).Add(lpszName);
  Result := True;
end;

procedure TForm2.Button1Click(Sender: TObject);
var k: NativeInt;
    L: TStringList;
    H: HMODULE;
begin
  H := LoadPackage('resource.bpl');
  L := TStringList.Create;
  try
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
    ShowMessage(L.Text);
  finally
    L.Free;
    UnloadPackage(H);
  end;
end;

第一次检查时,我希望编译器会在您的代码中发出错误:

E2094分配给过程变量的本地过程/功能“回调”

但是它没有这样做。 我深入研究,发现EnumResourceNames的回调参数被声明为Pointer类型。 如果标头转换已将其声明为类型的回调参数,则确实会发出上述错误消息。 在我看来,标题翻译在这方面很差。 放弃类型系统的安全性似乎没有什么收获。

您的代码可以在32位代码中工作的事实只是一个偶然的巧合,它取决于实现细节。 您的运气用完了64位。 同样,如果启用了类型检查系统,则编译器可能会立即告诉您出了什么问题。

其他一些评论:

  1. EnumRCDataProc有两个错误的类型: hModule的类型应为HMODULE ,函数的结果应为BOOL
  2. LoadPackage是获取模块句柄的一种相当重量级的方法。 我希望看到带有LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_IMAGE_RESOURCE选项的LoadLibraryEx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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