3 * Copyright (C) 2006 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 hive maker
22 * FILE: tools/mkhive/registry.c
23 * PURPOSE: Registry code
24 * PROGRAMMER: Hervé Poussineau
29 * - Implement RegDeleteKeyW() and RegDeleteValueW()
39 static CMHIVE RootHive
;
40 static PMEMKEY RootKey
;
41 CMHIVE DefaultHive
; /* \Registry\User\.DEFAULT */
42 CMHIVE SamHive
; /* \Registry\Machine\SAM */
43 CMHIVE SecurityHive
; /* \Registry\Machine\SECURITY */
44 CMHIVE SoftwareHive
; /* \Registry\Machine\SOFTWARE */
45 CMHIVE SystemHive
; /* \Registry\Machine\SYSTEM */
46 CMHIVE BcdHive
; /* \Registry\Machine\BCD00000000 */
49 // TODO: Write these values in a more human-readable form.
50 // See http://amnesia.gtisc.gatech.edu/~moyix/suzibandit.ltd.uk/MSc/Registry%20Structure%20-%20Appendices%20V4.pdf
51 // Appendix 12 "The Registry NT Security Descriptor" for more information.
53 // Those SECURITY_DESCRIPTORs were obtained by dumping the security block "sk"
54 // of registry hives created by setting their permissions to be the same as
55 // the ones of the BCD, SOFTWARE, or SYSTEM, SAM and .DEFAULT system hives.
56 // A cross-check was subsequently done with the system hives to verify that
57 // the security descriptors were the same.
61 // SECURITY_DESCRIPTOR_RELATIVE
64 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
65 // SE_DACL_PROTECTED (0x1000) |
66 // SE_DACL_AUTO_INHERITED (0x0400) |
67 // SE_DACL_PRESENT (0x0004)
68 0x48, 0x00, 0x00, 0x00, // Owner
69 0x58, 0x00, 0x00, 0x00, // Group
70 0x00, 0x00, 0x00, 0x00, // Sacl (None)
71 0x14, 0x00, 0x00, 0x00, // Dacl
76 0x34, 0x00, // AclSize
77 0x02, 0x00, // AceCount
81 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
82 0x02, // AceFlags: CONTAINER_INHERIT_ACE
83 0x18, 0x00, // AceSize
84 0x19, 0x00, 0x06, 0x00, // ACCESS_MASK: "Write DAC" (0x00040000) |
85 // "Read Control" (0x00020000) |
86 // "Notify" (0x00000010) |
87 // "Enumerate Subkeys" (0x00000008) |
88 // "Query Value" (0x00000001)
89 // (SidStart: S-1-5-32-544 "Administrators")
90 0x01, 0x02, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x05,
92 0x20, 0x00, 0x00, 0x00,
93 0x20, 0x02, 0x00, 0x00,
96 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
97 0x02, // AceFlags: CONTAINER_INHERIT_ACE
98 0x14, 0x00, // AceSize
99 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
100 // (SidStart: S-1-5-18 "Local System")
101 0x01, 0x01, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x05,
103 0x12, 0x00, 0x00, 0x00,
105 // Owner SID (S-1-5-32-544 "Administrators")
106 0x01, 0x02, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x05,
108 0x20, 0x00, 0x00, 0x00,
109 0x20, 0x02, 0x00, 0x00,
111 // Group SID (S-1-5-21-domain-513 "Domain Users")
112 0x01, 0x05, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x05,
114 0x15, 0x00, 0x00, 0x00,
115 0xAC, 0xD0, 0x49, 0xCB,
116 0xE6, 0x52, 0x47, 0x9C,
117 0xE4, 0x31, 0xDB, 0x5C,
118 0x01, 0x02, 0x00, 0x00
121 UCHAR SoftwareSecurity
[] =
123 // SECURITY_DESCRIPTOR_RELATIVE
126 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
127 // SE_DACL_PROTECTED (0x1000) |
128 // SE_DACL_AUTO_INHERITED (0x0400) |
129 // SE_DACL_PRESENT (0x0004)
130 0xA0, 0x00, 0x00, 0x00, // Owner
131 0xB0, 0x00, 0x00, 0x00, // Group
132 0x00, 0x00, 0x00, 0x00, // Sacl (None)
133 0x14, 0x00, 0x00, 0x00, // Dacl
138 0x8C, 0x00, // AclSize
139 0x06, 0x00, // AceCount
143 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
144 0x02, // AceFlags: CONTAINER_INHERIT_ACE
145 0x18, 0x00, // AceSize
146 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
147 // (SidStart: S-1-5-32-544 "Administrators")
148 0x01, 0x02, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x05,
150 0x20, 0x00, 0x00, 0x00,
151 0x20, 0x02, 0x00, 0x00,
154 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
155 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE
156 0x14, 0x00, // AceSize
157 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
158 // (SidStart: S-1-3-0 "Creator Owner")
159 0x01, 0x01, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x03,
161 0x00, 0x00, 0x00, 0x00,
164 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
165 0x02, // AceFlags: CONTAINER_INHERIT_ACE
166 0x14, 0x00, // AceSize
167 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
168 // (SidStart: S-1-5-18 "Local System")
169 0x01, 0x01, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x05,
171 0x12, 0x00, 0x00, 0x00,
174 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
175 0x02, // AceFlags: CONTAINER_INHERIT_ACE
176 0x14, 0x00, // AceSize
177 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
178 // "Delete" (0x00010000) |
179 // "Notify" (0x00000010) |
180 // "Enumerate Subkeys" (0x00000008) |
181 // "Create Subkey" (0x00000004) |
182 // "Set Value" (0x00000002) |
183 // "Query Value" (0x00000001)
184 // (SidStart: S-1-5-13 "Terminal Server Users")
185 0x01, 0x01, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x05,
187 0x0D, 0x00, 0x00, 0x00,
190 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
191 0x02, // AceFlags: CONTAINER_INHERIT_ACE
192 0x18, 0x00, // AceSize
193 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
194 // "Notify" (0x00000010) |
195 // "Enumerate Subkeys" (0x00000008) |
196 // "Query Value" (0x00000001)
197 // (SidStart: S-1-5-32-545 "Users")
198 0x01, 0x02, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x05,
200 0x20, 0x00, 0x00, 0x00,
201 0x21, 0x02, 0x00, 0x00,
204 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
205 0x02, // AceFlags: CONTAINER_INHERIT_ACE
206 0x18, 0x00, // AceSize
207 0x1F, 0x00, 0x03, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
208 // "Delete" (0x00010000) |
209 // "Notify" (0x00000010) |
210 // "Enumerate Subkeys" (0x00000008) |
211 // "Create Subkey" (0x00000004) |
212 // "Set Value" (0x00000002) |
213 // "Query Value" (0x00000001)
214 // (SidStart: S-1-5-32-547 "Power Users")
215 0x01, 0x02, 0x00, 0x00,
216 0x00, 0x00, 0x00, 0x05,
217 0x20, 0x00, 0x00, 0x00,
218 0x23, 0x02, 0x00, 0x00,
220 // Owner SID (S-1-5-32-544 "Administrators")
221 0x01, 0x02, 0x00, 0x00,
222 0x00, 0x00, 0x00, 0x05,
223 0x20, 0x00, 0x00, 0x00,
224 0x20, 0x02, 0x00, 0x00,
226 // Group SID (S-1-5-21-domain-513 "Domain Users")
227 0x01, 0x05, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x05,
229 0x15, 0x00, 0x00, 0x00,
230 0xAC, 0xD0, 0x49, 0xCB,
231 0xE6, 0x52, 0x47, 0x9C,
232 0xE4, 0x31, 0xDB, 0x5C,
233 0x01, 0x02, 0x00, 0x00
236 // Same security for SYSTEM, SAM and .DEFAULT
237 UCHAR SystemSecurity
[] =
239 // SECURITY_DESCRIPTOR_RELATIVE
242 0x04, 0x94, // Control: SE_SELF_RELATIVE (0x8000) |
243 // SE_DACL_PROTECTED (0x1000) |
244 // SE_DACL_AUTO_INHERITED (0x0400) |
245 // SE_DACL_PRESENT (0x0004)
246 0x8C, 0x00, 0x00, 0x00, // Owner
247 0x9C, 0x00, 0x00, 0x00, // Group
248 0x00, 0x00, 0x00, 0x00, // Sacl (None)
249 0x14, 0x00, 0x00, 0x00, // Dacl
254 0x78, 0x00, // AclSize
255 0x05, 0x00, // AceCount
259 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
260 0x02, // AceFlags: CONTAINER_INHERIT_ACE
261 0x18, 0x00, // AceSize
262 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
263 // (SidStart: S-1-5-32-544 "Administrators")
264 0x01, 0x02, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x05,
266 0x20, 0x00, 0x00, 0x00,
267 0x20, 0x02, 0x00, 0x00,
270 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
271 0x0A, // AceFlags: INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE
272 0x14, 0x00, // AceSize
273 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
274 // (SidStart: S-1-3-0 "Creator Owner")
275 0x01, 0x01, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x03,
277 0x00, 0x00, 0x00, 0x00,
280 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
281 0x02, // AceFlags: CONTAINER_INHERIT_ACE
282 0x14, 0x00, // AceSize
283 0x3F, 0x00, 0x0F, 0x00, // ACCESS_MASK: "Full Control" (0x000F003F)
284 // (SidStart: S-1-5-18 "Local System")
285 0x01, 0x01, 0x00, 0x00,
286 0x00, 0x00, 0x00, 0x05,
287 0x12, 0x00, 0x00, 0x00,
290 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
291 0x02, // AceFlags: CONTAINER_INHERIT_ACE
292 0x18, 0x00, // AceSize
293 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
294 // "Notify" (0x00000010) |
295 // "Enumerate Subkeys" (0x00000008) |
296 // "Query Value" (0x00000001)
297 // (SidStart: S-1-5-32-545 "Users")
298 0x01, 0x02, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x05,
300 0x20, 0x00, 0x00, 0x00,
301 0x21, 0x02, 0x00, 0x00,
304 0x00, // AceType : ACCESS_ALLOWED_ACE_TYPE
305 0x02, // AceFlags: CONTAINER_INHERIT_ACE
306 0x18, 0x00, // AceSize
307 0x19, 0x00, 0x02, 0x00, // ACCESS_MASK: "Read Control" (0x00020000) |
308 // "Notify" (0x00000010) |
309 // "Enumerate Subkeys" (0x00000008) |
310 // "Query Value" (0x00000001)
311 // (SidStart: S-1-5-32-547 "Power Users")
312 0x01, 0x02, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x05,
314 0x20, 0x00, 0x00, 0x00,
315 0x23, 0x02, 0x00, 0x00,
317 // Owner SID (S-1-5-32-544 "Administrators")
318 0x01, 0x02, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x05,
320 0x20, 0x00, 0x00, 0x00,
321 0x20, 0x02, 0x00, 0x00,
323 // Group SID (S-1-5-21-domain-513 "Domain Users")
324 0x01, 0x05, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x05,
326 0x15, 0x00, 0x00, 0x00,
327 0xAC, 0xD0, 0x49, 0xCB,
328 0xE6, 0x52, 0x47, 0x9C,
329 0xE4, 0x31, 0xDB, 0x5C,
330 0x01, 0x02, 0x00, 0x00
334 CreateInMemoryStructure(
335 IN PCMHIVE RegistryHive
,
336 IN HCELL_INDEX KeyCellOffset
)
340 Key
= (PMEMKEY
)malloc(sizeof(MEMKEY
));
344 Key
->RegistryHive
= RegistryHive
;
345 Key
->KeyCellOffset
= KeyCellOffset
;
349 LIST_ENTRY CmiReparsePointsHead
;
355 IN BOOL AllowCreation
,
361 UNICODE_STRING KeyString
;
363 PREPARSE_POINT CurrentReparsePoint
;
365 PCMHIVE ParentRegistryHive
;
366 HCELL_INDEX ParentCellOffset
;
367 PCM_KEY_NODE ParentKeyCell
;
369 PCM_KEY_NODE SubKeyCell
;
370 HCELL_INDEX BlockOffset
;
372 DPRINT("RegpCreateOpenKey('%S')\n", KeyName
);
374 if (*KeyName
== OBJ_NAME_PATH_SEPARATOR
)
377 ParentRegistryHive
= RootKey
->RegistryHive
;
378 ParentCellOffset
= RootKey
->KeyCellOffset
;
380 else if (hParentKey
== NULL
)
382 ParentRegistryHive
= RootKey
->RegistryHive
;
383 ParentCellOffset
= RootKey
->KeyCellOffset
;
387 ParentRegistryHive
= HKEY_TO_MEMKEY(hParentKey
)->RegistryHive
;
388 ParentCellOffset
= HKEY_TO_MEMKEY(hParentKey
)->KeyCellOffset
;
391 LocalKeyName
= (PWSTR
)KeyName
;
394 End
= (PWSTR
)strchrW(LocalKeyName
, OBJ_NAME_PATH_SEPARATOR
);
397 KeyString
.Buffer
= LocalKeyName
;
398 KeyString
.Length
= KeyString
.MaximumLength
=
399 (USHORT
)((ULONG_PTR
)End
- (ULONG_PTR
)LocalKeyName
);
403 RtlInitUnicodeString(&KeyString
, LocalKeyName
);
404 if (KeyString
.Length
== 0)
406 /* Trailing path separator: we're done */
411 ParentKeyCell
= (PCM_KEY_NODE
)HvGetCell(&ParentRegistryHive
->Hive
, ParentCellOffset
);
413 return STATUS_UNSUCCESSFUL
;
415 VERIFY_KEY_CELL(ParentKeyCell
);
417 BlockOffset
= CmpFindSubKeyByName(&ParentRegistryHive
->Hive
, ParentKeyCell
, &KeyString
);
418 if (BlockOffset
!= HCELL_NIL
)
420 Status
= STATUS_SUCCESS
;
422 /* Search for a possible reparse point */
423 Ptr
= CmiReparsePointsHead
.Flink
;
424 while (Ptr
!= &CmiReparsePointsHead
)
426 CurrentReparsePoint
= CONTAINING_RECORD(Ptr
, REPARSE_POINT
, ListEntry
);
427 if (CurrentReparsePoint
->SourceHive
== ParentRegistryHive
&&
428 CurrentReparsePoint
->SourceKeyCellOffset
== BlockOffset
)
430 ParentRegistryHive
= CurrentReparsePoint
->DestinationHive
;
431 BlockOffset
= CurrentReparsePoint
->DestinationKeyCellOffset
;
437 else if (AllowCreation
) // && (BlockOffset == HCELL_NIL)
439 Status
= CmiAddSubKey(ParentRegistryHive
,
446 HvReleaseCell(&ParentRegistryHive
->Hive
, ParentCellOffset
);
448 if (!NT_SUCCESS(Status
))
449 return ERROR_UNSUCCESSFUL
;
451 ParentCellOffset
= BlockOffset
;
453 LocalKeyName
= End
+ 1;
458 CurrentKey
= CreateInMemoryStructure(ParentRegistryHive
, ParentCellOffset
);
460 return ERROR_OUTOFMEMORY
;
462 *Key
= MEMKEY_TO_HKEY(CurrentKey
);
464 return ERROR_SUCCESS
;
473 return RegpOpenOrCreateKey(hKey
, lpSubKey
, TRUE
, FALSE
, phkResult
);
481 DPRINT1("RegDeleteKeyW(0x%p, '%S') is UNIMPLEMENTED!\n",
482 hKey
, (lpSubKey
? lpSubKey
: L
""));
483 return ERROR_SUCCESS
;
492 return RegpOpenOrCreateKey(hKey
, lpSubKey
, FALSE
, FALSE
, phkResult
);
500 IN LPWSTR lpClass OPTIONAL
,
502 IN REGSAM samDesired
,
503 IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL
,
505 OUT LPDWORD lpdwDisposition OPTIONAL
)
507 return RegpOpenOrCreateKey(hKey
,
510 (dwOptions
& REG_OPTION_VOLATILE
) != 0,
517 IN LPCWSTR lpValueName OPTIONAL
,
520 IN
const UCHAR
* lpData
,
523 PMEMKEY Key
= HKEY_TO_MEMKEY(hKey
); // ParentKey
525 PCM_KEY_NODE KeyNode
; // ParentNode
526 PCM_KEY_VALUE ValueCell
;
527 HCELL_INDEX CellIndex
;
528 UNICODE_STRING ValueNameString
;
534 if (dwType
== REG_LINK
)
538 /* Special handling of registry links */
539 if (cbData
!= sizeof(PVOID
))
540 return STATUS_INVALID_PARAMETER
;
542 DestKey
= HKEY_TO_MEMKEY(*(PHKEY
)lpData
);
544 // FIXME: Add additional checks for the validity of DestKey
546 /* Create the link in registry hive (if applicable) */
547 if (Key
->RegistryHive
!= DestKey
->RegistryHive
)
548 return STATUS_SUCCESS
;
550 DPRINT1("Save link to registry\n");
551 return STATUS_NOT_IMPLEMENTED
;
554 if ((cbData
& ~CM_KEY_VALUE_SPECIAL_SIZE
) != cbData
)
555 return STATUS_UNSUCCESSFUL
;
557 Hive
= &Key
->RegistryHive
->Hive
;
559 KeyNode
= (PCM_KEY_NODE
)HvGetCell(Hive
, Key
->KeyCellOffset
);
561 return ERROR_UNSUCCESSFUL
;
563 ASSERT(KeyNode
->Signature
== CM_KEY_NODE_SIGNATURE
);
565 /* Mark the parent as dirty since we are going to create a new value in it */
566 HvMarkCellDirty(Hive
, Key
->KeyCellOffset
, FALSE
);
568 /* Initialize value name string */
569 RtlInitUnicodeString(&ValueNameString
, lpValueName
);
570 CellIndex
= CmpFindValueByName(Hive
, KeyNode
, &ValueNameString
);
571 if (CellIndex
== HCELL_NIL
)
573 /* The value doesn't exist, create a new one */
574 Status
= CmiAddValueKey(Key
->RegistryHive
,
582 /* The value already exists, use it. Get the value cell. */
583 ValueCell
= HvGetCell(&Key
->RegistryHive
->Hive
, CellIndex
);
584 ASSERT(ValueCell
!= NULL
);
587 // /**/HvReleaseCell(Hive, CellIndex);/**/
589 if (!NT_SUCCESS(Status
))
590 return ERROR_UNSUCCESSFUL
;
592 /* Get size of the allocated cell (if any) */
593 if (!(ValueCell
->DataLength
& CM_KEY_VALUE_SPECIAL_SIZE
) &&
594 (ValueCell
->DataLength
& ~CM_KEY_VALUE_SPECIAL_SIZE
) != 0)
596 DataCell
= HvGetCell(Hive
, ValueCell
->Data
);
598 return ERROR_UNSUCCESSFUL
;
600 DataCellSize
= (ULONG
)(-HvGetCellSize(Hive
, DataCell
));
608 if (cbData
<= sizeof(HCELL_INDEX
))
610 /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
611 DPRINT("ValueCell->DataLength %u\n", ValueCell
->DataLength
);
613 HvFreeCell(Hive
, ValueCell
->Data
);
615 RtlCopyMemory(&ValueCell
->Data
, lpData
, cbData
);
616 ValueCell
->DataLength
= (cbData
| CM_KEY_VALUE_SPECIAL_SIZE
);
617 ValueCell
->Type
= dwType
;
621 if (cbData
> DataCellSize
)
623 /* New data size is larger than the current, destroy current
624 * data block and allocate a new one. */
625 HCELL_INDEX NewOffset
;
627 DPRINT("ValueCell->DataLength %u\n", ValueCell
->DataLength
);
629 NewOffset
= HvAllocateCell(Hive
, cbData
, Stable
, HCELL_NIL
);
630 if (NewOffset
== HCELL_NIL
)
632 DPRINT("HvAllocateCell() failed with status 0x%08x\n", Status
);
633 return ERROR_UNSUCCESSFUL
;
637 HvFreeCell(Hive
, ValueCell
->Data
);
639 ValueCell
->Data
= NewOffset
;
640 DataCell
= (PVOID
)HvGetCell(Hive
, NewOffset
);
643 /* Copy new contents to cell */
644 RtlCopyMemory(DataCell
, lpData
, cbData
);
645 ValueCell
->DataLength
= (cbData
& ~CM_KEY_VALUE_SPECIAL_SIZE
);
646 ValueCell
->Type
= dwType
;
647 HvMarkCellDirty(Hive
, ValueCell
->Data
, FALSE
);
650 HvMarkCellDirty(Hive
, CellIndex
, FALSE
);
652 /* Check if the maximum value name length changed, update it if so */
653 if (KeyNode
->MaxValueNameLen
< ValueNameString
.Length
)
654 KeyNode
->MaxValueNameLen
= ValueNameString
.Length
;
656 /* Check if the maximum data length changed, update it if so */
657 if (KeyNode
->MaxValueDataLen
< cbData
)
658 KeyNode
->MaxValueDataLen
= cbData
;
660 /* Save the write time */
661 KeQuerySystemTime(&KeyNode
->LastWriteTime
);
663 DPRINT("Return status 0x%08x\n", Status
);
668 // Synced with freeldr/windows/registry.c
673 IN PCM_KEY_VALUE ValueCell
,
674 OUT ULONG
* Type OPTIONAL
,
675 OUT PUCHAR Data OPTIONAL
,
676 IN OUT ULONG
* DataSize OPTIONAL
)
681 /* Does the caller want the type? */
683 *Type
= ValueCell
->Type
;
685 /* Does the caller provide DataSize? */
686 if (DataSize
!= NULL
)
688 // NOTE: CmpValueToData doesn't support big data (the function will
689 // bugcheck if so), FreeLdr is not supposed to read such data.
690 // If big data is needed, use instead CmpGetValueData.
691 // CmpGetValueData(Hive, ValueCell, DataSize, &DataCell, ...);
692 DataCell
= CmpValueToData(Hive
, ValueCell
, &DataLength
);
694 /* Does the caller want the data? */
695 if ((Data
!= NULL
) && (*DataSize
!= 0))
699 min(*DataSize
, DataLength
));
702 /* Return the actual data length */
703 *DataSize
= DataLength
;
707 // Similar to RegQueryValue in freeldr/windows/registry.c
711 IN LPCWSTR lpValueName
,
712 IN PULONG lpReserved
,
713 OUT PULONG lpType OPTIONAL
,
714 OUT PUCHAR lpData OPTIONAL
,
715 IN OUT PULONG lpcbData OPTIONAL
)
717 PMEMKEY ParentKey
= HKEY_TO_MEMKEY(hKey
);
718 PHHIVE Hive
= &ParentKey
->RegistryHive
->Hive
;
719 PCM_KEY_NODE KeyNode
;
720 PCM_KEY_VALUE ValueCell
;
721 HCELL_INDEX CellIndex
;
722 UNICODE_STRING ValueNameString
;
724 KeyNode
= (PCM_KEY_NODE
)HvGetCell(Hive
, ParentKey
->KeyCellOffset
);
726 return ERROR_UNSUCCESSFUL
;
728 ASSERT(KeyNode
->Signature
== CM_KEY_NODE_SIGNATURE
);
730 /* Initialize value name string */
731 RtlInitUnicodeString(&ValueNameString
, lpValueName
);
732 CellIndex
= CmpFindValueByName(Hive
, KeyNode
, &ValueNameString
);
733 if (CellIndex
== HCELL_NIL
)
734 return ERROR_FILE_NOT_FOUND
;
736 /* Get the value cell */
737 ValueCell
= HvGetCell(Hive
, CellIndex
);
738 ASSERT(ValueCell
!= NULL
);
740 RepGetValueData(Hive
, ValueCell
, lpType
, lpData
, lpcbData
);
742 HvReleaseCell(Hive
, CellIndex
);
744 return ERROR_SUCCESS
;
750 IN LPCWSTR lpValueName OPTIONAL
)
752 DPRINT1("RegDeleteValueW(0x%p, '%S') is UNIMPLEMENTED!\n",
753 hKey
, (lpValueName
? lpValueName
: L
""));
754 return ERROR_UNSUCCESSFUL
;
761 IN PCMHIVE HiveToConnect
,
762 IN PUCHAR Descriptor
,
763 IN ULONG DescriptorLength
,
767 PREPARSE_POINT ReparsePoint
;
771 ReparsePoint
= (PREPARSE_POINT
)malloc(sizeof(REPARSE_POINT
));
776 * Use a dummy root key name:
777 * - On 2k/XP/2k3, this is "$$$PROTO.HIV"
778 * - On Vista+, this is "CMI-CreateHive{guid}"
779 * See https://github.com/libyal/winreg-kb/blob/master/documentation/Registry%20files.asciidoc
780 * for more information.
782 Status
= CmiInitializeHive(HiveToConnect
, L
"$$$PROTO.HIV");
783 if (!NT_SUCCESS(Status
))
785 DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status
);
791 * Add security to the root key.
792 * NOTE: One can implement this using the lpSecurityAttributes
793 * parameter of RegCreateKeyExW.
795 Status
= CmiCreateSecurityKey(&HiveToConnect
->Hive
,
796 HiveToConnect
->Hive
.BaseBlock
->RootCell
,
797 Descriptor
, DescriptorLength
);
798 if (!NT_SUCCESS(Status
))
799 DPRINT1("Failed to add security for root key '%S'\n", Path
);
802 rc
= RegCreateKeyExW(RootKey
,
811 if (rc
!= ERROR_SUCCESS
)
817 ReparsePoint
->SourceHive
= NewKey
->RegistryHive
;
818 ReparsePoint
->SourceKeyCellOffset
= NewKey
->KeyCellOffset
;
819 NewKey
->RegistryHive
= HiveToConnect
;
820 NewKey
->KeyCellOffset
= HiveToConnect
->Hive
.BaseBlock
->RootCell
;
821 ReparsePoint
->DestinationHive
= NewKey
->RegistryHive
;
822 ReparsePoint
->DestinationKeyCellOffset
= NewKey
->KeyCellOffset
;
823 InsertTailList(&CmiReparsePointsHead
, &ReparsePoint
->ListEntry
);
827 LIST_ENTRY CmiHiveListHead
;
830 RegInitializeRegistry(VOID
)
832 UNICODE_STRING RootKeyName
= RTL_CONSTANT_STRING(L
"\\");
834 PMEMKEY ControlSetKey
, CurrentControlSetKey
;
835 PREPARSE_POINT ReparsePoint
;
837 InitializeListHead(&CmiHiveListHead
);
838 InitializeListHead(&CmiReparsePointsHead
);
840 Status
= CmiInitializeHive(&RootHive
, L
"");
841 if (!NT_SUCCESS(Status
))
843 DPRINT1("CmiInitializeHive() failed with status 0x%08x\n", Status
);
847 RootKey
= CreateInMemoryStructure(&RootHive
,
848 RootHive
.Hive
.BaseBlock
->RootCell
);
850 /* Create DEFAULT key */
851 ConnectRegistry(NULL
,
853 SystemSecurity
, sizeof(SystemSecurity
),
854 L
"Registry\\User\\.DEFAULT");
857 ConnectRegistry(NULL
,
859 SystemSecurity
, sizeof(SystemSecurity
),
860 L
"Registry\\Machine\\SAM");
862 /* Create SECURITY key */
863 ConnectRegistry(NULL
,
866 L
"Registry\\Machine\\SECURITY");
868 /* Create SOFTWARE key */
869 ConnectRegistry(NULL
,
871 SoftwareSecurity
, sizeof(SoftwareSecurity
),
872 L
"Registry\\Machine\\SOFTWARE");
875 ConnectRegistry(NULL
,
877 BcdSecurity
, sizeof(BcdSecurity
),
878 L
"Registry\\Machine\\BCD00000000");
880 /* Create SYSTEM key */
881 ConnectRegistry(NULL
,
883 SystemSecurity
, sizeof(SystemSecurity
),
884 L
"Registry\\Machine\\SYSTEM");
886 /* Create 'ControlSet001' key */
888 L
"Registry\\Machine\\SYSTEM\\ControlSet001",
889 (HKEY
*)&ControlSetKey
);
891 /* Create 'CurrentControlSet' key */
892 RegCreateKeyExW(NULL
,
893 L
"Registry\\Machine\\SYSTEM\\CurrentControlSet",
899 (HKEY
*)&CurrentControlSetKey
,
902 /* Connect 'CurrentControlSet' to 'ControlSet001' */
903 ReparsePoint
= (PREPARSE_POINT
)malloc(sizeof(REPARSE_POINT
));
904 ReparsePoint
->SourceHive
= CurrentControlSetKey
->RegistryHive
;
905 ReparsePoint
->SourceKeyCellOffset
= CurrentControlSetKey
->KeyCellOffset
;
906 ReparsePoint
->DestinationHive
= ControlSetKey
->RegistryHive
;
907 ReparsePoint
->DestinationKeyCellOffset
= ControlSetKey
->KeyCellOffset
;
908 InsertTailList(&CmiReparsePointsHead
, &ReparsePoint
->ListEntry
);
912 RegShutdownRegistry(VOID
)
914 /* FIXME: clean up the complete hive */