当我为正在测试的进程启用页面堆时,它会触发一个访问冲突,这表明在调用SHGetFileInfo时发生了某种类型的堆损坏。
调用堆栈的顶部显示msvcr90!wcspbrk并向下走,它显示ole32中与COM相关的项目,直到到达shell32,我们称之为SHGetFileInfo。
从我在网上找到的,使用shell32的奇怪的一个常见问题是不首先调用CoInitialize / CoInitializeEx,但是此时已经调用了CoInitializeEx(),并且在下面的代码之前立即调用它只是返回S_FALSE
下面的代码位于我们的DLL中,它是从.NET引入的(该代码用于检索用于特定文件的图标):
SHFILEINFOW shfi;
memset(&shfi,0,sizeof(shfi));
SHGetFileInfoW(A2W("C:\\logfile.txt"),
FILE_ATTRIBUTE_NORMAL,
&shfi,
sizeof(shfi),
SHGFI_USEFILEATTRIBUTES
| SHGFI_ICON
);
(其中logfile.txt是我的根驱动器上的随机文本文件)
为了简单起见,我已将第一个参数硬编码到我机器上的文件中。
我使用的是64位Windows操作系统,但代码是在32位上下文中运行的。如果我使用SHGetFileInfo的窄版本,我会得到相同的结果。
如果我为我的流程禁用了页面堆,则没有问题。
当我不使用标志SHGFI_ICON时,问题不会发生。
编辑:@HansPassant要求我添加一个可重现的示例,这里是Visual Studio 2010 Win32控制台应用程序的链接,演示了该问题:sample