mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 01:05:42 +00:00
[SETUPLIB][USETUP] Move all the code that performs file copying into the SETUPLIB.
This commit is contained in:
parent
f894631472
commit
3d137b05d1
5 changed files with 699 additions and 530 deletions
|
@ -17,6 +17,7 @@ list(APPEND SOURCE
|
||||||
utils/regutil.c
|
utils/regutil.c
|
||||||
bootsup.c
|
bootsup.c
|
||||||
fsutil.c
|
fsutil.c
|
||||||
|
install.c
|
||||||
mui.c
|
mui.c
|
||||||
registry.c
|
registry.c
|
||||||
settings.c
|
settings.c
|
||||||
|
|
643
base/setup/lib/install.c
Normal file
643
base/setup/lib/install.c
Normal file
|
@ -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 */
|
40
base/setup/lib/install.h
Normal file
40
base/setup/lib/install.h
Normal file
|
@ -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 */
|
|
@ -44,6 +44,8 @@ extern HANDLE ProcessHeap;
|
||||||
#include "mui.h"
|
#include "mui.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
// #include "install.h" // See at the end...
|
||||||
|
|
||||||
|
|
||||||
/* DEFINES ******************************************************************/
|
/* DEFINES ******************************************************************/
|
||||||
|
|
||||||
|
@ -124,6 +126,10 @@ typedef struct _USETUP_DATA
|
||||||
WCHAR InstallationDirectory[MAX_PATH];
|
WCHAR InstallationDirectory[MAX_PATH];
|
||||||
} USETUP_DATA, *PUSETUP_DATA;
|
} USETUP_DATA, *PUSETUP_DATA;
|
||||||
|
|
||||||
|
|
||||||
|
#include "install.h"
|
||||||
|
|
||||||
|
|
||||||
// HACK!!
|
// HACK!!
|
||||||
extern BOOLEAN IsUnattendedSetup;
|
extern BOOLEAN IsUnattendedSetup;
|
||||||
|
|
||||||
|
|
|
@ -69,19 +69,6 @@ static PNTOS_INSTALLATION CurrentInstallation = NULL;
|
||||||
static PGENERIC_LIST NtOsInstallsList = 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 ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
|
@ -3503,434 +3490,6 @@ USetupErrorRoutine(
|
||||||
va_end(arg_ptr);
|
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.
|
* Displays the PrepareCopyPage.
|
||||||
*
|
*
|
||||||
|
@ -3939,8 +3498,7 @@ PrepareCopyPageInfFile(HINF InfFile,
|
||||||
* QuitPage
|
* QuitPage
|
||||||
*
|
*
|
||||||
* SIDEEFFECTS
|
* SIDEEFFECTS
|
||||||
* Inits SetupFileQueue
|
* Calls PrepareFileCopy
|
||||||
* Calls PrepareCopyPageInfFile
|
|
||||||
*
|
*
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* Number of the next page.
|
* Number of the next page.
|
||||||
|
@ -3948,92 +3506,18 @@ PrepareCopyPageInfFile(HINF InfFile,
|
||||||
static PAGE_NUMBER
|
static PAGE_NUMBER
|
||||||
PrepareCopyPage(PINPUT_RECORD Ir)
|
PrepareCopyPage(PINPUT_RECORD Ir)
|
||||||
{
|
{
|
||||||
HINF InfHandle;
|
// ERROR_NUMBER ErrorNumber;
|
||||||
WCHAR PathBuffer[MAX_PATH];
|
BOOLEAN Success;
|
||||||
INFCONTEXT CabinetsContext;
|
|
||||||
ULONG InfFileSize;
|
|
||||||
PCWSTR KeyValue;
|
|
||||||
UINT ErrorLine;
|
|
||||||
PVOID InfFileData;
|
|
||||||
|
|
||||||
MUIDisplayPage(PREPARE_COPY_PAGE);
|
MUIDisplayPage(PREPARE_COPY_PAGE);
|
||||||
|
|
||||||
/* Create the file queue */
|
/* ErrorNumber = */ Success = PrepareFileCopy(&USetupData, NULL);
|
||||||
USetupData.SetupFileQueue = SpFileQueueOpen();
|
if (/*ErrorNumber != ERROR_SUCCESS*/ !Success)
|
||||||
if (USetupData.SetupFileQueue == NULL)
|
|
||||||
{
|
{
|
||||||
MUIDisplayError(ERROR_COPY_QUEUE, Ir, POPUP_WAIT_ENTER);
|
// MUIDisplayError(ErrorNumber, Ir, POPUP_WAIT_ENTER);
|
||||||
return QUIT_PAGE;
|
return QUIT_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PrepareCopyPageInfFile(USetupData.SetupInf, NULL, Ir))
|
|
||||||
{
|
|
||||||
/* FIXME: show an error dialog */
|
|
||||||
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;
|
return FILE_COPY_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4188,8 +3672,7 @@ FileCopyCallback(PVOID Context,
|
||||||
* RegistryPage(At once)
|
* RegistryPage(At once)
|
||||||
*
|
*
|
||||||
* SIDEEFFECTS
|
* SIDEEFFECTS
|
||||||
* Calls SetupCommitFileQueueW
|
* Calls DoFileCopy
|
||||||
* Calls SpFileQueueClose
|
|
||||||
*
|
*
|
||||||
* RETURNS
|
* RETURNS
|
||||||
* Number of the next page.
|
* Number of the next page.
|
||||||
|
@ -4251,13 +3734,9 @@ FileCopyPage(PINPUT_RECORD Ir)
|
||||||
"Free Memory");
|
"Free Memory");
|
||||||
|
|
||||||
/* Do the file copying */
|
/* Do the file copying */
|
||||||
SpFileQueueCommit(NULL,
|
DoFileCopy(&USetupData, FileCopyCallback, &CopyContext);
|
||||||
USetupData.SetupFileQueue,
|
|
||||||
FileCopyCallback,
|
|
||||||
&CopyContext);
|
|
||||||
|
|
||||||
/* If we get here, we're done, so cleanup the queue and progress bar */
|
/* If we get here, we're done, so cleanup the progress bar */
|
||||||
SpFileQueueClose(USetupData.SetupFileQueue);
|
|
||||||
DestroyProgressBar(CopyContext.ProgressBar);
|
DestroyProgressBar(CopyContext.ProgressBar);
|
||||||
DestroyProgressBar(CopyContext.MemoryBars[0]);
|
DestroyProgressBar(CopyContext.MemoryBars[0]);
|
||||||
DestroyProgressBar(CopyContext.MemoryBars[1]);
|
DestroyProgressBar(CopyContext.MemoryBars[1]);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue