[SETUPLIB] Properly cleanup the temporary registry keys created for setting up the...
[reactos.git] / base / setup / lib / utils / regutil.c
index f70d954..60e0e9f 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/* GLOBALS ******************************************************************/
+
+static UNICODE_STRING SymbolicLinkValueName =
+    RTL_CONSTANT_STRING(L"SymbolicLinkValue");
+
 /* FUNCTIONS ****************************************************************/
 
 /*
@@ -80,7 +85,7 @@ CreateNestedKey(PHANDLE KeyHandle,
                              &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)
@@ -244,19 +249,17 @@ CreateRegistryFile(
     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 */
@@ -264,11 +267,11 @@ CmpLinkKeyToHive(
     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,
@@ -277,39 +280,108 @@ CmpLinkKeyToHive(
                          &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;
 }
 
 /*
@@ -317,7 +389,7 @@ CmpLinkKeyToHive(
  */
 NTSTATUS
 ConnectRegistry(
-    IN HKEY RootKey OPTIONAL,
+    IN HANDLE RootKey OPTIONAL,
     IN PCWSTR RegMountPoint,
     // IN HANDLE RootDirectory OPTIONAL,
     IN PUNICODE_STRING NtSystemRoot,
@@ -358,7 +430,7 @@ ConnectRegistry(
  */
 NTSTATUS
 DisconnectRegistry(
-    IN HKEY RootKey OPTIONAL,
+    IN HANDLE RootKey OPTIONAL,
     IN PCWSTR RegMountPoint,
     IN ULONG Flags)
 {
@@ -381,7 +453,7 @@ DisconnectRegistry(
  */
 NTSTATUS
 VerifyRegistryHive(
-    // IN HKEY RootKey OPTIONAL,
+    // IN HANDLE RootKey OPTIONAL,
     // // IN HANDLE RootDirectory OPTIONAL,
     IN PUNICODE_STRING NtSystemRoot,
     IN PCWSTR RegistryKey /* ,