Author: hbelusca
Date: Wed Aug  9 20:39:45 2017
New Revision: 75518

URL: http://svn.reactos.org/svn/reactos?rev=75518&view=rev
Log:
[USETUP][SETUPLIB]: Code refactoring:
- Move several global setup variables into a structure "USETUP_DATA", similar 
to the syssetup structure "SETUPDATA"
  (or the WIP 1st-stage installer structure of the same name), so that these 
variables can be set easily by different helper setup functions;
- Move CheckUnattendedSetup() and GetSourcePaths() to setuplib and make 
CheckUnattendedSetup() use the USETUP_DATA structure;
- Add a LoadSetupInf() function that loads the txtsetup.sif file (factoring out 
the corresponding code in usetup);
- Add a InstallSetupInfFile() function (that I'll certainly rename later on) 
whose purpose is to create a valid "$winnt$.inf" setup installation file
  in the ReactOS\system32 directory, which should help the 2nd-stage installer 
to correctly retrieve the source installation media we used during 1st-stage,
  and contain the unattended setup lines copied from unattend.inf. This is done 
in a Windows-compatible way.
- Add the lib/infsupp.c and lib/setuplib.c to compilation.

Added:
    branches/setup_improvements/base/setup/lib/setuplib.c   (with props)
Modified:
    branches/setup_improvements/base/setup/lib/CMakeLists.txt
    branches/setup_improvements/base/setup/lib/setuplib.h
    branches/setup_improvements/base/setup/usetup/interface/usetup.c

Modified: branches/setup_improvements/base/setup/lib/CMakeLists.txt
URL: 
http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/lib/CMakeLists.txt?rev=75518&r1=75517&r2=75518&view=diff
==============================================================================
--- branches/setup_improvements/base/setup/lib/CMakeLists.txt   [iso-8859-1] 
(original)
+++ branches/setup_improvements/base/setup/lib/CMakeLists.txt   [iso-8859-1] 
Wed Aug  9 20:39:45 2017
@@ -5,12 +5,14 @@
     filesup.c
     fsutil.c
     genlist.c
+    infsupp.c
     inicache.c
     ntverrsrc.c
     osdetect.c
     partlist.c
     registry.c
     regutil.c
+    setuplib.c
     precomp.h)
 
 add_library(setuplib ${SOURCE})

Added: branches/setup_improvements/base/setup/lib/setuplib.c
URL: 
http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/lib/setuplib.c?rev=75518
==============================================================================
--- branches/setup_improvements/base/setup/lib/setuplib.c       (added)
+++ branches/setup_improvements/base/setup/lib/setuplib.c       [iso-8859-1] 
Wed Aug  9 20:39:45 2017
@@ -0,0 +1,512 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Setup Library
+ * FILE:            base/setup/lib/setuplib.c
+ * PURPOSE:         Setup Library - Main initialization helpers
+ * PROGRAMMERS:     Casper S. Hornstrup (cho...@users.sourceforge.net)
+ *                  Hermes Belusca-Maito (hermes.belu...@sfr.fr)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "precomp.h"
+#include "filesup.h"
+#include "infsupp.h"
+#include "inicache.h"
+
+#include "setuplib.h"
+
+#define NDEBUG
+#include <debug.h>
+
+
+/* GLOBALS ******************************************************************/
+
+/* FUNCTIONS ****************************************************************/
+
+VOID
+CheckUnattendedSetup(
+    IN OUT PUSETUP_DATA pSetupData)
+{
+    INFCONTEXT Context;
+    HINF UnattendInf;
+    UINT ErrorLine;
+    INT IntValue;
+    PWCHAR Value;
+    WCHAR UnattendInfPath[MAX_PATH];
+
+    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2,
+                 pSetupData->SourcePath.Buffer, L"unattend.inf");
+
+    if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
+    {
+        DPRINT("Does not exist: %S\n", UnattendInfPath);
+        return;
+    }
+
+    /* Load 'unattend.inf' from installation media */
+    UnattendInf = SetupOpenInfFileExW(UnattendInfPath,
+                                      NULL,
+                                      INF_STYLE_WIN4,
+                                      pSetupData->LanguageId,
+                                      &ErrorLine);
+
+    if (UnattendInf == INVALID_HANDLE_VALUE)
+    {
+        DPRINT("SetupOpenInfFileExW() failed\n");
+        return;
+    }
+
+    /* Open 'Unattend' section */
+    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
+    {
+        DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
+        goto Quit;
+    }
+
+    /* Get pointer 'Signature' key */
+    if (!INF_GetData(&Context, NULL, &Value))
+    {
+        DPRINT("INF_GetData() failed for key 'Signature'\n");
+        goto Quit;
+    }
+
+    /* Check 'Signature' string */
+    if (_wcsicmp(Value, L"$ReactOS$") != 0)
+    {
+        DPRINT("Signature not $ReactOS$\n");
+        INF_FreeData(Value);
+        goto Quit;
+    }
+
+    INF_FreeData(Value);
+
+    /* Check if Unattend setup is enabled */
+    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"UnattendSetupEnabled", &Context))
+    {
+        DPRINT("Can't find key 'UnattendSetupEnabled'\n");
+        goto Quit;
+    }
+
+    if (!INF_GetData(&Context, NULL, &Value))
+    {
+        DPRINT("Can't read key 'UnattendSetupEnabled'\n");
+        goto Quit;
+    }
+
+    if (_wcsicmp(Value, L"yes") != 0)
+    {
+        DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
+        INF_FreeData(Value);
+        goto Quit;
+    }
+
+    INF_FreeData(Value);
+
+    /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
+    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"DestinationDiskNumber", &Context))
+    {
+        DPRINT("SetupFindFirstLine() failed for key 
'DestinationDiskNumber'\n");
+        goto Quit;
+    }
+
+    if (!SetupGetIntField(&Context, 1, &IntValue))
+    {
+        DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
+        goto Quit;
+    }
+
+    pSetupData->DestinationDiskNumber = (LONG)IntValue;
+
+    /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
+    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"DestinationPartitionNumber", &Context))
+    {
+        DPRINT("SetupFindFirstLine() failed for key 
'DestinationPartitionNumber'\n");
+        goto Quit;
+    }
+
+    if (!SetupGetIntField(&Context, 1, &IntValue))
+    {
+        DPRINT("SetupGetIntField() failed for key 
'DestinationPartitionNumber'\n");
+        goto Quit;
+    }
+
+    pSetupData->DestinationPartitionNumber = (LONG)IntValue;
+
+    /* Search for 'InstallationDirectory' in the 'Unattend' section (optional) 
*/
+    if (SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"InstallationDirectory", &Context))
+    {
+        /* Get pointer 'InstallationDirectory' key */
+        if (!INF_GetData(&Context, NULL, &Value))
+        {
+            DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
+            goto Quit;
+        }
+        wcscpy(pSetupData->InstallationDirectory, Value);
+        INF_FreeData(Value);
+    }
+
+    IsUnattendedSetup = TRUE;
+    DPRINT("Running unattended setup\n");
+
+    /* Search for 'MBRInstallType' in the 'Unattend' section */
+    pSetupData->MBRInstallType = -1;
+    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", 
&Context))
+    {
+        if (SetupGetIntField(&Context, 1, &IntValue))
+        {
+            pSetupData->MBRInstallType = IntValue;
+        }
+    }
+
+    /* Search for 'FormatPartition' in the 'Unattend' section */
+    pSetupData->FormatPartition = 0;
+    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", 
&Context))
+    {
+        if (SetupGetIntField(&Context, 1, &IntValue))
+        {
+            pSetupData->FormatPartition = IntValue;
+        }
+    }
+
+    pSetupData->AutoPartition = 0;
+    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", 
&Context))
+    {
+        if (SetupGetIntField(&Context, 1, &IntValue))
+        {
+            pSetupData->AutoPartition = IntValue;
+        }
+    }
+
+    /* Search for LocaleID in the 'Unattend' section */
+    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"LocaleID", &Context))
+    {
+        if (INF_GetData(&Context, NULL, &Value))
+        {
+            LONG Id = wcstol(Value, NULL, 16);
+            swprintf(pSetupData->LocaleID, L"%08lx", Id);
+            INF_FreeData(Value);
+       }
+    }
+
+Quit:
+    SetupCloseInfFile(UnattendInf);
+}
+
+VOID
+InstallSetupInfFile(
+    IN OUT PUSETUP_DATA pSetupData)
+{
+    NTSTATUS Status;
+    PINICACHE IniCache;
+
+#if 0 // HACK FIXME!
+    PINICACHE UnattendCache;
+    PINICACHEITERATOR Iterator;
+#else
+    // PCWSTR CrLf = L"\r\n";
+    PCSTR CrLf = "\r\n";
+    HANDLE FileHandle, UnattendFileHandle, SectionHandle;
+    FILE_STANDARD_INFORMATION FileInfo;
+    ULONG FileSize;
+    PVOID ViewBase;
+    UNICODE_STRING FileName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+#endif
+
+    PINICACHESECTION IniSection;
+    WCHAR PathBuffer[MAX_PATH];
+    WCHAR UnattendInfPath[MAX_PATH];
+
+    /* Create a $winnt$.inf file with default entries */
+    IniCache = IniCacheCreate();
+    if (!IniCache)
+        return;
+
+    IniSection = IniCacheAppendSection(IniCache, L"SetupParams");
+    if (IniSection)
+    {
+        /* Key "skipmissingfiles" */
+        // StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         // L"\"%s\"", L"WinNt5.2");
+        // IniCacheInsertKey(IniSection, NULL, INSERT_LAST,
+                          // L"Version", PathBuffer);
+    }
+
+    IniSection = IniCacheAppendSection(IniCache, L"Data");
+    if (IniSection)
+    {
+        StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         L"\"%s\"", IsUnattendedSetup ? L"yes" : L"no");
+        IniCacheInsertKey(IniSection, NULL, INSERT_LAST,
+                          L"UnattendedInstall", PathBuffer);
+
+        // "floppylessbootpath" (yes/no)
+
+        StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         L"\"%s\"", L"winnt");
+        IniCacheInsertKey(IniSection, NULL, INSERT_LAST,
+                          L"ProductType", PathBuffer);
+
+        StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
+                         L"\"%s\\\"", pSetupData->SourceRootPath.Buffer);
+        IniCacheInsertKey(IniSection, NULL, INSERT_LAST,
+                          L"SourcePath", PathBuffer);
+
+        // "floppyless" ("0")
+    }
+
+#if 0
+
+    /* TODO: Append the standard unattend.inf file */
+    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2, 
pSetupData->SourcePath.Buffer, L"unattend.inf");
+    if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
+    {
+        DPRINT("Does not exist: %S\n", UnattendInfPath);
+        goto Quit;
+    }
+
+    Status = IniCacheLoad(&UnattendCache, UnattendInfPath, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Cannot load %S as an INI file!\n", UnattendInfPath);
+        goto Quit;
+    }
+
+    IniCacheDestroy(UnattendCache);
+
+Quit:
+    CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                 pSetupData->DestinationPath.Buffer, L"System32\\$winnt$.inf");
+    IniCacheSave(IniCache, PathBuffer);
+    IniCacheDestroy(IniCache);
+
+#else
+
+    CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
+                 pSetupData->DestinationPath.Buffer, L"System32\\$winnt$.inf");
+    IniCacheSave(IniCache, PathBuffer);
+    IniCacheDestroy(IniCache);
+
+    /* TODO: Append the standard unattend.inf file */
+    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2,
+                 pSetupData->SourcePath.Buffer, L"unattend.inf");
+    if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
+    {
+        DPRINT("Does not exist: %S\n", UnattendInfPath);
+        return;
+    }
+
+    RtlInitUnicodeString(&FileName, PathBuffer);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                               NULL,
+                               NULL);
+    Status = NtOpenFile(&FileHandle,
+                        FILE_APPEND_DATA | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT | 
FILE_NON_DIRECTORY_FILE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Cannot load %S as an INI file!\n", PathBuffer);
+        return;
+    }
+
+    /* Query the file size */
+    Status = NtQueryInformationFile(FileHandle,
+                                    &IoStatusBlock,
+                                    &FileInfo,
+                                    sizeof(FileInfo),
+                                    FileStandardInformation);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
+        FileInfo.EndOfFile.QuadPart = 0ULL;
+    }
+
+    Status = OpenAndMapFile(NULL,
+                            UnattendInfPath,
+                            &UnattendFileHandle,
+                            &SectionHandle,
+                            &ViewBase,
+                            &FileSize,
+                            FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Cannot load %S !\n", UnattendInfPath);
+        NtClose(FileHandle);
+        return;
+    }
+
+    /* Write to the INI file */
+
+    /* "\r\n" */
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         (PVOID)CrLf,
+                         2 * sizeof(CHAR), // 2 * sizeof(WCHAR),
+                         &FileInfo.EndOfFile,
+                         NULL);
+
+    Status = NtWriteFile(FileHandle,
+                         NULL,
+                         NULL,
+                         NULL,
+                         &IoStatusBlock,
+                         ViewBase,
+                         FileSize,
+                         NULL,
+                         NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
+    }
+
+    /* Finally, unmap and close the file */
+    UnMapFile(SectionHandle, ViewBase);
+    NtClose(UnattendFileHandle);
+
+    NtClose(FileHandle);
+#endif
+}
+
+
+
+NTSTATUS
+GetSourcePaths(
+    OUT PUNICODE_STRING SourcePath,
+    OUT PUNICODE_STRING SourceRootPath,
+    OUT PUNICODE_STRING SourceRootDir)
+{
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\SystemRoot");
+    UNICODE_STRING SourceName;
+    WCHAR SourceBuffer[MAX_PATH] = L"";
+    HANDLE Handle;
+    ULONG Length;
+    PWCHAR Ptr;
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = NtOpenSymbolicLinkObject(&Handle,
+                                      SYMBOLIC_LINK_ALL_ACCESS,
+                                      &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    RtlInitEmptyUnicodeString(&SourceName, SourceBuffer, sizeof(SourceBuffer));
+
+    Status = NtQuerySymbolicLinkObject(Handle,
+                                       &SourceName,
+                                       &Length);
+    NtClose(Handle);
+
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    RtlCreateUnicodeString(SourcePath,
+                           SourceName.Buffer);
+
+    /* Strip trailing directory */
+    Ptr = wcsrchr(SourceName.Buffer, OBJ_NAME_PATH_SEPARATOR);
+    if (Ptr)
+    {
+        RtlCreateUnicodeString(SourceRootDir, Ptr);
+        *Ptr = UNICODE_NULL;
+    }
+    else
+    {
+        RtlCreateUnicodeString(SourceRootDir, L"");
+    }
+
+    RtlCreateUnicodeString(SourceRootPath,
+                           SourceName.Buffer);
+
+    return STATUS_SUCCESS;
+}
+
+
+ERROR_NUMBER
+LoadSetupInf(
+    OUT HINF* SetupInf,
+    IN OUT PUSETUP_DATA pSetupData)
+{
+    INFCONTEXT Context;
+    UINT ErrorLine;
+    INT IntValue;
+    PWCHAR Value;
+    WCHAR FileNameBuffer[MAX_PATH];
+
+    CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2,
+                 pSetupData->SourcePath.Buffer, L"txtsetup.sif");
+
+    *SetupInf = SetupOpenInfFileExW(FileNameBuffer,
+                                   NULL,
+                                   INF_STYLE_WIN4,
+                                   pSetupData->LanguageId,
+                                   &ErrorLine);
+
+    if (*SetupInf == INVALID_HANDLE_VALUE)
+        return ERROR_LOAD_TXTSETUPSIF;
+
+    /* Open 'Version' section */
+    if (!SetupFindFirstLineW(*SetupInf, L"Version", L"Signature", &Context))
+        return ERROR_CORRUPT_TXTSETUPSIF;
+
+    /* Get pointer 'Signature' key */
+    if (!INF_GetData(&Context, NULL, &Value))
+        return ERROR_CORRUPT_TXTSETUPSIF;
+
+    /* Check 'Signature' string */
+    if (_wcsicmp(Value, L"$ReactOS$") != 0)
+    {
+        INF_FreeData(Value);
+        return ERROR_SIGNATURE_TXTSETUPSIF;
+    }
+
+    INF_FreeData(Value);
+
+    /* Open 'DiskSpaceRequirements' section */
+    if (!SetupFindFirstLineW(*SetupInf, L"DiskSpaceRequirements", 
L"FreeSysPartDiskSpace", &Context))
+        return ERROR_CORRUPT_TXTSETUPSIF;
+
+    pSetupData->RequiredPartitionDiskSpace = ~0;
+
+    /* Get the 'FreeSysPartDiskSpace' value */
+    if (!SetupGetIntField(&Context, 1, &IntValue))
+        return ERROR_CORRUPT_TXTSETUPSIF;
+
+    pSetupData->RequiredPartitionDiskSpace = (ULONG)IntValue;
+
+    //
+    // TODO: Support "SetupSourceDevice" and "SetupSourcePath" in txtsetup.sif
+    // See CORE-9023
+    //
+
+    /* Search for 'DefaultPath' in the 'SetupData' section */
+    if (SetupFindFirstLineW(*SetupInf, L"SetupData", L"DefaultPath", &Context))
+    {
+        /* Get pointer 'DefaultPath' key */
+        if (!INF_GetData(&Context, NULL, &Value))
+            return ERROR_CORRUPT_TXTSETUPSIF;
+
+        wcscpy(pSetupData->InstallationDirectory, Value);
+        INF_FreeData(Value);
+    }
+
+    return ERROR_SUCCESS;
+}
+
+/* EOF */

Propchange: branches/setup_improvements/base/setup/lib/setuplib.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: branches/setup_improvements/base/setup/lib/setuplib.h
URL: 
http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/lib/setuplib.h?rev=75518&r1=75517&r2=75518&view=diff
==============================================================================
--- branches/setup_improvements/base/setup/lib/setuplib.h       [iso-8859-1] 
(original)
+++ branches/setup_improvements/base/setup/lib/setuplib.h       [iso-8859-1] 
Wed Aug  9 20:39:45 2017
@@ -33,6 +33,7 @@
 #include "filesup.h"
 #include "fsutil.h"
 #include "genlist.h"
+#include "infsupp.h"
 #include "inicache.h"
 #include "partlist.h"
 #include "arcname.h"
@@ -50,4 +51,74 @@
 // #define PB (KB*KB*KB*KB*KB)
 
 
+/* TYPEDEFS *****************************************************************/
+
+typedef struct _USETUP_DATA
+{
+/* SOURCE Paths *****/
+    UNICODE_STRING SourceRootPath;
+    UNICODE_STRING SourceRootDir;
+    UNICODE_STRING SourcePath;
+
+/* DESTINATION Paths *****/
+    /*
+     * Path to the system partition, where the boot manager resides.
+     * On x86 PCs, this is usually the active partition.
+     * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
+     *
+     * For more information, see:
+     * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
+     * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
+     * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
+     * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
+     * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
+     * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
+     */
+    UNICODE_STRING SystemRootPath;
+
+    /* Path to the installation directory inside the ReactOS boot partition */
+    UNICODE_STRING DestinationPath;     /** Equivalent of 
'NTOS_INSTALLATION::SystemNtPath' **/
+    UNICODE_STRING DestinationArcPath;  /** Equivalent of 
'NTOS_INSTALLATION::SystemArcPath' **/
+    UNICODE_STRING DestinationRootPath;
+
+    LONG DestinationDiskNumber;
+    LONG DestinationPartitionNumber;
+    LONG MBRInstallType;
+
+    LONG FormatPartition;
+    LONG AutoPartition;
+
+    WCHAR LocaleID[9];
+    LANGID LanguageId;
+
+    ULONG RequiredPartitionDiskSpace;
+    WCHAR InstallationDirectory[MAX_PATH];
+} USETUP_DATA, *PUSETUP_DATA;
+
+// HACK!!
+extern BOOLEAN IsUnattendedSetup;
+
+
+/* FUNCTIONS ****************************************************************/
+
+VOID
+CheckUnattendedSetup(
+    IN OUT PUSETUP_DATA pSetupData);
+
+VOID
+InstallSetupInfFile(
+    IN OUT PUSETUP_DATA pSetupData);
+
+NTSTATUS
+GetSourcePaths(
+    OUT PUNICODE_STRING SourcePath,
+    OUT PUNICODE_STRING SourceRootPath,
+    OUT PUNICODE_STRING SourceRootDir);
+
+ERROR_NUMBER
+LoadSetupInf(
+    OUT HINF* SetupInf,
+    IN OUT PUSETUP_DATA pSetupData);
+
+
 /* EOF */

Modified: branches/setup_improvements/base/setup/usetup/interface/usetup.c
URL: 
http://svn.reactos.org/svn/reactos/branches/setup_improvements/base/setup/usetup/interface/usetup.c?rev=75518&r1=75517&r2=75518&view=diff
==============================================================================
--- branches/setup_improvements/base/setup/usetup/interface/usetup.c    
[iso-8859-1] (original)
+++ branches/setup_improvements/base/setup/usetup/interface/usetup.c    
[iso-8859-1] Wed Aug  9 20:39:45 2017
@@ -38,36 +38,12 @@
 #include <debug.h>
 
 
-/* GLOBALS ******************************************************************/
+/* GLOBALS & LOCALS *********************************************************/
 
 HANDLE ProcessHeap;
 
-static UNICODE_STRING SourceRootPath;
-static UNICODE_STRING SourceRootDir;
-static UNICODE_STRING SourcePath;
-
 BOOLEAN IsUnattendedSetup = FALSE;
-LONG UnattendDestinationDiskNumber;
-LONG UnattendDestinationPartitionNumber;
-LONG UnattendMBRInstallType = -1;
-LONG UnattendFormatPartition = 0;
-LONG AutoPartition = 0;
-WCHAR UnattendInstallationDirectory[MAX_PATH];
-PWCHAR SelectedLanguageId;
-WCHAR LocaleID[9];
-WCHAR DefaultLanguage[20];
-WCHAR DefaultKBLayout[20];
-static BOOLEAN RepairUpdateFlag = FALSE;
-static HANDLE hPnpThread = INVALID_HANDLE_VALUE;
-
-static PPARTLIST PartitionList = NULL;
-static PPARTENTRY TempPartition = NULL;
-static FORMATMACHINESTATE FormatState = Start;
-
-
-/* LOCALS *******************************************************************/
-
-static PFILE_SYSTEM_LIST FileSystemList = NULL;
+static USETUP_DATA USetupData;
 
 /*
  * NOTE: Technically only used for the COPYCONTEXT InstallPath member
@@ -75,28 +51,26 @@
  */
 static UNICODE_STRING InstallPath;
 
-/*
- * Path to the system partition, where the boot manager resides.
- * On x86 PCs, this is usually the active partition.
- * On ARC, (u)EFI, ... platforms, this is a dedicated partition.
- *
- * For more information, see:
- * https://en.wikipedia.org/wiki/System_partition_and_boot_partition
- * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/boot-and-system-volumes.html
- * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/arc-boot-process.html
- * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/efi-boot-process.html
- * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-system-volume.html
- * 
http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/determining-boot-volume.html
- */
-static UNICODE_STRING SystemRootPath;
-
-/* Path to the installation directory inside the ReactOS boot partition */
-static UNICODE_STRING DestinationPath;
-static UNICODE_STRING DestinationArcPath;
-static UNICODE_STRING DestinationRootPath;
-
 // FIXME: Is it really useful?? Just used for SetDefaultPagefile...
 static WCHAR DestinationDriveLetter;
+
+
+/* OTHER Stuff *****/
+
+PWCHAR SelectedLanguageId;
+static WCHAR DefaultLanguage[20];   // Copy of string inside LanguageList
+static WCHAR DefaultKBLayout[20];   // Copy of string inside KeyboardList
+
+static BOOLEAN RepairUpdateFlag = FALSE;
+
+static HANDLE hPnpThread = NULL;
+
+static PPARTLIST PartitionList = NULL;
+static PPARTENTRY TempPartition = NULL;
+static PFILE_SYSTEM_LIST FileSystemList = NULL;
+static FORMATMACHINESTATE FormatState = Start;
+
+/*****************************************************/
 
 static HINF SetupInf;
 
@@ -111,9 +85,6 @@
 static PGENERIC_LIST LayoutList   = NULL;
 static PGENERIC_LIST LanguageList = NULL;
 
-static LANGID LanguageId = 0;
-
-static ULONG RequiredPartitionDiskSpace = ~0;
 
 /* FUNCTIONS ****************************************************************/
 
@@ -427,178 +398,6 @@
 
 
 static VOID
-CheckUnattendedSetup(VOID)
-{
-    WCHAR UnattendInfPath[MAX_PATH];
-    INFCONTEXT Context;
-    HINF UnattendInf;
-    UINT ErrorLine;
-    INT IntValue;
-    PWCHAR Value;
-
-    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2, 
SourcePath.Buffer, L"unattend.inf");
-
-    if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
-    {
-        DPRINT("Does not exist: %S\n", UnattendInfPath);
-        return;
-    }
-
-    /* Load 'unattend.inf' from install media. */
-    UnattendInf = SetupOpenInfFileExW(UnattendInfPath,
-                                      NULL,
-                                      INF_STYLE_WIN4,
-                                      LanguageId,
-                                      &ErrorLine);
-
-    if (UnattendInf == INVALID_HANDLE_VALUE)
-    {
-        DPRINT("SetupOpenInfFileExW() failed\n");
-        return;
-    }
-
-    /* Open 'Unattend' section */
-    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", L"Signature", &Context))
-    {
-        DPRINT("SetupFindFirstLineW() failed for section 'Unattend'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    /* Get pointer 'Signature' key */
-    if (!INF_GetData(&Context, NULL, &Value))
-    {
-        DPRINT("INF_GetData() failed for key 'Signature'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    /* Check 'Signature' string */
-    if (_wcsicmp(Value, L"$ReactOS$") != 0)
-    {
-        DPRINT("Signature not $ReactOS$\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    /* Check if Unattend setup is enabled */
-    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"UnattendSetupEnabled", &Context))
-    {
-        DPRINT("Can't find key 'UnattendSetupEnabled'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    if (!INF_GetData(&Context, NULL, &Value))
-    {
-        DPRINT("Can't read key 'UnattendSetupEnabled'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    if (_wcsicmp(Value, L"yes") != 0)
-    {
-        DPRINT("Unattend setup is disabled by 'UnattendSetupEnabled' key!\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    /* Search for 'DestinationDiskNumber' in the 'Unattend' section */
-    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"DestinationDiskNumber", &Context))
-    {
-        DPRINT("SetupFindFirstLine() failed for key 
'DestinationDiskNumber'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    if (!SetupGetIntField(&Context, 1, &IntValue))
-    {
-        DPRINT("SetupGetIntField() failed for key 'DestinationDiskNumber'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    UnattendDestinationDiskNumber = (LONG)IntValue;
-
-    /* Search for 'DestinationPartitionNumber' in the 'Unattend' section */
-    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"DestinationPartitionNumber", &Context))
-    {
-        DPRINT("SetupFindFirstLine() failed for key 
'DestinationPartitionNumber'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    if (!SetupGetIntField(&Context, 1, &IntValue))
-    {
-        DPRINT("SetupGetIntField() failed for key 
'DestinationPartitionNumber'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    UnattendDestinationPartitionNumber = (LONG)IntValue;
-
-    /* Search for 'InstallationDirectory' in the 'Unattend' section */
-    if (!SetupFindFirstLineW(UnattendInf, L"Unattend", 
L"InstallationDirectory", &Context))
-    {
-        DPRINT("SetupFindFirstLine() failed for key 
'InstallationDirectory'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    /* Get pointer 'InstallationDirectory' key */
-    if (!INF_GetData(&Context, NULL, &Value))
-    {
-        DPRINT("INF_GetData() failed for key 'InstallationDirectory'\n");
-        SetupCloseInfFile(UnattendInf);
-        return;
-    }
-
-    wcscpy(UnattendInstallationDirectory, Value);
-
-    IsUnattendedSetup = TRUE;
-    DPRINT("Running unattended setup\n");
-
-    /* Search for 'MBRInstallType' in the 'Unattend' section */
-    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"MBRInstallType", 
&Context))
-    {
-        if (SetupGetIntField(&Context, 1, &IntValue))
-        {
-            UnattendMBRInstallType = IntValue;
-        }
-    }
-
-    /* Search for 'FormatPartition' in the 'Unattend' section */
-    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"FormatPartition", 
&Context))
-    {
-        if (SetupGetIntField(&Context, 1, &IntValue))
-        {
-            UnattendFormatPartition = IntValue;
-        }
-    }
-
-    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"AutoPartition", 
&Context))
-    {
-        if (SetupGetIntField(&Context, 1, &IntValue))
-        {
-            AutoPartition = IntValue;
-        }
-    }
-
-    /* search for LocaleID in the 'Unattend' section*/
-    if (SetupFindFirstLineW(UnattendInf, L"Unattend", L"LocaleID", &Context))
-    {
-        if (INF_GetData(&Context, NULL, &Value))
-        {
-            LONG Id = wcstol(Value, NULL, 16);
-            swprintf(LocaleID, L"%08lx", Id);
-       }
-    }
-
-    SetupCloseInfFile(UnattendInf);
-}
-
-
-static VOID
 UpdateKBLayout(VOID)
 {
     PGENERIC_LIST_ENTRY ListEntry;
@@ -642,7 +441,7 @@
  *
  * SIDEEFFECTS
  *  Init SelectedLanguageId
- *  Init LanguageId
+ *  Init USetupData.LanguageId
  *
  * RETURNS
  *   Number of the next page.
@@ -666,6 +465,7 @@
     }
 
     /* Load the font */
+    USetupData.LanguageId = 0;
     SelectedLanguageId = DefaultLanguage;
     SetConsoleCodePage();
     UpdateKBLayout();
@@ -674,7 +474,7 @@
      * the language selection process altogether! */
     if (GenericListHasSingleEntry(LanguageList))
     {
-        LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
+        USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) 
& 0xFFFF);
         return WELCOME_PAGE;
     }
 
@@ -729,7 +529,7 @@
         {
             SelectedLanguageId = 
(PWCHAR)GetListEntryUserData(GetCurrentListEntry(LanguageList));
 
-            LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 
0xFFFF);
+            USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 
16) & 0xFFFF);
 
             if (wcscmp(SelectedLanguageId, DefaultLanguage))
             {
@@ -771,65 +571,6 @@
     }
 
     return WELCOME_PAGE;
-}
-
-
-static NTSTATUS
-GetSourcePaths(
-    OUT PUNICODE_STRING SourcePath,
-    OUT PUNICODE_STRING SourceRootPath,
-    OUT PUNICODE_STRING SourceRootDir)
-{
-    NTSTATUS Status;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\SystemRoot");
-    UNICODE_STRING SourceName;
-    WCHAR SourceBuffer[MAX_PATH] = L"";
-    HANDLE Handle;
-    ULONG Length;
-    PWCHAR Ptr;
-
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &LinkName,
-                               OBJ_CASE_INSENSITIVE,
-                               NULL,
-                               NULL);
-
-    Status = NtOpenSymbolicLinkObject(&Handle,
-                                      SYMBOLIC_LINK_ALL_ACCESS,
-                                      &ObjectAttributes);
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    RtlInitEmptyUnicodeString(&SourceName, SourceBuffer, sizeof(SourceBuffer));
-
-    Status = NtQuerySymbolicLinkObject(Handle,
-                                       &SourceName,
-                                       &Length);
-    NtClose(Handle);
-
-    if (!NT_SUCCESS(Status))
-        return Status;
-
-    RtlCreateUnicodeString(SourcePath,
-                           SourceName.Buffer);
-
-    /* Strip trailing directory */
-    Ptr = wcsrchr(SourceName.Buffer, OBJ_NAME_PATH_SEPARATOR);
-    if (Ptr)
-    {
-        RtlCreateUnicodeString(SourceRootDir, Ptr);
-        *Ptr = UNICODE_NULL;
-    }
-    else
-    {
-        RtlCreateUnicodeString(SourceRootDir, L"");
-    }
-
-    RtlCreateUnicodeString(SourceRootPath,
-                           SourceName.Buffer);
-
-    return STATUS_SUCCESS;
 }
 
 
@@ -843,15 +584,15 @@
  *
  * SIDEEFFECTS
  *  Init Sdi
- *  Init SourcePath
- *  Init SourceRootPath
- *  Init SourceRootDir
+ *  Init USetupData.SourcePath
+ *  Init USetupData.SourceRootPath
+ *  Init USetupData.SourceRootDir
  *  Init SetupInf
- *  Init RequiredPartitionDiskSpace
+ *  Init USetupData.RequiredPartitionDiskSpace
  *  Init IsUnattendedSetup
  *  If unattended, init *List and sets the Codepage
  *  If unattended, init SelectedLanguageId
- *  If unattended, init LanguageId
+ *  If unattended, init USetupData.LanguageId
  *
  * RETURNS
  *   Number of the next page.
@@ -860,79 +601,32 @@
 SetupStartPage(PINPUT_RECORD Ir)
 {
     NTSTATUS Status;
-    WCHAR FileNameBuffer[MAX_PATH];
-    INFCONTEXT Context;
-    PWCHAR Value;
-    UINT ErrorLine;
+    ULONG Error;
     PGENERIC_LIST_ENTRY ListEntry;
-    INT IntValue;
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
     /* Get the source path and source root path */
-    Status = GetSourcePaths(&SourcePath,
-                            &SourceRootPath,
-                            &SourceRootDir);
+    Status = GetSourcePaths(&USetupData.SourcePath,
+                            &USetupData.SourceRootPath,
+                            &USetupData.SourceRootDir);
     if (!NT_SUCCESS(Status))
     {
         CONSOLE_PrintTextXY(6, 15, "GetSourcePaths() failed (Status 0x%08lx)", 
Status);
         MUIDisplayError(ERROR_NO_SOURCE_DRIVE, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
-    DPRINT1("SourcePath: '%wZ'\n", &SourcePath);
-    DPRINT1("SourceRootPath: '%wZ'\n", &SourceRootPath);
-    DPRINT1("SourceRootDir: '%wZ'\n", &SourceRootDir);
-
-    /* Load txtsetup.sif from install media. */
-    CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2, 
SourcePath.Buffer, L"txtsetup.sif");
-    SetupInf = SetupOpenInfFileExW(FileNameBuffer,
-                                   NULL,
-                                   INF_STYLE_WIN4,
-                                   LanguageId,
-                                   &ErrorLine);
-
-    if (SetupInf == INVALID_HANDLE_VALUE)
-    {
-        MUIDisplayError(ERROR_LOAD_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
+    DPRINT1("SourcePath: '%wZ'\n", &USetupData.SourcePath);
+    DPRINT1("SourceRootPath: '%wZ'\n", &USetupData.SourceRootPath);
+    DPRINT1("SourceRootDir: '%wZ'\n", &USetupData.SourceRootDir);
+
+    /* Load 'txtsetup.sif' from the installation media */
+    Error = LoadSetupInf(&SetupInf, &USetupData);
+    if (Error != ERROR_SUCCESS)
+    {
+        MUIDisplayError(Error, Ir, POPUP_WAIT_ENTER);
         return QUIT_PAGE;
     }
-
-    /* Open 'Version' section */
-    if (!SetupFindFirstLineW(SetupInf, L"Version", L"Signature", &Context))
-    {
-        MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    /* Get pointer 'Signature' key */
-    if (!INF_GetData(&Context, NULL, &Value))
-    {
-        MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    /* Check 'Signature' string */
-    if (_wcsicmp(Value, L"$ReactOS$") != 0)
-    {
-        MUIDisplayError(ERROR_SIGNATURE_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    /* Open 'DiskSpaceRequirements' section */
-    if (!SetupFindFirstLineW(SetupInf, L"DiskSpaceRequirements", 
L"FreeSysPartDiskSpace", &Context))
-    {
-        MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    /* Get the 'FreeSysPartDiskSpace' value */
-    if (!SetupGetIntField(&Context, 1, &IntValue))
-    {
-        MUIDisplayError(ERROR_CORRUPT_TXTSETUPSIF, Ir, POPUP_WAIT_ENTER);
-        return QUIT_PAGE;
-    }
-
-    RequiredPartitionDiskSpace = (ULONG)IntValue;
 
     /* Start the PnP thread */
     if (hPnpThread != INVALID_HANDLE_VALUE)
@@ -941,7 +635,7 @@
         hPnpThread = INVALID_HANDLE_VALUE;
     }
 
-    CheckUnattendedSetup();
+    CheckUnattendedSetup(&USetupData);
 
     if (IsUnattendedSetup)
     {
@@ -953,14 +647,14 @@
         LanguageList = CreateLanguageList(SetupInf, DefaultLanguage);
 
         /* new part */
-        wcscpy(SelectedLanguageId, LocaleID);
-        LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) & 0xFFFF);
+        wcscpy(SelectedLanguageId, USetupData.LocaleID);
+        USetupData.LanguageId = (LANGID)(wcstol(SelectedLanguageId, NULL, 16) 
& 0xFFFF);
 
         /* first we hack LanguageList */
         ListEntry = GetFirstListEntry(LanguageList);
         while (ListEntry != NULL)
         {
-            if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
+            if (!wcsicmp(USetupData.LocaleID, GetListEntryUserData(ListEntry)))
             {
                 DPRINT("found %S in 
LanguageList\n",GetListEntryUserData(ListEntry));
                 SetCurrentListEntry(LanguageList, ListEntry);
@@ -974,7 +668,7 @@
         ListEntry = GetFirstListEntry(LayoutList);
         while (ListEntry != NULL)
         {
-            if (!wcsicmp(LocaleID, GetListEntryUserData(ListEntry)))
+            if (!wcsicmp(USetupData.LocaleID, GetListEntryUserData(ListEntry)))
             {
                 DPRINT("found %S in 
LayoutList\n",GetListEntryUserData(ListEntry));
                 SetCurrentListEntry(LayoutList, ListEntry);
@@ -1651,10 +1345,10 @@
     size = PartEntry->SectorCount.QuadPart * 
PartEntry->DiskEntry->BytesPerSector;
     size = (size + (512 * KB)) / MB;  /* in MBytes */
 
-    if (size < RequiredPartitionDiskSpace)
+    if (size < USetupData.RequiredPartitionDiskSpace)
     {
         /* Partition is too small so ask for another one */
-        DPRINT1("Partition is too small (size: %I64u MB), required disk space 
is %lu MB\n", size, RequiredPartitionDiskSpace);
+        DPRINT1("Partition is too small (size: %I64u MB), required disk space 
is %lu MB\n", size, USetupData.RequiredPartitionDiskSpace);
         return FALSE;
     }
     else
@@ -1733,9 +1427,11 @@
 
     if (IsUnattendedSetup)
     {
-        if (!SelectPartition(PartitionList, UnattendDestinationDiskNumber, 
UnattendDestinationPartitionNumber))
-        {
-            if (AutoPartition)
+        if (!SelectPartition(PartitionList,
+                             USetupData.DestinationDiskNumber,
+                             USetupData.DestinationPartitionNumber))
+        {
+            if (USetupData.AutoPartition)
             {
                 if (PartitionList->CurrentPartition->LogicalPartition)
                 {
@@ -1754,7 +1450,7 @@
                 if (!IsDiskSizeValid(PartitionList->CurrentPartition))
                 {
                     MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, 
POPUP_WAIT_ANY_KEY,
-                                    RequiredPartitionDiskSpace);
+                                    USetupData.RequiredPartitionDiskSpace);
                     return SELECT_PARTITION_PAGE; /* let the user select 
another partition */
                 }
 
@@ -1769,7 +1465,7 @@
             if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, 
POPUP_WAIT_ANY_KEY,
-                                RequiredPartitionDiskSpace);
+                                USetupData.RequiredPartitionDiskSpace);
                 return SELECT_PARTITION_PAGE; /* let the user select another 
partition */
             }
 
@@ -1863,7 +1559,7 @@
             if (!IsDiskSizeValid(PartitionList->CurrentPartition))
             {
                 MUIDisplayError(ERROR_INSUFFICIENT_PARTITION_SIZE, Ir, 
POPUP_WAIT_ANY_KEY,
-                                RequiredPartitionDiskSpace);
+                                USetupData.RequiredPartitionDiskSpace);
                 return SELECT_PARTITION_PAGE; /* let the user select another 
partition */
             }
 
@@ -2726,8 +2422,8 @@
  *
  * Next pages:
  *  CheckFileSystemPage (At once if RepairUpdate is selected)
- *  CheckFileSystemPage (At once if Unattended and not UnattendFormatPartition)
- *  FormatPartitionPage (At once if Unattended and UnattendFormatPartition)
+ *  CheckFileSystemPage (At once if Unattended and not 
USetupData.FormatPartition)
+ *  FormatPartitionPage (At once if Unattended and USetupData.FormatPartition)
  *  SelectPartitionPage (If the user aborts)
  *  FormatPartitionPage (Default)
  *  QuitPage
@@ -2995,7 +2691,7 @@
 
     if (IsUnattendedSetup)
     {
-        if (UnattendFormatPartition)
+        if (USetupData.FormatPartition)
         {
             /*
              * We use whatever currently selected file system we have
@@ -3065,7 +2761,7 @@
  *
  * SIDEEFFECTS
  *  Sets PartitionList->CurrentPartition->FormatState
- *  Sets DestinationRootPath
+ *  Sets USetupData.DestinationRootPath
  *
  * RETURNS
  *   Number of the next page.
@@ -3319,9 +3015,9 @@
  *  PrepareCopyPage (At once)
  *
  * SIDEEFFECTS
- *  Inits DestinationRootPath
- *  Inits DestinationPath
- *  Inits DestinationArcPath
+ *  Inits USetupData.DestinationRootPath
+ *  Inits USetupData.DestinationPath
+ *  Inits USetupData.DestinationArcPath
  *  Inits DestinationDriveLetter
  *
  * RETURNS
@@ -3339,31 +3035,31 @@
     RtlFreeUnicodeString(&InstallPath);
     RtlCreateUnicodeString(&InstallPath, InstallDir);
 
-    /* Create 'DestinationRootPath' string */
-    RtlFreeUnicodeString(&DestinationRootPath);
+    /* Create 'USetupData.DestinationRootPath' string */
+    RtlFreeUnicodeString(&USetupData.DestinationRootPath);
     StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
             DiskEntry->DiskNumber,
             PartEntry->PartitionNumber);
-    RtlCreateUnicodeString(&DestinationRootPath, PathBuffer);
-    DPRINT("DestinationRootPath: %wZ\n", &DestinationRootPath);
+    RtlCreateUnicodeString(&USetupData.DestinationRootPath, PathBuffer);
+    DPRINT("DestinationRootPath: %wZ\n", &USetupData.DestinationRootPath);
 
 /** Equivalent of 'NTOS_INSTALLATION::SystemNtPath' **/
-    /* Create 'DestinationPath' string */
-    RtlFreeUnicodeString(&DestinationPath);
+    /* Create 'USetupData.DestinationPath' string */
+    RtlFreeUnicodeString(&USetupData.DestinationPath);
     CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                 DestinationRootPath.Buffer, InstallDir);
-    RtlCreateUnicodeString(&DestinationPath, PathBuffer);
+                 USetupData.DestinationRootPath.Buffer, InstallDir);
+    RtlCreateUnicodeString(&USetupData.DestinationPath, PathBuffer);
 
 /** Equivalent of 'NTOS_INSTALLATION::SystemArcPath' **/
-    /* Create 'DestinationArcPath' */
-    RtlFreeUnicodeString(&DestinationArcPath);
+    /* Create 'USetupData.DestinationArcPath' */
+    RtlFreeUnicodeString(&USetupData.DestinationArcPath);
     StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"multi(0)disk(0)rdisk(%lu)partition(%lu)\\",
             DiskEntry->BiosDiskNumber,
             PartEntry->PartitionNumber);
     ConcatPaths(PathBuffer, ARRAYSIZE(PathBuffer), 1, InstallDir);
-    RtlCreateUnicodeString(&DestinationArcPath, PathBuffer);
+    RtlCreateUnicodeString(&USetupData.DestinationArcPath, PathBuffer);
 
     /* Initialize DestinationDriveLetter */
     DestinationDriveLetter = (WCHAR)PartEntry->DriveLetter;
@@ -3387,7 +3083,7 @@
 {
     PDISKENTRY DiskEntry;
     PPARTENTRY PartEntry;
-    WCHAR InstallDir[51];
+    WCHAR InstallDir[MAX_PATH];
     WCHAR c;
     ULONG Length;
 
@@ -3409,10 +3105,11 @@
     DiskEntry = PartitionList->CurrentDisk;
     PartEntry = PartitionList->CurrentPartition;
 
-    if (IsUnattendedSetup)
-        wcscpy(InstallDir, UnattendInstallationDirectory);
-    else if (RepairUpdateFlag)
+    // if (IsUnattendedSetup)
+    if (RepairUpdateFlag)
         wcscpy(InstallDir, CurrentInstallation->PathComponent); // SystemNtPath
+    else if (USetupData.InstallationDirectory[0])
+        wcscpy(InstallDir, USetupData.InstallationDirectory);
     else
         wcscpy(InstallDir, L"\\ReactOS");
 
@@ -3564,8 +3261,8 @@
 
         if (!SetupQueueCopy(SetupFileQueue,
                             SourceCabinet,
-                            SourceRootPath.Buffer,
-                            SourceRootDir.Buffer,
+                            USetupData.SourceRootPath.Buffer,
+                            USetupData.SourceRootDir.Buffer,
                             FileKeyName,
                             DirKeyValue,
                             TargetFileName))
@@ -3673,7 +3370,7 @@
             DPRINT("InstallationPath: '%S'\n", DirKeyValue);
 
             StringCchCopyW(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName),
-                           SourceRootDir.Buffer);
+                           USetupData.SourceRootDir.Buffer);
 
             DPRINT("InstallationPath(2): '%S'\n", CompleteOrigDirName);
         }
@@ -3693,14 +3390,14 @@
             DPRINT("RelativePath: '%S'\n", DirKeyValue);
 
             CombinePaths(CompleteOrigDirName, ARRAYSIZE(CompleteOrigDirName), 
2,
-                         SourceRootDir.Buffer, DirKeyValue);
+                         USetupData.SourceRootDir.Buffer, DirKeyValue);
 
             DPRINT("RelativePath(2): '%S'\n", CompleteOrigDirName);
         }
 
         if (!SetupQueueCopy(SetupFileQueue,
                             SourceCabinet,
-                            SourceRootPath.Buffer,
+                            USetupData.SourceRootPath.Buffer,
                             CompleteOrigDirName,
                             FileKeyName,
                             DirKeyValue,
@@ -3731,7 +3428,7 @@
     WCHAR PathBuffer[MAX_PATH];
 
     /* Add common files */
-    if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, 
&DestinationPath, Ir))
+    if (!AddSectionToCopyQueue(InfFile, L"SourceDisksFiles", SourceCabinet, 
&USetupData.DestinationPath, Ir))
         return FALSE;
 
     /* Add specific files depending of computer type */
@@ -3742,7 +3439,7 @@
 
         if (AdditionalSectionName)
         {
-            if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, 
SourceCabinet, &DestinationPath, Ir))
+            if (!AddSectionToCopyQueue(InfFile, AdditionalSectionName, 
SourceCabinet, &USetupData.DestinationPath, Ir))
                 return FALSE;
         }
     }
@@ -3751,14 +3448,14 @@
 
     /*
      * FIXME:
-     * Copying files to DestinationRootPath should be done from within
+     * 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 DestinationPath specify just '\' .
+     * For installing to USetupData.DestinationPath specify just '\' .
      */
 
     /* Get destination path */
-    StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), DestinationPath.Buffer);
+    StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer), 
USetupData.DestinationPath.Buffer);
 
     DPRINT("FullPath(1): '%S'\n", PathBuffer);
 
@@ -3801,7 +3498,7 @@
             DPRINT("InstallationPath: '%S'\n", DirKeyValue);
 
             StringCchCopyW(PathBuffer, ARRAYSIZE(PathBuffer),
-                           DestinationPath.Buffer);
+                           USetupData.DestinationPath.Buffer);
 
             DPRINT("InstallationPath(2): '%S'\n", PathBuffer);
         }
@@ -3811,7 +3508,7 @@
             DPRINT("AbsolutePath: '%S'\n", DirKeyValue);
 
             CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         DestinationRootPath.Buffer, DirKeyValue);
+                         USetupData.DestinationRootPath.Buffer, DirKeyValue);
 
             DPRINT("AbsolutePath(2): '%S'\n", PathBuffer);
 
@@ -3830,7 +3527,7 @@
             DPRINT("RelativePath: '%S'\n", DirKeyValue);
 
             CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                         DestinationPath.Buffer, DirKeyValue);
+                         USetupData.DestinationPath.Buffer, DirKeyValue);
 
             DPRINT("RelativePath(2): '%S'\n", PathBuffer);
 
@@ -3908,7 +3605,7 @@
             break;
 
         CombinePaths(PathBuffer, ARRAYSIZE(PathBuffer), 2,
-                     SourcePath.Buffer, KeyValue);
+                     USetupData.SourcePath.Buffer, KeyValue);
 
 #ifdef __REACTOS__
         CabinetInitialize();
@@ -3937,7 +3634,7 @@
                                           InfFileSize,
                                           NULL,
                                           INF_STYLE_WIN4,
-                                          LanguageId,
+                                          USetupData.LanguageId,
                                           &ErrorLine);
 
         if (InfHandle == INVALID_HANDLE_VALUE)
@@ -4053,7 +3750,7 @@
     MUIDisplayPage(FILE_COPY_PAGE);
 
     /* Create context for the copy process */
-    CopyContext.DestinationRootPath = DestinationRootPath.Buffer;
+    CopyContext.DestinationRootPath = USetupData.DestinationRootPath.Buffer;
     CopyContext.InstallPath = InstallPath.Buffer;
     CopyContext.TotalOperations = 0;
     CopyContext.CompletedOperations = 0;
@@ -4114,6 +3811,9 @@
     DestroyProgressBar(CopyContext.MemoryBars[0]);
     DestroyProgressBar(CopyContext.MemoryBars[1]);
     DestroyProgressBar(CopyContext.MemoryBars[2]);
+
+    /* Create the $winnt$.inf file */
+    InstallSetupInfFile(&USetupData);
 
     /* Go display the next page */
     return REGISTRY_PAGE;
@@ -4156,7 +3856,7 @@
         DPRINT1("TODO: Updating / repairing the registry is not completely 
implemented yet!\n");
 
         /* Verify the registry hives and check whether we need to update or 
repair any of them */
-        Status = VerifyRegistryHives(&DestinationPath, &ShouldRepairRegistry);
+        Status = VerifyRegistryHives(&USetupData.DestinationPath, 
&ShouldRepairRegistry);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("VerifyRegistryHives failed, Status 0x%08lx\n", Status);
@@ -4171,7 +3871,7 @@
     CONSOLE_SetStatusText(MUIGetString(STRING_REGHIVEUPDATE));
 
     /* Initialize the registry and setup the registry hives */
-    Status = RegInitializeRegistry(&DestinationPath);
+    Status = RegInitializeRegistry(&USetupData.DestinationPath);
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("RegInitializeRegistry() failed\n");
@@ -4260,7 +3960,7 @@
 
         CONSOLE_SetStatusText(MUIGetString(STRING_IMPORTFILE), File);
 
-        if (!ImportRegistryFile(SourcePath.Buffer, File, Section, LanguageId, 
Delete))
+        if (!ImportRegistryFile(USetupData.SourcePath.Buffer, File, Section, 
USetupData.LanguageId, Delete))
         {
             DPRINT1("Importing %S failed\n", File);
             INF_FreeData(File);
@@ -4337,7 +4037,7 @@
     // TODO: Unload all the registry stuff, perform cleanup,
     // and copy the created hive files into .sav files.
     //
-    RegCleanupRegistry(&DestinationPath);
+    RegCleanupRegistry(&USetupData.DestinationPath);
 
     /*
      * Check whether we were in update/repair mode but we were actually
@@ -4393,28 +4093,30 @@
 
     CONSOLE_SetStatusText(MUIGetString(STRING_PLEASEWAIT));
 
-    RtlFreeUnicodeString(&SystemRootPath);
+    RtlFreeUnicodeString(&USetupData.SystemRootPath);
     StringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
             L"\\Device\\Harddisk%lu\\Partition%lu\\",
             PartitionList->SystemPartition->DiskEntry->DiskNumber,
             PartitionList->SystemPartition->PartitionNumber);
-    RtlCreateUnicodeString(&SystemRootPath, PathBuffer);
-    DPRINT1("SystemRootPath: %wZ\n", &SystemRootPath);
+    RtlCreateUnicodeString(&USetupData.SystemRootPath, PathBuffer);
+    DPRINT1("SystemRootPath: %wZ\n", &USetupData.SystemRootPath);
 
     PartitionType = PartitionList->SystemPartition->PartitionType;
 
+    /* For unattended setup, skip MBR installation or install on floppy if 
needed */
     if (IsUnattendedSetup)
     {
-        if (UnattendMBRInstallType == 0) /* skip MBR installation */
-        {
-            return SUCCESS_PAGE;
-        }
-        else if (UnattendMBRInstallType == 1) /* install on floppy */
-        {
-            return BOOT_LOADER_FLOPPY_PAGE;
-        }
-    }
-
+        if ((USetupData.MBRInstallType == 0) ||
+            (USetupData.MBRInstallType == 1))
+        {
+            goto Quit;
+        }
+    }
+
+    /*
+     * We may install an MBR or VBR, but before that, check whether
+     * we need to actually install the VBR on floppy.
+     */
     if (PartitionType == PARTITION_ENTRY_UNUSED)
     {
         DPRINT("Error: system partition invalid (unused)\n");
@@ -4457,15 +4159,21 @@
         InstallOnFloppy = TRUE;
     }
 
-    if (InstallOnFloppy == TRUE)
-    {
-        return BOOT_LOADER_FLOPPY_PAGE;
-    }
-
-    /* Unattended install on hdd? */
-    if (IsUnattendedSetup && UnattendMBRInstallType == 2)
-    {
-        return BOOT_LOADER_HARDDISK_MBR_PAGE;
+    /* We should install on floppy */
+    if (InstallOnFloppy)
+    {
+        USetupData.MBRInstallType = 1;
+        goto Quit;
+    }
+
+    /* Is it an unattended install on hdd? */
+    if (IsUnattendedSetup)
+    {
+        if ((USetupData.MBRInstallType == 2) ||
+            (USetupData.MBRInstallType == 3))
+        {
+            goto Quit;
+        }
     }
 
     MUIDisplayPage(BOOT_LOADER_PAGE);
@@ -4515,23 +4223,51 @@
         {
             if (Line == 12)
             {
-                return BOOT_LOADER_HARDDISK_MBR_PAGE;
+                /* Install on both MBR and VBR */
+                USetupData.MBRInstallType = 2;
+                break;
             }
             else if (Line == 13)
             {
-                return BOOT_LOADER_HARDDISK_VBR_PAGE;
+                /* Install on VBR only */
+                USetupData.MBRInstallType = 3;
+                break;
             }
             else if (Line == 14)
             {
-                return BOOT_LOADER_FLOPPY_PAGE;
+                /* Install on floppy */
+                USetupData.MBRInstallType = 1;
+                break;
             }
             else if (Line == 15)
             {
-                return SUCCESS_PAGE;
+                /* Skip MBR installation */
+                USetupData.MBRInstallType = 0;
+                break;
             }
 
             return BOOT_LOADER_PAGE;
         }
+    }
+
+Quit:
+    switch (USetupData.MBRInstallType)
+    {
+        /* Skip MBR installation */
+        case 0:
+            return SUCCESS_PAGE;
+
+        /* Install on floppy */
+        case 1:
+            return BOOT_LOADER_FLOPPY_PAGE;
+
+        /* Install on both MBR and VBR */
+        case 2:
+            return BOOT_LOADER_HARDDISK_MBR_PAGE;
+
+        /* Install on VBR only */
+        case 3:
+            return BOOT_LOADER_HARDDISK_VBR_PAGE;
     }
 
     return BOOT_LOADER_PAGE;
@@ -4580,7 +4316,7 @@
                 return BOOT_LOADER_FLOPPY_PAGE;
             }
 
-            Status = InstallFatBootcodeToFloppy(&SourceRootPath, 
&DestinationArcPath);
+            Status = InstallFatBootcodeToFloppy(&USetupData.SourceRootPath, 
&USetupData.DestinationArcPath);
             if (!NT_SUCCESS(Status))
             {
                 /* Print error message */
@@ -4613,9 +4349,9 @@
 {
     NTSTATUS Status;
 
-    Status = InstallVBRToPartition(&SystemRootPath,
-                                   &SourceRootPath,
-                                   &DestinationArcPath,
+    Status = InstallVBRToPartition(&USetupData.SystemRootPath,
+                                   &USetupData.SourceRootPath,
+                                   &USetupData.DestinationArcPath,
                                    
PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
@@ -4650,9 +4386,9 @@
     WCHAR DstPath[MAX_PATH];
 
     /* Step 1: Write the VBR */
-    Status = InstallVBRToPartition(&SystemRootPath,
-                                   &SourceRootPath,
-                                   &DestinationArcPath,
+    Status = InstallVBRToPartition(&USetupData.SystemRootPath,
+                                   &USetupData.SourceRootPath,
+                                   &USetupData.DestinationArcPath,
                                    
PartitionList->SystemPartition->PartitionType);
     if (!NT_SUCCESS(Status))
     {
@@ -4665,12 +4401,12 @@
             L"\\Device\\Harddisk%d\\Partition0",
             PartitionList->SystemPartition->DiskEntry->DiskNumber);
 
-    CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, 
SourceRootPath.Buffer, L"\\loader\\dosmbr.bin");
+    CombinePaths(SourceMbrPathBuffer, ARRAYSIZE(SourceMbrPathBuffer), 2, 
USetupData.SourceRootPath.Buffer, L"\\loader\\dosmbr.bin");
 
     if (IsThereAValidBootSector(DestinationDevicePathBuffer))
     {
         /* Save current MBR */
-        CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, SystemRootPath.Buffer, 
L"mbr.old");
+        CombinePaths(DstPath, ARRAYSIZE(DstPath), 2, 
USetupData.SystemRootPath.Buffer, L"mbr.old");
 
         DPRINT1("Save MBR: %S ==> %S\n", DestinationDevicePathBuffer, DstPath);
         Status = SaveBootSector(DestinationDevicePathBuffer, DstPath, 
sizeof(PARTITION_SECTOR));
@@ -4882,14 +4618,14 @@
     }
 
     /* Initialize global unicode strings */
-    RtlInitUnicodeString(&SourcePath, NULL);
-    RtlInitUnicodeString(&SourceRootPath, NULL);
-    RtlInitUnicodeString(&SourceRootDir, NULL);
+    RtlInitUnicodeString(&USetupData.SourcePath, NULL);
+    RtlInitUnicodeString(&USetupData.SourceRootPath, NULL);
+    RtlInitUnicodeString(&USetupData.SourceRootDir, NULL);
     RtlInitUnicodeString(&InstallPath, NULL);
-    RtlInitUnicodeString(&DestinationPath, NULL);
-    RtlInitUnicodeString(&DestinationArcPath, NULL);
-    RtlInitUnicodeString(&DestinationRootPath, NULL);
-    RtlInitUnicodeString(&SystemRootPath, NULL);
+    RtlInitUnicodeString(&USetupData.DestinationPath, NULL);
+    RtlInitUnicodeString(&USetupData.DestinationArcPath, NULL);
+    RtlInitUnicodeString(&USetupData.DestinationRootPath, NULL);
+    RtlInitUnicodeString(&USetupData.SystemRootPath, NULL);
 
     /* Hide the cursor */
     CONSOLE_SetCursorType(TRUE, FALSE);


Reply via email to