3 * Copyright (C) 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/registry.c
23 * PURPOSE: Registry creation functions
27 /* INCLUDES *****************************************************************/
34 #define FLG_ADDREG_BINVALUETYPE 0x00000001
35 #define FLG_ADDREG_NOCLOBBER 0x00000002
36 #define FLG_ADDREG_DELVAL 0x00000004
37 #define FLG_ADDREG_APPEND 0x00000008
38 #define FLG_ADDREG_KEYONLY 0x00000010
39 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
40 #define FLG_ADDREG_TYPE_SZ 0x00000000
41 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
42 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
43 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
44 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
45 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
46 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
49 #define Architecture L"x86"
50 #elif defined(_M_AMD64)
51 #define Architecture L"amd64"
52 #elif defined(_M_IA64)
53 #define Architecture L"ia64"
55 #define Architecture L"arm"
57 #define Architecture L"ppc"
60 /* FUNCTIONS ****************************************************************/
62 typedef struct _ROOT_KEY
67 } ROOT_KEY
, *PROOT_KEY
;
71 // L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SOFTWARE\\Classes\\"
72 { L
"HKCR", L
"\\Registry\\Machine\\USetup_SOFTWARE\\Classes\\", NULL
}, /* "\\Registry\\Machine\\SOFTWARE\\Classes\\" */ // HKEY_CLASSES_ROOT
73 { L
"HKCU", L
"\\Registry\\User\\USetup_DEFAULT\\" , NULL
}, /* "\\Registry\\User\\.DEFAULT\\" */ // HKEY_CURRENT_USER
74 { L
"HKLM", L
"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\" , NULL
}, /* "\\Registry\\Machine\\" */ // HKEY_LOCAL_MACHINE
75 { L
"HKU" , L
"\\Registry\\Machine\\SYSTEM\\USetup_User\\" , NULL
}, /* "\\Registry\\User\\" */ // HKEY_USERS
77 { L
"HKR", NULL
, NULL
},
81 #define IsPredefKey(HKey) \
82 (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
84 #define GetPredefKeyIndex(HKey) \
85 ((ULONG_PTR)(HKey) & 0x0FFFFFFF)
88 GetRootKeyByPredefKey(
90 OUT PCWSTR
* RootKeyMountPoint OPTIONAL
)
92 ULONG_PTR Index
= GetPredefKeyIndex(KeyHandle
);
94 if (!IsPredefKey(KeyHandle
))
96 if (GetPredefKeyIndex(KeyHandle
) >= ARRAYSIZE(RootKeys
))
99 if (RootKeyMountPoint
)
100 *RootKeyMountPoint
= RootKeys
[Index
].MountPoint
;
101 return RootKeys
[Index
].Handle
;
106 IN PCWSTR RootKeyName
,
107 OUT PCWSTR
* RootKeyMountPoint OPTIONAL
)
111 for (i
= 0; i
< ARRAYSIZE(RootKeys
); ++i
)
113 if (!_wcsicmp(RootKeyName
, RootKeys
[i
].Name
))
115 if (RootKeyMountPoint
)
116 *RootKeyMountPoint
= RootKeys
[i
].MountPoint
;
117 return RootKeys
[i
].Handle
;
125 /***********************************************************************
126 * append_multi_sz_value
128 * Append a multisz string to a multisz registry value.
130 // NOTE: Synced with setupapi/install.c ; see also mkhive/reginf.c
133 append_multi_sz_value (HANDLE hkey
,
135 const WCHAR
*strings
,
138 DWORD size
, type
, total
;
141 if (RegQueryValueExW( hkey
, value
, NULL
, &type
, NULL
, &size
)) return;
142 if (type
!= REG_MULTI_SZ
) return;
144 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
+ str_size
* sizeof(WCHAR
) ))) return;
145 if (RegQueryValueExW( hkey
, value
, NULL
, NULL
, (BYTE
*)buffer
, &size
)) goto done
;
147 /* compare each string against all the existing ones */
151 int len
= strlenW(strings
) + 1;
153 for (p
= buffer
; *p
; p
+= strlenW(p
) + 1)
154 if (!strcmpiW( p
, strings
)) break;
156 if (!*p
) /* not found, need to append it */
158 memcpy( p
, strings
, len
* sizeof(WCHAR
) );
166 TRACE( "setting value %s to %s\n", debugstr_w(value
), debugstr_w(buffer
) );
167 RegSetValueExW( hkey
, value
, 0, REG_MULTI_SZ
, (BYTE
*)buffer
, total
);
170 HeapFree( GetProcessHeap(), 0, buffer
);
174 /***********************************************************************
175 * delete_multi_sz_value
177 * Remove a string from a multisz registry value.
180 static void delete_multi_sz_value( HKEY hkey
, const WCHAR
*value
, const WCHAR
*string
)
183 WCHAR
*buffer
, *src
, *dst
;
185 if (RegQueryValueExW( hkey
, value
, NULL
, &type
, NULL
, &size
)) return;
186 if (type
!= REG_MULTI_SZ
) return;
187 /* allocate double the size, one for value before and one for after */
188 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
* 2 * sizeof(WCHAR
) ))) return;
189 if (RegQueryValueExW( hkey
, value
, NULL
, NULL
, (BYTE
*)buffer
, &size
)) goto done
;
194 int len
= strlenW(src
) + 1;
195 if (strcmpiW( src
, string
))
197 memcpy( dst
, src
, len
* sizeof(WCHAR
) );
203 if (dst
!= buffer
+ 2*size
) /* did we remove something? */
205 TRACE( "setting value %s to %s\n", debugstr_w(value
), debugstr_w(buffer
+ size
) );
206 RegSetValueExW( hkey
, value
, 0, REG_MULTI_SZ
,
207 (BYTE
*)(buffer
+ size
), dst
- (buffer
+ size
) );
210 HeapFree( GetProcessHeap(), 0, buffer
);
214 /***********************************************************************
217 * Perform an add/delete registry operation depending on the flags.
220 do_reg_operation(HANDLE KeyHandle
,
221 PUNICODE_STRING ValueName
,
229 if (Flags
& FLG_ADDREG_DELVAL
) /* deletion */
234 RegDeleteValueW( KeyHandle
, ValueName
);
238 RegDeleteKeyW( KeyHandle
, NULL
);
244 if (Flags
& FLG_ADDREG_KEYONLY
)
248 if (Flags
& (FLG_ADDREG_NOCLOBBER
| FLG_ADDREG_OVERWRITEONLY
))
250 BOOL exists
= !RegQueryValueExW( hkey
, ValueName
, NULL
, NULL
, NULL
, NULL
);
251 if (exists
&& (flags
& FLG_ADDREG_NOCLOBBER
))
253 if (!exists
& (flags
& FLG_ADDREG_OVERWRITEONLY
))
258 switch (Flags
& FLG_ADDREG_TYPE_MASK
)
260 case FLG_ADDREG_TYPE_SZ
:
264 case FLG_ADDREG_TYPE_MULTI_SZ
:
268 case FLG_ADDREG_TYPE_EXPAND_SZ
:
269 Type
= REG_EXPAND_SZ
;
272 case FLG_ADDREG_TYPE_BINARY
:
276 case FLG_ADDREG_TYPE_DWORD
:
280 case FLG_ADDREG_TYPE_NONE
:
289 if (!(Flags
& FLG_ADDREG_BINVALUETYPE
) ||
290 (Type
== REG_DWORD
&& SetupGetFieldCount (Context
) == 5))
294 if (Type
== REG_MULTI_SZ
)
296 if (!SetupGetMultiSzFieldW (Context
, 5, NULL
, 0, &Size
))
301 Str
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
, 0, Size
* sizeof(WCHAR
));
305 SetupGetMultiSzFieldW (Context
, 5, Str
, Size
, NULL
);
308 if (Flags
& FLG_ADDREG_APPEND
)
313 DPRINT1("append_multi_sz_value '%S' commented out, WHY??\n", ValueName
);
314 // append_multi_sz_value( hkey, value, str, size );
316 RtlFreeHeap (ProcessHeap
, 0, Str
);
319 /* else fall through to normal string handling */
323 if (!SetupGetStringFieldW(Context
, 5, NULL
, 0, &Size
))
328 Str
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
, 0, Size
* sizeof(WCHAR
));
332 SetupGetStringFieldW(Context
, 5, Str
, Size
, NULL
);
336 if (Type
== REG_DWORD
)
338 ULONG dw
= Str
? wcstoul (Str
, NULL
, 0) : 0;
340 DPRINT("setting dword %wZ to %lx\n", ValueName
, dw
);
342 NtSetValueKey (KeyHandle
,
351 DPRINT("setting value %wZ to %S\n", ValueName
, Str
);
355 NtSetValueKey (KeyHandle
,
360 Size
* sizeof(WCHAR
));
364 NtSetValueKey (KeyHandle
,
372 RtlFreeHeap (ProcessHeap
, 0, Str
);
374 else /* get the binary data */
378 if (!SetupGetBinaryField (Context
, 5, NULL
, 0, &Size
))
383 Data
= (unsigned char*) RtlAllocateHeap(ProcessHeap
, 0, Size
);
387 DPRINT("setting binary data %wZ len %lu\n", ValueName
, Size
);
388 SetupGetBinaryField (Context
, 5, Data
, Size
, NULL
);
391 NtSetValueKey (KeyHandle
,
398 RtlFreeHeap (ProcessHeap
, 0, Data
);
405 CreateNestedKey(PHANDLE KeyHandle
,
406 ACCESS_MASK DesiredAccess
,
407 POBJECT_ATTRIBUTES ObjectAttributes
)
409 OBJECT_ATTRIBUTES LocalObjectAttributes
;
410 UNICODE_STRING LocalKeyName
;
413 USHORT FullNameLength
;
415 HANDLE LocalKeyHandle
;
417 Status
= NtCreateKey(KeyHandle
,
424 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
425 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
428 /* Copy object attributes */
429 RtlCopyMemory(&LocalObjectAttributes
,
431 sizeof(OBJECT_ATTRIBUTES
));
432 RtlCreateUnicodeString(&LocalKeyName
,
433 ObjectAttributes
->ObjectName
->Buffer
);
434 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
435 FullNameLength
= LocalKeyName
.Length
;
437 /* Remove the last part of the key name and try to create the key again. */
438 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
440 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
441 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
443 Status
= STATUS_UNSUCCESSFUL
;
447 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
449 Status
= NtCreateKey(&LocalKeyHandle
,
451 &LocalObjectAttributes
,
456 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
459 if (!NT_SUCCESS(Status
))
461 RtlFreeUnicodeString (&LocalKeyName
);
465 /* Add removed parts of the key name and create them too. */
468 if (LocalKeyName
.Length
== FullNameLength
)
470 Status
= STATUS_SUCCESS
;
471 *KeyHandle
= LocalKeyHandle
;
474 NtClose(LocalKeyHandle
);
476 LocalKeyName
.Buffer
[LocalKeyName
.Length
/ sizeof(WCHAR
)] = L
'\\';
477 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
479 Status
= NtCreateKey(&LocalKeyHandle
,
481 &LocalObjectAttributes
,
486 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
487 if (!NT_SUCCESS(Status
))
491 RtlFreeUnicodeString(&LocalKeyName
);
496 /***********************************************************************
499 * Called once for each AddReg and DelReg entry in a given section.
502 registry_callback(HINF hInf
, PCWSTR Section
, BOOLEAN Delete
)
505 OBJECT_ATTRIBUTES ObjectAttributes
;
506 UNICODE_STRING Name
, Value
;
507 PUNICODE_STRING ValuePtr
;
509 WCHAR Buffer
[MAX_INF_STRING_LENGTH
];
513 HANDLE RootKeyHandle
, KeyHandle
;
516 Ok
= SetupFindFirstLineW(hInf
, Section
, NULL
, &Context
);
518 return TRUE
; /* Don't fail if the section isn't present */
520 for (;Ok
; Ok
= SetupFindNextLine (&Context
, &Context
))
523 if (!SetupGetStringFieldW(&Context
, 1, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
525 RootKeyHandle
= GetRootKeyByName(Buffer
, &RootKeyName
);
530 if (!SetupGetStringFieldW(&Context
, 2, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
533 DPRINT("KeyName: <%S\\%S>\n", RootKeyName
, Buffer
);
536 if (!SetupGetIntField(&Context
, 4, (PINT
)&Flags
))
539 DPRINT("Flags: %lx\n", Flags
);
541 RtlInitUnicodeString(&Name
, Buffer
);
542 InitializeObjectAttributes(&ObjectAttributes
,
544 OBJ_CASE_INSENSITIVE
,
548 if (Delete
|| (Flags
& FLG_ADDREG_OVERWRITEONLY
))
550 Status
= NtOpenKey(&KeyHandle
,
553 if (!NT_SUCCESS(Status
))
555 DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &Name
, Status
);
556 continue; /* ignore if it doesn't exist */
561 Status
= CreateNestedKey(&KeyHandle
,
564 if (!NT_SUCCESS(Status
))
566 DPRINT1("CreateNestedKey(%wZ) failed (Status %lx)\n", &Name
, Status
);
572 if (SetupGetStringFieldW(&Context
, 3, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
574 RtlInitUnicodeString(&Value
, Buffer
);
583 if (!do_reg_operation(KeyHandle
, ValuePtr
, &Context
, Flags
))
603 WCHAR FileNameBuffer
[MAX_PATH
];
607 /* Load inf file from install media. */
608 CombinePaths(FileNameBuffer
, ARRAYSIZE(FileNameBuffer
), 2,
609 SourcePath
.Buffer
, Filename
);
611 hInf
= SetupOpenInfFileW(FileNameBuffer
,
616 if (hInf
== INVALID_HANDLE_VALUE
)
618 DPRINT1("SetupOpenInfFile() failed\n");
623 if (!registry_callback(hInf
, L
"DelReg", FALSE
))
625 DPRINT1("registry_callback() failed\n");
631 if (!registry_callback(hInf
, L
"AddReg", FALSE
))
633 DPRINT1("registry_callback() failed\n");
638 if (!registry_callback(hInf
, L
"AddReg.NT" Architecture
, FALSE
))
640 DPRINT1("registry_callback() failed\n");
650 * Should be called under privileges
655 IN PUNICODE_STRING InstallPath
,
656 IN PCWSTR RegistryKey
,
657 IN HANDLE ProtoKeyHandle
)
661 UNICODE_STRING FileName
;
662 OBJECT_ATTRIBUTES ObjectAttributes
;
663 IO_STATUS_BLOCK IoStatusBlock
;
664 WCHAR PathBuffer
[MAX_PATH
];
666 /* Create the file */
667 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 3,
668 InstallPath
->Buffer
, L
"System32\\config", RegistryKey
);
669 RtlInitUnicodeString(&FileName
, PathBuffer
);
670 InitializeObjectAttributes(&ObjectAttributes
,
672 OBJ_CASE_INSENSITIVE
,
673 NULL
, // Could have been installpath, etc...
676 Status
= NtCreateFile(&FileHandle
,
681 FILE_ATTRIBUTE_NORMAL
,
684 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
,
687 if (!NT_SUCCESS(Status
))
689 DPRINT1("NtCreateFile(%wZ) failed, Status 0x%08lx\n", &FileName
, Status
);
693 /* Save the selected hive into the file */
694 Status
= NtSaveKeyEx(ProtoKeyHandle
, FileHandle
, REG_LATEST_FORMAT
);
695 if (!NT_SUCCESS(Status
))
697 DPRINT1("NtSaveKeyEx(%wZ) failed, Status 0x%08lx\n", &FileName
, Status
);
700 /* Close the file and return */
707 IN HANDLE RootLinkKeyHandle OPTIONAL
,
708 IN PCWSTR LinkKeyName
,
709 IN PCWSTR TargetKeyName
)
711 static UNICODE_STRING CmSymbolicLinkValueName
=
712 RTL_CONSTANT_STRING(L
"SymbolicLinkValue");
715 OBJECT_ATTRIBUTES ObjectAttributes
;
716 UNICODE_STRING KeyName
;
717 HANDLE TargetKeyHandle
;
720 /* Initialize the object attributes */
721 RtlInitUnicodeString(&KeyName
, LinkKeyName
);
722 InitializeObjectAttributes(&ObjectAttributes
,
724 OBJ_CASE_INSENSITIVE
,
728 /* Create the link key */
729 Status
= NtCreateKey(&TargetKeyHandle
,
730 KEY_SET_VALUE
| KEY_CREATE_LINK
,
734 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
736 if (!NT_SUCCESS(Status
))
738 DPRINT1("CmpLinkKeyToHive: couldn't create %S, Status = 0x%08lx\n",
739 LinkKeyName
, Status
);
743 /* Check if the new key was actually created */
744 if (Disposition
!= REG_CREATED_NEW_KEY
)
746 DPRINT1("CmpLinkKeyToHive: %S already exists!\n", LinkKeyName
);
747 NtClose(TargetKeyHandle
);
751 /* Set the target key name as link target */
752 RtlInitUnicodeString(&KeyName
, TargetKeyName
);
753 Status
= NtSetValueKey(TargetKeyHandle
,
754 &CmSymbolicLinkValueName
,
760 /* Close the link key handle */
761 NtClose(TargetKeyHandle
);
763 if (!NT_SUCCESS(Status
))
765 DPRINT1("CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%08lx\n",
766 TargetKeyName
, Status
);
774 * Should be called under privileges
779 IN HKEY RootKey OPTIONAL
,
780 // IN HANDLE RootDirectory OPTIONAL,
781 IN PUNICODE_STRING InstallPath
,
782 IN PCWSTR RegistryKey
,
783 // IN PUCHAR Descriptor,
784 // IN ULONG DescriptorLength,
785 IN PCWSTR RegMountPoint
)
788 UNICODE_STRING KeyName
, FileName
;
789 OBJECT_ATTRIBUTES KeyObjectAttributes
;
790 OBJECT_ATTRIBUTES FileObjectAttributes
;
791 WCHAR PathBuffer
[MAX_PATH
];
793 RtlInitUnicodeString(&KeyName
, RegMountPoint
);
794 InitializeObjectAttributes(&KeyObjectAttributes
,
796 OBJ_CASE_INSENSITIVE
,
800 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 3,
801 InstallPath
->Buffer
, L
"System32\\config", RegistryKey
);
802 RtlInitUnicodeString(&FileName
, PathBuffer
);
803 InitializeObjectAttributes(&FileObjectAttributes
,
805 OBJ_CASE_INSENSITIVE
,
806 NULL
, // RootDirectory,
810 IN PCMHIVE HiveToConnect
;
812 * Add security to the root key.
813 * NOTE: One can implement this using the lpSecurityAttributes
814 * parameter of RegCreateKeyExW.
816 Status
= CmiCreateSecurityKey(&HiveToConnect
->Hive
,
817 HiveToConnect
->Hive
.BaseBlock
->RootCell
,
818 Descriptor
, DescriptorLength
);
819 if (!NT_SUCCESS(Status
))
820 DPRINT1("Failed to add security for root key '%S'\n", Path
);
823 /* Mount the registry hive in the registry namespace */
824 Status
= NtLoadKey(&KeyObjectAttributes
, &FileObjectAttributes
);
830 RegInitializeRegistry(
831 IN PUNICODE_STRING InstallPath
)
835 UNICODE_STRING KeyName
;
836 OBJECT_ATTRIBUTES ObjectAttributes
;
837 BOOLEAN PrivilegeSet
[2] = {FALSE
, FALSE
};
840 PCWSTR RegistryKeys
[] =
844 L
"DEFAULT", // L".DEFAULT",
851 /* Initialize the current session registry */
852 Status
= NtInitializeRegistry(CM_BOOT_FLAG_SETUP
);
853 if (!NT_SUCCESS(Status
))
855 DPRINT1("NtInitializeRegistry() failed (Status %lx)\n", Status
);
860 /* Acquire restore privilege */
861 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[0]);
862 if (!NT_SUCCESS(Status
))
864 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
865 /* Exit prematurely here.... */
869 /* Acquire backup privilege */
870 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[1]);
871 if (!NT_SUCCESS(Status
))
873 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
874 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
875 /* Exit prematurely here.... */
880 * Create the template proto-hive.
882 * Use a dummy root key name:
883 * - On 2k/XP/2k3, this is "$$$PROTO.HIV"
884 * - On Vista+, this is "CMI-CreateHive{guid}"
885 * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc
886 * for more information.
888 RtlInitUnicodeString(&KeyName
,
889 L
"\\Registry\\Machine\\SYSTEM\\$$$PROTO.HIV");
890 InitializeObjectAttributes(&ObjectAttributes
,
892 OBJ_CASE_INSENSITIVE
,
895 Status
= NtCreateKey(&KeyHandle
,
900 REG_OPTION_NON_VOLATILE
,
902 if (!NT_SUCCESS(Status
))
904 DPRINT1("NtCreateKey() failed to create the proto-hive (Status %lx)\n", Status
);
907 NtFlushKey(KeyHandle
);
909 for (i
= 0; i
< ARRAYSIZE(RegistryKeys
); ++i
)
911 Status
= CreateRegistryFile(InstallPath
,
914 if (!NT_SUCCESS(Status
))
916 DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryKeys
[i
], Status
);
917 /* Exit prematurely here.... */
918 /* That is now done, clean everything up! */
919 NtDeleteKey(KeyHandle
);
925 /* That is now done, clean everything up! */
926 NtDeleteKey(KeyHandle
);
931 * Prepare the installation roots. Since we cannot create real registry keys
932 * inside the master keys (\Registry, \Registry\Machine or \Registry\User),
933 * we need to perform some SymLink tricks instead.
936 /* Our offline HKLM '\Registry\Machine' is inside '\Registry\Machine\SYSTEM\USetup_Machine' */
937 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].MountPoint
);
938 InitializeObjectAttributes(&ObjectAttributes
,
940 OBJ_CASE_INSENSITIVE
,
944 Status
= NtCreateKey(&KeyHandle
,
951 if (!NT_SUCCESS(Status
))
953 DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName
, Status
);
956 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
= KeyHandle
;
958 /* Our offline HKU '\Registry\User' is inside '\Registry\Machine\SYSTEM\USetup_User' */
959 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].MountPoint
);
960 InitializeObjectAttributes(&ObjectAttributes
,
962 OBJ_CASE_INSENSITIVE
,
966 Status
= NtCreateKey(&KeyHandle
,
973 if (!NT_SUCCESS(Status
))
975 DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName
, Status
);
978 RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].Handle
= KeyHandle
;
983 * Now properly mount the offline hive files
986 /* Create SYSTEM key */
988 ConnectRegistry(NULL
,
991 // SystemSecurity, sizeof(SystemSecurity),
992 L
"\\Registry\\Machine\\USetup_SYSTEM");
993 if (!NT_SUCCESS(Status
))
995 DPRINT1("ConnectRegistry(SYSTEM) failed, Status 0x%08lx\n", Status
);
998 /* Create the 'HKLM\SYSTEM' symlink to this key */
999 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1001 L
"\\Registry\\Machine\\USetup_SYSTEM"))
1003 DPRINT1("CmpLinkKeyToHive(SYSTEM) failed!\n");
1007 /* Create SOFTWARE key */
1009 ConnectRegistry(NULL
,
1012 // SoftwareSecurity, sizeof(SoftwareSecurity),
1013 L
"\\Registry\\Machine\\USetup_SOFTWARE");
1014 if (!NT_SUCCESS(Status
))
1016 DPRINT1("ConnectRegistry(SOFTWARE) failed, Status 0x%08lx\n", Status
);
1019 /* Create the 'HKLM\Software' symlink to this key */
1020 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1022 L
"\\Registry\\Machine\\USetup_SOFTWARE"))
1024 DPRINT1("CmpLinkKeyToHive(SOFTWARE) failed!\n");
1028 /* Create DEFAULT key */
1030 ConnectRegistry(NULL
,
1033 // SystemSecurity, sizeof(SystemSecurity),
1034 L
"\\Registry\\User\\USetup_DEFAULT");
1035 if (!NT_SUCCESS(Status
))
1037 DPRINT1("ConnectRegistry(DEFAULT) failed, Status 0x%08lx\n", Status
);
1040 /* Create the 'HKU\.DEFAULT' symlink to this key */
1041 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].Handle
,
1043 L
"\\Registry\\User\\USetup_DEFAULT"))
1045 DPRINT1("CmpLinkKeyToHive(DEFAULT) failed!\n");
1048 /* HKCU is a handle to 'HKU\.DEFAULT' */
1050 RtlInitUnicodeString(&KeyName
, L
".DEFAULT");
1051 InitializeObjectAttributes(&ObjectAttributes
,
1053 OBJ_CASE_INSENSITIVE
,
1054 RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].Handle
,
1057 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_CURRENT_USER
)].MountPoint
);
1058 InitializeObjectAttributes(&ObjectAttributes
,
1060 OBJ_CASE_INSENSITIVE
,
1065 Status
= NtOpenKey(&KeyHandle
,
1068 if (!NT_SUCCESS(Status
))
1070 DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &KeyName
, Status
);
1072 RootKeys
[GetPredefKeyIndex(HKEY_CURRENT_USER
)].Handle
= KeyHandle
;
1075 /* HKCR is a handle to 'HKLM\Software\Classes' */
1077 RtlInitUnicodeString(&KeyName
, L
"Software\\Classes");
1078 InitializeObjectAttributes(&ObjectAttributes
,
1080 OBJ_CASE_INSENSITIVE
,
1081 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1084 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_CLASSES_ROOT
)].MountPoint
);
1085 InitializeObjectAttributes(&ObjectAttributes
,
1087 OBJ_CASE_INSENSITIVE
,
1092 Status
= NtCreateKey(&KeyHandle
,
1099 if (!NT_SUCCESS(Status
))
1101 DPRINT1("NtCreateKey(%wZ) failed (Status %lx)\n", &KeyName
, Status
);
1105 DPRINT1("NtCreateKey() succeeded to %s the %wZ key (Status %lx)\n",
1106 Disposition
== REG_CREATED_NEW_KEY
? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
1109 RootKeys
[GetPredefKeyIndex(HKEY_CLASSES_ROOT
)].Handle
= KeyHandle
;
1113 /* Create SAM key */
1114 ConnectRegistry(NULL
,
1116 // SystemSecurity, sizeof(SystemSecurity),
1117 L
"\\Registry\\Machine\\USetup_SAM");
1119 /* Create SECURITY key */
1120 ConnectRegistry(NULL
,
1123 L
"\\Registry\\Machine\\USetup_SECURITY");
1125 /* Create BCD key */
1126 ConnectRegistry(NULL
,
1128 // BcdSecurity, sizeof(BcdSecurity),
1129 L
"\\Registry\\Machine\\USetup_BCD00000000");
1132 Status
= STATUS_SUCCESS
;
1135 /* Create the 'HKLM\SYSTEM\ControlSet001' key */
1136 // L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SYSTEM\\ControlSet001"
1137 RtlInitUnicodeString(&KeyName
, L
"SYSTEM\\ControlSet001");
1138 InitializeObjectAttributes(&ObjectAttributes
,
1140 OBJ_CASE_INSENSITIVE
,
1141 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1143 Status
= NtCreateKey(&KeyHandle
,
1148 REG_OPTION_NON_VOLATILE
,
1150 if (!NT_SUCCESS(Status
))
1152 DPRINT1("NtCreateKey() failed to create the ControlSet001 key (Status %lx)\n", Status
);
1157 DPRINT1("NtCreateKey() succeeded to %s the ControlSet001 key (Status %lx)\n",
1158 Disposition
== REG_CREATED_NEW_KEY
? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
1163 /* Create the 'HKLM\SYSTEM\CurrentControlSet' symlink */
1164 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1165 L
"SYSTEM\\CurrentControlSet",
1166 L
"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\SYSTEM\\ControlSet001"))
1168 DPRINT1("CmpLinkKeyToHive(CurrentControlSet) failed!\n");
1173 /* Remove restore and backup privileges */
1174 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, PrivilegeSet
[1], FALSE
, &PrivilegeSet
[1]);
1175 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1181 RegCleanupRegistry(VOID
)
1184 UNICODE_STRING KeyName
;
1185 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1186 BOOLEAN PrivilegeSet
[2] = {FALSE
, FALSE
};
1189 for (i
= 0; i
< ARRAYSIZE(RootKeys
); ++i
)
1191 if (RootKeys
[i
].Handle
)
1193 NtClose(RootKeys
[i
].Handle
);
1194 RootKeys
[i
].Handle
= NULL
;
1198 /* Acquire restore privilege */
1199 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[0]);
1200 if (!NT_SUCCESS(Status
))
1202 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1203 /* Exit prematurely here.... */
1207 /* Acquire backup privilege */
1208 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[1]);
1209 if (!NT_SUCCESS(Status
))
1211 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1212 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1213 /* Exit prematurely here.... */
1217 InitializeObjectAttributes(&KeyObjectAttributes
,
1219 OBJ_CASE_INSENSITIVE
,
1223 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_SYSTEM");
1224 Status
= NtUnloadKey(&KeyObjectAttributes
);
1226 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_SOFTWARE");
1227 Status
= NtUnloadKey(&KeyObjectAttributes
);
1229 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\User\\USetup_DEFAULT");
1230 Status
= NtUnloadKey(&KeyObjectAttributes
);
1233 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_SAM");
1234 Status
= NtUnloadKey(&KeyObjectAttributes
);
1236 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_SECURITY");
1237 Status
= NtUnloadKey(&KeyObjectAttributes
);
1239 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_BCD00000000");
1240 Status
= NtUnloadKey(&KeyObjectAttributes
);
1243 /* Remove restore and backup privileges */
1244 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, PrivilegeSet
[1], FALSE
, &PrivilegeSet
[1]);
1245 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1252 OBJECT_ATTRIBUTES ObjectAttributes
;
1253 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
1254 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"PagingFiles");
1255 WCHAR ValueBuffer
[] = L
"?:\\pagefile.sys 0 0\0";
1259 InitializeObjectAttributes(&ObjectAttributes
,
1261 OBJ_CASE_INSENSITIVE
,
1262 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1264 Status
= NtOpenKey(&KeyHandle
,
1267 if (!NT_SUCCESS(Status
))
1270 ValueBuffer
[0] = Drive
;
1272 NtSetValueKey(KeyHandle
,
1276 (PVOID
)&ValueBuffer
,
1277 sizeof(ValueBuffer
));