[USETUP] When overwriting a file, if open fails, it might be because the file is...
authorPierre Schweitzer <pierre@reactos.org>
Thu, 4 Jan 2018 20:47:59 +0000 (21:47 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Thu, 4 Jan 2018 20:49:56 +0000 (21:49 +0100)
In such situation, try to drop the readonly attribute before overwritting the file.

This fixes setup not being able to overwrite FAT bootcode when reusing a FAT partition
already installed without reformatting.

CORE-14158

base/setup/usetup/filesup.c

index bed30c4..65a372a 100644 (file)
@@ -348,8 +348,72 @@ SetupCopyFile(
                           0);
     if (!NT_SUCCESS(Status))
     {
                           0);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
-        goto unmapsrcsec;
+        /* Open may have failed because the file to overwrite
+         * is in readonly mode
+         */
+        if (Status == STATUS_ACCESS_DENIED)
+        {
+            FILE_BASIC_INFORMATION FileBasicInfo;
+
+            /* Reattempt to open it */
+            Status = NtCreateFile(&FileHandleDest,
+                                  GENERIC_WRITE | SYNCHRONIZE,
+                                  &ObjectAttributes,
+                                  &IoStatusBlock,
+                                  NULL,
+                                  FILE_ATTRIBUTE_NORMAL,
+                                  0,
+                                  FILE_OPEN,
+                                  FILE_NO_INTERMEDIATE_BUFFERING |
+                                  FILE_SEQUENTIAL_ONLY |
+                                  FILE_SYNCHRONOUS_IO_NONALERT,
+                                  NULL,
+                                  0);
+            /* Fail for real if we cannot open it that way
+             * XXX: actually, we should try to refine access rights
+             * to only have write_attributes, should be enough
+             */
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
+                goto unmapsrcsec;
+            }
+
+            /* Zero our basic info, just to set attributes */
+            RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo));
+            /* Reset attributes to normal, no read-only */
+            FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+            /* We basically don't care about whether it succeed:
+             * if it didn't, later open will fail
+             */
+            NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasicInfo,
+                                 sizeof(FileBasicInfo), FileBasicInformation);
+
+            /* Close file */
+            NtClose(FileHandleDest);
+
+            /* And re-attempt overwrite */
+            Status = NtCreateFile(&FileHandleDest,
+                                  GENERIC_WRITE | SYNCHRONIZE,
+                                  &ObjectAttributes,
+                                  &IoStatusBlock,
+                                  NULL,
+                                  FILE_ATTRIBUTE_NORMAL,
+                                  0,
+                                  FILE_OVERWRITE_IF,
+                                  FILE_NO_INTERMEDIATE_BUFFERING |
+                                  FILE_SEQUENTIAL_ONLY |
+                                  FILE_SYNCHRONOUS_IO_NONALERT,
+                                  NULL,
+                                  0);
+        }
+
+        /* We failed */
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName);
+            goto unmapsrcsec;
+        }
     }
 
     RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
     }
 
     RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);