delphi - EnumResourceNames 返回 Windows 错误 998(对内存位置的访问无效)

标签 delphi dll

(请参阅底部的编辑)

使用 EnumResourceNames,我试图找到作为资源存储在我自己的 dll 中的图标。这是完整的dll代码:

library focusRes;

{$R focusResResource.res} // contains the icons I need to load
{$R *.res}

begin
end.

我可以使用 LoadLibrary 和 LoadLibraryEx 正确加载 dll(已验证)。但是对 EnumResourceNames 的调用返回 false,并且 GetLastError 返回 998(对内存位置的访问无效)。调用代码为:

hdll := LoadLibraryEx( PChar( DLLFilename ), 0, LOAD_LIBRARY_AS_DATAFILE );
// OR: hdll := LoadLibrary( PChar( DLLFilename ));
enumResult := EnumResourceNames( hDll, RT_ICON, @EnumResFlags, 0 );
// (hDll is the handle returned from LoadLibrary)

和回调函数:

function EnumResFlags( hDll : HMODULE; ResType, ResName : PChar; 
   notUsed : pointer ) : integer; stdcall;
begin
  // NEVER GETS CALLED
  // log( ResName);
  result := 1; // continue enumeration
end;

回调是一个独立函数(不是对象方法或本地函数)。

在我的调查中,我发现了一些令人困惑的线索:

  • 问题似乎出在我的 dll 上,因为如果我替换一个随机的 来自第三方应用程序的 dll,问题就消失了。

  • 问题似乎出在我的 dll 上,因为我可以打开它 在第三方图标编辑器中,dll中存储的所有图标都是 正确加载。

  • 当我尝试为特定图标名称创建资源流时, 异常(exception)是“未找到资源[名称]”。 (但是图标编辑器觉得还好)

(Windows 7 32 位上的 Delphi XE)

编辑1:创建一个新的Delphi项目并将以下行放入其中:

enumResult := EnumResourceNames( hInstance, RT_ICON, @EnumCallback, 0 );

结果:错误 998。将 RT_ICON 更改为其他内容,例如 RT_RTCDATA,问题就消失了。

编辑2:如果我不在回调中引用ResName参数,则问题不会发生。 (如果我在回调中只说“结果:= 1”,则没有错误。)回到Delphi 3(!)并得到相同的精确结果,因此它不是XE所特有的。如果我尝试枚举 RT_RCDATA 而不是 RT_ICON,则没有问题,并且我可以读取 ResName。

最佳答案

您没有正确解析回调的 lpszTypelpszName 参数。失败的测试涉及传递给回调的资源 ID,而不是资源名称。当您尝试通过指针访问进程内存的前 64kb 时,这是一次无效的内存访问。

您需要测试 ResType/ResName 是否是名称或 ID,然后进行相应处理,如下所示:

function EnumResFlags( hDll : HMODULE; ResType, ResName : PChar; notUsed : pointer ) : integer; stdcall;
begin
  if IS_INTRESOURCE(ResName) then
    log(IntToStr(Integer(ResName)))
  else
    log(ResName);
  ...
end;

如果您的 Delphi 版本没有定义 IS_INTRESOURCE(),您可以手动定义它:

function IS_INTRESOURCE(lpszType: PChar): BOOL;
begin
  Result := ULONG_PTR(lpszType) shr 16 = 0;
end;

关于delphi - EnumResourceNames 返回 Windows 错误 998(对内存位置的访问无效),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23024402/

相关文章:

visual-studio - Delphi (.NET) 的最佳替代 IDE 是什么

delphi - 如何隐藏其他应用程序/进程的托盘图标(从我的应用程序)?

string - Delphi:如何将 TIdBytes 编码为 Base64 字符串?

vb.net - 在 Visual Basic .NET 中访问 MTP/WPD 设备

delphi - 从回调函数的参数中获取值

delphi - Delphi PasLibVLC-无需安装VLC播放器即可使用

delphi - Indy TCPServer 在客户端连接时出现 `Connection reset by peer` 错误

delphi - 树状数据结构(与 VirtualTreeview 一起使用)

PHP 5.4.7 编译 ext php_printer

c# - 如何在 WiX MSI 中降级第三方文件