+BOOLEAN
+NTAPI
+CmpLinkKeyToHive(
+ _In_z_ PCWSTR LinkKeyName,
+ _In_z_ PCWSTR TargetKeyName)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE LinkKeyHandle;
+ ULONG Disposition;
+
+ PAGED_CODE();
+
+ /* Initialize the object attributes */
+ RtlInitUnicodeString(&KeyName, LinkKeyName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ /* Create the link key */
+ Status = ZwCreateKey(&LinkKeyHandle,
+ KEY_CREATE_LINK,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
+ &Disposition);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: couldn't create %S, Status = 0x%lx\n",
+ LinkKeyName, Status);
+ return FALSE;
+ }
+
+ /* Check if the new key was actually created */
+ if (Disposition != REG_CREATED_NEW_KEY)
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: %S already exists!\n", LinkKeyName);
+ ZwClose(LinkKeyHandle);
+ return FALSE;
+ }
+
+ /* Set the target key name as link target */
+ RtlInitUnicodeString(&KeyName, TargetKeyName);
+ Status = ZwSetValueKey(LinkKeyHandle,
+ &CmSymbolicLinkValueName,
+ 0,
+ REG_LINK,
+ KeyName.Buffer,
+ KeyName.Length);
+
+ /* Close the link key handle */
+ ObCloseHandle(LinkKeyHandle, KernelMode);
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("CM: CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%lx\n",
+ TargetKeyName, Status);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+