https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2268b3d64512f93fdeb0a…
commit 2268b3d64512f93fdeb0a8c5e1591f9e85db879e
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Jun 30 22:28:06 2017 +0000
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sat Oct 27 03:17:29 2018 +0200
[USETUP] Move Setup[Delete|Copy|Move]File() from usetup code into the setuplib's
filesup.c .
Remove the commented-out IsValidPath() in that file, and remove
as well the temporary prototypes in regutil.c .
svn path=/branches/setup_improvements/; revision=75249
---
base/setup/lib/filesup.c | 457 ++++++++++++++++++++++++++++++++++++++++++++
base/setup/lib/filesup.h | 25 ++-
base/setup/lib/regutil.c | 21 --
base/setup/usetup/filesup.c | 448 +------------------------------------------
base/setup/usetup/filesup.h | 35 +---
5 files changed, 480 insertions(+), 506 deletions(-)
diff --git a/base/setup/lib/filesup.c b/base/setup/lib/filesup.c
index c6314c222e..03d1ad8003 100644
--- a/base/setup/lib/filesup.c
+++ b/base/setup/lib/filesup.c
@@ -12,8 +12,465 @@
#define NDEBUG
#include <debug.h>
+
+// ACHTUNG! HAXX FIXME!!
+#define _SEH2_TRY
+#define _SEH2_LEAVE goto __SEH2_FINALLY__label;
+#define _SEH2_FINALLY __SEH2_FINALLY__label:
+#define _SEH2_END
+
+
/* FUNCTIONS ****************************************************************/
+// TODO: Move SetupCreateDirectory later...
+
+NTSTATUS
+SetupDeleteFile(
+ IN PCWSTR FileName,
+ IN BOOLEAN ForceDelete) // ForceDelete can be used to delete read-only files
+{
+ NTSTATUS Status;
+ UNICODE_STRING NtPathU;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE FileHandle;
+ FILE_DISPOSITION_INFORMATION FileDispInfo;
+ BOOLEAN RetryOnce = FALSE;
+
+ /* Open the directory name that was passed in */
+ RtlInitUnicodeString(&NtPathU, FileName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &NtPathU,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+Retry: // We go back there once if RetryOnce == TRUE
+ Status = NtOpenFile(&FileHandle,
+ DELETE | FILE_READ_ATTRIBUTES |
+ (RetryOnce ? FILE_WRITE_ATTRIBUTES : 0),
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile failed with Status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ if (RetryOnce)
+ {
+ FILE_BASIC_INFORMATION FileInformation;
+
+ Status = NtQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInformation,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile failed with Status 0x%08lx\n",
Status);
+ NtClose(FileHandle);
+ return Status;
+ }
+
+ FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileInformation,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ NtClose(FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtSetInformationFile failed with Status 0x%08lx\n",
Status);
+ return Status;
+ }
+ }
+
+ /* Ask for the file to be deleted */
+ FileDispInfo.DeleteFile = TRUE;
+ Status = NtSetInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileDispInfo,
+ sizeof(FILE_DISPOSITION_INFORMATION),
+ FileDispositionInformation);
+ NtClose(FileHandle);
+
+ if (!NT_SUCCESS(Status))
+ DPRINT1("Deletion of file '%S' failed, Status 0x%08lx\n",
FileName, Status);
+
+ // FIXME: Check the precise value of Status!
+ if (!NT_SUCCESS(Status) && ForceDelete && !RetryOnce)
+ {
+ /* Retry once */
+ RetryOnce = TRUE;
+ goto Retry;
+ }
+
+ /* Return result to the caller */
+ return Status;
+}
+
+NTSTATUS
+SetupCopyFile(
+ IN PCWSTR SourceFileName,
+ IN PCWSTR DestinationFileName,
+ IN BOOLEAN FailIfExists)
+{
+ NTSTATUS Status;
+ UNICODE_STRING FileName;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE FileHandleSource;
+ HANDLE FileHandleDest;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_STANDARD_INFORMATION FileStandard;
+ FILE_BASIC_INFORMATION FileBasic;
+ ULONG RegionSize;
+ HANDLE SourceFileSection;
+ PVOID SourceFileMap = NULL;
+ SIZE_T SourceSectionSize = 0;
+ LARGE_INTEGER ByteOffset;
+
+ RtlInitUnicodeString(&FileName, SourceFileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtOpenFile(&FileHandleSource,
+ GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ,
+ FILE_SEQUENTIAL_ONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
+ goto done;
+ }
+
+ Status = NtQueryInformationFile(FileHandleSource,
+ &IoStatusBlock,
+ &FileStandard,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile failed: %x\n", Status);
+ goto closesrc;
+ }
+
+ Status = NtQueryInformationFile(FileHandleSource,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtQueryInformationFile failed: %x\n", Status);
+ goto closesrc;
+ }
+
+ Status = NtCreateSection(&SourceFileSection,
+ SECTION_MAP_READ,
+ NULL,
+ NULL,
+ PAGE_READONLY,
+ SEC_COMMIT,
+ FileHandleSource);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
+ goto closesrc;
+ }
+
+ Status = NtMapViewOfSection(SourceFileSection,
+ NtCurrentProcess(),
+ &SourceFileMap,
+ 0,
+ 0,
+ NULL,
+ &SourceSectionSize,
+ ViewUnmap,
+ 0,
+ PAGE_READONLY);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status,
SourceFileName);
+ goto closesrcsec;
+ }
+
+ RtlInitUnicodeString(&FileName, DestinationFileName);
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = NtCreateFile(&FileHandleDest,
+ GENERIC_WRITE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FileBasic.FileAttributes, // FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FailIfExists ? FILE_CREATE : FILE_OVERWRITE_IF,
+ FILE_NO_INTERMEDIATE_BUFFERING |
+ FILE_SEQUENTIAL_ONLY |
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /*
+ * 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 with limited access */
+ Status = NtCreateFile(&FileHandleDest,
+ FILE_WRITE_ATTRIBUTES | 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 */
+ 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);
+ IoStatusBlock.Status = 0;
+ ByteOffset.QuadPart = 0ULL;
+ Status = NtWriteFile(FileHandleDest,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatusBlock,
+ SourceFileMap,
+ RegionSize,
+ &ByteOffset,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n",
+ Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap,
RegionSize);
+ goto closedest;
+ }
+
+ /* Copy file date/time from source file */
+ Status = NtSetInformationFile(FileHandleDest,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtSetInformationFile failed: %x\n", Status);
+ goto closedest;
+ }
+
+ /* Shorten the file back to its real size after completing the write */
+ Status = NtSetInformationFile(FileHandleDest,
+ &IoStatusBlock,
+ &FileStandard.EndOfFile,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtSetInformationFile failed: %x\n", Status);
+ }
+
+closedest:
+ NtClose(FileHandleDest);
+
+unmapsrcsec:
+ NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
+
+closesrcsec:
+ NtClose(SourceFileSection);
+
+closesrc:
+ NtClose(FileHandleSource);
+
+done:
+ return Status;
+}
+
+/*
+ * Synchronized with its kernel32 counterpart, but we don't manage reparse points
here.
+ */
+NTSTATUS
+SetupMoveFile(
+ IN PCWSTR ExistingFileName,
+ IN PCWSTR NewFileName,
+ IN ULONG Flags)
+{
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PFILE_RENAME_INFORMATION RenameInfo;
+ UNICODE_STRING NewPathU, ExistingPathU;
+ HANDLE SourceHandle = NULL;
+ BOOLEAN ReplaceIfExists;
+
+ RtlInitUnicodeString(&ExistingPathU, ExistingFileName);
+ RtlInitUnicodeString(&NewPathU, NewFileName);
+
+ _SEH2_TRY
+ {
+ ReplaceIfExists = !!(Flags & MOVEFILE_REPLACE_EXISTING);
+
+ /* Unless we manage a proper opening, we'll attempt to reopen without reparse
support */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &ExistingPathU,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ /* Attempt to open source file */
+ Status = NtOpenFile(&SourceHandle,
+ FILE_READ_ATTRIBUTES | DELETE | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN_FOR_BACKUP_INTENT | ((Flags &
MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0));
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status != STATUS_INVALID_PARAMETER)
+ {
+ _SEH2_LEAVE;
+ }
+ }
+
+ /* At that point, we MUST have a source handle */
+ ASSERT(SourceHandle);
+
+ /* Allocate renaming buffer and fill it */
+ RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length +
sizeof(FILE_RENAME_INFORMATION));
+ if (RenameInfo == NULL)
+ {
+ Status = STATUS_NO_MEMORY;
+ _SEH2_LEAVE;
+ }
+
+ RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
+ RenameInfo->ReplaceIfExists = ReplaceIfExists;
+ RenameInfo->RootDirectory = NULL;
+ RenameInfo->FileNameLength = NewPathU.Length;
+
+ /* Attempt to rename the file */
+ Status = NtSetInformationFile(SourceHandle,
+ &IoStatusBlock,
+ RenameInfo,
+ NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
+ FileRenameInformation);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
+ if (NT_SUCCESS(Status))
+ {
+ /* If it succeeded, all fine, quit */
+ _SEH2_LEAVE;
+ }
+ /*
+ * If we failed for any other reason than not the same device, fail.
+ * If we failed because of different devices, only allow renaming
+ * if user allowed copy.
+ */
+ if (Status != STATUS_NOT_SAME_DEVICE || !(Flags & MOVEFILE_COPY_ALLOWED))
+ {
+ /* ReactOS hack! To be removed once all FSD have proper renaming support
+ * Just leave status to error and leave
+ */
+ if (Status == STATUS_NOT_IMPLEMENTED)
+ {
+ DPRINT1("Forcing copy, renaming not supported by FSD\n");
+ }
+ else
+ {
+ _SEH2_LEAVE;
+ }
+ }
+
+ /* Close the source file */
+ NtClose(SourceHandle);
+ SourceHandle = NULL;
+
+ /* Perform the file copy */
+ Status = SetupCopyFile(ExistingFileName,
+ NewFileName,
+ !ReplaceIfExists);
+
+ /* If it succeeded, delete the source file */
+ if (NT_SUCCESS(Status))
+ {
+ /* Force-delete files even if read-only */
+ SetupDeleteFile(ExistingFileName, TRUE);
+ }
+ }
+ _SEH2_FINALLY
+ {
+ if (SourceHandle)
+ NtClose(SourceHandle);
+ }
+ _SEH2_END;
+
+ return Status;
+}
+
NTSTATUS
ConcatPathsV(
IN OUT PWSTR PathBuffer,
diff --git a/base/setup/lib/filesup.h b/base/setup/lib/filesup.h
index abc1b1c58d..0b82069185 100644
--- a/base/setup/lib/filesup.h
+++ b/base/setup/lib/filesup.h
@@ -7,14 +7,31 @@
#pragma once
-#if 0
+NTSTATUS
+SetupDeleteFile(
+ IN PCWSTR FileName,
+ IN BOOLEAN ForceDelete); // ForceDelete can be used to delete read-only files
-BOOLEAN
-IsValidPath(
- IN PCWSTR InstallDir);
+NTSTATUS
+SetupCopyFile(
+ IN PCWSTR SourceFileName,
+ IN PCWSTR DestinationFileName,
+ IN BOOLEAN FailIfExists);
+
+#ifndef _WINBASE_
+
+#define MOVEFILE_REPLACE_EXISTING 1
+#define MOVEFILE_COPY_ALLOWED 2
+#define MOVEFILE_WRITE_THROUGH 8
#endif
+NTSTATUS
+SetupMoveFile(
+ IN PCWSTR ExistingFileName,
+ IN PCWSTR NewFileName,
+ IN ULONG Flags);
+
NTSTATUS
ConcatPathsV(
IN OUT PWSTR PathBuffer,
diff --git a/base/setup/lib/regutil.c b/base/setup/lib/regutil.c
index eebbac0feb..2ede224164 100644
--- a/base/setup/lib/regutil.c
+++ b/base/setup/lib/regutil.c
@@ -19,27 +19,6 @@
#define NDEBUG
#include <debug.h>
-
-// HACK!! These functions should actually be moved in the setup lib!
-// For the moment, see usetup/filesup.c (or .h)
-#if 1
-
-NTSTATUS
-SetupCopyFile(
- IN PCWSTR SourceFileName,
- IN PCWSTR DestinationFileName,
- IN BOOLEAN FailIfExists);
-
-#define MOVEFILE_REPLACE_EXISTING 1
-
-NTSTATUS
-SetupMoveFile(
- IN PCWSTR ExistingFileName,
- IN PCWSTR NewFileName,
- IN ULONG Flags);
-
-#endif
-
/* FUNCTIONS ****************************************************************/
/*
diff --git a/base/setup/usetup/filesup.c b/base/setup/usetup/filesup.c
index 06d9d86344..261bfd9fa8 100644
--- a/base/setup/usetup/filesup.c
+++ b/base/setup/usetup/filesup.c
@@ -3,7 +3,7 @@
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/filesup.c
* PURPOSE: File support functions
- * PROGRAMMER: Casper S. Hornstrup (chorns(a)users.sourceforge.net)
+ * PROGRAMMERS: Casper S. Hornstrup (chorns(a)users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
@@ -142,451 +142,6 @@ done:
return Status;
}
-NTSTATUS
-SetupDeleteFile(
- IN PCWSTR FileName,
- IN BOOLEAN ForceDelete) // ForceDelete can be used to delete read-only files
-{
- NTSTATUS Status;
- UNICODE_STRING NtPathU;
- OBJECT_ATTRIBUTES ObjectAttributes;
- IO_STATUS_BLOCK IoStatusBlock;
- HANDLE FileHandle;
- FILE_DISPOSITION_INFORMATION FileDispInfo;
- BOOLEAN RetryOnce = FALSE;
-
- /* Open the directory name that was passed in */
- RtlInitUnicodeString(&NtPathU, FileName);
- InitializeObjectAttributes(&ObjectAttributes,
- &NtPathU,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
-Retry: // We go back there once if RetryOnce == TRUE
- Status = NtOpenFile(&FileHandle,
- DELETE | FILE_READ_ATTRIBUTES |
- (RetryOnce ? FILE_WRITE_ATTRIBUTES : 0),
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile failed with Status 0x%08lx\n", Status);
- return Status;
- }
-
- if (RetryOnce)
- {
- FILE_BASIC_INFORMATION FileInformation;
-
- Status = NtQueryInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInformation,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationFile failed with Status 0x%08lx\n",
Status);
- NtClose(FileHandle);
- return Status;
- }
-
- FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
- Status = NtSetInformationFile(FileHandle,
- &IoStatusBlock,
- &FileInformation,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- NtClose(FileHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationFile failed with Status 0x%08lx\n",
Status);
- return Status;
- }
- }
-
- /* Ask for the file to be deleted */
- FileDispInfo.DeleteFile = TRUE;
- Status = NtSetInformationFile(FileHandle,
- &IoStatusBlock,
- &FileDispInfo,
- sizeof(FILE_DISPOSITION_INFORMATION),
- FileDispositionInformation);
- NtClose(FileHandle);
-
- if (!NT_SUCCESS(Status))
- DPRINT1("Deletion of file '%S' failed, Status 0x%08lx\n",
FileName, Status);
-
- // FIXME: Check the precise value of Status!
- if (!NT_SUCCESS(Status) && ForceDelete && !RetryOnce)
- {
- /* Retry once */
- RetryOnce = TRUE;
- goto Retry;
- }
-
- /* Return result to the caller */
- return Status;
-}
-
-NTSTATUS
-SetupCopyFile(
- IN PCWSTR SourceFileName,
- IN PCWSTR DestinationFileName,
- IN BOOLEAN FailIfExists)
-{
- NTSTATUS Status;
- UNICODE_STRING FileName;
- OBJECT_ATTRIBUTES ObjectAttributes;
- HANDLE FileHandleSource;
- HANDLE FileHandleDest;
- IO_STATUS_BLOCK IoStatusBlock;
- FILE_STANDARD_INFORMATION FileStandard;
- FILE_BASIC_INFORMATION FileBasic;
- ULONG RegionSize;
- HANDLE SourceFileSection;
- PVOID SourceFileMap = NULL;
- SIZE_T SourceSectionSize = 0;
- LARGE_INTEGER ByteOffset;
-
- RtlInitUnicodeString(&FileName, SourceFileName);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &FileName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtOpenFile(&FileHandleSource,
- GENERIC_READ,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ,
- FILE_SEQUENTIAL_ONLY);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName);
- goto done;
- }
-
- Status = NtQueryInformationFile(FileHandleSource,
- &IoStatusBlock,
- &FileStandard,
- sizeof(FILE_STANDARD_INFORMATION),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationFile failed: %x\n", Status);
- goto closesrc;
- }
-
- Status = NtQueryInformationFile(FileHandleSource,
- &IoStatusBlock,
- &FileBasic,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationFile failed: %x\n", Status);
- goto closesrc;
- }
-
- Status = NtCreateSection(&SourceFileSection,
- SECTION_MAP_READ,
- NULL,
- NULL,
- PAGE_READONLY,
- SEC_COMMIT,
- FileHandleSource);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName);
- goto closesrc;
- }
-
- Status = NtMapViewOfSection(SourceFileSection,
- NtCurrentProcess(),
- &SourceFileMap,
- 0,
- 0,
- NULL,
- &SourceSectionSize,
- ViewUnmap,
- 0,
- PAGE_READONLY);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status,
SourceFileName);
- goto closesrcsec;
- }
-
- RtlInitUnicodeString(&FileName, DestinationFileName);
-
- InitializeObjectAttributes(&ObjectAttributes,
- &FileName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = NtCreateFile(&FileHandleDest,
- GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- NULL,
- FileBasic.FileAttributes, // FILE_ATTRIBUTE_NORMAL,
- 0,
- FailIfExists ? FILE_CREATE : FILE_OVERWRITE_IF,
- FILE_NO_INTERMEDIATE_BUFFERING |
- FILE_SEQUENTIAL_ONLY |
- FILE_SYNCHRONOUS_IO_NONALERT,
- NULL,
- 0);
- if (!NT_SUCCESS(Status))
- {
- /* 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 with limited access */
- Status = NtCreateFile(&FileHandleDest,
- FILE_WRITE_ATTRIBUTES | 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 */
- 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);
- IoStatusBlock.Status = 0;
- ByteOffset.QuadPart = 0ULL;
- Status = NtWriteFile(FileHandleDest,
- NULL,
- NULL,
- NULL,
- &IoStatusBlock,
- SourceFileMap,
- RegionSize,
- &ByteOffset,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n",
- Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap,
RegionSize);
- goto closedest;
- }
-
- /* Copy file date/time from source file */
- Status = NtSetInformationFile(FileHandleDest,
- &IoStatusBlock,
- &FileBasic,
- sizeof(FILE_BASIC_INFORMATION),
- FileBasicInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationFile failed: %x\n", Status);
- goto closedest;
- }
-
- /* Shorten the file back to its real size after completing the write */
- Status = NtSetInformationFile(FileHandleDest,
- &IoStatusBlock,
- &FileStandard.EndOfFile,
- sizeof(FILE_END_OF_FILE_INFORMATION),
- FileEndOfFileInformation);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtSetInformationFile failed: %x\n", Status);
- }
-
-closedest:
- NtClose(FileHandleDest);
-
-unmapsrcsec:
- NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap);
-
-closesrcsec:
- NtClose(SourceFileSection);
-
-closesrc:
- NtClose(FileHandleSource);
-
-done:
- return Status;
-}
-
-/*
- * Synchronized with its kernel32 counterpart, but we don't manage reparse points
here.
- */
-NTSTATUS
-SetupMoveFile(
- IN PCWSTR ExistingFileName,
- IN PCWSTR NewFileName,
- IN ULONG Flags)
-{
- NTSTATUS Status;
- IO_STATUS_BLOCK IoStatusBlock;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PFILE_RENAME_INFORMATION RenameInfo;
- UNICODE_STRING NewPathU, ExistingPathU;
- HANDLE SourceHandle = NULL;
- BOOLEAN ReplaceIfExists;
-
- RtlInitUnicodeString(&ExistingPathU, ExistingFileName);
- RtlInitUnicodeString(&NewPathU, NewFileName);
-
- _SEH2_TRY
- {
- ReplaceIfExists = !!(Flags & MOVEFILE_REPLACE_EXISTING);
-
- /* Unless we manage a proper opening, we'll attempt to reopen without reparse
support */
- InitializeObjectAttributes(&ObjectAttributes,
- &ExistingPathU,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- /* Attempt to open source file */
- Status = NtOpenFile(&SourceHandle,
- FILE_READ_ATTRIBUTES | DELETE | SYNCHRONIZE,
- &ObjectAttributes,
- &IoStatusBlock,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- FILE_OPEN_FOR_BACKUP_INTENT | ((Flags &
MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0));
- if (!NT_SUCCESS(Status))
- {
- if (Status != STATUS_INVALID_PARAMETER)
- {
- _SEH2_LEAVE;
- }
- }
-
- /* At that point, we MUST have a source handle */
- ASSERT(SourceHandle);
-
- /* Allocate renaming buffer and fill it */
- RenameInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, NewPathU.Length +
sizeof(FILE_RENAME_INFORMATION));
- if (RenameInfo == NULL)
- {
- Status = STATUS_NO_MEMORY;
- _SEH2_LEAVE;
- }
-
- RtlCopyMemory(&RenameInfo->FileName, NewPathU.Buffer, NewPathU.Length);
- RenameInfo->ReplaceIfExists = ReplaceIfExists;
- RenameInfo->RootDirectory = NULL;
- RenameInfo->FileNameLength = NewPathU.Length;
-
- /* Attempt to rename the file */
- Status = NtSetInformationFile(SourceHandle,
- &IoStatusBlock,
- RenameInfo,
- NewPathU.Length + sizeof(FILE_RENAME_INFORMATION),
- FileRenameInformation);
- RtlFreeHeap(RtlGetProcessHeap(), 0, RenameInfo);
- if (NT_SUCCESS(Status))
- {
- /* If it succeeded, all fine, quit */
- _SEH2_LEAVE;
- }
- /*
- * If we failed for any other reason than not the same device, fail.
- * If we failed because of different devices, only allow renaming
- * if user allowed copy.
- */
- if (Status != STATUS_NOT_SAME_DEVICE || !(Flags & MOVEFILE_COPY_ALLOWED))
- {
- /* ReactOS hack! To be removed once all FSD have proper renaming support
- * Just leave status to error and leave
- */
- if (Status == STATUS_NOT_IMPLEMENTED)
- {
- DPRINT1("Forcing copy, renaming not supported by FSD\n");
- }
- else
- {
- _SEH2_LEAVE;
- }
- }
-
- /* Close the source file */
- NtClose(SourceHandle);
- SourceHandle = NULL;
-
- /* Perform the file copy */
- Status = SetupCopyFile(ExistingFileName,
- NewFileName,
- !ReplaceIfExists);
-
- /* If it succeeded, delete the source file */
- if (NT_SUCCESS(Status))
- {
- /* Force-delete files even if read-only */
- SetupDeleteFile(ExistingFileName, TRUE);
- }
- }
- _SEH2_FINALLY
- {
- if (SourceHandle)
- NtClose(SourceHandle);
- }
- _SEH2_END;
-
- return Status;
-}
-
NTSTATUS
SetupExtractFile(
PWCHAR CabinetFileName,
@@ -665,7 +220,6 @@ SetupExtractFile(
return STATUS_SUCCESS;
}
-
BOOLEAN
IsValidPath(
IN PCWSTR InstallDir)
diff --git a/base/setup/usetup/filesup.h b/base/setup/usetup/filesup.h
index a8cc7940a7..884d384efa 100644
--- a/base/setup/usetup/filesup.h
+++ b/base/setup/usetup/filesup.h
@@ -3,7 +3,7 @@
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/filesup.h
* PURPOSE: File support functions
- * PROGRAMMER:
+ * PROGRAMMERS: Casper S. Hornstrup (chorns(a)users.sourceforge.net)
*/
#pragma once
@@ -12,45 +12,12 @@ NTSTATUS
SetupCreateDirectory(
PWCHAR DirectoryName);
-NTSTATUS
-SetupDeleteFile(
- IN PCWSTR FileName,
- IN BOOLEAN ForceDelete); // ForceDelete can be used to delete read-only files
-
-NTSTATUS
-SetupCopyFile(
- IN PCWSTR SourceFileName,
- IN PCWSTR DestinationFileName,
- IN BOOLEAN FailIfExists);
-
-#ifndef _WINBASE_
-
-#define MOVEFILE_REPLACE_EXISTING 1
-#define MOVEFILE_COPY_ALLOWED 2
-#define MOVEFILE_WRITE_THROUGH 8
-
-#endif
-
-// ACHTUNG! HAXX FIXME!!
-#define _SEH2_TRY
-#define _SEH2_LEAVE goto __SEH2_FINALLY__label;
-#define _SEH2_FINALLY __SEH2_FINALLY__label:
-#define _SEH2_END
-
-
-NTSTATUS
-SetupMoveFile(
- IN PCWSTR ExistingFileName,
- IN PCWSTR NewFileName,
- IN ULONG Flags);
-
NTSTATUS
SetupExtractFile(
PWCHAR CabinetFileName,
PWCHAR SourceFileName,
PWCHAR DestinationFileName);
-
BOOLEAN
IsValidPath(
IN PCWSTR InstallDir);