查看程序的log,无非是报告 32/64位不兼容什么的信息。OK,那就弄些64位版本的Dll吧。于是乎从服务器上弄下来那些 n年都没人碰过的代码,略微瞻仰了一下,发现是些DDK的工程,丫的,还得去搭建DDK环境,于是G了一把,哪知斗转星移,DDK换马甲改叫WDK了。不管它叫神马DK,反正我也不懂它的开发,但是搭个环境编译编译还是没问题的。于是从同事那里讨来了WDK的安装包。一通忙活后,64位版本的驱动DLL出炉了。
这下安装驱动总该没问题了吧,可真正的问题却刚刚来,说找不到模块。找不到?找不到谁?为什么找不到?不就是拷贝个文件吗?出什么妖蛾子了?到 System32目录下浏两眼,确实没看到我的Dll们,可是整个安装过程并没有给我报告复制文件失败,而且我的代码里每次复制完成后,还要检测一下文件是否存在了。这两步,一步是调用Win API CopyFile(...) 复制文件到 System32 目录下,第二步是调用 C库函数: _access(...) 检查一下,文件是否复制到位。任何一个函数的调用有错,就会立即终止安装过程,绝不会走到调用安装打印机的API函数的,而找不到模块的错误信息确实是 由 Win API AddMonitor(...) 报告的。
启动 Windbg 开始跟踪,果然,程序执行到 CopyFile( lpszSrcFullPath, szDestPath, FALSE ) 语句的时候,函数返回TRUE! 此时 du szDestPath, 变量值为: C:/Windows/System32/psptmon64.dll, 赶紧跑到 System32 目录下,但是并未找到 psptmon64.dll, 怪了!往下执行: _taccess(szDestPath,AMPS_READ_PERMISSION); 返回值是0, 而不是找不到文件时的 -1, 困惑了,彻底困惑了!
明明 System32 目录下没有的东西,硬是说有,手动复制 psptmon64.dll 到 System32目录下,非常正常的复制过去,没有报告覆盖文件。看来是这个文件确实不存在,CopyFile(...)和_taccess(...)合伙涮了我?写了一段测试用的代码,发现CopyFile(...)可以正确制文件到磁盘的其他目录,但是就是不能吧文件复制到System32目录下,而且调用结束后它还告诉我TRUE! 实在是想不通了,G一了一把,发现了一些蛛丝马迹: File System Redirector! 翻看MSDN相关章节:找到如下内容:
File System Redirector
The %windir%/System32 directory is reserved for 64-bit applications. Most DLL file names were not changed when porting to 64-bit, so 32-bit applications must use a different directory as their System32 directory. WOW64 hides this difference using a file system redirector .
Whenever a 32-bit application attempts to access %windir%/System32, the access is redirected to a new directory, %windir%/SysWOW64. To retrieve the name of the 32-bit system directory, 64-bit applications should use the GetSystemWow64Directory function. Certain subdirectories are exempt from redirection:
%windir%/system32/catroot
%windir%/system32/catroot2
%windir%/system32/drivers/etc
%windir%/system32/logfiles
%windir%/system32/spool
Applications should use the SHGetSpecialFolderPath function to determine the %ProgramFiles% directory name.
Applications can control the WOW64 file system redirector using the Wow64DisableWow64FsRedirection , Wow64EnableWow64FsRedirection , and Wow64RevertWow64FsRedirection functions.
乖乖! 到我的 SysWoW64 目录下一看,psptmon64.dll 还真在!原来躲到这了!
赶紧修改一下代码,将传给 AddMonitor(...) 函数中涉及到 System32 的路径改为: SysWoW64, 然后安装,一切在正常了!终于被我和谐了!
总结一下:因为我们的程序是 32-Bit 的,当它调用 CopyFile(...) 和 access(...) 函数时,传给他们的参数里有 System32的路径,就会被 转向到 SysWoW64 目录下。但是不知为什么 AddMonitor(...) 没这么聪明,没转向(微软的Bug?),傻傻的去 System32目录下找文件,当然找不到了。
这个问题,知道的很容易,不知道的还以为自己电脑中邪了!