我有一个旧的32位安装程序,它将一些32位依赖项DLL安装到Windows系统文件夹中。我发现它无法在64位系统上安装某些32位DLL,因为SysWOW重定向正在做一些我不理解的事情。
安装程序依赖于Windows API函数GetFileVersionInfo来指示DLL是否已经存在较新的版本号。但是,我现在看到的情况是文件MSVCR100.DLL已存在于System32文件夹中,但不存在于SysWOW64文件夹中。当GetFileVersionInfo用于测试C:\ Windows \ System32 \ MSVCR100.DLL时,我希望它重定向到C:\ Windows \ SysWOW64 \ MSVCR100.DLL。似乎如果SysWOW64中不存在该文件,那么它在System32中看起来是一个后备。因此,安装程序认为MSVCR100.DLL已经存在并且无法安装它。
我创建了一个C ++ Win32控制台应用程序来测试它。整个代码是:
int _tmain(int argc, _TCHAR* argv[])
{
char sysDirName[64], sysWow64DirName[64];
char fileName[256];
strcpy_s(fileName, argv[1]);
GetSystemDirectory((LPSTR)sysDirName, 256);
GetSystemWow64Directory((LPSTR)sysWow64DirName, 256);
test_file(sysDirName, fileName);
test_file(sysWow64DirName, fileName);
return 0;
}
void test_file(char *dir, char* fileName)
{
char filePath[256];
DWORD verInfoSize, tempDWORD;
BOOL found;
byte buff[8192];
PathCombine((LPSTR)filePath, (LPSTR)dir, (LPSTR)fileName);
verInfoSize = GetFileVersionInfoSize((LPSTR)filePath, &tempDWORD);
found = GetFileVersionInfo((LPSTR)filePath, 0, verInfoSize, buff);
if (found)
printf("%s --found\n", filePath);
else
printf("%s --NOT found\n", filePath);
}
我在3台不同的64位计算机上测试过,包括Win 10,Win 7,我得到的结果相同。
如果MSVCR100.DLL在SysWOW64中但在System32中没有,那么我的测试显示重定向按预期工作:
>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll --found
C:\WINDOWS\SysWOW64\msvcr100.dll --found
如果MSVCR100.DLL既不在System32也不在SysWOW64中,那么结果是预期的:
>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll --NOT found
C:\WINDOWS\SysWOW64\msvcr100.dll --NOT found
如果MSVCR100.DLL在System32但不在SysWOW64中,那么结果会显示出意想不到的错误:
>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll --found
C:\WINDOWS\SysWOW64\msvcr100.dll --NOT found
网络搜索向我展示了有关SysWOW重定向的大量信息,但我找不到任何关于此行为的文档或讨论。这真的是我应该期待的吗?我的测试还显示,如果我使用API函数GetSystemWow64Directory,我可以拥有一个不依赖于重定向的文件路径。是否可以安全地复制DLL并在那条路径上注册它们?
答案 0 :(得分:2)
GetFileVersionInfo*
使用LoadLibraryEx
通过将文件作为数据文件加载来完成其工作。
由于某些原因KERNELBASE!BasepLoadLibraryAsDataFile
LoadLibraryW
调用ntdll!RtlWow64EnableFsRedirectionEx
来禁用重定向,如果请求的文件位于“%WinDir%\ System32”内,则它会再次尝试加载文件,这次来自“真正的”system32目录。
这显然是设计上的,我想不出一个不是一个巨大的黑客的方法。我认为出于兼容性原因,他们会这样做。
然而,您可以使用以下内容检测它:
bool validFile = !(GetFileAttributes(filePath) & FILE_ATTRIBUTE_DIRECTORY);
bool falsePositive = gotversioninfo && !validFile;