簡體   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