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,
OUT PHANDLE Key
)
{
- OBJECT_ATTRIBUTES Attributes;
+ PWCHAR Buffer;
+ HANDLE Root;
+ 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);
+
+ Root = Parent;
+
+ if (Parent != NULL) {
+ 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;
}
{
ANSI_STRING Ansi;
UNICODE_STRING Unicode;
- OBJECT_ATTRIBUTES Attributes;
NTSTATUS status;
RtlInitAnsiString(&Ansi, Name);
if (!NT_SUCCESS(status))
goto fail1;
- InitializeObjectAttributes(&Attributes,
- &Unicode,
- OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
- Key,
- NULL);
+ status = RegistryCreateKey(Key, &Unicode, Options, SubKey);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ RtlFreeUnicodeString(&Unicode);
+
+ return STATUS_SUCCESS;
+
+fail2:
+ RtlFreeUnicodeString(&Unicode);
+
+fail1:
+ return status;
+}
- status = ZwCreateKey(SubKey,
- KEY_ALL_ACCESS,
- &Attributes,
- 0,
- NULL,
- Options,
- NULL
- );
+NTSTATUS
+RegistryDeleteSubKey(
+ IN PHANDLE Key,
+ IN PCHAR Name
+ )
+{
+ ANSI_STRING Ansi;
+ UNICODE_STRING Unicode;
+ HANDLE SubKey;
+ NTSTATUS status;
+
+ RtlInitAnsiString(&Ansi, Name);
+
+ status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
+ status = RegistryOpenKey(Key, &Unicode, KEY_ALL_ACCESS, &SubKey);
if (!NT_SUCCESS(status))
goto fail2;
+ status = ZwDeleteKey(SubKey);
+ if (!NT_SUCCESS(status))
+ goto fail3;
+
+ ZwClose(SubKey);
+
+ (VOID) ZwFlushKey(Key);
+
RtlFreeUnicodeString(&Unicode);
return STATUS_SUCCESS;
+fail3:
+ ZwClose(SubKey);
+
fail2:
RtlFreeUnicodeString(&Unicode);
return status;
}
-static NTSTATUS
-RegistryDeleteSubKeyTree(
- IN PVOID Context,
- IN PHANDLE Key,
- IN PANSI_STRING Name
- )
-{
- HANDLE SubKey;
- NTSTATUS status;
-
- UNREFERENCED_PARAMETER(Context);
-
- status = RegistryOpenSubKey(Key,
- Name->Buffer,
- KEY_ALL_ACCESS,
- &SubKey);
- if (!NT_SUCCESS(status))
- goto fail1;
-
- (VOID) RegistryEnumerateSubKeys(SubKey,
- RegistryDeleteSubKeyTree,
- NULL);
-
- status = ZwDeleteKey(SubKey);
- if (!NT_SUCCESS(status))
- goto fail2;
-
- ZwClose(SubKey);
-
- return STATUS_SUCCESS;
-
-fail2:
- ZwClose(SubKey);
-
-fail1:
- return status;
-}
-
-NTSTATUS
-RegistryDeleteSubKey(
- IN PHANDLE Key,
- IN PCHAR Name
- )
-{
- ANSI_STRING Ansi;
- NTSTATUS status;
-
- RtlInitAnsiString(&Ansi, Name);
-
- status = RegistryDeleteSubKeyTree(NULL,
- Key,
- &Ansi);
-
- (VOID) ZwFlushKey(Key);
-
- return status;
-}
-
NTSTATUS
RegistryEnumerateValues(
IN HANDLE Key,