[SETUPLIB][USETUP] Move all the code that performs file copying into the SETUPLIB.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sun, 7 Jan 2018 00:35:48 +0000 (01:35 +0100)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 5 Nov 2018 22:18:47 +0000 (23:18 +0100)
base/setup/lib/CMakeLists.txt
base/setup/lib/install.c [new file with mode: 0644]
base/setup/lib/install.h [new file with mode: 0644]
base/setup/lib/setuplib.h
base/setup/usetup/usetup.c

index 7c23e24..0d2f3a8 100644 (file)
@@ -17,6 +17,7 @@ list(APPEND SOURCE
     utils/regutil.c
     bootsup.c
     fsutil.c
+    install.c
     mui.c
     registry.c
     settings.c
diff --git a/base/setup/lib/install.c b/base/setup/lib/install.c
new file mode 100644 (file)
index 0000000..31ece47
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Setup Library
+ * FILE:            base/setup/lib/install.c
+ * PURPOSE:         Installation functions
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "precomp.h"
+#include "filesup.h"
+#include "infsupp.h"
+
+#include "setuplib.h" // HAXX for USETUP_DATA!!
+
+#include "install.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* FUNCTIONS ****************************************************************/
+
+/*
+ * This code enumerates the list of files in reactos.dff / reactos.inf
+ * that need to be extracted from reactos.cab and be installed in their
+ * respective directories.
+ */
+/*
+ * IMPORTANT NOTE: The INF file specification used for the .CAB in ReactOS
+ * is not compliant with respect to TXTSETUP.SIF syntax or the standard syntax.
+ */
+static BOOLEAN
+AddSectionToCopyQueueCab(
+    IN PUSETUP_DATA pSetupData,
+    IN HINF InfFile,
+    IN PCWSTR SectionName,
+    IN PCWSTR SourceCabinet,
+    IN PCUNICODE_STRING DestinationPath)
+{
+    INFCONTEXT FilesContext;
+    INFCONTEXT DirContext;
+    PCWSTR FileKeyName;
+    PCWSTR FileKeyValue;
+    PCWSTR DirKeyValue;
+    PCWSTR TargetFileName;
+    WCHAR FileDstPath[MAX_PATH];
+
+    /* Search for the SectionName section */
+    if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
+    {
+        pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
+        if (pSetupData->ErrorRoutine)
+            pSetupData->ErrorRoutine(pSetupData, SectionName);
+        return FALSE;
+    }
+
+    /*
+     * Enumerate the files in the section and add them to the file queue.
+     */
+    do
+    {
+        /* Get source file name and target directory id */
+        if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("INF_GetData() failed\n");
+            break;
+        }
+
+        /* Get optional target file name */
+        if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
+            TargetFileName = NULL;
+
+        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
+
+        /* Lookup target directory */
+        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("SetupFindFirstLine() failed\n");
+            INF_FreeData(FileKeyName);
+            INF_FreeData(FileKeyValue);
+            INF_FreeData(TargetFileName);
+            break;
+        }
+
+        INF_FreeData(FileKeyValue);
+
+        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("INF_GetData() failed\n");
+            INF_FreeData(FileKeyName);
+            INF_FreeData(TargetFileName);
+            break;
+        }
+
+#if 1 // HACK moved! (r66604)
+        {
+        ULONG Length = wcslen(DirKeyValue);
+        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
+            Length--;
+        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
+        }
+
+        /* Build the full target path */
+        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
+                          pSetupData->DestinationRootPath.Buffer);
+        if (DirKeyValue[0] == UNICODE_NULL)
+        {
+            /* Installation path */
+
+            /* Add the installation path */
+            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, pSetupData->InstallPath.Buffer);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            // if (DirKeyValue[1] != UNICODE_NULL)
+                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
+        }
+        else // if (DirKeyValue[0] != L'\\')
+        {
+            /* Path relative to the installation path */
+
+            /* Add the installation path */
+            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
+                        pSetupData->InstallPath.Buffer, DirKeyValue);
+        }
+#endif
+
+        if (!SpFileQueueCopy((HSPFILEQ)pSetupData->SetupFileQueue,
+                             pSetupData->SourceRootPath.Buffer,
+                             pSetupData->SourceRootDir.Buffer,
+                             FileKeyName,
+                             NULL,
+                             SourceCabinet,
+                             NULL,
+                             FileDstPath,
+                             TargetFileName,
+                             0 /* FIXME */))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("SpFileQueueCopy() failed\n");
+        }
+
+        INF_FreeData(FileKeyName);
+        INF_FreeData(TargetFileName);
+        INF_FreeData(DirKeyValue);
+    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
+
+    return TRUE;
+}
+
+// Note: Modeled after the SetupQueueCopySection() API
+/*
+BOOL SetupQueueCopySection(
+  _In_ HSPFILEQ QueueHandle,
+  _In_ PCTSTR   SourceRootPath,
+  _In_ HINF     InfHandle,
+  _In_ HINF     ListInfHandle,
+  _In_ PCTSTR   Section,
+  _In_ DWORD    CopyStyle
+);
+*/
+static BOOLEAN
+AddSectionToCopyQueue(
+    IN PUSETUP_DATA pSetupData,
+    IN HINF InfFile,
+    IN PCWSTR SectionName,
+    IN PCWSTR SourceCabinet,
+    IN PCUNICODE_STRING DestinationPath)
+{
+    INFCONTEXT FilesContext;
+    INFCONTEXT DirContext;
+    PCWSTR FileKeyName;
+    PCWSTR FileKeyValue;
+    PCWSTR DirKeyValue;
+    PCWSTR TargetFileName;
+    WCHAR CompleteOrigDirName[512]; // FIXME: MAX_PATH is not enough?
+    WCHAR FileDstPath[MAX_PATH];
+
+    if (SourceCabinet)
+        return AddSectionToCopyQueueCab(pSetupData, InfFile, L"SourceFiles", SourceCabinet, DestinationPath);
+
+    /*
+     * This code enumerates the list of files in txtsetup.sif
+     * that need to be installed in their respective directories.
+     */
+
+    /* Search for the SectionName section */
+    if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
+    {
+        pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
+        if (pSetupData->ErrorRoutine)
+            pSetupData->ErrorRoutine(pSetupData, SectionName);
+        return FALSE;
+    }
+
+    /*
+     * Enumerate the files in the section and add them to the file queue.
+     */
+    do
+    {
+        /* Get source file name */
+        if (!INF_GetDataField(&FilesContext, 0, &FileKeyName))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("INF_GetData() failed\n");
+            break;
+        }
+
+        /* Get target directory id */
+        if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("INF_GetData() failed\n");
+            INF_FreeData(FileKeyName);
+            break;
+        }
+
+        /* Get optional target file name */
+        if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
+            TargetFileName = NULL;
+        else if (!*TargetFileName)
+            TargetFileName = NULL;
+
+        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
+
+        /* Lookup target directory */
+        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("SetupFindFirstLine() failed\n");
+            INF_FreeData(FileKeyName);
+            INF_FreeData(FileKeyValue);
+            INF_FreeData(TargetFileName);
+            break;
+        }
+
+        INF_FreeData(FileKeyValue);
+
+        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("INF_GetData() failed\n");
+            INF_FreeData(FileKeyName);
+            INF_FreeData(TargetFileName);
+            break;
+        }
+
+        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
+        {
+            /* Installation path */
+            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
+
+            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                              pSetupData->SourceRootDir.Buffer);
+
+            DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
+
+            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
+                              DirKeyValue);
+
+            DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName);
+        }
+        else // if (DirKeyValue[0] != L'\\')
+        {
+            /* Path relative to the installation path */
+            DPRINT("RelativePath: '%S'\n", DirKeyValue);
+
+            CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 2,
+                         pSetupData->SourceRootDir.Buffer, DirKeyValue);
+
+            DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName);
+        }
+
+#if 1 // HACK moved! (r66604)
+        {
+        ULONG Length = wcslen(DirKeyValue);
+        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
+            Length--;
+        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
+        }
+
+        /* Build the full target path */
+        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
+                          pSetupData->DestinationRootPath.Buffer);
+        if (DirKeyValue[0] == UNICODE_NULL)
+        {
+            /* Installation path */
+
+            /* Add the installation path */
+            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, pSetupData->InstallPath.Buffer);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            // if (DirKeyValue[1] != UNICODE_NULL)
+                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
+        }
+        else // if (DirKeyValue[0] != L'\\')
+        {
+            /* Path relative to the installation path */
+
+            /* Add the installation path */
+            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
+                        pSetupData->InstallPath.Buffer, DirKeyValue);
+        }
+#endif
+
+        if (!SpFileQueueCopy((HSPFILEQ)pSetupData->SetupFileQueue,
+                             pSetupData->SourceRootPath.Buffer,
+                             CompleteOrigDirName,
+                             FileKeyName,
+                             NULL,
+                             SourceCabinet,
+                             NULL,
+                             FileDstPath,
+                             TargetFileName,
+                             0 /* FIXME */))
+        {
+            /* FIXME: Handle error! */
+            DPRINT1("SpFileQueueCopy() failed\n");
+        }
+
+        INF_FreeData(FileKeyName);
+        INF_FreeData(TargetFileName);
+        INF_FreeData(DirKeyValue);
+    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
+
+    return TRUE;
+}
+
+BOOLEAN // ERROR_NUMBER
+PrepareCopyInfFile(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN HINF InfFile,
+    IN PCWSTR SourceCabinet OPTIONAL)
+{
+    NTSTATUS Status;
+    INFCONTEXT DirContext;
+    PWCHAR AdditionalSectionName = NULL;
+    PCWSTR DirKeyValue;
+    WCHAR PathBuffer[MAX_PATH];
+
+    /* Add common files */
+    if (!AddSectionToCopyQueue(pSetupData, InfFile, L"SourceDisksFiles", SourceCabinet, &pSetupData->DestinationPath))
+        return FALSE;
+
+    /* Add specific files depending of computer type */
+    if (SourceCabinet == NULL)
+    {
+        if (!ProcessComputerFiles(InfFile, pSetupData->ComputerList, &AdditionalSectionName))
+            return FALSE;
+
+        if (AdditionalSectionName)
+        {
+            if (!AddSectionToCopyQueue(pSetupData, InfFile, AdditionalSectionName, SourceCabinet, &pSetupData->DestinationPath))
+                return FALSE;
+        }
+    }
+
+    /* Create directories */
+
+    /*
+     * FIXME:
+     * Copying files to pSetupData->DestinationRootPath should be done from within
+     * the SystemPartitionFiles section.
+     * At the moment we check whether we specify paths like '\foo' or '\\' for that.
+     * For installing to pSetupData->DestinationPath specify just '\' .
+     */
+
+    /* Get destination path */
+    RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), pSetupData->DestinationPath.Buffer);
+
+    DPRINT("FullPath(1): '%S'\n", PathBuffer);
+
+    /* Create the install directory */
+    Status = SetupCreateDirectory(PathBuffer);
+    if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+    {
+        DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
+        pSetupData->LastErrorNumber = ERROR_CREATE_INSTALL_DIR;
+        if (pSetupData->ErrorRoutine)
+            pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+        return FALSE;
+    }
+
+    /* Search for the 'Directories' section */
+    if (!SpInfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
+    {
+        if (SourceCabinet)
+            pSetupData->LastErrorNumber = ERROR_CABINET_SECTION;
+        else
+            pSetupData->LastErrorNumber = ERROR_TXTSETUP_SECTION;
+
+        if (pSetupData->ErrorRoutine)
+            pSetupData->ErrorRoutine(pSetupData, L"Directories");
+        return FALSE;
+    }
+
+    /* Enumerate the directory values and create the subdirectories */
+    do
+    {
+        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
+        {
+            DPRINT1("break\n");
+            break;
+        }
+
+        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
+        {
+            /* Installation path */
+            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
+
+            RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
+                              pSetupData->DestinationPath.Buffer);
+
+            DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
+        }
+        else if (DirKeyValue[0] == L'\\')
+        {
+            /* Absolute path */
+            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
+
+            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                         pSetupData->DestinationRootPath.Buffer, DirKeyValue);
+
+            DPRINT("AbsolutePath(2): '%S'\n", PathBuffer);
+
+            Status = SetupCreateDirectory(PathBuffer);
+            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+            {
+                INF_FreeData(DirKeyValue);
+                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
+                pSetupData->LastErrorNumber = ERROR_CREATE_DIR;
+                if (pSetupData->ErrorRoutine)
+                    pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+                return FALSE;
+            }
+        }
+        else // if (DirKeyValue[0] != L'\\')
+        {
+            /* Path relative to the installation path */
+            DPRINT("RelativePath: '%S'\n", DirKeyValue);
+
+            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                         pSetupData->DestinationPath.Buffer, DirKeyValue);
+
+            DPRINT("RelativePath(2): '%S'\n", PathBuffer);
+
+            Status = SetupCreateDirectory(PathBuffer);
+            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
+            {
+                INF_FreeData(DirKeyValue);
+                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
+                pSetupData->LastErrorNumber = ERROR_CREATE_DIR;
+                if (pSetupData->ErrorRoutine)
+                    pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+                return FALSE;
+            }
+        }
+
+        INF_FreeData(DirKeyValue);
+    } while (SpInfFindNextLine(&DirContext, &DirContext));
+
+    return TRUE;
+}
+
+
+// #define USE_CABINET_INF
+
+BOOLEAN // ERROR_NUMBER
+PrepareFileCopy(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL)
+{
+    HINF InfHandle;
+    INFCONTEXT CabinetsContext;
+    PCWSTR CabinetName;
+    UINT ErrorLine;
+#if defined(__REACTOS__) && defined(USE_CABINET_INF)
+    ULONG InfFileSize;
+    PVOID InfFileData;
+    CABINET_CONTEXT CabinetContext;
+#endif
+    WCHAR PathBuffer[MAX_PATH];
+
+    /* Create the file queue */
+    pSetupData->SetupFileQueue = (PVOID)SpFileQueueOpen();
+    if (pSetupData->SetupFileQueue == NULL)
+    {
+        pSetupData->LastErrorNumber = ERROR_COPY_QUEUE;
+        if (pSetupData->ErrorRoutine)
+            pSetupData->ErrorRoutine(pSetupData);
+        return FALSE;
+    }
+
+    /* Prepare the copy of the common files that are not in installation cabinets */
+    if (!PrepareCopyInfFile(pSetupData, pSetupData->SetupInf, NULL))
+    {
+        /* FIXME: show an error dialog */
+        return FALSE;
+    }
+
+    /* Search for the 'Cabinets' section */
+    if (!SpInfFindFirstLine(pSetupData->SetupInf, L"Cabinets", NULL, &CabinetsContext))
+    {
+        /* Skip this step and return success if no cabinet file is listed */
+        return TRUE;
+    }
+
+    /*
+     * Enumerate the installation cabinets listed in the
+     * 'Cabinets' section and parse their inf files.
+     */
+    do
+    {
+        if (!INF_GetData(&CabinetsContext, NULL, &CabinetName))
+            break;
+
+        CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                     pSetupData->SourcePath.Buffer, CabinetName);
+
+#if defined(__REACTOS__) && defined(USE_CABINET_INF)
+        INF_FreeData(CabinetName);
+
+        CabinetInitialize(&CabinetContext);
+        CabinetSetEventHandlers(&CabinetContext, NULL, NULL, NULL);
+        CabinetSetCabinetName(&CabinetContext, PathBuffer);
+
+        if (CabinetOpen(&CabinetContext) == CAB_STATUS_SUCCESS)
+        {
+            DPRINT("Cabinet %S\n", PathBuffer);
+
+            InfFileData = CabinetGetCabinetReservedArea(&CabinetContext, &InfFileSize);
+            if (InfFileData == NULL)
+            {
+                CabinetCleanup(&CabinetContext);
+
+                pSetupData->LastErrorNumber = ERROR_CABINET_SCRIPT;
+                if (pSetupData->ErrorRoutine)
+                    pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+                return FALSE;
+            }
+        }
+        else
+        {
+            DPRINT("Cannot open cabinet: %S.\n", PathBuffer);
+            CabinetCleanup(&CabinetContext);
+
+            pSetupData->LastErrorNumber = ERROR_CABINET_MISSING;
+            if (pSetupData->ErrorRoutine)
+                pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+            return FALSE;
+        }
+
+        InfHandle = INF_OpenBufferedFileA((PSTR)InfFileData,
+                                          InfFileSize,
+                                          NULL,
+                                          INF_STYLE_WIN4,
+                                          pSetupData->LanguageId,
+                                          &ErrorLine);
+
+        CabinetCleanup(&CabinetContext);
+#else
+        {
+        PWCHAR ptr;
+
+        /* First find the filename */
+        ptr = wcsrchr(PathBuffer, L'\\');
+        if (!ptr) ptr = PathBuffer;
+
+        /* Then find its extension */
+        ptr = wcsrchr(ptr, L'.');
+        if (!ptr)
+            ptr = PathBuffer + wcslen(PathBuffer);
+
+        /* Replace it by '.inf' */
+        wcscpy(ptr, L".inf");
+
+        InfHandle = SpInfOpenInfFile(PathBuffer,
+                                     NULL,
+                                     INF_STYLE_OLDNT, // INF_STYLE_WIN4,
+                                     pSetupData->LanguageId,
+                                     &ErrorLine);
+        }
+#endif
+
+        if (InfHandle == INVALID_HANDLE_VALUE)
+        {
+            pSetupData->LastErrorNumber = ERROR_INVALID_CABINET_INF;
+            if (pSetupData->ErrorRoutine)
+                pSetupData->ErrorRoutine(pSetupData, PathBuffer);
+            return FALSE;
+        }
+
+        if (!PrepareCopyInfFile(pSetupData, InfHandle, CabinetName))
+        {
+#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
+            SpInfCloseInfFile(InfHandle);
+#endif
+            /* FIXME: show an error dialog */
+            return FALSE;
+        }
+
+#if !(defined(__REACTOS__) && defined(USE_CABINET_INF))
+        SpInfCloseInfFile(InfHandle);
+#endif
+    } while (SpInfFindNextLine(&CabinetsContext, &CabinetsContext));
+
+    return TRUE;
+}
+
+BOOLEAN
+DoFileCopy(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN PSP_FILE_CALLBACK_W MsgHandler,
+    IN PVOID Context OPTIONAL)
+{
+    BOOLEAN Success;
+
+    Success = SpFileQueueCommit(NULL,
+                                (HSPFILEQ)pSetupData->SetupFileQueue,
+                                MsgHandler,
+                                Context);
+
+    SpFileQueueClose((HSPFILEQ)pSetupData->SetupFileQueue);
+    pSetupData->SetupFileQueue = NULL;
+
+    return Success;
+}
+
+/* EOF */
diff --git a/base/setup/lib/install.h b/base/setup/lib/install.h
new file mode 100644 (file)
index 0000000..8c3e84b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Setup Library
+ * FILE:            base/setup/lib/install.c
+ * PURPOSE:         Installation functions
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
+ */
+
+#pragma once
+
+typedef enum _FILE_COPY_STATUS
+{
+    None = 0,
+    // Success = 0,
+} FILE_COPY_STATUS;
+
+typedef VOID
+(__cdecl *PFILE_COPY_STATUS_ROUTINE)(IN FILE_COPY_STATUS, ...);
+
+#if 0
+BOOLEAN // ERROR_NUMBER
+PrepareCopyInfFile(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN HINF InfFile,
+    IN PCWSTR SourceCabinet OPTIONAL);
+#endif
+
+BOOLEAN // ERROR_NUMBER
+PrepareFileCopy(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN PFILE_COPY_STATUS_ROUTINE StatusRoutine OPTIONAL);
+
+BOOLEAN
+DoFileCopy(
+    IN OUT PUSETUP_DATA pSetupData,
+    IN PSP_FILE_CALLBACK_W MsgHandler,
+    IN PVOID Context OPTIONAL);
+
+/* EOF */
index 837633a..4bd5981 100644 (file)
@@ -44,6 +44,8 @@ extern HANDLE ProcessHeap;
 #include "mui.h"
 #include "settings.h"
 
+// #include "install.h" // See at the end...
+
 
 /* DEFINES ******************************************************************/
 
@@ -124,6 +126,10 @@ typedef struct _USETUP_DATA
     WCHAR InstallationDirectory[MAX_PATH];
 } USETUP_DATA, *PUSETUP_DATA;
 
+
+#include "install.h"
+
+
 // HACK!!
 extern BOOLEAN IsUnattendedSetup;
 
index 4dbf388..5181949 100644 (file)
@@ -69,19 +69,6 @@ static PNTOS_INSTALLATION CurrentInstallation = NULL;
 static PGENERIC_LIST NtOsInstallsList = NULL;
 
 
-// HACK: Temporary compatibility code.
-#if 1
-    static CABINET_CONTEXT CabinetContext;
-    #define CabinetInitialize() (CabinetInitialize(&CabinetContext))
-    #define CabinetSetEventHandlers(a,b,c) (CabinetSetEventHandlers(&CabinetContext,(a),(b),(c)))
-    #define CabinetSetCabinetName(a) (CabinetSetCabinetName(&CabinetContext,(a)))
-    #define CabinetOpen() (CabinetOpen(&CabinetContext))
-    #define CabinetGetCabinetName() (CabinetGetCabinetName(&CabinetContext))
-    #define CabinetGetCabinetReservedArea(a) (CabinetGetCabinetReservedArea(&CabinetContext,(a)))
-    #define CabinetCleanup() (CabinetCleanup(&CabinetContext))
-#endif
-
-
 /* FUNCTIONS ****************************************************************/
 
 static VOID
@@ -3503,434 +3490,6 @@ USetupErrorRoutine(
     va_end(arg_ptr);
 }
 
-
-static BOOLEAN
-AddSectionToCopyQueueCab(HINF InfFile,
-                         PCWSTR SectionName,
-                         PCWSTR SourceCabinet,
-                         PCUNICODE_STRING DestinationPath,
-                         PINPUT_RECORD Ir)
-{
-    INFCONTEXT FilesContext;
-    INFCONTEXT DirContext;
-    PCWSTR FileKeyName;
-    PCWSTR FileKeyValue;
-    PCWSTR DirKeyValue;
-    PCWSTR TargetFileName;
-    WCHAR FileDstPath[MAX_PATH];
-
-    /*
-     * This code enumerates the list of files in reactos.dff / reactos.inf
-     * that need to be extracted from reactos.cab and be installed in their
-     * respective directories.
-     */
-
-    /* Search for the SectionName section */
-    if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
-    {
-        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
-        return FALSE;
-    }
-
-    /*
-     * Enumerate the files in the section and add them to the file queue.
-     */
-    do
-    {
-        /* Get source file name and target directory id */
-        if (!INF_GetData(&FilesContext, &FileKeyName, &FileKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            break;
-        }
-
-        /* Get optional target file name */
-        if (!INF_GetDataField(&FilesContext, 2, &TargetFileName))
-            TargetFileName = NULL;
-
-        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
-
-        /* Lookup target directory */
-        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SetupFindFirstLine() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(FileKeyValue);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        INF_FreeData(FileKeyValue);
-
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-#if 1 // HACK moved! (r66604)
-        {
-        ULONG Length = wcslen(DirKeyValue);
-        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
-            Length--;
-        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
-        }
-
-        /* Build the full target path */
-        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
-                          USetupData.DestinationRootPath.Buffer);
-        if (DirKeyValue[0] == UNICODE_NULL)
-        {
-            /* Installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            // if (DirKeyValue[1] != UNICODE_NULL)
-                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
-                        USetupData.InstallPath.Buffer, DirKeyValue);
-        }
-#endif
-
-        if (!SpFileQueueCopy((HSPFILEQ)USetupData.SetupFileQueue,
-                             USetupData.SourceRootPath.Buffer,
-                             USetupData.SourceRootDir.Buffer,
-                             FileKeyName,
-                             NULL,
-                             SourceCabinet,
-                             NULL,
-                             FileDstPath,
-                             TargetFileName,
-                             0 /* FIXME */))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SpFileQueueCopy() failed\n");
-        }
-
-        INF_FreeData(FileKeyName);
-        INF_FreeData(TargetFileName);
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
-
-    return TRUE;
-}
-
-
-static BOOLEAN
-AddSectionToCopyQueue(HINF InfFile,
-                      PCWSTR SectionName,
-                      PCWSTR SourceCabinet,
-                      PCUNICODE_STRING DestinationPath,
-                      PINPUT_RECORD Ir)
-{
-    INFCONTEXT FilesContext;
-    INFCONTEXT DirContext;
-    PCWSTR FileKeyName;
-    PCWSTR FileKeyValue;
-    PCWSTR DirKeyValue;
-    PCWSTR TargetFileName;
-    WCHAR CompleteOrigDirName[512]; // FIXME: MAX_PATH is not enough?
-    WCHAR FileDstPath[MAX_PATH];
-
-    if (SourceCabinet)
-        return AddSectionToCopyQueueCab(InfFile, L"SourceFiles", SourceCabinet, DestinationPath, Ir);
-
-    /*
-     * This code enumerates the list of files in txtsetup.sif
-     * that need to be installed in their respective directories.
-     */
-
-    /* Search for the SectionName section */
-    if (!SpInfFindFirstLine(InfFile, SectionName, NULL, &FilesContext))
-    {
-        MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, SectionName);
-        return FALSE;
-    }
-
-    /*
-     * Enumerate the files in the section and add them to the file queue.
-     */
-    do
-    {
-        /* Get source file name */
-        if (!INF_GetDataField(&FilesContext, 0, &FileKeyName))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            break;
-        }
-
-        /* Get target directory id */
-        if (!INF_GetDataField(&FilesContext, 13, &FileKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            break;
-        }
-
-        /* Get optional target file name */
-        if (!INF_GetDataField(&FilesContext, 11, &TargetFileName))
-            TargetFileName = NULL;
-        else if (!*TargetFileName)
-            TargetFileName = NULL;
-
-        DPRINT("FileKeyName: '%S'  FileKeyValue: '%S'\n", FileKeyName, FileKeyValue);
-
-        /* Lookup target directory */
-        if (!SpInfFindFirstLine(InfFile, L"Directories", FileKeyValue, &DirContext))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SetupFindFirstLine() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(FileKeyValue);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        INF_FreeData(FileKeyValue);
-
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("INF_GetData() failed\n");
-            INF_FreeData(FileKeyName);
-            INF_FreeData(TargetFileName);
-            break;
-        }
-
-        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
-        {
-            /* Installation path */
-            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                              USetupData.SourceRootDir.Buffer);
-
-            DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                              DirKeyValue);
-
-            DPRINT("AbsolutePath(2): '%S'\n", CompleteOrigDirName);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-            DPRINT("RelativePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 2,
-                         USetupData.SourceRootDir.Buffer, DirKeyValue);
-
-            DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName);
-        }
-
-#if 1 // HACK moved! (r66604)
-        {
-        ULONG Length = wcslen(DirKeyValue);
-        if ((Length > 0) && (DirKeyValue[Length - 1] == L'\\'))
-            Length--;
-        *((PWSTR)DirKeyValue + Length) = UNICODE_NULL;
-        }
-
-        /* Build the full target path */
-        RtlStringCchCopyW(FileDstPath, ARRAYSIZE(FileDstPath),
-                          USetupData.DestinationRootPath.Buffer);
-        if (DirKeyValue[0] == UNICODE_NULL)
-        {
-            /* Installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, USetupData.InstallPath.Buffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            // if (DirKeyValue[1] != UNICODE_NULL)
-                ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 1, DirKeyValue);
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-
-            /* Add the installation path */
-            ConcatPaths(FileDstPath, ARRAYSIZE(FileDstPath), 2,
-                        USetupData.InstallPath.Buffer, DirKeyValue);
-        }
-#endif
-
-        if (!SpFileQueueCopy((HSPFILEQ)USetupData.SetupFileQueue,
-                             USetupData.SourceRootPath.Buffer,
-                             CompleteOrigDirName,
-                             FileKeyName,
-                             NULL,
-                             SourceCabinet,
-                             NULL,
-                             FileDstPath,
-                             TargetFileName,
-                             0 /* FIXME */))
-        {
-            /* FIXME: Handle error! */
-            DPRINT1("SpFileQueueCopy() failed\n");
-        }
-
-        INF_FreeData(FileKeyName);
-        INF_FreeData(TargetFileName);
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&FilesContext, &FilesContext));
-
-    return TRUE;
-}
-
-
-static BOOLEAN
-PrepareCopyPageInfFile(HINF InfFile,
-                       PCWSTR SourceCabinet,
-                       PINPUT_RECORD Ir)
-{
-    NTSTATUS Status;
-    INFCONTEXT DirContext;
-    PWCHAR AdditionalSectionName = NULL;
-    PCWSTR DirKeyValue;
-    WCHAR PathBuffer[MAX_PATH];
-
-    /* Add common files */
-    if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, &USetupData.DestinationPath, Ir))
-        return FALSE;
-
-    /* Add specific files depending of computer type */
-    if (SourceCabinet == NULL)
-    {
-        if (!ProcessComputerFiles(InfFile, USetupData.ComputerList, &AdditionalSectionName))
-            return FALSE;
-
-        if (AdditionalSectionName)
-        {
-            if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, SourceCabinet, &USetupData.DestinationPath, Ir))
-                return FALSE;
-        }
-    }
-
-    /* Create directories */
-
-    /*
-     * FIXME:
-     * Copying files to USetupData.DestinationRootPath should be done from within
-     * the SystemPartitionFiles section.
-     * At the moment we check whether we specify paths like '\foo' or '\\' for that.
-     * For installing to USetupData.DestinationPath specify just '\' .
-     */
-
-    /* Get destination path */
-    RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), USetupData.DestinationPath.Buffer);
-
-    DPRINT("FullPath(1): '%S'\n", PathBuffer);
-
-    /* Create the install directory */
-    Status = SetupCreateDirectory(PathBuffer);
-    if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
-    {
-        DPRINT1("Creating directory '%S' failed: Status = 0x%08lx\n", PathBuffer, Status);
-        MUIDisplayError(ERROR_CREATE_INSTALL_DIR, Ir, POPUP_WAIT_ENTER);
-        return FALSE;
-    }
-
-    /* Search for the 'Directories' section */
-    if (!SpInfFindFirstLine(InfFile, L"Directories", NULL, &DirContext))
-    {
-        if (SourceCabinet)
-            MUIDisplayError(ERROR_CABINET_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
-        else
-            MUIDisplayError(ERROR_TXTSETUP_SECTION, Ir, POPUP_WAIT_ENTER, L"Directories");
-
-        return FALSE;
-    }
-
-    /* Enumerate the directory values and create the subdirectories */
-    do
-    {
-        if (!INF_GetData(&DirContext, NULL, &DirKeyValue))
-        {
-            DPRINT1("break\n");
-            break;
-        }
-
-        if ((DirKeyValue[0] == UNICODE_NULL) || (DirKeyValue[0] == L'\\' && DirKeyValue[1] == UNICODE_NULL))
-        {
-            /* Installation path */
-            DPRINT("InstallationPath: '%S'\n", DirKeyValue);
-
-            RtlStringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
-                              USetupData.DestinationPath.Buffer);
-
-            DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
-        }
-        else if (DirKeyValue[0] == L'\\')
-        {
-            /* Absolute path */
-            DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         USetupData.DestinationRootPath.Buffer, DirKeyValue);
-
-            DPRINT("AbsolutePath(2): '%S'\n", PathBuffer);
-
-            Status = SetupCreateDirectory(PathBuffer);
-            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
-            {
-                INF_FreeData(DirKeyValue);
-                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
-                MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
-                return FALSE;
-            }
-        }
-        else // if (DirKeyValue[0] != L'\\')
-        {
-            /* Path relative to the installation path */
-            DPRINT("RelativePath: '%S'\n", DirKeyValue);
-
-            CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         USetupData.DestinationPath.Buffer, DirKeyValue);
-
-            DPRINT("RelativePath(2): '%S'\n", PathBuffer);
-
-            Status = SetupCreateDirectory(PathBuffer);
-            if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_COLLISION)
-            {
-                INF_FreeData(DirKeyValue);
-                DPRINT("Creating directory '%S' failed: Status = 0x%08lx", PathBuffer, Status);
-                MUIDisplayError(ERROR_CREATE_DIR, Ir, POPUP_WAIT_ENTER);
-                return FALSE;
-            }
-        }
-
-        INF_FreeData(DirKeyValue);
-    } while (SpInfFindNextLine(&DirContext, &DirContext));
-
-    return TRUE;
-}
-
-
 /*
  * Displays the PrepareCopyPage.
  *
@@ -3939,8 +3498,7 @@ PrepareCopyPageInfFile(HINF InfFile,
  *  QuitPage
  *
  * SIDEEFFECTS
- * Inits SetupFileQueue
- * Calls PrepareCopyPageInfFile
+ * Calls PrepareFileCopy
  *
  * RETURNS
  *   Number of the next page.
@@ -3948,92 +3506,18 @@ PrepareCopyPageInfFile(HINF InfFile,
 static PAGE_NUMBER
 PrepareCopyPage(PINPUT_RECORD Ir)
 {
-    HINF InfHandle;
-    WCHAR PathBuffer[MAX_PATH];
-    INFCONTEXT CabinetsContext;
-    ULONG InfFileSize;
-    PCWSTR KeyValue;
-    UINT ErrorLine;
-    PVOID InfFileData;
+    // ERROR_NUMBER ErrorNumber;
+    BOOLEAN Success;
 
     MUIDisplayPage(PREPARE_COPY_PAGE);
 
-    /* Create the file queue */
-    USetupData.SetupFileQueue = SpFileQueueOpen();
-    if (USetupData.SetupFileQueue == NULL)
-    {
-        MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    if (!PrepareCopyPageInfFile(USetupData.SetupInf, NULL, Ir))
+    /* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
+    if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
     {
-        /* FIXME: show an error dialog */
+        // MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
 
-    /* Search for the 'Cabinets' section */
-    if (!SpInfFindFirstLine(USetupData.SetupInf, L"Cabinets", NULL, &CabinetsContext))
-    {
-        return FILE_COPY_PAGE;
-    }
-
-    /*
-     * Enumerate the directory values in the 'Cabinets'
-     * section and parse their inf files.
-     */
-    do
-    {
-        if (!INF_GetData(&CabinetsContext, NULL, &KeyValue))
-            break;
-
-        CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                     USetupData.SourcePath.Buffer, KeyValue);
-
-        CabinetInitialize();
-        CabinetSetEventHandlers(NULL, NULL, NULL);
-        CabinetSetCabinetName(PathBuffer);
-
-        if (CabinetOpen() == CAB_STATUS_SUCCESS)
-        {
-            DPRINT("Cabinet %S\n", CabinetGetCabinetName());
-
-            InfFileData = CabinetGetCabinetReservedArea(&InfFileSize);
-            if (InfFileData == NULL)
-            {
-                MUIDisplayError(ERROR_CABINET_SCRIPT, Ir, POPUP_WAIT_ENTER);
-                return QUIT_PAGE;
-            }
-        }
-        else
-        {
-            DPRINT("Cannot open cabinet: %S.\n", CabinetGetCabinetName());
-            MUIDisplayError(ERROR_CABINET_MISSING, Ir, POPUP_WAIT_ENTER);
-            return QUIT_PAGE;
-        }
-
-        InfHandle = INF_OpenBufferedFileA((PSTR)InfFileData,
-                                          InfFileSize,
-                                          NULL,
-                                          INF_STYLE_WIN4,
-                                          USetupData.LanguageId,
-                                          &ErrorLine);
-
-        if (InfHandle == INVALID_HANDLE_VALUE)
-        {
-            MUIDisplayError(ERROR_INVALID_CABINET_INF, Ir, POPUP_WAIT_ENTER);
-            return QUIT_PAGE;
-        }
-
-        CabinetCleanup();
-
-        if (!PrepareCopyPageInfFile(InfHandle, KeyValue, Ir))
-        {
-            /* FIXME: show an error dialog */
-            return QUIT_PAGE;
-        }
-    } while (SpInfFindNextLine(&CabinetsContext, &CabinetsContext));
-
     return FILE_COPY_PAGE;
 }
 
@@ -4188,8 +3672,7 @@ FileCopyCallback(PVOID Context,
  *  RegistryPage(At once)
  *
  * SIDEEFFECTS
- *  Calls SetupCommitFileQueueW
- *  Calls SpFileQueueClose
+ *  Calls DoFileCopy
  *
  * RETURNS
  *   Number of the next page.
@@ -4251,13 +3734,9 @@ FileCopyPage(PINPUT_RECORD Ir)
                                                   "Free Memory");
 
     /* Do the file copying */
-    SpFileQueueCommit(NULL,
-                      USetupData.SetupFileQueue,
-                      FileCopyCallback,
-                      &CopyContext);
+    DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
 
-    /* If we get here, we're done, so cleanup the queue and progress bar */
-    SpFileQueueClose(USetupData.SetupFileQueue);
+    /* If we get here, we're done, so cleanup the progress bar */
     DestroyProgressBar(CopyContext.ProgressBar);
     DestroyProgressBar(CopyContext.MemoryBars[0]);
     DestroyProgressBar(CopyContext.MemoryBars[1]);