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 *****************************************************************/
37 #define FLG_ADDREG_BINVALUETYPE 0x00000001
38 #define FLG_ADDREG_NOCLOBBER 0x00000002
39 #define FLG_ADDREG_DELVAL 0x00000004
40 #define FLG_ADDREG_APPEND 0x00000008
41 #define FLG_ADDREG_KEYONLY 0x00000010
42 #define FLG_ADDREG_OVERWRITEONLY 0x00000020
43 #define FLG_ADDREG_TYPE_SZ 0x00000000
44 #define FLG_ADDREG_TYPE_MULTI_SZ 0x00010000
45 #define FLG_ADDREG_TYPE_EXPAND_SZ 0x00020000
46 #define FLG_ADDREG_TYPE_BINARY (0x00000000 | FLG_ADDREG_BINVALUETYPE)
47 #define FLG_ADDREG_TYPE_DWORD (0x00010000 | FLG_ADDREG_BINVALUETYPE)
48 #define FLG_ADDREG_TYPE_NONE (0x00020000 | FLG_ADDREG_BINVALUETYPE)
49 #define FLG_ADDREG_TYPE_MASK (0xFFFF0000 | FLG_ADDREG_BINVALUETYPE)
52 #define Architecture L"x86"
53 #elif defined(_M_AMD64)
54 #define Architecture L"amd64"
55 #elif defined(_M_IA64)
56 #define Architecture L"ia64"
58 #define Architecture L"arm"
60 #define Architecture L"ppc"
63 /* FUNCTIONS ****************************************************************/
65 #define REGISTRY_SETUP_MACHINE L"\\Registry\\Machine\\SYSTEM\\USetup_Machine\\"
66 #define REGISTRY_SETUP_USER L"\\Registry\\Machine\\SYSTEM\\USetup_User\\"
68 typedef struct _ROOT_KEY
73 } ROOT_KEY
, *PROOT_KEY
;
77 { L
"HKCR", REGISTRY_SETUP_MACHINE L
"SOFTWARE\\Classes\\", NULL
}, /* "\\Registry\\Machine\\SOFTWARE\\Classes\\" */ // HKEY_CLASSES_ROOT
78 { L
"HKCU", REGISTRY_SETUP_USER L
".DEFAULT\\" , NULL
}, /* "\\Registry\\User\\.DEFAULT\\" */ // HKEY_CURRENT_USER
79 { L
"HKLM", REGISTRY_SETUP_MACHINE
, NULL
}, /* "\\Registry\\Machine\\" */ // HKEY_LOCAL_MACHINE
80 { L
"HKU" , REGISTRY_SETUP_USER
, NULL
}, /* "\\Registry\\User\\" */ // HKEY_USERS
82 { L
"HKR", NULL
, NULL
},
86 #define IsPredefKey(HKey) \
87 (((ULONG_PTR)(HKey) & 0xF0000000) == 0x80000000)
89 #define GetPredefKeyIndex(HKey) \
90 ((ULONG_PTR)(HKey) & 0x0FFFFFFF)
93 GetRootKeyByPredefKey(
95 OUT PCWSTR
* RootKeyMountPoint OPTIONAL
)
97 ULONG_PTR Index
= GetPredefKeyIndex(KeyHandle
);
99 if (!IsPredefKey(KeyHandle
))
101 if (GetPredefKeyIndex(KeyHandle
) >= ARRAYSIZE(RootKeys
))
104 if (RootKeyMountPoint
)
105 *RootKeyMountPoint
= RootKeys
[Index
].MountPoint
;
106 return RootKeys
[Index
].Handle
;
111 IN PCWSTR RootKeyName
,
112 OUT PCWSTR
* RootKeyMountPoint OPTIONAL
)
116 for (i
= 0; i
< ARRAYSIZE(RootKeys
); ++i
)
118 if (!_wcsicmp(RootKeyName
, RootKeys
[i
].Name
))
120 if (RootKeyMountPoint
)
121 *RootKeyMountPoint
= RootKeys
[i
].MountPoint
;
122 return RootKeys
[i
].Handle
;
130 /***********************************************************************
131 * append_multi_sz_value
133 * Append a multisz string to a multisz registry value.
135 // NOTE: Synced with setupapi/install.c ; see also mkhive/reginf.c
138 append_multi_sz_value (HANDLE hkey
,
140 const WCHAR
*strings
,
143 DWORD size
, type
, total
;
146 if (RegQueryValueExW( hkey
, value
, NULL
, &type
, NULL
, &size
)) return;
147 if (type
!= REG_MULTI_SZ
) return;
149 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
+ str_size
* sizeof(WCHAR
) ))) return;
150 if (RegQueryValueExW( hkey
, value
, NULL
, NULL
, (BYTE
*)buffer
, &size
)) goto done
;
152 /* compare each string against all the existing ones */
156 int len
= strlenW(strings
) + 1;
158 for (p
= buffer
; *p
; p
+= strlenW(p
) + 1)
159 if (!strcmpiW( p
, strings
)) break;
161 if (!*p
) /* not found, need to append it */
163 memcpy( p
, strings
, len
* sizeof(WCHAR
) );
171 TRACE( "setting value %s to %s\n", debugstr_w(value
), debugstr_w(buffer
) );
172 RegSetValueExW( hkey
, value
, 0, REG_MULTI_SZ
, (BYTE
*)buffer
, total
);
175 HeapFree( GetProcessHeap(), 0, buffer
);
179 /***********************************************************************
180 * delete_multi_sz_value
182 * Remove a string from a multisz registry value.
185 static void delete_multi_sz_value( HKEY hkey
, const WCHAR
*value
, const WCHAR
*string
)
188 WCHAR
*buffer
, *src
, *dst
;
190 if (RegQueryValueExW( hkey
, value
, NULL
, &type
, NULL
, &size
)) return;
191 if (type
!= REG_MULTI_SZ
) return;
192 /* allocate double the size, one for value before and one for after */
193 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
* 2 * sizeof(WCHAR
) ))) return;
194 if (RegQueryValueExW( hkey
, value
, NULL
, NULL
, (BYTE
*)buffer
, &size
)) goto done
;
199 int len
= strlenW(src
) + 1;
200 if (strcmpiW( src
, string
))
202 memcpy( dst
, src
, len
* sizeof(WCHAR
) );
208 if (dst
!= buffer
+ 2*size
) /* did we remove something? */
210 TRACE( "setting value %s to %s\n", debugstr_w(value
), debugstr_w(buffer
+ size
) );
211 RegSetValueExW( hkey
, value
, 0, REG_MULTI_SZ
,
212 (BYTE
*)(buffer
+ size
), dst
- (buffer
+ size
) );
215 HeapFree( GetProcessHeap(), 0, buffer
);
219 /***********************************************************************
222 * Perform an add/delete registry operation depending on the flags.
225 do_reg_operation(HANDLE KeyHandle
,
226 PUNICODE_STRING ValueName
,
234 if (Flags
& FLG_ADDREG_DELVAL
) /* deletion */
239 RegDeleteValueW( KeyHandle
, ValueName
);
243 RegDeleteKeyW( KeyHandle
, NULL
);
249 if (Flags
& FLG_ADDREG_KEYONLY
)
253 if (Flags
& (FLG_ADDREG_NOCLOBBER
| FLG_ADDREG_OVERWRITEONLY
))
255 BOOL exists
= !RegQueryValueExW( hkey
, ValueName
, NULL
, NULL
, NULL
, NULL
);
256 if (exists
&& (flags
& FLG_ADDREG_NOCLOBBER
))
258 if (!exists
& (flags
& FLG_ADDREG_OVERWRITEONLY
))
263 switch (Flags
& FLG_ADDREG_TYPE_MASK
)
265 case FLG_ADDREG_TYPE_SZ
:
269 case FLG_ADDREG_TYPE_MULTI_SZ
:
273 case FLG_ADDREG_TYPE_EXPAND_SZ
:
274 Type
= REG_EXPAND_SZ
;
277 case FLG_ADDREG_TYPE_BINARY
:
281 case FLG_ADDREG_TYPE_DWORD
:
285 case FLG_ADDREG_TYPE_NONE
:
294 if (!(Flags
& FLG_ADDREG_BINVALUETYPE
) ||
295 (Type
== REG_DWORD
&& SetupGetFieldCount (Context
) == 5))
299 if (Type
== REG_MULTI_SZ
)
301 if (!SetupGetMultiSzFieldW (Context
, 5, NULL
, 0, &Size
))
306 Str
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
, 0, Size
* sizeof(WCHAR
));
310 SetupGetMultiSzFieldW (Context
, 5, Str
, Size
, NULL
);
313 if (Flags
& FLG_ADDREG_APPEND
)
318 DPRINT1("append_multi_sz_value '%S' commented out, WHY??\n", ValueName
);
319 // append_multi_sz_value( hkey, value, str, size );
321 RtlFreeHeap (ProcessHeap
, 0, Str
);
324 /* else fall through to normal string handling */
328 if (!SetupGetStringFieldW(Context
, 5, NULL
, 0, &Size
))
333 Str
= (WCHAR
*)RtlAllocateHeap(ProcessHeap
, 0, Size
* sizeof(WCHAR
));
337 SetupGetStringFieldW(Context
, 5, Str
, Size
, NULL
);
341 if (Type
== REG_DWORD
)
343 ULONG dw
= Str
? wcstoul (Str
, NULL
, 0) : 0;
345 DPRINT("setting dword %wZ to %lx\n", ValueName
, dw
);
347 NtSetValueKey (KeyHandle
,
356 DPRINT("setting value %wZ to %S\n", ValueName
, Str
);
360 NtSetValueKey (KeyHandle
,
365 Size
* sizeof(WCHAR
));
369 NtSetValueKey (KeyHandle
,
377 RtlFreeHeap (ProcessHeap
, 0, Str
);
379 else /* get the binary data */
383 if (!SetupGetBinaryField (Context
, 5, NULL
, 0, &Size
))
388 Data
= (unsigned char*) RtlAllocateHeap(ProcessHeap
, 0, Size
);
392 DPRINT("setting binary data %wZ len %lu\n", ValueName
, Size
);
393 SetupGetBinaryField (Context
, 5, Data
, Size
, NULL
);
396 NtSetValueKey (KeyHandle
,
403 RtlFreeHeap (ProcessHeap
, 0, Data
);
410 * This function is similar to the one in dlls/win32/advapi32/reg/reg.c
411 * TODO: I should review both of them very carefully, because they may need
412 * some adjustments in their NtCreateKey calls, especially for CreateOptions
416 CreateNestedKey(PHANDLE KeyHandle
,
417 ACCESS_MASK DesiredAccess
,
418 POBJECT_ATTRIBUTES ObjectAttributes
,
421 OBJECT_ATTRIBUTES LocalObjectAttributes
;
422 UNICODE_STRING LocalKeyName
;
425 USHORT FullNameLength
;
427 HANDLE LocalKeyHandle
;
429 Status
= NtCreateKey(KeyHandle
,
436 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
437 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
439 if (!NT_SUCCESS(Status
))
440 DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
445 /* Copy object attributes */
446 RtlCopyMemory(&LocalObjectAttributes
,
448 sizeof(OBJECT_ATTRIBUTES
));
449 RtlCreateUnicodeString(&LocalKeyName
,
450 ObjectAttributes
->ObjectName
->Buffer
);
451 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
452 FullNameLength
= LocalKeyName
.Length
;
454 /* Remove the last part of the key name and try to create the key again. */
455 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
457 Ptr
= wcsrchr(LocalKeyName
.Buffer
, '\\');
458 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
460 Status
= STATUS_UNSUCCESSFUL
;
464 LocalKeyName
.Length
= wcslen(LocalKeyName
.Buffer
) * sizeof(WCHAR
);
466 Status
= NtCreateKey(&LocalKeyHandle
,
468 &LocalObjectAttributes
,
471 REG_OPTION_NON_VOLATILE
,
473 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
474 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
475 DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", LocalObjectAttributes
.ObjectName
, Status
);
478 if (!NT_SUCCESS(Status
))
480 RtlFreeUnicodeString(&LocalKeyName
);
484 /* Add removed parts of the key name and create them too. */
487 if (LocalKeyName
.Length
== FullNameLength
)
489 Status
= STATUS_SUCCESS
;
490 *KeyHandle
= LocalKeyHandle
;
493 NtClose(LocalKeyHandle
);
495 LocalKeyName
.Buffer
[LocalKeyName
.Length
/ sizeof(WCHAR
)] = L
'\\';
496 LocalKeyName
.Length
= wcslen(LocalKeyName
.Buffer
) * sizeof(WCHAR
);
498 Status
= NtCreateKey(&LocalKeyHandle
,
500 &LocalObjectAttributes
,
505 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
506 if (!NT_SUCCESS(Status
))
508 DPRINT1("CreateNestedKey: NtCreateKey(%wZ) failed (Status %lx)\n", LocalObjectAttributes
.ObjectName
, Status
);
513 RtlFreeUnicodeString(&LocalKeyName
);
518 /***********************************************************************
521 * Called once for each AddReg and DelReg entry in a given section.
524 registry_callback(HINF hInf
, PCWSTR Section
, BOOLEAN Delete
)
527 OBJECT_ATTRIBUTES ObjectAttributes
;
528 UNICODE_STRING Name
, Value
;
529 PUNICODE_STRING ValuePtr
;
531 WCHAR Buffer
[MAX_INF_STRING_LENGTH
];
535 HANDLE RootKeyHandle
, KeyHandle
;
538 Ok
= SetupFindFirstLineW(hInf
, Section
, NULL
, &Context
);
540 return TRUE
; /* Don't fail if the section isn't present */
542 for (;Ok
; Ok
= SetupFindNextLine (&Context
, &Context
))
545 if (!SetupGetStringFieldW(&Context
, 1, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
547 RootKeyHandle
= GetRootKeyByName(Buffer
, &RootKeyName
);
552 if (!SetupGetStringFieldW(&Context
, 2, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
555 DPRINT("KeyName: <%S\\%S>\n", RootKeyName
, Buffer
);
558 if (!SetupGetIntField(&Context
, 4, (PINT
)&Flags
))
561 DPRINT("Flags: %lx\n", Flags
);
563 RtlInitUnicodeString(&Name
, Buffer
);
564 InitializeObjectAttributes(&ObjectAttributes
,
566 OBJ_CASE_INSENSITIVE
,
570 if (Delete
|| (Flags
& FLG_ADDREG_OVERWRITEONLY
))
572 Status
= NtOpenKey(&KeyHandle
,
575 if (!NT_SUCCESS(Status
))
577 DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &Name
, Status
);
578 continue; /* ignore if it doesn't exist */
583 Status
= CreateNestedKey(&KeyHandle
,
586 REG_OPTION_NON_VOLATILE
);
587 if (!NT_SUCCESS(Status
))
589 DPRINT1("CreateNestedKey(%wZ) failed (Status %lx)\n", &Name
, Status
);
595 if (SetupGetStringFieldW(&Context
, 3, Buffer
, sizeof(Buffer
)/sizeof(WCHAR
), NULL
))
597 RtlInitUnicodeString(&Value
, Buffer
);
606 if (!do_reg_operation(KeyHandle
, ValuePtr
, &Context
, Flags
))
627 WCHAR FileNameBuffer
[MAX_PATH
];
631 /* Load inf file from install media. */
632 CombinePaths(FileNameBuffer
, ARRAYSIZE(FileNameBuffer
), 2,
633 SourcePath
, Filename
);
635 hInf
= SetupOpenInfFileExW(FileNameBuffer
,
640 if (hInf
== INVALID_HANDLE_VALUE
)
642 DPRINT1("SetupOpenInfFile() failed\n");
647 if (!registry_callback(hInf
, L
"DelReg", FALSE
))
649 DPRINT1("registry_callback() failed\n");
655 if (!registry_callback(hInf
, L
"AddReg", FALSE
))
657 DPRINT1("registry_callback() failed\n");
662 if (!registry_callback(hInf
, L
"AddReg.NT" Architecture
, FALSE
))
664 DPRINT1("registry_callback() failed\n");
674 * Should be called under privileges
678 IN PUNICODE_STRING InstallPath
,
679 IN PCWSTR RegistryKey
,
680 IN BOOLEAN IsHiveNew
,
681 IN HANDLE ProtoKeyHandle
683 IN PUCHAR Descriptor,
684 IN ULONG DescriptorLength
688 /* '.old' is for old valid hives, while '.brk' is for old broken hives */
689 static PCWSTR Extensions
[] = {L
"old", L
"brk"};
693 UNICODE_STRING FileName
;
694 OBJECT_ATTRIBUTES ObjectAttributes
;
695 IO_STATUS_BLOCK IoStatusBlock
;
697 WCHAR PathBuffer
[MAX_PATH
];
698 WCHAR PathBuffer2
[MAX_PATH
];
700 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 3,
701 InstallPath
->Buffer
, L
"System32\\config", RegistryKey
);
703 Extension
= Extensions
[IsHiveNew
? 0 : 1];
706 // FIXME: The best, actually, would be to rename (move) the existing
707 // System32\config\RegistryKey file to System32\config\RegistryKey.old,
708 // and if it already existed some System32\config\RegistryKey.old, we should
709 // first rename this one into System32\config\RegistryKey_N.old before
710 // performing the original rename.
713 /* Check whether the registry hive file already existed, and if so, rename it */
714 if (DoesFileExist(NULL
, PathBuffer
))
718 DPRINT1("Registry hive '%S' already exists, rename it\n", PathBuffer
);
721 /* Try first by just appending the '.old' extension */
722 StringCchPrintfW(PathBuffer2
, ARRAYSIZE(PathBuffer2
), L
"%s.%s", PathBuffer
, Extension
);
724 while (DoesFileExist(NULL
, PathBuffer2
))
726 /* An old file already exists, increments its index, but not too much */
729 /* Append '_N.old' extension */
730 StringCchPrintfW(PathBuffer2
, ARRAYSIZE(PathBuffer2
), L
"%s_%lu.%s", PathBuffer
, i
, Extension
);
736 * Too many old files exist, we will rename the file
737 * using the name of the oldest one.
739 StringCchPrintfW(PathBuffer2
, ARRAYSIZE(PathBuffer2
), L
"%s.%s", PathBuffer
, Extension
);
745 /* Now rename the file (force the move) */
746 Status
= SetupMoveFile(PathBuffer
, PathBuffer2
, MOVEFILE_REPLACE_EXISTING
);
749 /* Create the file */
750 RtlInitUnicodeString(&FileName
, PathBuffer
);
751 InitializeObjectAttributes(&ObjectAttributes
,
753 OBJ_CASE_INSENSITIVE
,
754 NULL
, // Could have been InstallPath, etc...
757 Status
= NtCreateFile(&FileHandle
,
762 FILE_ATTRIBUTE_NORMAL
,
765 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
,
768 if (!NT_SUCCESS(Status
))
770 DPRINT1("NtCreateFile(%wZ) failed, Status 0x%08lx\n", &FileName
, Status
);
774 /* Save the selected hive into the file */
775 Status
= NtSaveKeyEx(ProtoKeyHandle
, FileHandle
, REG_LATEST_FORMAT
);
776 if (!NT_SUCCESS(Status
))
778 DPRINT1("NtSaveKeyEx(%wZ) failed, Status 0x%08lx\n", &FileName
, Status
);
781 /* Close the file and return */
788 IN HANDLE RootLinkKeyHandle OPTIONAL
,
789 IN PCWSTR LinkKeyName
,
790 IN PCWSTR TargetKeyName
)
792 static UNICODE_STRING CmSymbolicLinkValueName
=
793 RTL_CONSTANT_STRING(L
"SymbolicLinkValue");
796 OBJECT_ATTRIBUTES ObjectAttributes
;
797 UNICODE_STRING KeyName
;
798 HANDLE TargetKeyHandle
;
801 /* Initialize the object attributes */
802 RtlInitUnicodeString(&KeyName
, LinkKeyName
);
803 InitializeObjectAttributes(&ObjectAttributes
,
805 OBJ_CASE_INSENSITIVE
,
809 /* Create the link key */
810 Status
= NtCreateKey(&TargetKeyHandle
,
811 KEY_SET_VALUE
| KEY_CREATE_LINK
,
815 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
817 if (!NT_SUCCESS(Status
))
819 DPRINT1("CmpLinkKeyToHive: couldn't create %S, Status = 0x%08lx\n",
820 LinkKeyName
, Status
);
824 /* Check if the new key was actually created */
825 if (Disposition
!= REG_CREATED_NEW_KEY
)
827 DPRINT1("CmpLinkKeyToHive: %S already exists!\n", LinkKeyName
);
828 NtClose(TargetKeyHandle
);
832 /* Set the target key name as link target */
833 RtlInitUnicodeString(&KeyName
, TargetKeyName
);
834 Status
= NtSetValueKey(TargetKeyHandle
,
835 &CmSymbolicLinkValueName
,
841 /* Close the link key handle */
842 NtClose(TargetKeyHandle
);
844 if (!NT_SUCCESS(Status
))
846 DPRINT1("CmpLinkKeyToHive: couldn't create symbolic link for %S, Status = 0x%08lx\n",
847 TargetKeyName
, Status
);
855 * Should be called under privileges
859 IN HKEY RootKey OPTIONAL
,
860 IN PCWSTR RegMountPoint
,
861 // IN HANDLE RootDirectory OPTIONAL,
862 IN PUNICODE_STRING InstallPath
,
863 IN PCWSTR RegistryKey
865 IN PUCHAR Descriptor,
866 IN ULONG DescriptorLength
870 UNICODE_STRING KeyName
, FileName
;
871 OBJECT_ATTRIBUTES KeyObjectAttributes
;
872 OBJECT_ATTRIBUTES FileObjectAttributes
;
873 WCHAR PathBuffer
[MAX_PATH
];
875 RtlInitUnicodeString(&KeyName
, RegMountPoint
);
876 InitializeObjectAttributes(&KeyObjectAttributes
,
878 OBJ_CASE_INSENSITIVE
,
882 CombinePaths(PathBuffer
, ARRAYSIZE(PathBuffer
), 3,
883 InstallPath
->Buffer
, L
"System32\\config", RegistryKey
);
884 RtlInitUnicodeString(&FileName
, PathBuffer
);
885 InitializeObjectAttributes(&FileObjectAttributes
,
887 OBJ_CASE_INSENSITIVE
,
888 NULL
, // RootDirectory,
891 /* Mount the registry hive in the registry namespace */
892 return NtLoadKey(&KeyObjectAttributes
, &FileObjectAttributes
);
898 // IN HKEY RootKey OPTIONAL,
899 // // IN HANDLE RootDirectory OPTIONAL,
900 IN PUNICODE_STRING InstallPath
,
901 IN PCWSTR RegistryKey
/* ,
902 IN PCWSTR RegMountPoint */)
905 UNICODE_STRING KeyName
;
906 OBJECT_ATTRIBUTES ObjectAttributes
;
908 /* Try to mount the specified registry hive */
909 Status
= ConnectRegistry(NULL
,
910 L
"\\Registry\\Machine\\USetup_VerifyHive",
914 if (!NT_SUCCESS(Status
))
916 DPRINT1("ConnectRegistry(%S) failed, Status 0x%08lx\n", RegistryKey
, Status
);
919 DPRINT1("VerifyRegistryHive: ConnectRegistry(%S) returns Status 0x%08lx\n", RegistryKey
, Status
);
922 // TODO: Check the Status error codes: STATUS_SUCCESS, STATUS_REGISTRY_RECOVERED,
923 // STATUS_REGISTRY_HIVE_RECOVERED, STATUS_REGISTRY_CORRUPT, STATUS_REGISTRY_IO_FAILED,
924 // STATUS_NOT_REGISTRY_FILE, STATUS_CANNOT_LOAD_REGISTRY_FILE ;
925 //(STATUS_HIVE_UNLOADED) ; STATUS_SYSTEM_HIVE_TOO_LARGE
928 if (Status
== STATUS_REGISTRY_HIVE_RECOVERED
) // NT_SUCCESS is still FALSE in this case!
929 DPRINT1("VerifyRegistryHive: Registry hive %S was recovered but some data may be lost (Status 0x%08lx)\n", RegistryKey
, Status
);
931 if (!NT_SUCCESS(Status
))
933 DPRINT1("VerifyRegistryHive: Registry hive %S is corrupted (Status 0x%08lx)\n", RegistryKey
, Status
);
937 if (Status
== STATUS_REGISTRY_RECOVERED
)
938 DPRINT1("VerifyRegistryHive: Registry hive %S succeeded recovered (Status 0x%08lx)\n", RegistryKey
, Status
);
940 /* Unmount the hive */
941 InitializeObjectAttributes(&ObjectAttributes
,
943 OBJ_CASE_INSENSITIVE
,
947 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\USetup_VerifyHive");
948 Status
= NtUnloadKey(&ObjectAttributes
);
949 if (!NT_SUCCESS(Status
))
951 DPRINT1("NtUnloadKey(%S, %wZ) failed, Status 0x%08lx\n", RegistryKey
, &KeyName
, Status
);
958 typedef enum _HIVE_UPDATE_STATE
960 Create
, // Create a new hive file and save possibly existing old one with a .old extension.
961 Repair
, // Re-create a new hive file and save possibly existing old one with a .brk extension.
962 Update
// Hive update, do not need to be recreated.
965 typedef struct _HIVE_LIST_ENTRY
967 PCWSTR HiveName
; // HiveFileName;
968 PCWSTR HiveRegistryPath
; // HiveRegMountPoint;
969 HANDLE PredefKeyHandle
;
971 HIVE_UPDATE_STATE State
;
972 // PUCHAR SecurityDescriptor;
973 // ULONG SecurityDescriptorLength;
974 } HIVE_LIST_ENTRY
, *PHIVE_LIST_ENTRY
;
976 #define NUMBER_OF_STANDARD_REGISTRY_HIVES 3
978 HIVE_LIST_ENTRY RegistryHives
[/*NUMBER_OF_STANDARD_REGISTRY_HIVES*/] =
980 { L
"SYSTEM" , L
"\\Registry\\Machine\\USetup_SYSTEM" , HKEY_LOCAL_MACHINE
, L
"SYSTEM" , Create
/* , SystemSecurity , sizeof(SystemSecurity) */ },
981 { L
"SOFTWARE", L
"\\Registry\\Machine\\USetup_SOFTWARE", HKEY_LOCAL_MACHINE
, L
"SOFTWARE", Create
/* , SoftwareSecurity, sizeof(SoftwareSecurity) */ },
982 { L
"DEFAULT" , L
"\\Registry\\User\\USetup_DEFAULT" , HKEY_USERS
, L
".DEFAULT", Create
/* , SystemSecurity , sizeof(SystemSecurity) */ },
984 // { L"BCD" , L"\\Registry\\Machine\\USetup_BCD", HKEY_LOCAL_MACHINE, L"BCD00000000", Create /* , BcdSecurity , sizeof(BcdSecurity) */ },
986 C_ASSERT(_countof(RegistryHives
) == NUMBER_OF_STANDARD_REGISTRY_HIVES
);
988 #define NUMBER_OF_SECURITY_REGISTRY_HIVES 2
990 /** These hives are created by LSASS during 2nd stage setup */
991 HIVE_LIST_ENTRY SecurityRegistryHives
[/*NUMBER_OF_SECURITY_REGISTRY_HIVES*/] =
993 { L
"SAM" , L
"\\Registry\\Machine\\USetup_SAM" , HKEY_LOCAL_MACHINE
, L
"SAM" , Create
/* , SystemSecurity , sizeof(SystemSecurity) */ },
994 { L
"SECURITY", L
"\\Registry\\Machine\\USetup_SECURITY", HKEY_LOCAL_MACHINE
, L
"SECURITY", Create
/* , NULL , 0 */ },
996 C_ASSERT(_countof(SecurityRegistryHives
) == NUMBER_OF_SECURITY_REGISTRY_HIVES
);
1000 VerifyRegistryHives(
1001 IN PUNICODE_STRING InstallPath
,
1002 OUT PBOOLEAN ShouldRepairRegistry
)
1005 BOOLEAN PrivilegeSet
[2] = {FALSE
, FALSE
};
1008 /* Suppose first the registry hives do not have to be fully recreated */
1009 *ShouldRepairRegistry
= FALSE
;
1011 /* Acquire restore privilege */
1012 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[0]);
1013 if (!NT_SUCCESS(Status
))
1015 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1016 /* Exit prematurely here.... */
1020 /* Acquire backup privilege */
1021 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[1]);
1022 if (!NT_SUCCESS(Status
))
1024 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1025 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1026 /* Exit prematurely here.... */
1030 for (i
= 0; i
< ARRAYSIZE(RegistryHives
); ++i
)
1032 Status
= VerifyRegistryHive(InstallPath
, RegistryHives
[i
].HiveName
);
1033 if (!NT_SUCCESS(Status
))
1035 DPRINT1("Registry hive '%S' needs repair!\n", RegistryHives
[i
].HiveName
);
1036 RegistryHives
[i
].State
= Repair
;
1037 *ShouldRepairRegistry
= TRUE
;
1041 RegistryHives
[i
].State
= Update
;
1045 /** These hives are created by LSASS during 2nd stage setup */
1046 for (i
= 0; i
< ARRAYSIZE(SecurityRegistryHives
); ++i
)
1048 Status
= VerifyRegistryHive(InstallPath
, SecurityRegistryHives
[i
].HiveName
);
1049 if (!NT_SUCCESS(Status
))
1051 DPRINT1("Registry hive '%S' needs repair!\n", SecurityRegistryHives
[i
].HiveName
);
1052 SecurityRegistryHives
[i
].State
= Repair
;
1054 * Note that it's not the role of the 1st-stage installer to fix
1055 * the security hives. This should be done at 2nd-stage installation
1061 SecurityRegistryHives
[i
].State
= Update
;
1065 /* Reset the status (we succeeded in checking all the hives) */
1066 Status
= STATUS_SUCCESS
;
1068 /* Remove restore and backup privileges */
1069 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, PrivilegeSet
[1], FALSE
, &PrivilegeSet
[1]);
1070 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1077 RegInitializeRegistry(
1078 IN PUNICODE_STRING InstallPath
)
1082 UNICODE_STRING KeyName
;
1083 OBJECT_ATTRIBUTES ObjectAttributes
;
1084 BOOLEAN PrivilegeSet
[2] = {FALSE
, FALSE
};
1088 /* Acquire restore privilege */
1089 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[0]);
1090 if (!NT_SUCCESS(Status
))
1092 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1093 /* Exit prematurely here.... */
1097 /* Acquire backup privilege */
1098 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[1]);
1099 if (!NT_SUCCESS(Status
))
1101 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1102 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1103 /* Exit prematurely here.... */
1108 * Create the template proto-hive.
1110 * Use a dummy root key name:
1111 * - On 2k/XP/2k3, this is "$$$PROTO.HIV"
1112 * - On Vista+, this is "CMI-CreateHive{guid}"
1113 * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc
1114 * for more information.
1116 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\SYSTEM\\$$$PROTO.HIV");
1117 InitializeObjectAttributes(&ObjectAttributes
,
1119 OBJ_CASE_INSENSITIVE
,
1122 Status
= NtCreateKey(&KeyHandle
,
1127 REG_OPTION_NON_VOLATILE
,
1129 if (!NT_SUCCESS(Status
))
1131 DPRINT1("NtCreateKey() failed to create the proto-hive (Status %lx)\n", Status
);
1134 NtFlushKey(KeyHandle
);
1136 for (i
= 0; i
< ARRAYSIZE(RegistryHives
); ++i
)
1138 if (RegistryHives
[i
].State
!= Create
&& RegistryHives
[i
].State
!= Repair
)
1141 Status
= CreateRegistryFile(InstallPath
,
1142 RegistryHives
[i
].HiveName
,
1143 RegistryHives
[i
].State
!= Repair
, // RegistryHives[i].State == Create,
1145 if (!NT_SUCCESS(Status
))
1147 DPRINT1("CreateRegistryFile(%S) failed, Status 0x%08lx\n", RegistryHives
[i
].HiveName
, Status
);
1148 /* Exit prematurely here.... */
1149 /* That is now done, remove the proto-hive */
1150 NtDeleteKey(KeyHandle
);
1156 /* That is now done, remove the proto-hive */
1157 NtDeleteKey(KeyHandle
);
1162 * Prepare the registry root keys. Since we cannot create real registry keys
1163 * inside the master keys (\Registry, \Registry\Machine or \Registry\User),
1164 * we need to perform some SymLink tricks instead.
1167 /* Our offline HKLM '\Registry\Machine' is inside '\Registry\Machine\SYSTEM\USetup_Machine' */
1168 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].MountPoint
);
1169 InitializeObjectAttributes(&ObjectAttributes
,
1171 OBJ_CASE_INSENSITIVE
,
1175 Status
= NtCreateKey(&KeyHandle
,
1180 REG_OPTION_NON_VOLATILE
, // REG_OPTION_VOLATILE, // FIXME!
1182 if (!NT_SUCCESS(Status
))
1184 DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName
, Status
);
1187 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
= KeyHandle
;
1189 /* Our offline HKU '\Registry\User' is inside '\Registry\Machine\SYSTEM\USetup_User' */
1190 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].MountPoint
);
1191 InitializeObjectAttributes(&ObjectAttributes
,
1193 OBJ_CASE_INSENSITIVE
,
1197 Status
= NtCreateKey(&KeyHandle
,
1202 REG_OPTION_NON_VOLATILE
, // REG_OPTION_VOLATILE, // FIXME!
1204 if (!NT_SUCCESS(Status
))
1206 DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName
, Status
);
1209 RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].Handle
= KeyHandle
;
1213 * Now properly mount the offline hive files
1215 for (i
= 0; i
< ARRAYSIZE(RegistryHives
); ++i
)
1217 // if (RegistryHives[i].State != Create && RegistryHives[i].State != Repair)
1220 if (RegistryHives
[i
].State
== Create
|| RegistryHives
[i
].State
== Repair
)
1222 Status
= ConnectRegistry(NULL
,
1223 RegistryHives
[i
].HiveRegistryPath
,
1225 RegistryHives
[i
].HiveName
1226 /* SystemSecurity, sizeof(SystemSecurity) */);
1227 if (!NT_SUCCESS(Status
))
1229 DPRINT1("ConnectRegistry(%S) failed, Status 0x%08lx\n", RegistryHives
[i
].HiveName
, Status
);
1232 /* Create the registry symlink to this key */
1233 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(RegistryHives
[i
].PredefKeyHandle
)].Handle
,
1234 RegistryHives
[i
].RegSymLink
,
1235 RegistryHives
[i
].HiveRegistryPath
))
1237 DPRINT1("CmpLinkKeyToHive(%S) failed!\n", RegistryHives
[i
].HiveName
);
1242 /* Create *DUMMY* volatile hives just to make the update procedure working */
1244 RtlInitUnicodeString(&KeyName
, RegistryHives
[i
].RegSymLink
);
1245 InitializeObjectAttributes(&ObjectAttributes
,
1247 OBJ_CASE_INSENSITIVE
,
1248 RootKeys
[GetPredefKeyIndex(RegistryHives
[i
].PredefKeyHandle
)].Handle
,
1251 Status
= NtCreateKey(&KeyHandle
,
1256 REG_OPTION_NON_VOLATILE
, // REG_OPTION_VOLATILE, // FIXME!
1258 if (!NT_SUCCESS(Status
))
1260 DPRINT1("NtCreateKey(%wZ) failed (Status 0x%08lx)\n", &KeyName
, Status
);
1268 /* HKCU is a handle to 'HKU\.DEFAULT' */
1270 RtlInitUnicodeString(&KeyName
, L
".DEFAULT");
1271 InitializeObjectAttributes(&ObjectAttributes
,
1273 OBJ_CASE_INSENSITIVE
,
1274 RootKeys
[GetPredefKeyIndex(HKEY_USERS
)].Handle
,
1277 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_CURRENT_USER
)].MountPoint
);
1278 InitializeObjectAttributes(&ObjectAttributes
,
1280 OBJ_CASE_INSENSITIVE
,
1285 Status
= NtOpenKey(&KeyHandle
,
1288 if (!NT_SUCCESS(Status
))
1290 DPRINT1("NtOpenKey(%wZ) failed (Status %lx)\n", &KeyName
, Status
);
1292 RootKeys
[GetPredefKeyIndex(HKEY_CURRENT_USER
)].Handle
= KeyHandle
;
1295 /* HKCR is a handle to 'HKLM\Software\Classes' */
1297 RtlInitUnicodeString(&KeyName
, L
"Software\\Classes");
1298 InitializeObjectAttributes(&ObjectAttributes
,
1300 OBJ_CASE_INSENSITIVE
,
1301 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1304 RtlInitUnicodeString(&KeyName
, RootKeys
[GetPredefKeyIndex(HKEY_CLASSES_ROOT
)].MountPoint
);
1305 InitializeObjectAttributes(&ObjectAttributes
,
1307 OBJ_CASE_INSENSITIVE
,
1312 /* We use NtCreateKey instead of NtOpenKey because Software\Classes doesn't exist originally */
1313 Status
= NtCreateKey(&KeyHandle
,
1318 REG_OPTION_NON_VOLATILE
,
1320 if (!NT_SUCCESS(Status
))
1322 DPRINT1("NtCreateKey(%wZ) failed (Status %lx)\n", &KeyName
, Status
);
1326 DPRINT1("NtCreateKey() succeeded to %s the %wZ key (Status %lx)\n",
1327 Disposition
== REG_CREATED_NEW_KEY
? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
1330 RootKeys
[GetPredefKeyIndex(HKEY_CLASSES_ROOT
)].Handle
= KeyHandle
;
1333 Status
= STATUS_SUCCESS
;
1336 /* Create the 'HKLM\SYSTEM\ControlSet001' key */
1337 // REGISTRY_SETUP_MACHINE L"SYSTEM\\ControlSet001"
1338 RtlInitUnicodeString(&KeyName
, L
"SYSTEM\\ControlSet001");
1339 InitializeObjectAttributes(&ObjectAttributes
,
1341 OBJ_CASE_INSENSITIVE
,
1342 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1344 Status
= NtCreateKey(&KeyHandle
,
1349 REG_OPTION_NON_VOLATILE
,
1351 if (!NT_SUCCESS(Status
))
1353 DPRINT1("NtCreateKey() failed to create the ControlSet001 key (Status %lx)\n", Status
);
1358 DPRINT1("NtCreateKey() succeeded to %s the ControlSet001 key (Status %lx)\n",
1359 Disposition
== REG_CREATED_NEW_KEY
? "create" : /* REG_OPENED_EXISTING_KEY */ "open",
1364 /* Create the 'HKLM\SYSTEM\CurrentControlSet' symlink */
1365 if (!CmpLinkKeyToHive(RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1366 L
"SYSTEM\\CurrentControlSet",
1367 REGISTRY_SETUP_MACHINE L
"SYSTEM\\ControlSet001"))
1369 DPRINT1("CmpLinkKeyToHive(CurrentControlSet) failed!\n");
1373 Status
= STATUS_SUCCESS
;
1377 /* Remove restore and backup privileges */
1378 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, PrivilegeSet
[1], FALSE
, &PrivilegeSet
[1]);
1379 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1386 IN PUNICODE_STRING InstallPath
)
1390 UNICODE_STRING KeyName
;
1391 OBJECT_ATTRIBUTES ObjectAttributes
;
1392 BOOLEAN PrivilegeSet
[2] = {FALSE
, FALSE
};
1394 WCHAR SrcPath
[MAX_PATH
];
1395 WCHAR DstPath
[MAX_PATH
];
1397 /* Acquire restore privilege */
1398 Status
= RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[0]);
1399 if (!NT_SUCCESS(Status
))
1401 DPRINT1("RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1402 /* Exit prematurely here.... */
1406 /* Acquire backup privilege */
1407 Status
= RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, TRUE
, FALSE
, &PrivilegeSet
[1]);
1408 if (!NT_SUCCESS(Status
))
1410 DPRINT1("RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE) failed (Status 0x%08lx)\n", Status
);
1411 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1412 /* Exit prematurely here.... */
1417 * Note that we don't need to explicitly remove the symlinks we have created
1418 * since they are created volatile, inside registry keys that will be however
1419 * removed explictly in the following.
1422 for (i
= 0; i
< ARRAYSIZE(RegistryHives
); ++i
)
1424 if (RegistryHives
[i
].State
!= Create
&& RegistryHives
[i
].State
!= Repair
)
1426 RtlInitUnicodeString(&KeyName
, RegistryHives
[i
].RegSymLink
);
1427 InitializeObjectAttributes(&ObjectAttributes
,
1429 OBJ_CASE_INSENSITIVE
,
1430 RootKeys
[GetPredefKeyIndex(RegistryHives
[i
].PredefKeyHandle
)].Handle
,
1433 Status
= NtOpenKey(&KeyHandle
,
1436 if (!NT_SUCCESS(Status
))
1438 DPRINT1("NtOpenKey(%wZ) failed, Status 0x%08lx\n", &KeyName
, Status
);
1442 NtDeleteKey(KeyHandle
);
1447 RtlInitUnicodeString(&KeyName
, RegistryHives
[i
].HiveRegistryPath
);
1448 InitializeObjectAttributes(&ObjectAttributes
,
1450 OBJ_CASE_INSENSITIVE
,
1453 // Status = NtUnloadKey(&ObjectAttributes);
1454 Status
= NtUnloadKey2(&ObjectAttributes
, 1 /* REG_FORCE_UNLOAD */);
1455 DPRINT1("Unmounting '%S' %s\n", RegistryHives
[i
].HiveRegistryPath
, NT_SUCCESS(Status
) ? "succeeded" : "failed");
1457 /* Switch the hive state to 'Update' */
1458 RegistryHives
[i
].State
= Update
;
1463 * FIXME: Once force-unloading keys is correctly fixed, I'll fix
1464 * this code that closes some of the registry keys that were opened
1465 * inside the hives we've just unmounted above...
1468 /* Remove the registry root keys */
1469 for (i
= 0; i
< ARRAYSIZE(RootKeys
); ++i
)
1471 if (RootKeys
[i
].Handle
)
1473 /**/NtFlushKey(RootKeys
[i
].Handle
);/**/ // FIXME: Why does it hang? Answer: because we have some problems in CMAPI!
1474 NtDeleteKey(RootKeys
[i
].Handle
);
1475 NtClose(RootKeys
[i
].Handle
);
1476 RootKeys
[i
].Handle
= NULL
;
1481 // RegBackupRegistry()
1483 /* Now backup the hives into .sav files */
1484 for (i
= 0; i
< ARRAYSIZE(RegistryHives
); ++i
)
1486 if (RegistryHives
[i
].State
!= Create
&& RegistryHives
[i
].State
!= Repair
)
1489 CombinePaths(SrcPath
, ARRAYSIZE(SrcPath
), 3,
1490 InstallPath
->Buffer
, L
"System32\\config", RegistryHives
[i
].HiveName
);
1491 StringCchCopyW(DstPath
, ARRAYSIZE(DstPath
), SrcPath
);
1492 StringCchCatW(DstPath
, ARRAYSIZE(DstPath
), L
".sav");
1494 DPRINT1("Copy hive: %S ==> %S\n", SrcPath
, DstPath
);
1495 Status
= SetupCopyFile(SrcPath
, DstPath
, FALSE
);
1496 if (!NT_SUCCESS(Status
))
1498 DPRINT1("SetupCopyFile() failed (Status %lx)\n", Status
);
1503 /* Remove restore and backup privileges */
1504 RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE
, PrivilegeSet
[1], FALSE
, &PrivilegeSet
[1]);
1505 RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE
, PrivilegeSet
[0], FALSE
, &PrivilegeSet
[0]);
1513 OBJECT_ATTRIBUTES ObjectAttributes
;
1514 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management");
1515 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"PagingFiles");
1516 WCHAR ValueBuffer
[] = L
"?:\\pagefile.sys 0 0\0";
1520 InitializeObjectAttributes(&ObjectAttributes
,
1522 OBJ_CASE_INSENSITIVE
,
1523 RootKeys
[GetPredefKeyIndex(HKEY_LOCAL_MACHINE
)].Handle
,
1525 Status
= NtOpenKey(&KeyHandle
,
1528 if (!NT_SUCCESS(Status
))
1531 ValueBuffer
[0] = Drive
;
1533 NtSetValueKey(KeyHandle
,
1537 (PVOID
)&ValueBuffer
,
1538 sizeof(ValueBuffer
));