[SETUPLIB] Diverse fixes (incl. initialization fixes).
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 25 Aug 2017 09:19:44 +0000 (09:19 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Sat, 27 Oct 2018 16:13:42 +0000 (18:13 +0200)
- 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
base/setup/lib/setuplib.c

index 677fb9a..db6043c 100644 (file)
@@ -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
index a1744cc..c5a8a6f 100644 (file)
@@ -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);