前言

因为一次偶然的机会,需要访问系统目录“C:/Windows/System32“文件夹下的内容,使用的测试机器上预装了win7 64系统。在程序运行中竟然发生了该文件路径不存在的问题!!通过查看网上相关的资料,了解到64位系统下,System32(同时也包括Program Files)这两个文件夹被动态地重定向了。为了可以直观的反映这个问题,这里将编写一个小的测试程序进行验证。

实例验证

首先随机选择一个文件,并将其拷贝到系统目录的System32文件夹下。本文选择QQ启动程序进行验证(主要是QQ自带企鹅图标易于辨认,哈哈),如图1所示

图1 手动将QQ拷贝到系统System32文件夹下

编写实际测试程序,直接上代码(调用了windows系统API PathFileExists来判断文件是否存在)

/************************************************************************/
/* file : 验证在64位机器上system32以及Program Files的exe不能用API直接找到
* author : Huagang Li
* date : 2014-8-23 01:22:55
* tips : 64位系统下system32 文件夹重定向机制
*
*/
/************************************************************************/
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <Shlwapi.h> #pragma comment(lib,"Shlwapi.lib") // PathFileExists链接时需要 int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
std::wstring strFile = L"C:\\Windows\\System32\\QQProtect.exe"; if (::PathFileExists(strFile.c_str()))
{
::MessageBox(NULL, _T("文件存在"), _T("Good"), MB_OK);
}
else
{
::MessageBox(NULL, _T("文件不存在"), _T("Opps"), MB_OK);
} return EXIT_SUCCESS;
}

运行的结果如图2所示:

图2 文件不存在??

从上面的结果可以看出,在调用windows API检测QQ文件是否存在时,系统给出了一个令人匪夷所思的结论:文件不存在!!但这个文件确实被拷贝进了该目录下啊。要解释这个奇怪的现象,就得从windows 64位系统中的文件系统重定向说起。当微软开发了64位系统时,为了做到向前兼容,需要重新实现32为系统中需要的相关文件(system32文件夹下的dll以及exe)。然而,这些新的实现版本是基于64位系统开发的,因此如果继续存放于System32文件夹下,显得名不副实。可是为了做到向前兼容,又需要将这些依赖文件存放于这个目录下,为了解决上述冲突,微软采用了一种文件系统重定向机制:在64位系统下,System32文件夹下的文件实际重定向到SysNative这个文件夹(注意,这个文件夹不能直接找到)。这样,就可以将64位系统下64位的库和应用程序存放于System32文件夹下(因为已经重定向到SysNative了),而32位的库和应用程序则被存放在另一个叫做SysWOW64的文件夹中。具体的对应关系为:

\Windows\SysWOW64  文件夹下存放32位的库和应用程序 (WOW64 == Windows on Windows 64 bit )

\Windows\System32  文件夹下存放64位的库和应用程序

为了验证文件系统重定向,将前文中的测试路径改为:

std::wstring strFile = L"C:\\Windows\\SysNative\\QQProtect.exe";

测试结果如图3所示:

图3 改为Sysnative结果

上述结果显示了,64位系统下如果需要访问System32目录下的文件,一个可行的方法是将访问路径改为SysNative。但是由于sysnative文件夹不能通过windows资源管理器访问到(如图4所示),因此对于一般人来讲,这样的改名其实很困惑。

图4 资源管理器访问不到Sysnative文件夹

既然微软开发了文件系统重定向机制机制,那就可以通过一定的方式操作这种机制。通过查看msdn可以发现,http://msdn.microsoft.com/en-us/library/aa365743.aspx 提供的方式可以禁用文件系统重定向问题。因此,本文尝试调用这个API接口进行验证:

/************************************************************************/
/* file : 验证在64位机器上system32以及Program Files的exe不能用API直接找到
* author : Huagang Li
* date : 2014-8-23 01:22:55
* tips : 64位系统下system32 文件夹重定向机制
*
*/
/************************************************************************/
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <Shlwapi.h> #pragma comment(lib,"Shlwapi.lib") // PathFileExists链接时需要 int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd )
{
std::wstring strFile = L"C:\\Windows\\System32\\QQProtect.exe";
// 64位系统下 system32 文件系统重定向 PVOID OldValue = NULL;
Wow64DisableWow64FsRedirection(&OldValue);
if (::PathFileExists(strFile.c_str()))
{
::MessageBox(NULL, _T("文件存在"), _T("Good"), MB_OK);
}
else
{
::MessageBox(NULL, _T("文件不存在"), _T("Opps"), MB_OK);
}
Wow64RevertWow64FsRedirection(OldValue); return EXIT_SUCCESS;
}

运行后得到的结果和上文中Sysnative一样,如图5所示:

图5 禁用文件系统重定向机制后的结果

注意,由于禁用文件系统重定向后可能引起其他一些问题(例如原本依赖于System32下的dll文件加载失败),因此在禁用并完成需要的操作后,要回复原来的禁用状态(如程序中Wow64RevertWow64FsRedirection(OldValue);)。这样,在调用PathFileExists后,恢复了文件系统重定向机制,不会影响后续操作。

另外,64位系统下Program Files与Program Files(x86)的关系就与上面的System32和S也是WOW64一致,也存在文件系统重定向。

结论

1. 64位系统下存在文件系统重定向机制(File System Redirector)

2. System32文件夹动态被定向到SysNative文件夹

3. 可以通过windows API Wow64DisableWow64FsRedirection禁用这种定向机制

参考链接

[1] http://msdn.microsoft.com/en-us/library/aa384187.aspx

[2] http://msdn.microsoft.com/en-us/library/aa365743.aspx

[3] http://blog.sina.com.cn/s/blog_792da39c01013bzh.html

64位系统下System32文件系统重定向的更多相关文章

  1. C# 32位程序在64位系统下注册表操作

    在64位的Windows操作系统中,为了兼容32位程序的运行,64位的Windows操作系统采用重定向机制.目的是为了能让32位程序在64位的操作系统不仅能操作关键文件文夹和关键的注册表并且又要避免与 ...

  2. 64位系统下注册32位dll文件

    64位系统下注册32位dll文件 在64位系统里注册32位软件所需的一些dll会提示不兼容,大概因为32 位进程不能加载64位Dll,64位进程也不可以加载32的导致. 若要支持的32 位和64 位C ...

  3. delphi在64位系统下写注册表注意事项

    HKEY_LOCAL_MACHINE写这个主键下的项,在64位系统下可能会重定向,所以构造时要加KEY_WOW64_64KEY reg := TRegistry.Create(KEY_WRITE or ...

  4. PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验

    PL/SQL Developer 在windows7 64位系统下连Oaracle11g64位系统的解决经验 一.问题现象及解决方法 现象: 1.PL/SQL 无法登录64位数据库 2.在PL/SQL ...

  5. win7 64位系统下安装autoitlibrary库遇到问题解决

    转载来自http://blog.sina.com.cn/s/blog_53f023270101skyq.html 今天需要在win7 64位系统下安装autoitlibrary库,起初安装好了robo ...

  6. (转)Win7 64位系统下 Retional rose 2003 安装及破解

    网上关于Retional rose 2003安装和破解的文章比较多,这里,我结合自己的亲身体验,和大家分享一下win7 旗舰版 64位系统下Retional rose 2003(下面简称rose200 ...

  7. 64位系统下注册32位dll、ax文件

    64位系统下注册32位dll.ax文件. 换了64位系统遇到的新问题,目前常用的影音处理软件多数为32位. 注册这些32的滤镜会提示不兼容,大概因为32 位进程不能加载64位Dll,64位进程也不可以 ...

  8. Win7 64位系统下 Retional rose 2003 安装及破解

    网上关于Retional rose 2003安装和破解的文章比较多,这里,我结合自己的亲身体验,和大家分享一下win7 旗舰版 64位系统下Retional rose 2003(下面简称rose200 ...

  9. 64位系统下,一个32位的程序究竟可以申请到多少内存,4GB还是更多?(一)

    前言: cpu的位是指一次性可处理的数据量是多少,1字节=8位,32位处理器可以一次性处理4个字节的数据量,依次类推.32位操作系统针对的32位的CPU设计.64位操作系统针对的64位的CPU设计.操 ...

随机推荐

  1. Linux Shell编程(28)——进程替换

    进程替换与命令替换很相似. 命令替换把一个命令的结果赋给一个变量,例如 dir_contents=`ls -al`或xref=$. 进程替换则是把一个进程的输出回馈给另一个进程 (换句话说,它把一个命 ...

  2. Linux Shell编程(11)——退出和退出状态

    exit命令一般用于结束一个脚本,就像C语言的exit一样.它也能返回一个值给父进程.每一个命令都能返回一个退出状态(有时也看做返回状态).一个命令执行成功返回0,一个执行不成功的命令则返回一个非零值 ...

  3. loadrunner打不开ie&ie默认浏览器设置方法

    loadrunner使用过程中频繁的出现问题,出现次数最多的就是lr打不开ie,或者ie一闪就关闭了,问题出在我默认浏览器的设置上,因为我原先并没有成功设置ie为默认浏览器.这是一个无意识的错误,我以 ...

  4. Oracle数据库12560及更改密码为永久

    小厂子的程序员还要折腾Oracle维护.这这里简单记录一下Oracle数据库服务器使用时遇到并解决的一些问题. 1. 在Oracle数据库服务器上(即安装Oracle数据库端的机器上),可以使用命令 ...

  5. C/C++基础(二)

    (1)运算符优先级 #include <cstdio> using namespace std; int main() {    unsigned char a = 0xA5;    un ...

  6. redux-applyMiddleware实现理解+自定义中间件

    前言: 终于好好理解了middleware.... 1.redux middleware提供的是位于 action 被发起之后,到达 reducer 之前的扩展点. redux通过store.disp ...

  7. 【Android - 框架】之Retrofit+RxJava的使用

    前几天分别对Retrofit和RxJava进行了总结,这个帖子打算把Retrofit结合RxJava使用的方法总结以下.有还不了解Retrofit或RxJava的朋友可以参考下面的帖子学习~ [And ...

  8. Vim 程序编辑器 经常使用操作

    按下 i 进入编辑模式 wq! 强制保存并退出 q!  不保存,强制退出 !有强制的意思 方向键位: k h  j  l Ctrl + f 向下移动一页 Ctrl + b 向上移动一页 0 一行的开头 ...

  9. TOJ3660家庭关系(并查集+hash+图的连通性)

    家庭关系   时间限制(普通/Java):1000MS/3000MS     运行内存限制:65536KByte 总提交: 38            测试通过: 9 描述 给定若干家庭成员之间的关系 ...

  10. TOJ 2732存钱计划(三)(单源最短路)

    存钱计划(三)   时间限制(普通/Java):1000MS/30000MS     运行内存限制:65536KByte 总提交: 18            测试通过: 16 描述 TZC的店铺比较 ...