reactos/base/setup/usetup/filesup.c
2018-10-27 18:13:40 +02:00

269 lines
6.9 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: base/setup/usetup/filesup.c
* PURPOSE: File support functions
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
#include "usetup.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
static BOOLEAN HasCurrentCabinet = FALSE;
static WCHAR CurrentCabinetName[MAX_PATH];
static CAB_SEARCH Search;
static
NTSTATUS
SetupCreateSingleDirectory(
PWCHAR DirectoryName)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING PathName;
HANDLE DirectoryHandle;
NTSTATUS Status;
if (!RtlCreateUnicodeString(&PathName, DirectoryName))
return STATUS_NO_MEMORY;
if (PathName.Length > sizeof(WCHAR) &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
{
PathName.Length -= sizeof(WCHAR);
PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
}
if (PathName.Length > sizeof(WCHAR) &&
PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
{
PathName.Length -= sizeof(WCHAR);
PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
}
InitializeObjectAttributes(&ObjectAttributes,
&PathName,
OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
NULL,
NULL);
Status = NtCreateFile(&DirectoryHandle,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE,
NULL,
0);
if (NT_SUCCESS(Status))
{
NtClose(DirectoryHandle);
}
RtlFreeUnicodeString(&PathName);
return Status;
}
NTSTATUS
SetupCreateDirectory(
PWCHAR PathName)
{
PWCHAR PathBuffer = NULL;
PWCHAR Ptr, EndPtr;
ULONG BackslashCount;
ULONG Size;
NTSTATUS Status = STATUS_SUCCESS;
Size = (wcslen(PathName) + 1) * sizeof(WCHAR);
PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Size);
if (PathBuffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
wcscpy(PathBuffer, PathName);
EndPtr = PathBuffer + wcslen(PathName);
Ptr = PathBuffer;
/* Skip the '\Device\HarddiskX\PartitionY\ part */
BackslashCount = 0;
while (Ptr < EndPtr && BackslashCount < 4)
{
if (*Ptr == L'\\')
BackslashCount++;
Ptr++;
}
while (Ptr < EndPtr)
{
if (*Ptr == L'\\')
{
*Ptr = 0;
DPRINT("PathBuffer: %S\n", PathBuffer);
if (!DoesDirExist(NULL, PathBuffer))
{
DPRINT("Create: %S\n", PathBuffer);
Status = SetupCreateSingleDirectory(PathBuffer);
if (!NT_SUCCESS(Status))
goto done;
}
*Ptr = L'\\';
}
Ptr++;
}
if (!DoesDirExist(NULL, PathBuffer))
{
DPRINT("Create: %S\n", PathBuffer);
Status = SetupCreateSingleDirectory(PathBuffer);
if (!NT_SUCCESS(Status))
goto done;
}
done:
DPRINT("Done.\n");
if (PathBuffer != NULL)
RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
return Status;
}
NTSTATUS
SetupExtractFile(
PWCHAR CabinetFileName,
PWCHAR SourceFileName,
PWCHAR DestinationPathName)
{
ULONG CabStatus;
DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
CabinetFileName, SourceFileName, DestinationPathName);
if (HasCurrentCabinet)
{
DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
}
if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
{
DPRINT("Using same cabinet as last time\n");
/* Use our last location because the files should be sequential */
CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search);
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT("Sequential miss on file: %S\n", SourceFileName);
/* Looks like we got unlucky */
CabStatus = CabinetFindFirst(SourceFileName, &Search);
}
}
else
{
DPRINT("Using new cabinet\n");
if (HasCurrentCabinet)
{
CabinetCleanup();
}
wcscpy(CurrentCabinetName, CabinetFileName);
CabinetInitialize();
CabinetSetEventHandlers(NULL, NULL, NULL);
CabinetSetCabinetName(CabinetFileName);
CabStatus = CabinetOpen();
if (CabStatus == CAB_STATUS_SUCCESS)
{
DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
HasCurrentCabinet = TRUE;
}
else
{
DPRINT("Cannot open cabinet (%d)\n", CabStatus);
return STATUS_UNSUCCESSFUL;
}
/* We have to start at the beginning here */
CabStatus = CabinetFindFirst(SourceFileName, &Search);
}
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName());
return STATUS_UNSUCCESSFUL;
}
CabinetSetDestinationPath(DestinationPathName);
CabStatus = CabinetExtractFile(&Search);
if (CabStatus != CAB_STATUS_SUCCESS)
{
DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
BOOLEAN
IsValidPath(
IN PCWSTR InstallDir)
{
UINT i, Length;
Length = wcslen(InstallDir);
// TODO: Add check for 8.3 too.
/* Path must be at least 2 characters long */
// if (Length < 2)
// return FALSE;
/* Path must start with a backslash */
// if (InstallDir[0] != L'\\')
// return FALSE;
/* Path must not end with a backslash */
if (InstallDir[Length - 1] == L'\\')
return FALSE;
/* Path must not contain whitespace characters */
for (i = 0; i < Length; i++)
{
if (iswspace(InstallDir[i]))
return FALSE;
}
/* Path component must not end with a dot */
for (i = 0; i < Length; i++)
{
if (InstallDir[i] == L'\\' && i > 0)
{
if (InstallDir[i - 1] == L'.')
return FALSE;
}
}
if (InstallDir[Length - 1] == L'.')
return FALSE;
return TRUE;
}
/* EOF */