我的应用程序包含一些关于 DLL 的特定逻辑(这里解释有点复杂)。但在这种逻辑中,我注意到以下内容(在客户的 Citrix 终端服务器上):
在 NTDLL.DLL 上调用 GetModuleInformation 时,返回的 MODULEINFO 返回 0x7d600000 的第一个地址 (lpBaseOfDll) 和 0xf0000 的大小(因此它的最后一个字节应该在 0x7d6effff)。
但是,在故障转储文件中,我在 WinDbg 中看到以下内容(使用!address):
* 7d600000 7d601000 1000 Image "J:\WINDOWS\system32\ntdll.dll"
* 7d610000 7d65f000 4f000 <unclassified>
* 7d65f000 7d660000 1000 <unclassified>
* 7d660000 7d699000 39000 <unclassified>
* 7d6a0000 7d6a6000 6000 <unclassified>
* 7d6b0000 7d6df000 2f000 <unclassified>
* 7d6e0000 7d6e4000 4000 <unclassified>
* 7d800000 7d801000 1000 Image "J:\WINDOWS\SysWOW64\gdi32.dll"
* 7d810000 7d855000 45000 <unclassified>
* 7d860000 7d861000 1000 <unclassified>
* 7d861000 7d862000 1000 <unclassified>
* 7d870000 7d871000 1000 <unclassified>
* 7d880000 7d882000 2000 <unclassified>
所以看起来 NTDLL.DLL 的大小只有 0x1000 而不是 0xf0000。
这就解释了为什么对超过 0x1000 大小的 VirtualLock 的调用会失败(错误代码 998:对内存位置的访问无效)并且访问内存会使应用程序崩溃。
我在哪里可以找到解释为什么 DLL 仅部分加载?Citrix 是否将 DLL 替换为存根,但未通过 GetModuleInformation 正确报告?还是发生了其他事情?
为什么 NTDLL.DLL 是从 J:\WINDOWS\SYSTEM32 加载的,而大多数其他 DLL 是从 J:\WINDOWS\SYSWOW64 加载的?(这可能表明确实使用了一些 32/64 存根)。
这是我第一次遇到这个问题。