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

人盡茶涼 提交于 2019-12-07 05:34:39

问题


Running the following code in Delphi XE2 Win32 platform works. However, the same code compile in win64 platform will cause access violation in "EnumRCDataProc" if run in debug mode:

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. However, I can't figure out how. Any ideas?


回答1:


The problem is that you have made EnumRCDataProc a local procedure. 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

But it does not do so. I dug a little deeper and discovered that the callback parameter for EnumResourceNames is declared as type 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. Your luck runs out on 64 bit. 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.
  2. LoadPackage is a rather heavyweight approach to getting a module handle. I would prefer to see LoadLibraryEx with the LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE and LOAD_LIBRARY_AS_IMAGE_RESOURCE options.


来源:https://stackoverflow.com/questions/8837080/delphi-xe2-invoke-winapi-enumresourcenames-cause-access-violation-in-win64-plat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!