mirror of
https://github.com/reactos/reactos.git
synced 2025-05-30 22:49:12 +00:00
[USETUP] Support a custom way to extract files for cabinet files
This will be used to extract files from cabinet to memory, instead of writing them to disk.
This commit is contained in:
parent
0d51c71ed7
commit
04ec14e23e
3 changed files with 147 additions and 124 deletions
|
@ -1018,134 +1018,147 @@ CabinetExtractFile(
|
||||||
DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n",
|
DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n",
|
||||||
(UINT)Search->File->FileOffset, (UINT)Search->File->FileSize);
|
(UINT)Search->File->FileOffset, (UINT)Search->File->FileSize);
|
||||||
|
|
||||||
RtlInitAnsiString(&AnsiString, Search->File->FileName);
|
if (CabinetContext->CreateFileHandler)
|
||||||
wcscpy(DestName, CabinetContext->DestPath);
|
|
||||||
UnicodeString.MaximumLength = sizeof(DestName) - wcslen(DestName) * sizeof(WCHAR);
|
|
||||||
UnicodeString.Buffer = DestName + wcslen(DestName);
|
|
||||||
UnicodeString.Length = 0;
|
|
||||||
RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
|
|
||||||
|
|
||||||
/* Create destination file, fail if it already exists */
|
|
||||||
RtlInitUnicodeString(&UnicodeString, DestName);
|
|
||||||
|
|
||||||
InitializeObjectAttributes(&ObjectAttributes,
|
|
||||||
&UnicodeString,
|
|
||||||
OBJ_CASE_INSENSITIVE,
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
NtStatus = NtCreateFile(&DestFile,
|
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
NULL,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
0,
|
|
||||||
FILE_CREATE,
|
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
||||||
NULL, 0);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
|
||||||
{
|
{
|
||||||
DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
|
/* Call create context */
|
||||||
|
CurrentDestBuffer = CabinetContext->CreateFileHandler(CabinetContext, Search->File->FileSize);
|
||||||
/* If file exists, ask to overwrite file */
|
if (!CurrentDestBuffer)
|
||||||
if (CabinetContext->OverwriteHandler == NULL ||
|
|
||||||
CabinetContext->OverwriteHandler(CabinetContext, Search->File, DestName))
|
|
||||||
{
|
{
|
||||||
/* Create destination file, overwrite if it already exists */
|
DPRINT1("CreateFileHandler() failed\n");
|
||||||
NtStatus = NtCreateFile(&DestFile,
|
return CAB_STATUS_CANNOT_CREATE;
|
||||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
|
||||||
&ObjectAttributes,
|
|
||||||
&IoStatusBlock,
|
|
||||||
NULL,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
0,
|
|
||||||
FILE_OVERWRITE,
|
|
||||||
FILE_SYNCHRONOUS_IO_ALERT,
|
|
||||||
NULL, 0);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
|
||||||
{
|
|
||||||
DPRINT1("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
|
|
||||||
return CAB_STATUS_CANNOT_CREATE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT1("File (%S) exists\n", DestName);
|
|
||||||
return CAB_STATUS_FILE_EXISTS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaxDestFileSize.QuadPart = Search->File->FileSize;
|
|
||||||
NtStatus = NtCreateSection(&DestFileSection,
|
|
||||||
SECTION_ALL_ACCESS,
|
|
||||||
0,
|
|
||||||
&MaxDestFileSize,
|
|
||||||
PAGE_READWRITE,
|
|
||||||
SEC_COMMIT,
|
|
||||||
DestFile);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
|
||||||
{
|
|
||||||
DPRINT1("NtCreateSection failed for %ls: %x\n", DestName, NtStatus);
|
|
||||||
Status = CAB_STATUS_NOMEMORY;
|
|
||||||
goto CloseDestFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
DestFileBuffer = 0;
|
|
||||||
CabinetContext->DestFileSize = 0;
|
|
||||||
NtStatus = NtMapViewOfSection(DestFileSection,
|
|
||||||
NtCurrentProcess(),
|
|
||||||
&DestFileBuffer,
|
|
||||||
0, 0, 0,
|
|
||||||
&CabinetContext->DestFileSize,
|
|
||||||
ViewUnmap,
|
|
||||||
0,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
|
||||||
{
|
|
||||||
DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
|
|
||||||
Status = CAB_STATUS_NOMEMORY;
|
|
||||||
goto CloseDestFileSection;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentDestBuffer = DestFileBuffer;
|
|
||||||
if (!ConvertDosDateTimeToFileTime(Search->File->FileDate,
|
|
||||||
Search->File->FileTime,
|
|
||||||
&FileTime))
|
|
||||||
{
|
|
||||||
DPRINT1("DosDateTimeToFileTime() failed\n");
|
|
||||||
Status = CAB_STATUS_CANNOT_WRITE;
|
|
||||||
goto UnmapDestFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
NtStatus = NtQueryInformationFile(DestFile,
|
|
||||||
&IoStatusBlock,
|
|
||||||
&FileBasic,
|
|
||||||
sizeof(FILE_BASIC_INFORMATION),
|
|
||||||
FileBasicInformation);
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
|
||||||
{
|
|
||||||
DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME));
|
RtlInitAnsiString(&AnsiString, Search->File->FileName);
|
||||||
|
wcscpy(DestName, CabinetContext->DestPath);
|
||||||
|
UnicodeString.MaximumLength = sizeof(DestName) - wcslen(DestName) * sizeof(WCHAR);
|
||||||
|
UnicodeString.Buffer = DestName + wcslen(DestName);
|
||||||
|
UnicodeString.Length = 0;
|
||||||
|
RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
|
||||||
|
|
||||||
|
/* Create destination file, fail if it already exists */
|
||||||
|
RtlInitUnicodeString(&UnicodeString, DestName);
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&UnicodeString,
|
||||||
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
NtStatus = NtCreateFile(&DestFile,
|
||||||
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0,
|
||||||
|
FILE_CREATE,
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||||
|
NULL, 0);
|
||||||
|
|
||||||
NtStatus = NtSetInformationFile(DestFile,
|
|
||||||
&IoStatusBlock,
|
|
||||||
&FileBasic,
|
|
||||||
sizeof(FILE_BASIC_INFORMATION),
|
|
||||||
FileBasicInformation);
|
|
||||||
if (!NT_SUCCESS(NtStatus))
|
if (!NT_SUCCESS(NtStatus))
|
||||||
{
|
{
|
||||||
DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
|
DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetAttributesOnFile(Search->File, DestFile);
|
/* If file exists, ask to overwrite file */
|
||||||
|
if (CabinetContext->OverwriteHandler == NULL ||
|
||||||
|
CabinetContext->OverwriteHandler(CabinetContext, Search->File, DestName))
|
||||||
|
{
|
||||||
|
/* Create destination file, overwrite if it already exists */
|
||||||
|
NtStatus = NtCreateFile(&DestFile,
|
||||||
|
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
||||||
|
&ObjectAttributes,
|
||||||
|
&IoStatusBlock,
|
||||||
|
NULL,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0,
|
||||||
|
FILE_OVERWRITE,
|
||||||
|
FILE_SYNCHRONOUS_IO_ALERT,
|
||||||
|
NULL, 0);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(NtStatus))
|
||||||
|
{
|
||||||
|
DPRINT1("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
|
||||||
|
return CAB_STATUS_CANNOT_CREATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("File (%S) exists\n", DestName);
|
||||||
|
return CAB_STATUS_FILE_EXISTS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaxDestFileSize.QuadPart = Search->File->FileSize;
|
||||||
|
NtStatus = NtCreateSection(&DestFileSection,
|
||||||
|
SECTION_ALL_ACCESS,
|
||||||
|
0,
|
||||||
|
&MaxDestFileSize,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
SEC_COMMIT,
|
||||||
|
DestFile);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(NtStatus))
|
||||||
|
{
|
||||||
|
DPRINT1("NtCreateSection failed for %ls: %x\n", DestName, NtStatus);
|
||||||
|
Status = CAB_STATUS_NOMEMORY;
|
||||||
|
goto CloseDestFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
DestFileBuffer = 0;
|
||||||
|
CabinetContext->DestFileSize = 0;
|
||||||
|
NtStatus = NtMapViewOfSection(DestFileSection,
|
||||||
|
NtCurrentProcess(),
|
||||||
|
&DestFileBuffer,
|
||||||
|
0, 0, 0,
|
||||||
|
&CabinetContext->DestFileSize,
|
||||||
|
ViewUnmap,
|
||||||
|
0,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(NtStatus))
|
||||||
|
{
|
||||||
|
DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
|
||||||
|
Status = CAB_STATUS_NOMEMORY;
|
||||||
|
goto CloseDestFileSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentDestBuffer = DestFileBuffer;
|
||||||
|
if (!ConvertDosDateTimeToFileTime(Search->File->FileDate,
|
||||||
|
Search->File->FileTime,
|
||||||
|
&FileTime))
|
||||||
|
{
|
||||||
|
DPRINT1("DosDateTimeToFileTime() failed\n");
|
||||||
|
Status = CAB_STATUS_CANNOT_WRITE;
|
||||||
|
goto UnmapDestFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
NtStatus = NtQueryInformationFile(DestFile,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileBasic,
|
||||||
|
sizeof(FILE_BASIC_INFORMATION),
|
||||||
|
FileBasicInformation);
|
||||||
|
if (!NT_SUCCESS(NtStatus))
|
||||||
|
{
|
||||||
|
DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME));
|
||||||
|
|
||||||
|
NtStatus = NtSetInformationFile(DestFile,
|
||||||
|
&IoStatusBlock,
|
||||||
|
&FileBasic,
|
||||||
|
sizeof(FILE_BASIC_INFORMATION),
|
||||||
|
FileBasicInformation);
|
||||||
|
if (!NT_SUCCESS(NtStatus))
|
||||||
|
{
|
||||||
|
DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetAttributesOnFile(Search->File, DestFile);
|
||||||
|
}
|
||||||
|
|
||||||
/* Call extract event handler */
|
/* Call extract event handler */
|
||||||
if (CabinetContext->ExtractHandler != NULL)
|
if (CabinetContext->ExtractHandler != NULL)
|
||||||
|
@ -1250,13 +1263,16 @@ CabinetExtractFile(
|
||||||
Status = CAB_STATUS_SUCCESS;
|
Status = CAB_STATUS_SUCCESS;
|
||||||
|
|
||||||
UnmapDestFile:
|
UnmapDestFile:
|
||||||
NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
|
if (!CabinetContext->CreateFileHandler)
|
||||||
|
NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
|
||||||
|
|
||||||
CloseDestFileSection:
|
CloseDestFileSection:
|
||||||
NtClose(DestFileSection);
|
if (!CabinetContext->CreateFileHandler)
|
||||||
|
NtClose(DestFileSection);
|
||||||
|
|
||||||
CloseDestFile:
|
CloseDestFile:
|
||||||
NtClose(DestFile);
|
if (!CabinetContext->CreateFileHandler)
|
||||||
|
NtClose(DestFile);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1316,11 +1332,13 @@ CabinetSetEventHandlers(
|
||||||
IN PCABINET_CONTEXT CabinetContext,
|
IN PCABINET_CONTEXT CabinetContext,
|
||||||
IN PCABINET_OVERWRITE Overwrite,
|
IN PCABINET_OVERWRITE Overwrite,
|
||||||
IN PCABINET_EXTRACT Extract,
|
IN PCABINET_EXTRACT Extract,
|
||||||
IN PCABINET_DISK_CHANGE DiskChange)
|
IN PCABINET_DISK_CHANGE DiskChange,
|
||||||
|
IN PCABINET_CREATE_FILE CreateFile)
|
||||||
{
|
{
|
||||||
CabinetContext->OverwriteHandler = Overwrite;
|
CabinetContext->OverwriteHandler = Overwrite;
|
||||||
CabinetContext->ExtractHandler = Extract;
|
CabinetContext->ExtractHandler = Extract;
|
||||||
CabinetContext->DiskChangeHandler = DiskChange;
|
CabinetContext->DiskChangeHandler = DiskChange;
|
||||||
|
CabinetContext->CreateFileHandler = CreateFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -65,6 +65,9 @@ typedef VOID (*PCABINET_DISK_CHANGE)(
|
||||||
IN PCWSTR CabinetName,
|
IN PCWSTR CabinetName,
|
||||||
IN PCWSTR DiskLabel);
|
IN PCWSTR DiskLabel);
|
||||||
|
|
||||||
|
typedef PVOID (*PCABINET_CREATE_FILE)(
|
||||||
|
IN struct _CABINET_CONTEXT* CabinetContext,
|
||||||
|
IN ULONG FileSize);
|
||||||
|
|
||||||
/* Classes */
|
/* Classes */
|
||||||
|
|
||||||
|
@ -106,6 +109,7 @@ typedef struct _CABINET_CONTEXT
|
||||||
PCABINET_OVERWRITE OverwriteHandler;
|
PCABINET_OVERWRITE OverwriteHandler;
|
||||||
PCABINET_EXTRACT ExtractHandler;
|
PCABINET_EXTRACT ExtractHandler;
|
||||||
PCABINET_DISK_CHANGE DiskChangeHandler;
|
PCABINET_DISK_CHANGE DiskChangeHandler;
|
||||||
|
PCABINET_CREATE_FILE CreateFileHandler;
|
||||||
PVOID CabinetReservedArea;
|
PVOID CabinetReservedArea;
|
||||||
} CABINET_CONTEXT, *PCABINET_CONTEXT;
|
} CABINET_CONTEXT, *PCABINET_CONTEXT;
|
||||||
|
|
||||||
|
@ -204,7 +208,8 @@ CabinetSetEventHandlers(
|
||||||
IN PCABINET_CONTEXT CabinetContext,
|
IN PCABINET_CONTEXT CabinetContext,
|
||||||
IN PCABINET_OVERWRITE Overwrite,
|
IN PCABINET_OVERWRITE Overwrite,
|
||||||
IN PCABINET_EXTRACT Extract,
|
IN PCABINET_EXTRACT Extract,
|
||||||
IN PCABINET_DISK_CHANGE DiskChange);
|
IN PCABINET_DISK_CHANGE DiskChange,
|
||||||
|
IN PCABINET_CREATE_FILE CreateFile);
|
||||||
|
|
||||||
/* Get pointer to cabinet reserved area. NULL if none */
|
/* Get pointer to cabinet reserved area. NULL if none */
|
||||||
PVOID
|
PVOID
|
||||||
|
|
|
@ -117,7 +117,7 @@ SetupExtractFile(
|
||||||
|
|
||||||
CabinetInitialize(&QueueHeader->CabinetContext);
|
CabinetInitialize(&QueueHeader->CabinetContext);
|
||||||
CabinetSetEventHandlers(&QueueHeader->CabinetContext,
|
CabinetSetEventHandlers(&QueueHeader->CabinetContext,
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
CabinetSetCabinetName(&QueueHeader->CabinetContext, CabinetFileName);
|
CabinetSetCabinetName(&QueueHeader->CabinetContext, CabinetFileName);
|
||||||
|
|
||||||
CabStatus = CabinetOpen(&QueueHeader->CabinetContext);
|
CabStatus = CabinetOpen(&QueueHeader->CabinetContext);
|
||||||
|
|
Loading…
Reference in a new issue