https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c560342f08edfa2824a6d…
commit c560342f08edfa2824a6dc0a1fc7188f169c12b7
Author:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Aug 25 09:19:44 2017 +0000
Commit:     Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sat Oct 27 18:13:42 2018 +0200
    [SETUPLIB] Diverse fixes (incl. initialization fixes).
    - Compute the installation source paths based on the full path of the
      installer program that uses the setup library.
    - Add INF_STYLE_OLDNT define in infsupp.h.
    - Add some (silenced) diagnostic DPRINTs.
    svn path=/branches/setup_improvements/; revision=75667
    - Use correct inf style flags in SetupOpenInfFileEx() calls when opening
      txtsetup.sif and unattend.inf. Technically txtsetup.sif would be
      INF_STYLE_WIN4, but since we use "$ReactOS$" as its version signature,
      it would not work when opening it with setupapi.dll functions.
      Hence this flag is combined with INF_STYLE_OLDNT too.
    - Don't fail if opening the \SystemRoot symbolic link doesn't work
      (usually due to incorrect access rights); in that case, just use the
      installer image file path as the installation source path.
    svn path=/branches/setup_improvements/; revision=75676
---
 base/setup/lib/infsupp.h  |   4 ++
 base/setup/lib/setuplib.c | 103 +++++++++++++++++++++++++++++++++++-----------
 2 files changed, 84 insertions(+), 23 deletions(-)
diff --git a/base/setup/lib/infsupp.h b/base/setup/lib/infsupp.h
index 677fb9af2a..db6043c03f 100644
--- a/base/setup/lib/infsupp.h
+++ b/base/setup/lib/infsupp.h
@@ -95,6 +95,10 @@ SetupGetStringFieldW(PINFCONTEXT Context,
 #undef MAX_INF_STRING_LENGTH
 #define MAX_INF_STRING_LENGTH   1024 // Still larger than in infcommon.h
+#ifndef INF_STYLE_OLDNT
+#define INF_STYLE_OLDNT 0x00000001
+#endif
+
 #ifndef INF_STYLE_WIN4
 #define INF_STYLE_WIN4  0x00000002
 #endif
diff --git a/base/setup/lib/setuplib.c b/base/setup/lib/setuplib.c
index a1744cc99e..c5a8a6f981 100644
--- a/base/setup/lib/setuplib.c
+++ b/base/setup/lib/setuplib.c
@@ -41,6 +41,8 @@ CheckUnattendedSetup(
     CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2,
                  pSetupData->SourcePath.Buffer, L"unattend.inf");
+    DPRINT("UnattendInf path: '%S'\n", UnattendInfPath);
+
     if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
     {
         DPRINT("Does not exist: %S\n", UnattendInfPath);
@@ -50,7 +52,7 @@ CheckUnattendedSetup(
     /* Load 'unattend.inf' from installation media */
     UnattendInf = SetupOpenInfFileExW(UnattendInfPath,
                                       NULL,
-                                      INF_STYLE_WIN4,
+                                      INF_STYLE_OLDNT,
                                       pSetupData->LanguageId,
                                       &ErrorLine);
@@ -263,7 +265,8 @@ InstallSetupInfFile(
 #if 0
     /* TODO: Append the standard unattend.inf file */
-    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2,
pSetupData->SourcePath.Buffer, L"unattend.inf");
+    CombinePaths(UnattendInfPath, ARRAYSIZE(UnattendInfPath), 2,
+                 pSetupData->SourcePath.Buffer, L"unattend.inf");
     if (DoesFileExist(NULL, UnattendInfPath) == FALSE)
     {
         DPRINT("Does not exist: %S\n", UnattendInfPath);
@@ -379,8 +382,6 @@ Quit:
 #endif
 }
-
-
 NTSTATUS
 GetSourcePaths(
     OUT PUNICODE_STRING SourcePath,
@@ -388,41 +389,97 @@ GetSourcePaths(
     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;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UCHAR ImageFileBuffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)];
+    PUNICODE_STRING InstallSourcePath = (PUNICODE_STRING)&ImageFileBuffer;
+    WCHAR SystemRootBuffer[MAX_PATH] = L"";
+    UNICODE_STRING SystemRootPath = RTL_CONSTANT_STRING(L"\\SystemRoot");
+    ULONG BufferSize;
     PWCHAR Ptr;
+    /* Determine the installation source path via the full path of the installer */
+    RtlInitEmptyUnicodeString(InstallSourcePath,
+                              (PWSTR)((ULONG_PTR)ImageFileBuffer +
sizeof(UNICODE_STRING)),
+                              sizeof(ImageFileBuffer) - sizeof(UNICODE_STRING)
+            /* Reserve space for a NULL terminator */ - sizeof(UNICODE_NULL));
+    BufferSize = sizeof(ImageFileBuffer);
+    Status = NtQueryInformationProcess(NtCurrentProcess(),
+                                       ProcessImageFileName,
+                                       InstallSourcePath,
+                                       BufferSize,
+                                       NULL);
+    // STATUS_INFO_LENGTH_MISMATCH or STATUS_BUFFER_TOO_SMALL ?
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* Manually NULL-terminate */
+    InstallSourcePath->Buffer[InstallSourcePath->Length / sizeof(WCHAR)] =
UNICODE_NULL;
+
+    /* Strip the trailing file name */
+    Ptr = wcsrchr(InstallSourcePath->Buffer, OBJ_NAME_PATH_SEPARATOR);
+    if (Ptr)
+        *Ptr = UNICODE_NULL;
+    InstallSourcePath->Length = wcslen(InstallSourcePath->Buffer) * sizeof(WCHAR);
+
+
+    /*
+     * Now resolve the full path to \SystemRoot. In case it prefixes
+     * the installation source path determined from the full path of
+     * the installer, we use instead the resolved \SystemRoot as the
+     * installation source path.
+     * Otherwise, we use instead the path from the full installer path.
+     */
+
     InitializeObjectAttributes(&ObjectAttributes,
-                               &LinkName,
+                               &SystemRootPath,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL);
     Status = NtOpenSymbolicLinkObject(&Handle,
-                                      SYMBOLIC_LINK_ALL_ACCESS,
+                                      SYMBOLIC_LINK_QUERY,
                                       &ObjectAttributes);
     if (!NT_SUCCESS(Status))
-        return Status;
+    {
+        /*
+         * We failed at opening the \SystemRoot link (usually due to wrong
+         * access rights). Do not consider this as a fatal error, but use
+         * instead the image file path as the installation source path.
+         */
+        DPRINT1("NtOpenSymbolicLinkObject(%wZ) failed with Status 0x%08lx\n",
+                &SystemRootPath, Status);
+        goto InitPaths;
+    }
-    RtlInitEmptyUnicodeString(&SourceName, SourceBuffer, sizeof(SourceBuffer));
+    RtlInitEmptyUnicodeString(&SystemRootPath,
+                              SystemRootBuffer,
+                              sizeof(SystemRootBuffer));
     Status = NtQuerySymbolicLinkObject(Handle,
-                                       &SourceName,
-                                       &Length);
+                                       &SystemRootPath,
+                                       &BufferSize);
     NtClose(Handle);
     if (!NT_SUCCESS(Status))
-        return Status;
+        return Status; // Unexpected error
+
+    /* Check whether the resolved \SystemRoot is a prefix of the image file path */
+    if (RtlPrefixUnicodeString(&SystemRootPath, InstallSourcePath, TRUE))
+    {
+        /* Yes it is, so we use instead SystemRoot as the installation source path */
+        InstallSourcePath = &SystemRootPath;
+    }
-    RtlCreateUnicodeString(SourcePath,
-                           SourceName.Buffer);
+
+InitPaths:
+    /*
+     * Retrieve the different source path components
+     */
+    RtlCreateUnicodeString(SourcePath, InstallSourcePath->Buffer);
     /* Strip trailing directory */
-    Ptr = wcsrchr(SourceName.Buffer, OBJ_NAME_PATH_SEPARATOR);
+    Ptr = wcsrchr(InstallSourcePath->Buffer, OBJ_NAME_PATH_SEPARATOR);
     if (Ptr)
     {
         RtlCreateUnicodeString(SourceRootDir, Ptr);
@@ -433,13 +490,11 @@ GetSourcePaths(
         RtlCreateUnicodeString(SourceRootDir, L"");
     }
-    RtlCreateUnicodeString(SourceRootPath,
-                           SourceName.Buffer);
+    RtlCreateUnicodeString(SourceRootPath, InstallSourcePath->Buffer);
     return STATUS_SUCCESS;
 }
-
 ERROR_NUMBER
 LoadSetupInf(
     OUT HINF* SetupInf,
@@ -454,9 +509,11 @@ LoadSetupInf(
     CombinePaths(FileNameBuffer, ARRAYSIZE(FileNameBuffer), 2,
                  pSetupData->SourcePath.Buffer, L"txtsetup.sif");
+    DPRINT("SetupInf path: '%S'\n", FileNameBuffer);
+
     *SetupInf = SetupOpenInfFileExW(FileNameBuffer,
                                    NULL,
-                                   INF_STYLE_WIN4,
+                                   INF_STYLE_WIN4 | INF_STYLE_OLDNT,
                                    pSetupData->LanguageId,
                                    &ErrorLine);