64位系统已经非常普及了,因此我们写代码的时候,了解32位与64位系统的编码差异就显得很重要了。
我用的计算机是win10,64位,之前对于任务管理器里的进程32和64分不清,而且对于System32与SestemWow64两个文件夹也时常搞错,今天看书查资料才终于弄懂一些。
64位系统有两个System目录,C:WindowsSystem32和C:WindowsSysWOW64,前者主要包含64位系统文件,后者目录下主要是32位系统文件,这个跟它们名字里的数字刚好是相反的(困扰我好长时间)。
一般来说,32位应用程序只能加载32位动态库,64位只能加载64位的,那么当一个32位程序在64位系统下运行时,它同样会去System32下寻找所需dll,发现不匹配,那这样就无法运行了呀,为了解决这个问题,就出现了重定向。WOW64有两个重要模块,是文件系统重定向器和注册表重定向器,当一个32位程序运行时,WOW64子系统拦截这个调用,如果其参数包含指针,就把指针长度转成合适长度,提交给内核,这个拦截转换的过程称为"thunking",在绝大多数情况下,32位应用程序在访问System32时会被重定向到SestemWow64目录下。
文件重定向器并非把所有System32下的目录文件都重定向到SysWOW64,有一些特殊目录是不能重定向的,例如:
C:WindowsSystem32CatRoot
C:WindowsSystem32CatRoot2
C:WindowsSystem32driversetc
C:WindowsSystem32LogFiles
C:WindowsSystem32spool
注册表重定向器与文件重定向器功能类似。
看如下的例子:
注意,一定要以管理员权限运行,编译成x86。
#include "stdafx.h"
#include <windows.h>
int main()
{
HANDLE FileHandle = INVALID_HANDLE_VALUE;
FileHandle = CreateFile(L"C:\Windows\System32\a.txt",
GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
0,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(FileHandle);
printf("Create Success
");
}
else
{
printf("Create Fail
");
}
return 0;
}
上面代码想在C:\Windows\System32目录下创建文件a.txt,成功之后,该目录下却没有,它出现在了C:Windows\SysWOW64目录下,想要解决这个问题,一种办法是改为x64编译,另一种在x86下访问的办法是调用API函数关闭文件重定向功能,
BOOL WINAPI Wow64DisableWow64FsRedirection(
_Out_ PVOID *OldValue
);
参数OldValue保存原来文件重定向的状态,将来在恢复回去,
BOOL WINAPI Wow64RevertWow64FsRedirection(
_In_ PVOID OldValue
);
int main()
{
PVOID Value = NULL;
BOOL Ret = Wow64DisableWow64FsRedirection(&Value);
if (Ret == TRUE)
{
HANDLE FileHandle = INVALID_HANDLE_VALUE;
FileHandle = CreateFile(L"C:\Windows\System32\a.txt",
GENERIC_READ,
0,
NULL,
CREATE_ALWAYS,
0,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(FileHandle);
printf("Create Success
");
}
else
{
printf("Create Fail
");
}
}
Wow64RevertWow64FsRedirection(Value);
return 0;
}
这样就创建在C:\Windows\System32目录下了。