[英]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: 其他一些评论:
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
。 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_EXCLUSIVE
和LOAD_LIBRARY_AS_IMAGE_RESOURCE
选项的LoadLibraryEx
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.