https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0e6bc236a11de9c62d64cc8f02473162c208cc44

commit 0e6bc236a11de9c62d64cc8f02473162c208cc44
Author:     Hermès Bélusca-Maïto <[email protected]>
AuthorDate: Mon Oct 22 00:39:50 2018 +0200
Commit:     Hermès Bélusca-Maïto <[email protected]>
CommitDate: Mon Oct 22 00:39:50 2018 +0200

    [NTOS:CM] CmpCmdHiveOpen(): Resolve FileAttributes->RootDirectory when a 
hive file name is provided relative to it.
    
    Fixes registry hive loading. CORE-13448
---
 ntoskrnl/config/cmhvlist.c |  3 +-
 ntoskrnl/config/cmlazy.c   | 97 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 95 insertions(+), 5 deletions(-)

diff --git a/ntoskrnl/config/cmhvlist.c b/ntoskrnl/config/cmhvlist.c
index 0428ed7c8c..25f8414052 100644
--- a/ntoskrnl/config/cmhvlist.c
+++ b/ntoskrnl/config/cmhvlist.c
@@ -136,7 +136,8 @@ CmpAddToHiveFileList(IN PCMHIVE Hive)
     PWCHAR FilePath;
     UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
     ULONG Length = sizeof(Buffer);
-    POBJECT_NAME_INFORMATION FileNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
+    POBJECT_NAME_INFORMATION FileNameInfo = (POBJECT_NAME_INFORMATION)Buffer;
+
     HivePath.Buffer = NULL;
 
     /* Create or open the hive list key */
diff --git a/ntoskrnl/config/cmlazy.c b/ntoskrnl/config/cmlazy.c
index cd643452c2..0b19924216 100644
--- a/ntoskrnl/config/cmlazy.c
+++ b/ntoskrnl/config/cmlazy.c
@@ -274,13 +274,97 @@ CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes,
                OUT PCMHIVE *NewHive,
                IN ULONG CheckFlags)
 {
-    PUNICODE_STRING FileName;
     NTSTATUS Status;
+    UNICODE_STRING FileName;
+    PWCHAR FilePath;
+    UCHAR Buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR)];
+    ULONG Length = sizeof(Buffer);
+    POBJECT_NAME_INFORMATION FileNameInfo = (POBJECT_NAME_INFORMATION)Buffer;
+
     PAGED_CODE();
 
+    if (FileAttributes->RootDirectory)
+    {
+        /*
+         * Validity check: The ObjectName is relative to RootDirectory,
+         * therefore it must not start with a path separator.
+         */
+        if (FileAttributes->ObjectName && FileAttributes->ObjectName->Buffer &&
+            FileAttributes->ObjectName->Length >= sizeof(WCHAR) &&
+            *FileAttributes->ObjectName->Buffer == OBJ_NAME_PATH_SEPARATOR)
+        {
+            return STATUS_OBJECT_PATH_SYNTAX_BAD;
+        }
+
+        /* Try to get the value */
+        Status = ZwQueryObject(FileAttributes->RootDirectory,
+                               ObjectNameInformation,
+                               FileNameInfo,
+                               Length,
+                               &Length);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Fail */
+            DPRINT1("CmpCmdHiveOpen(): Root directory handle object name query 
failed, Status = 0x%08lx\n", Status);
+            return Status;
+        }
+
+        /* Null-terminate and add the length of the terminator */
+        Length -= sizeof(OBJECT_NAME_INFORMATION);
+        FilePath = FileNameInfo->Name.Buffer;
+        FilePath[Length / sizeof(WCHAR)] = UNICODE_NULL;
+        Length += sizeof(UNICODE_NULL);
+
+        /* Compute the size of the full path; Length already counts the 
terminating NULL */
+        Length = Length + sizeof(WCHAR) + FileAttributes->ObjectName->Length;
+        if (Length > MAXUSHORT)
+        {
+            /* Name size too long, bail out */
+            return STATUS_OBJECT_PATH_INVALID;
+        }
+
+        /* Build the full path */
+        RtlInitEmptyUnicodeString(&FileName, NULL, 0);
+        FileName.Buffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
+        if (!FileName.Buffer)
+        {
+            /* Fail */
+            DPRINT1("CmpCmdHiveOpen(): Unable to allocate memory\n");
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+        FileName.MaximumLength = Length;
+        RtlCopyUnicodeString(&FileName, &FileNameInfo->Name);
+
+        /*
+         * Append a path terminator if needed (we have already accounted
+         * for a possible extra one when allocating the buffer).
+         */
+        if (/* FileAttributes->ObjectName->Buffer[0] != 
OBJ_NAME_PATH_SEPARATOR && */ // We excluded ObjectName starting with a path 
separator above.
+            FileName.Length > 0 && FileName.Buffer[FileName.Length / 
sizeof(WCHAR) - 1] != OBJ_NAME_PATH_SEPARATOR)
+        {
+            /* ObjectName does not start with '\' and PathBuffer does not end 
with '\' */
+            FileName.Buffer[FileName.Length / sizeof(WCHAR)] = 
OBJ_NAME_PATH_SEPARATOR;
+            FileName.Length += sizeof(WCHAR);
+            FileName.Buffer[FileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
+        }
+
+        /* Append the object name */
+        Status = RtlAppendUnicodeStringToString(&FileName, 
FileAttributes->ObjectName);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Fail */
+            DPRINT1("CmpCmdHiveOpen(): RtlAppendUnicodeStringToString() 
failed, Status = 0x%08lx\n", Status);
+            ExFreePoolWithTag(FileName.Buffer, TAG_CM);
+            return Status;
+        }
+    }
+    else
+    {
+        FileName = *FileAttributes->ObjectName;
+    }
+
     /* Open the file in the current security context */
-    FileName = FileAttributes->ObjectName;
-    Status = CmpInitHiveFromFile(FileName,
+    Status = CmpInitHiveFromFile(&FileName,
                                  0,
                                  NewHive,
                                  Allocate,
@@ -298,7 +382,7 @@ CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes,
         if (NT_SUCCESS(Status))
         {
             /* Now try again */
-            Status = CmpInitHiveFromFile(FileName,
+            Status = CmpInitHiveFromFile(&FileName,
                                          0,
                                          NewHive,
                                          Allocate,
@@ -309,6 +393,11 @@ CmpCmdHiveOpen(IN POBJECT_ATTRIBUTES FileAttributes,
         }
     }
 
+    if (FileAttributes->RootDirectory)
+    {
+        ExFreePoolWithTag(FileName.Buffer, TAG_CM);
+    }
+
     /* Return status of open attempt */
     return Status;
 }

Reply via email to