From 3d137b05d16dfbd8a2c93e6485d28374acd3aeee Mon Sep 17 00:00:00 2001 From: =?utf8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 7 Jan 2018 01:35:48 +0100 Subject: [PATCH] [SETUPLIB][USETUP] Move all the code that performs file copying into the SETUPLIB. --- base/setup/lib/CMakeLists.txt | 1 + base/setup/lib/install.c | 643 ++++++++++++++++++++++++++++++++++ base/setup/lib/install.h | 40 +++ base/setup/lib/setuplib.h | 6 + base/setup/usetup/usetup.c | 539 +--------------------------- 5 files changed, 699 insertions(+), 530 deletions(-) create mode 100644 base/setup/lib/install.c create mode 100644 base/setup/lib/install.h diff --git a/base/setup/lib/CMakeLists.txt b/base/setup/lib/CMakeLists.txt index 7c23e240451..0d2f3a8aeb5 100644 --- a/base/setup/lib/CMakeLists.txt +++ b/base/setup/lib/CMakeLists.txt @@ -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 index 00000000000..31ece47b0d0 --- /dev/null +++ b/base/setup/lib/install.c @@ -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 + + +/* 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 index 00000000000..8c3e84b3257 --- /dev/null +++ b/base/setup/lib/install.h @@ -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 */ diff --git a/base/setup/lib/setuplib.h b/base/setup/lib/setuplib.h index 837633a7e7c..4bd5981ff24 100644 --- a/base/setup/lib/setuplib.h +++ b/base/setup/lib/setuplib.h @@ -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; diff --git a/base/setup/usetup/usetup.c b/base/setup/usetup/usetup.c index 4dbf3885c32..518194937f9 100644 --- a/base/setup/usetup/usetup.c +++ b/base/setup/usetup/usetup.c @@ -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]); -- 2.17.1