简体   繁体   English

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

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

Running the following code in Delphi XE2 Win32 platform works. 在Delphi XE2 Win32平台上运行以下代码即可。 However, the same code compile in win64 platform will cause access violation in "EnumRCDataProc" if run in debug mode: 但是,如果在调试模式下运行,则在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;

When debug the code in Delphi XE2 IDE on Win64 platform, I found the value of hModule in EnumRCDataProc doesn't match with variable H. I suspect that might be something wrong about the parameters I constructed for the EnumRCDataProc. 在Win64平台上的Delphi XE2 IDE中调试代码时,我发现EnumRCDataProc中的hModule的值与变量H不匹配。我怀疑为EnumRCDataProc构造的参数可能有问题。 However, I can't figure out how. 但是,我不知道如何。 Any ideas? 有任何想法吗?

The problem is that you have made EnumRCDataProc a local procedure. 问题是您已经使EnumRCDataProc成为本地过程。 You need to move it outside the method. 您需要将其移到方法之外。

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;

On first inspection I expected that the compiler would emit an error with your code: 第一次检查时,我希望编译器会在您的代码中发出错误:

E2094 Local procedure/function 'Callback' assigned to procedure variable E2094分配给过程变量的本地过程/功能“回调”

But it does not do so. 但是它没有这样做。 I dug a little deeper and discovered that the callback parameter for EnumResourceNames is declared as type Pointer . 我深入研究,发现EnumResourceNames的回调参数被声明为Pointer类型。 If the header translation had declared this as a typed callback parameter then the above error message would indeed have been emitted. 如果标头转换已将其声明为类型的回调参数,则确实会发出上述错误消息。 To my mind the header translation is poor in this regard. 在我看来,标题翻译在这方面很差。 There seems very little to be gained from abandoning the safety of the type system. 放弃类型系统的安全性似乎没有什么收获。

The fact that your code works in 32 bit code is just a happy coincidence that relies on implementation details. 您的代码可以在32位代码中工作的事实只是一个偶然的巧合,它取决于实现细节。 Your luck runs out on 64 bit. 您的运气用完了64位。 Again, if the type checking system had been enabled, the compiler could have told you what was wrong immediately. 同样,如果启用了类型检查系统,则编译器可能会立即告诉您出了什么问题。

Some other comments: 其他一些评论:

  1. The EnumRCDataProc has a couple of incorrect types in its declaration: hModule should be of type HMODULE and the function result should be BOOL . EnumRCDataProc有两个错误的类型: hModule的类型应为HMODULE ,函数的结果应为BOOL
  2. LoadPackage is a rather heavyweight approach to getting a module handle. LoadPackage是获取模块句柄的一种相当重量级的方法。 I would prefer to see LoadLibraryEx with the LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE and LOAD_LIBRARY_AS_IMAGE_RESOURCE options. 我希望看到带有LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVELOAD_LIBRARY_AS_IMAGE_RESOURCE选项的LoadLibraryEx

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

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