Search code examples
c++windowscreatefilesystem32

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


I would like to know whether anyone can explain a reason for ReOpenFile failing with "error-invalid-name", when CreateFile has successfully opened the file.

Here are the details:

I open a file C:\Windows\system32\unit_test.txt using CreateFile, and it opens fine. When I later attempt to change permissions using ReOpenFile, this fails with error code 123 (decimal) which the debugger shows as "ERROR_INVALID_NAME: The filename directory name or volume label syntax is incorrect".

ReOpenFile works fine if "unit_test.txt" is placed in a more conventional directory. ReOpenFile does not take a filename parameter, but rather the handle that is returned from CreateFile. The code that I have written is not requesting additional privileges nor conflicting privileges (which results in a different error), so I am curious as to why CreateFile would succeed and ReOpenFile fail in this one situation.

Admittedly the placing of the file in Windows\System32 was accidental, but if I can do it by accident, then a user of our software might stumble upon the same issue.

I have since created this example using identical function calls, but I can't get it to fail. It shows essentially what had been producing the error though:

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);
}
}

Solution

  • As soon as I recompiled my "minimal example" as 32-bit rather than 64-bit, it started to exhibit the problem of ReOpenFile failing.

    This lead me to an article that explains the situation: Accessing files from System32 directory using 32 bit application on 64 bit machine

    Quote from the article: " As you seen, on a computer that is running a 64-bit version of Windows Server 2003 or of Windows XP, a 32-bit application cannot access the following folder: %WinDir%\System32

    This behavior occurs because Windows on Windows 64-bit (WOW64) provides file system redirection. In a 64-bit version of Windows Server 2003 or of Windows XP, the %WinDir%\System32 folder is reserved for 64-bit applications. When a 32-bit application tries to access the System32 folder, access is redirected to the following folder:

    %WinDir%\SysWOW64
    

    By default, file system redirection is enabled.

    As a walk-around solution, 32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access. "

    Sadly the fact that the 32-bit application cannot fully access the directory does not stop Microsoft Windows from setting it as the working directory for the application in certain situations that I'm not fully aware of (possibly relating to sandboxing in more recent versions of Windows).