Finally get the fake (and broken by design) DOS device check to work
authorThomas Bluemel <thomas@reactsoft.com>
Sun, 15 Jul 2007 08:33:49 +0000 (08:33 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Sun, 15 Jul 2007 08:33:49 +0000 (08:33 +0000)
svn path=/trunk/; revision=27673

reactos/dll/win32/kernel32/file/find.c

index 129b5c9..64a6ccb 100644 (file)
@@ -350,7 +350,7 @@ InternalFindFirstFile (
        UNICODE_STRING NtPathU, FileName, PathFileName;
        NTSTATUS Status;
        PWSTR NtPathBuffer;
-       BOOLEAN RemovedSlash = FALSE;
+       BOOLEAN RemovedLastChar = FALSE;
        BOOL bResult;
        CURDIR DirInfo;
        ULONG DeviceNameInfo;
@@ -406,13 +406,20 @@ InternalFindFirstFile (
            }
        }
 
-       /* Remove a trailing backslash from the path, unless it's a DOS drive directly */
-       if (NtPathU.Length > 3 * sizeof(WCHAR) &&
-           NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 1] == L'\\' &&
+       /* Remove the last character of the path (Unless the path is a drive and
+          ends with ":\"). If the caller however supplies a path to a device, such
+          as "C:\NUL" then the last character gets cut off, which later results in
+          NtOpenFile to return STATUS_OBJECT_NAME_NOT_FOUND, which in turn triggers
+          a fake DOS device check with RtlIsDosDeviceName_U. However, if there is a
+          real device with a name eg. "NU" in the system, FindFirstFile will succeed,
+          rendering the fake DOS device check useless... Why would they invent such a
+          stupid and broken behavior?! */
+       if (NtPathU.Length >= 2 * sizeof(WCHAR) &&
+           NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 1] != L'\\' &&
            NtPathU.Buffer[(NtPathU.Length / sizeof(WCHAR)) - 2] != L':')
        {
            NtPathU.Length -= sizeof(WCHAR);
-           RemovedSlash = TRUE;
+           RemovedLastChar = TRUE;
        }
 
        DPRINT("lpFileName: \"%ws\"\n", lpFileName);
@@ -433,10 +440,10 @@ InternalFindFirstFile (
                             FILE_SHARE_READ|FILE_SHARE_WRITE,
                             FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
 
-       if (!NT_SUCCESS(Status) && RemovedSlash)
+       if (Status == STATUS_NOT_A_DIRECTORY && RemovedLastChar)
        {
-           /* Try again, this time with the trailing slash... */
-           NtPathU.Length -= sizeof(WCHAR);
+           /* Try again, this time with the last character ... */
+           NtPathU.Length += sizeof(WCHAR);
 
            Status = NtOpenFile (&hDirectory,
                                 FILE_LIST_DIRECTORY | SYNCHRONIZE,
@@ -444,6 +451,8 @@ InternalFindFirstFile (
                                 &IoStatusBlock,
                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
                                 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
+
+           NtPathU.Length += sizeof(WCHAR);
        }
 
        if (!NT_SUCCESS(Status))