[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Bring RegistryCreateKey()'s semantics in line with Win32 RegCreateKeyEx()



RegCreateKeyEx() will create intermediate keys in a path whereas
ZwCreateKey() will not. Thus, to align the semantics, this patch will
parse the path passwed to RegistryCreateKey() and create subkeys one by
one.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/common/registry.c | 144 +++++++++++++++++++++++++++++++++++++++-----------
 src/common/util.h     |  42 ++++++++++++++-
 2 files changed, 153 insertions(+), 33 deletions(-)

diff --git a/src/common/registry.c b/src/common/registry.c
index d994e13..2467290 100644
--- a/src/common/registry.c
+++ b/src/common/registry.c
@@ -115,36 +115,132 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+RegistryOpenRoot(
+    IN  PWCHAR          Path,
+    OUT PHANDLE         Parent,
+    OUT PWCHAR          *ChildPath
+    )
+{
+    const WCHAR         Prefix[] = L"\\Registry\\Machine\\";
+    ULONG               Length;
+    UNICODE_STRING      Unicode;
+    NTSTATUS            status;
+
+    Length = (ULONG)wcslen(Prefix);
+
+    status = STATUS_INVALID_PARAMETER;
+    if (_wcsnicmp(Path, Prefix, Length) != 0)
+        goto fail1;
+
+    RtlInitUnicodeString(&Unicode, Prefix);
+
+    status = RegistryOpenKey(NULL, &Unicode, KEY_ALL_ACCESS, Parent);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    *ChildPath = Path + Length;
+
+    return STATUS_SUCCESS;
+
+fail2:
+fail1:
+    return status;
+}
+
 NTSTATUS
 RegistryCreateKey(
-    IN  HANDLE          Parent,
+    IN  HANDLE          Root,
     IN  PUNICODE_STRING Path,
     IN  ULONG           Options,
     OUT PHANDLE         Key
     )
 {
-    OBJECT_ATTRIBUTES   Attributes;
+    PWCHAR              Buffer;
+    HANDLE              Parent;
+    PWCHAR              ChildPath;
+    PWCHAR              ChildName;
+    PWCHAR              Context;
+    HANDLE              Child;
     NTSTATUS            status;
 
-    InitializeObjectAttributes(&Attributes,
-                               Path,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Parent,
-                               NULL);
+    //
+    // UNICODE_STRINGs are not guaranteed to have NUL terminated
+    // buffers.
+    //
 
-    status = ZwCreateKey(Key,
-                         KEY_ALL_ACCESS,
-                         &Attributes,
-                         0,
-                         NULL,
-                         Options,
-                         NULL
-                         );
-    if (!NT_SUCCESS(status))
+    Buffer = __RegistryAllocate(Path->MaximumLength + sizeof (WCHAR));
+
+    status = STATUS_NO_MEMORY;
+    if (Buffer == NULL)
         goto fail1;
 
+    RtlCopyMemory(Buffer, Path->Buffer, Path->Length);
+
+    if (Root != NULL) {
+        Parent = Root;
+        ChildPath = Buffer;
+    } else {
+        status = RegistryOpenRoot(Buffer, &Parent, &ChildPath);
+        if (!NT_SUCCESS(status))
+            goto fail2;
+    }
+
+    ChildName = __wcstok_r(ChildPath, L"\\", &Context);
+
+    status = STATUS_INVALID_PARAMETER;
+    if (ChildName == NULL)
+        goto fail3;
+
+    Child = NULL;
+
+    while (ChildName != NULL) {
+        UNICODE_STRING      Unicode;
+        OBJECT_ATTRIBUTES   Attributes;
+
+        RtlInitUnicodeString(&Unicode, ChildName);
+
+        InitializeObjectAttributes(&Attributes,
+                                   &Unicode,
+                                   OBJ_CASE_INSENSITIVE |
+                                   OBJ_KERNEL_HANDLE |
+                                   OBJ_OPENIF,
+                                   Parent,
+                                   NULL);
+
+        status = ZwCreateKey(&Child,
+                             KEY_ALL_ACCESS,
+                             &Attributes,
+                             0,
+                             NULL,
+                             Options,
+                             NULL
+                             );
+        if (!NT_SUCCESS(status))
+            goto fail4;
+
+        ChildName = __wcstok_r(NULL, L"\\", &Context);
+
+        if (Parent != Root)
+            ZwClose(Parent);
+
+        Parent = Child;
+    }
+
+    ASSERT(Child != NULL);
+
+    *Key = Child;
+
     return STATUS_SUCCESS;
 
+fail4:
+fail3:
+    if (Parent != Root)
+        ZwClose(Parent);
+
+fail2:
+    __RegistryFree(Buffer);
+
 fail1:
     return status;
 }
@@ -308,7 +404,6 @@ RegistryCreateSubKey(
 {
     ANSI_STRING         Ansi;
     UNICODE_STRING      Unicode;
-    OBJECT_ATTRIBUTES   Attributes;
     NTSTATUS            status;
 
     RtlInitAnsiString(&Ansi, Name);
@@ -317,20 +412,7 @@ RegistryCreateSubKey(
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    InitializeObjectAttributes(&Attributes,
-                               &Unicode,
-                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                               Key,
-                               NULL);
-
-    status = ZwCreateKey(SubKey,
-                         KEY_ALL_ACCESS,
-                         &Attributes,
-                         0,
-                         NULL,
-                         Options,
-                         NULL
-                         );
+    status = RegistryCreateKey(Key, &Unicode, Options, SubKey);
     if (!NT_SUCCESS(status))
         goto fail2;
 
diff --git a/src/common/util.h b/src/common/util.h
index 7798ebd..dc8a60e 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -267,16 +267,54 @@ __strtok_r(
     if (Token == NULL)
         return NULL;
 
-    while (*Token != L'\0' &&
+    while (*Token != '\0' &&
            strchr(Delimiter, *Token) != NULL)
         Token++;
 
+    if (*Token == '\0')
+        return NULL;
+
+    End = Token + 1;
+    while (*End != '\0' &&
+           strchr(Delimiter, *End) == NULL)
+        End++;
+
+    if (*End != '\0')
+        *End++ = '\0';
+
+    *Context = End;
+
+    return Token;
+}
+
+static FORCEINLINE PWCHAR
+__wcstok_r(
+    IN      PWCHAR  Buffer,
+    IN      PWCHAR  Delimiter,
+    IN OUT  PWCHAR  *Context
+    )
+{
+    PWCHAR          Token;
+    PWCHAR          End;
+
+    if (Buffer != NULL)
+        *Context = Buffer;
+
+    Token = *Context;
+
+    if (Token == NULL)
+        return NULL;
+
+    while (*Token != L'\0' &&
+           wcschr(Delimiter, *Token) != NULL)
+        Token++;
+
     if (*Token == L'\0')
         return NULL;
 
     End = Token + 1;
     while (*End != L'\0' &&
-           strchr(Delimiter, *End) == NULL)
+           wcschr(Delimiter, *End) == NULL)
         End++;
 
     if (*End != L'\0')
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.