Windows64下32位程序文件系统重定向

Windows64下32位程序文件系统重定向

在默认情况下,64位环境运行32位程序,会为这个程序启用文件系统重定向。就是这个32位程序访问文件系统时(如 CreateFile/WinVerifyTrust 等操作),会把 C:\Windows\System32 文件夹重定向到 C:\Windows\Syswow64 等。

什么是 WOW64

WOW64 是 "Windows 32-bit on Windows 64-bit" 的缩写。

  • 它是一个 Windows 操作系统的子系统,负责在 64 位版本的 Windows 上运行 32 位的应用程序。
  • 它提供了一套兼容性层,使得 32 位程序能够调用 64 位系统的内核功能,从而无需修改就能在 64 位 Windows 上运行。

文件系统重定向 (File System Redirection)

为了实现64位系统兼容32位程序,WOW64 引入了文件系统重定向机制。当 32 位程序运行在 64 位 Windows 上时,WOW64 子系统会自动将其对 C:\Windows\System32 的访问重定向C:\Windows\SysWOW64 目录。

  • C:\Windows\System32:存放 64 位的系统文件和 DLL。
  • C:\Windows\SysWOW64:存放 32 位的系统文件和 DLL。

为什么要这么做?

这是为了防止 32 位程序错误地加载 64 位的 DLL,因为 32 位程序无法与 64 位的 DLL 进行交互,强行加载会导致程序崩溃。通过自动重定向,32 位程序总能找到为其架构编译的正确版本的系统文件。

一共提供了3个相关函数:

// 启用重定向(单独一组)
BOOLEAN Wow64EnableWow64FsRedirection(BOOLEAN Wow64FsEnableRedirection);

////// 以下两个为一组

// 禁用重定向
BOOL Wow64DisableWow64FsRedirection([out] PVOID *OldValue);
// 恢复重定向状态为OldValue指定的值
BOOL Wow64RevertWow64FsRedirection([in] PVOID OldValue);

注意

  • 不要将 Wow64EnableWow64FsRedirectionWow64DisableWow64FsRedirection/Wow64RevertWow64FsRedirection 混用。Wow64EnableWow64FsRedirection 是已经过时的API,在存在嵌套调用时有BUG。因此推荐配套使用 Wow64DisableWow64FsRedirectionWow64RevertWow64FsRedirection
  • 每次调用 Wow64DisableWow64FsRedirection 函数都必须具有对 Wow64RevertWow64FsRedirection 函数的匹配调用。
  • 禁用重定向会破坏 WOW64 子系统提供的兼容性保障。应该只在绝对必要的代码段中禁用它,并在操作完成后立即恢复。
  • 避免在整个进程生命周期内禁用:绝对不要在 main 函数开始时禁用,直到程序结束才恢复。这会导致进程中的所有文件操作都绕过重定向,极有可能引发难以预料的错误和崩溃。
  • 线程级别的操作:这个函数的效果是线程级别的,而不是进程级别的。这意味着如果你在一个线程中禁用了重定向,其他线程的重定向行为不会受到影响。
  • 错误处理:总是检查函数的返回值。如果禁用或恢复操作失败,你的后续文件操作可能会不符合预期。
  • 适用于 32 位进程:这个函数在 64 位进程中调用是无效的,因为 64 位进程本身就直接运行在原生系统上,不存在重定向的问题。

示例

使用 Wow64EnableWow64FsRedirection

#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>

void main()
 {
  HANDLE hFile = INVALID_HANDLE_VALUE;

  // 在调用 CreateFile 之前,禁用文件系统重定向
  if( Wow64EnableWow64FsRedirection(FALSE) ) 
   {
    // 演示访问64位的目录
    hFile = CreateFile(TEXT("C:\\Windows\\System32\\Notepad.exe"),
                       GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);

    // 重新启用文件系统重定向
    if ( FALSE == Wow64EnableWow64FsRedirection(TRUE) )
     {
      // 重新启用失败,应该被视作致命错误,因为后续所有的文件系统访问操作都不正常了
      abort();
     }
   }
    
  // 即使禁用了文件系统重定向,刚才打开的文件句柄仍然可以继续使用
 
  if( INVALID_HANDLE_VALUE != hFile )  
   {
    // Use the file handle
    printf("ok\n");
    CloseHandle(hFile);
   }
 }

使用 Wow64DisableWow64FsRedirectionWow64RevertWow64FsRedirection

#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    HANDLE hFile    = INVALID_HANDLE_VALUE;
    PVOID  OldValue = NULL;  // 保存重定向的原始状态

    // 禁用文件系统重定向
    if (Wow64DisableWow64FsRedirection(&OldValue)) {
        // 演示访问64位的目录
        hFile = CreateFile(TEXT("C:\\Windows\\System32\\Notepad.exe"), GENERIC_READ,
                           FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        // 恢复文件系统重定向
        if (FALSE == Wow64RevertWow64FsRedirection(OldValue)) {
            // 重新启用失败,应该被视作致命错误,因为后续所有的文件系统访问操作都不正常了
            abort();
        }
    }

    // 即使禁用了文件系统重定向,刚才打开的文件句柄仍然可以继续使用

    if (INVALID_HANDLE_VALUE != hFile) {
        // Use the file handle
        printf("ok\n");
        CloseHandle(hFile);
    }
}
posted @ 2025-11-26 10:54  3的4次方  阅读(66)  评论(0)    收藏  举报