https://git.reactos.org/?p=reactos.git;a=commitdiff;h=04ec14e23ee9b7b5d0f2b5edecea6c819110e068

commit 04ec14e23ee9b7b5d0f2b5edecea6c819110e068
Author:     Hervé Poussineau <[email protected]>
AuthorDate: Mon May 13 23:28:19 2019 +0200
Commit:     Hervé Poussineau <[email protected]>
CommitDate: Sun Apr 26 14:57:40 2020 +0200

    [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.
---
 base/setup/usetup/spapisup/cabinet.c  | 248 ++++++++++++++++++----------------
 base/setup/usetup/spapisup/cabinet.h  |   7 +-
 base/setup/usetup/spapisup/fileqsup.c |   2 +-
 3 files changed, 140 insertions(+), 117 deletions(-)

diff --git a/base/setup/usetup/spapisup/cabinet.c 
b/base/setup/usetup/spapisup/cabinet.c
index 7e8450ca42c..8d8391a3250 100644
--- a/base/setup/usetup/spapisup/cabinet.c
+++ b/base/setup/usetup/spapisup/cabinet.c
@@ -1018,134 +1018,147 @@ CabinetExtractFile(
     DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n",
            (UINT)Search->File->FileOffset, (UINT)Search->File->FileSize);
 
-    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);
-
-    if (!NT_SUCCESS(NtStatus))
+    if (CabinetContext->CreateFileHandler)
     {
-        DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
+        /* Call create context */
+        CurrentDestBuffer = CabinetContext->CreateFileHandler(CabinetContext, 
Search->File->FileSize);
+        if (!CurrentDestBuffer)
+        {
+            DPRINT1("CreateFileHandler() failed\n");
+            return CAB_STATUS_CANNOT_CREATE;
+        }
+    }
+    else
+    {
+        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);
 
-        /* If file exists, ask to overwrite file */
-        if (CabinetContext->OverwriteHandler == NULL ||
-            CabinetContext->OverwriteHandler(CabinetContext, Search->File, 
DestName))
+        if (!NT_SUCCESS(NtStatus))
         {
-            /* 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);
+            DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
 
-            if (!NT_SUCCESS(NtStatus))
+            /* If file exists, ask to overwrite file */
+            if (CabinetContext->OverwriteHandler == NULL ||
+                CabinetContext->OverwriteHandler(CabinetContext, Search->File, 
DestName))
             {
-                DPRINT1("NtCreateFile() failed (%S) (%x)\n", DestName, 
NtStatus);
-                return CAB_STATUS_CANNOT_CREATE;
+                /* 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;
             }
         }
-        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);
+        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;
-    }
+        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);
+        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;
-    }
+        if (!NT_SUCCESS(NtStatus))
+        {
+            DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
+            Status = CAB_STATUS_NOMEMORY;
+            goto CloseDestFileSection;
+        }
 
-    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));
+        CurrentDestBuffer = DestFileBuffer;
+        if (!ConvertDosDateTimeToFileTime(Search->File->FileDate,
+                                          Search->File->FileTime,
+                                          &FileTime))
+        {
+            DPRINT1("DosDateTimeToFileTime() failed\n");
+            Status = CAB_STATUS_CANNOT_WRITE;
+            goto UnmapDestFile;
+        }
 
-        NtStatus = NtSetInformationFile(DestFile,
-                                        &IoStatusBlock,
-                                        &FileBasic,
-                                        sizeof(FILE_BASIC_INFORMATION),
-                                        FileBasicInformation);
+        NtStatus = NtQueryInformationFile(DestFile,
+                                          &IoStatusBlock,
+                                          &FileBasic,
+                                          sizeof(FILE_BASIC_INFORMATION),
+                                          FileBasicInformation);
         if (!NT_SUCCESS(NtStatus))
         {
-            DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
+            DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
         }
-    }
+        else
+        {
+            memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME));
 
-    SetAttributesOnFile(Search->File, DestFile);
+            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 */
     if (CabinetContext->ExtractHandler != NULL)
@@ -1250,13 +1263,16 @@ CabinetExtractFile(
     Status = CAB_STATUS_SUCCESS;
 
 UnmapDestFile:
-    NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
+    if (!CabinetContext->CreateFileHandler)
+        NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
 
 CloseDestFileSection:
-    NtClose(DestFileSection);
+    if (!CabinetContext->CreateFileHandler)
+        NtClose(DestFileSection);
 
 CloseDestFile:
-    NtClose(DestFile);
+    if (!CabinetContext->CreateFileHandler)
+        NtClose(DestFile);
 
     return Status;
 }
@@ -1316,11 +1332,13 @@ CabinetSetEventHandlers(
     IN PCABINET_CONTEXT CabinetContext,
     IN PCABINET_OVERWRITE Overwrite,
     IN PCABINET_EXTRACT Extract,
-    IN PCABINET_DISK_CHANGE DiskChange)
+    IN PCABINET_DISK_CHANGE DiskChange,
+    IN PCABINET_CREATE_FILE CreateFile)
 {
     CabinetContext->OverwriteHandler = Overwrite;
     CabinetContext->ExtractHandler = Extract;
     CabinetContext->DiskChangeHandler = DiskChange;
+    CabinetContext->CreateFileHandler = CreateFile;
 }
 
 /*
diff --git a/base/setup/usetup/spapisup/cabinet.h 
b/base/setup/usetup/spapisup/cabinet.h
index 4dfd36e7506..0ba74c9e9d6 100644
--- a/base/setup/usetup/spapisup/cabinet.h
+++ b/base/setup/usetup/spapisup/cabinet.h
@@ -65,6 +65,9 @@ typedef VOID (*PCABINET_DISK_CHANGE)(
     IN PCWSTR CabinetName,
     IN PCWSTR DiskLabel);
 
+typedef PVOID (*PCABINET_CREATE_FILE)(
+    IN struct _CABINET_CONTEXT* CabinetContext,
+    IN ULONG FileSize);
 
 /* Classes */
 
@@ -106,6 +109,7 @@ typedef struct _CABINET_CONTEXT
     PCABINET_OVERWRITE OverwriteHandler;
     PCABINET_EXTRACT ExtractHandler;
     PCABINET_DISK_CHANGE DiskChangeHandler;
+    PCABINET_CREATE_FILE CreateFileHandler;
     PVOID CabinetReservedArea;
 } CABINET_CONTEXT, *PCABINET_CONTEXT;
 
@@ -204,7 +208,8 @@ CabinetSetEventHandlers(
     IN PCABINET_CONTEXT CabinetContext,
     IN PCABINET_OVERWRITE Overwrite,
     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 */
 PVOID
diff --git a/base/setup/usetup/spapisup/fileqsup.c 
b/base/setup/usetup/spapisup/fileqsup.c
index b82fcd889d5..d6846881d96 100644
--- a/base/setup/usetup/spapisup/fileqsup.c
+++ b/base/setup/usetup/spapisup/fileqsup.c
@@ -117,7 +117,7 @@ SetupExtractFile(
 
         CabinetInitialize(&QueueHeader->CabinetContext);
         CabinetSetEventHandlers(&QueueHeader->CabinetContext,
-                                NULL, NULL, NULL);
+                                NULL, NULL, NULL, NULL);
         CabinetSetCabinetName(&QueueHeader->CabinetContext, CabinetFileName);
 
         CabStatus = CabinetOpen(&QueueHeader->CabinetContext);

Reply via email to