#define NDEBUG
#include <debug.h>
+/* GLOBALS ******************************************************************/
+
+static UNICODE_STRING SymbolicLinkValueName =
+ RTL_CONSTANT_STRING(L"SymbolicLinkValue");
+
/* FUNCTIONS ****************************************************************/
/*
&LocalObjectAttributes,
0,
NULL,
- REG_OPTION_NON_VOLATILE,
+ REG_OPTION_NON_VOLATILE, // FIXME ?
&Disposition);
DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName, Status);
if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_NAME_NOT_FOUND)
return Status;
}
-BOOLEAN
-CmpLinkKeyToHive(
- IN HANDLE RootLinkKeyHandle OPTIONAL,
+/* Adapted from ntoskrnl/config/cmsysini.c:CmpLinkKeyToHive() */
+NTSTATUS
+CreateSymLinkKey(
+ IN HANDLE RootKey OPTIONAL,
IN PCWSTR LinkKeyName,
IN PCWSTR TargetKeyName)
{
- static UNICODE_STRING CmSymbolicLinkValueName =
- RTL_CONSTANT_STRING(L"SymbolicLinkValue");
-
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
- HANDLE TargetKeyHandle;
+ HANDLE LinkKeyHandle;
ULONG Disposition;
/* Initialize the object attributes */
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
- RootLinkKeyHandle,
+ RootKey,
NULL);
/* Create the link key */
- Status = NtCreateKey(&TargetKeyHandle,
+ Status = NtCreateKey(&LinkKeyHandle,
KEY_SET_VALUE | KEY_CREATE_LINK,
&ObjectAttributes,
0,
&Disposition);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CmpLinkKeyToHive: couldn't create %S, Status = 0x%08lx\n",
+ DPRINT1("CreateSymLinkKey: couldn't create '%S', Status = 0x%08lx\n",
LinkKeyName, Status);
- return FALSE;
+ return Status;
}
/* Check if the new key was actually created */
if (Disposition != REG_CREATED_NEW_KEY)
{
- DPRINT1("CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
- NtClose(TargetKeyHandle);
- return FALSE;
+ DPRINT1("CreateSymLinkKey: %S already exists!\n", LinkKeyName);
+ NtClose(LinkKeyHandle);
+ return STATUS_OBJECT_NAME_EXISTS; // STATUS_OBJECT_NAME_COLLISION;
}
/* Set the target key name as link target */
RtlInitUnicodeString(&KeyName, TargetKeyName);
- Status = NtSetValueKey(TargetKeyHandle,
- &CmSymbolicLinkValueName,
+ Status = NtSetValueKey(LinkKeyHandle,
+ &SymbolicLinkValueName,
0,
REG_LINK,
KeyName.Buffer,
KeyName.Length);
/* Close the link key handle */
- NtClose(TargetKeyHandle);
+ NtClose(LinkKeyHandle);
if (!NT_SUCCESS(Status))
{
- DPRINT1("CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%08lx\n",
- TargetKeyName, Status);
- return FALSE;
+ DPRINT1("CreateSymLinkKey: couldn't create symbolic link '%S' for '%S', Status = 0x%08lx\n",
+ LinkKeyName, TargetKeyName, Status);
}
- return TRUE;
+ return Status;
+}
+
+NTSTATUS
+DeleteSymLinkKey(
+ IN HANDLE RootKey OPTIONAL,
+ IN PCWSTR LinkKeyName)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE LinkKeyHandle;
+ // ULONG Disposition;
+
+ /* Initialize the object attributes */
+ RtlInitUnicodeString(&KeyName, LinkKeyName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ /* Open the symlink key itself if it exists, and not its target */
+ OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
+ RootKey,
+ NULL);
+
+ /*
+ * Note: We could use here NtOpenKey() but it does not allow to pass
+ * opening options. NtOpenKeyEx() could do it but is Windows 7+.
+ * So we use the good old NtCreateKey() that can open the key.
+ */
+#if 0
+ Status = NtCreateKey(&LinkKeyHandle,
+ DELETE | KEY_SET_VALUE | KEY_CREATE_LINK,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ /*REG_OPTION_VOLATILE |*/ REG_OPTION_OPEN_LINK,
+ &Disposition);
+#else
+ Status = NtOpenKey(&LinkKeyHandle,
+ DELETE | KEY_SET_VALUE | KEY_CREATE_LINK,
+ &ObjectAttributes);
+#endif
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &KeyName, Status);
+ return Status;
+ }
+
+ /*
+ * Delete the special "SymbolicLinkValue" value.
+ * This is technically not needed since we are going to remove
+ * the key anyways, but it is good practice to do it.
+ */
+ Status = NtDeleteValueKey(LinkKeyHandle, &SymbolicLinkValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("NtDeleteValueKey(%wZ) failed (Status %lx)\n", &KeyName, Status);
+ NtClose(LinkKeyHandle);
+ return Status;
+ }
+
+ /* Finally delete the key itself and close the link key handle */
+ Status = NtDeleteKey(LinkKeyHandle);
+ NtClose(LinkKeyHandle);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("DeleteSymLinkKey: couldn't delete symbolic link '%S', Status = 0x%08lx\n",
+ LinkKeyName, Status);
+ }
+
+ return Status;
}
/*
*/
NTSTATUS
ConnectRegistry(
- IN HKEY RootKey OPTIONAL,
+ IN HANDLE RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
// IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING NtSystemRoot,
*/
NTSTATUS
DisconnectRegistry(
- IN HKEY RootKey OPTIONAL,
+ IN HANDLE RootKey OPTIONAL,
IN PCWSTR RegMountPoint,
IN ULONG Flags)
{
*/
NTSTATUS
VerifyRegistryHive(
- // IN HKEY RootKey OPTIONAL,
+ // IN HANDLE RootKey OPTIONAL,
// // IN HANDLE RootDirectory OPTIONAL,
IN PUNICODE_STRING NtSystemRoot,
IN PCWSTR RegistryKey /* ,