mirror of
https://github.com/reactos/reactos.git
synced 2025-05-29 05:58:13 +00:00
[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
This commit is contained in:
parent
60d9ea76d1
commit
2268b3d645
5 changed files with 480 additions and 506 deletions
|
@ -12,8 +12,465 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#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 ****************************************************************/
|
/* 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
|
NTSTATUS
|
||||||
ConcatPathsV(
|
ConcatPathsV(
|
||||||
IN OUT PWSTR PathBuffer,
|
IN OUT PWSTR PathBuffer,
|
||||||
|
|
|
@ -7,14 +7,31 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if 0
|
NTSTATUS
|
||||||
|
SetupDeleteFile(
|
||||||
|
IN PCWSTR FileName,
|
||||||
|
IN BOOLEAN ForceDelete); // ForceDelete can be used to delete read-only files
|
||||||
|
|
||||||
BOOLEAN
|
NTSTATUS
|
||||||
IsValidPath(
|
SetupCopyFile(
|
||||||
IN PCWSTR InstallDir);
|
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
|
#endif
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
SetupMoveFile(
|
||||||
|
IN PCWSTR ExistingFileName,
|
||||||
|
IN PCWSTR NewFileName,
|
||||||
|
IN ULONG Flags);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
ConcatPathsV(
|
ConcatPathsV(
|
||||||
IN OUT PWSTR PathBuffer,
|
IN OUT PWSTR PathBuffer,
|
||||||
|
|
|
@ -19,27 +19,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#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 ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* PROJECT: ReactOS text-mode setup
|
* PROJECT: ReactOS text-mode setup
|
||||||
* FILE: base/setup/usetup/filesup.c
|
* FILE: base/setup/usetup/filesup.c
|
||||||
* PURPOSE: File support functions
|
* PURPOSE: File support functions
|
||||||
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -142,451 +142,6 @@ done:
|
||||||
return Status;
|
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
|
NTSTATUS
|
||||||
SetupExtractFile(
|
SetupExtractFile(
|
||||||
PWCHAR CabinetFileName,
|
PWCHAR CabinetFileName,
|
||||||
|
@ -665,7 +220,6 @@ SetupExtractFile(
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
IsValidPath(
|
IsValidPath(
|
||||||
IN PCWSTR InstallDir)
|
IN PCWSTR InstallDir)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* PROJECT: ReactOS text-mode setup
|
* PROJECT: ReactOS text-mode setup
|
||||||
* FILE: base/setup/usetup/filesup.h
|
* FILE: base/setup/usetup/filesup.h
|
||||||
* PURPOSE: File support functions
|
* PURPOSE: File support functions
|
||||||
* PROGRAMMER:
|
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -12,45 +12,12 @@ NTSTATUS
|
||||||
SetupCreateDirectory(
|
SetupCreateDirectory(
|
||||||
PWCHAR DirectoryName);
|
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
|
NTSTATUS
|
||||||
SetupExtractFile(
|
SetupExtractFile(
|
||||||
PWCHAR CabinetFileName,
|
PWCHAR CabinetFileName,
|
||||||
PWCHAR SourceFileName,
|
PWCHAR SourceFileName,
|
||||||
PWCHAR DestinationFileName);
|
PWCHAR DestinationFileName);
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
IsValidPath(
|
IsValidPath(
|
||||||
IN PCWSTR InstallDir);
|
IN PCWSTR InstallDir);
|
||||||
|
|
Loading…
Reference in a new issue