在 C:\windows\system32 中重新打开文件时,ReOpenFile Windows API 失败并显示 "error invalid name"

ReOpenFile Windows API fails with "error invalid name" when reopening a file in C:\windows\system32

我想知道当 CreateFile 成功打开文件时,是否有人可以解释 ReOpenFile 因“error-invalid-name”而失败的原因。

详情如下:

我使用 CreateFile 打开文件 C:\Windows\system32\unit_test.txt,它打开得很好。当我稍后尝试使用 ReOpenFile 更改权限时,失败并显示错误代码 123(十进制),调试器显示为“ERROR_INVALID_NAME:文件名目录名称或卷标语法不正确”。

如果将“unit_test.txt”放置在更常规的目录中,

ReOpenFile 工作正常。 ReOpenFile 不采用文件名参数,而是采用从 CreateFile 返回的句柄。 我编写的代码既没有请求额外的权限也没有冲突的权限(这会导致不同的错误),所以我很好奇为什么在这种情况下 CreateFile 会成功而 ReOpenFile 会失败。

诚然,将文件放在 Windows\System32 中是偶然的,但如果我能偶然做到,那么我们软件的用户可能会遇到同样的问题。

此后我使用相同的函数调用创建了这个示例,但我不能让它失败。它基本上显示了产生错误的原因:

int main ()
{
HANDLE h1 = ::CreateFile (_T("c:\windows\system32\test.txt"),
                          GENERIC_READ | GENERIC_WRITE | DELETE,
                          FILE_SHARE_READ,
                          nullptr,
                          CREATE_ALWAYS,
                          FILE_FLAG_SEQUENTIAL_SCAN,
                          NULL);

if (h1 != INVALID_HANDLE_VALUE)
{
    HANDLE h2 = ::ReOpenFile (h1,
                              GENERIC_READ,
                              FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                              FILE_FLAG_SEQUENTIAL_SCAN);

    ::CloseHandle (h1);

    if (h2 != INVALID_HANDLE_VALUE)
        ::CloseHandle (h2);
}
}

一旦我将我的“最小示例”重新编译为 32 位而不是 64 位,它就开始出现 ReOpenFile 失败的问题。

这让我看到一篇解释情况的文章:Accessing files from System32 directory using 32 bit application on 64 bit machine

文章引述: “ 如您所见,在 运行 64 位版本 Windows Server 2003 或 Windows XP 的计算机上,32 位应用程序无法访问以下文件夹:%WinDir% \System32

出现此行为是因为 Windows 在 Windows 64 位 (WOW64) 上提供文件系统重定向。 在 Windows Server 2003 或 Windows XP 的 64 位版本中,%WinDir%\System32 文件夹是为 64 位应用程序保留的。当 32 位应用程序尝试访问 System32 文件夹时,访问将重定向到以下文件夹:

%WinDir%\SysWOW64

默认启用文件系统重定向。

作为 walk-around 解决方案,32 位应用程序可以通过将 %windir%\Sysnative 替换为 %windir%\System32 来访问本机系统目录。 WOW64 将 Sysnative 识别为一个特殊的别名,用于指示文件系统不应重定向访问。 “

遗憾的是,32 位应用程序无法完全访问目录这一事实并不能阻止 Microsoft Windows 在某些我不完全了解的情况下将其设置为应用程序的工作目录(可能与 Windows) 的最新版本中的沙盒有关。