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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS hive maker
21 * FILE: tools/mkhive/registry.c
22 * PURPOSE: Registry code
23 * PROGRAMMER: Hervé Poussineau
28 * - Implement RegDeleteKey()
29 * - Implement RegEnumValue()
30 * - Implement RegQueryValueExA()
40 static EREGISTRY_HIVE RootHive
;
41 static MEMKEY RootKey
;
42 EREGISTRY_HIVE DefaultHive
; /* \Registry\User\.DEFAULT */
43 EREGISTRY_HIVE SamHive
; /* \Registry\Machine\SAM */
44 EREGISTRY_HIVE SecurityHive
; /* \Registry\Machine\SECURITY */
45 EREGISTRY_HIVE SoftwareHive
; /* \Registry\Machine\SOFTWARE */
46 EREGISTRY_HIVE SystemHive
; /* \Registry\Machine\SYSTEM */
49 CreateInMemoryStructure(
50 IN PEREGISTRY_HIVE RegistryHive
,
51 IN HCELL_INDEX KeyCellOffset
,
52 IN PCUNICODE_STRING KeyName
)
56 Key
= (MEMKEY
) malloc (sizeof(KEY
));
60 InitializeListHead (&Key
->SubKeyList
);
61 InitializeListHead (&Key
->ValueList
);
62 InitializeListHead (&Key
->KeyList
);
67 Key
->NameSize
= KeyName
->Length
;
68 Key
->Name
= malloc (Key
->NameSize
);
71 memcpy(Key
->Name
, KeyName
->Buffer
, KeyName
->Length
);
77 Key
->RegistryHive
= RegistryHive
;
78 Key
->KeyCellOffset
= KeyCellOffset
;
79 Key
->KeyCell
= HvGetCell (&RegistryHive
->Hive
, Key
->KeyCellOffset
);
85 Key
->LinkedKey
= NULL
;
93 IN BOOL AllowCreation
,
98 UNICODE_STRING KeyString
;
103 PCM_KEY_NODE SubKeyCell
;
104 HCELL_INDEX BlockOffset
;
106 DPRINT("RegpCreateOpenKey('%S')\n", KeyName
);
108 if (*KeyName
== L
'\\')
113 else if (hParentKey
== NULL
)
119 ParentKey
= HKEY_TO_MEMKEY(RootKey
);
122 LocalKeyName
= (PWSTR
)KeyName
;
125 End
= (PWSTR
) xwcschr(LocalKeyName
, '\\');
128 KeyString
.Buffer
= LocalKeyName
;
129 KeyString
.Length
= KeyString
.MaximumLength
=
130 (USHORT
)((ULONG_PTR
)End
- (ULONG_PTR
)LocalKeyName
);
133 RtlInitUnicodeString(&KeyString
, LocalKeyName
);
135 /* Redirect from 'CurrentControlSet' to 'ControlSet001' */
136 if (!wcsncmp(LocalKeyName
, L
"CurrentControlSet", 17) &&
137 ParentKey
->NameSize
== 12 &&
138 !memcmp(ParentKey
->Name
, L
"SYSTEM", 12))
139 RtlInitUnicodeString(&KeyString
, L
"ControlSet001");
141 /* Check subkey in memory structure */
142 Ptr
= ParentKey
->SubKeyList
.Flink
;
143 while (Ptr
!= &ParentKey
->SubKeyList
)
145 CurrentKey
= CONTAINING_RECORD(Ptr
, KEY
, KeyList
);
146 if (CurrentKey
->NameSize
== KeyString
.Length
147 && memcmp(CurrentKey
->Name
, KeyString
.Buffer
, KeyString
.Length
) == 0)
155 Status
= CmiScanForSubKey(
156 ParentKey
->RegistryHive
,
159 OBJ_CASE_INSENSITIVE
,
162 if (AllowCreation
&& Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
164 Status
= CmiAddSubKey(
165 ParentKey
->RegistryHive
,
167 ParentKey
->KeyCellOffset
,
173 if (!NT_SUCCESS(Status
))
174 return ERROR_UNSUCCESSFUL
;
176 /* Now, SubKeyCell/BlockOffset are valid */
177 CurrentKey
= CreateInMemoryStructure(
178 ParentKey
->RegistryHive
,
182 return ERROR_OUTOFMEMORY
;
184 /* Add CurrentKey in ParentKey */
185 InsertTailList(&ParentKey
->SubKeyList
, &CurrentKey
->KeyList
);
186 ParentKey
->SubKeyCount
++;
189 ParentKey
= CurrentKey
;
191 LocalKeyName
= End
+ 1;
196 *Key
= MEMKEY_TO_HKEY(ParentKey
);
198 return ERROR_SUCCESS
;
207 return RegpOpenOrCreateKey(hKey
, lpSubKey
, TRUE
, phkResult
);
212 IN PCSTR MultiByteString
)
215 UNICODE_STRING Destination
;
218 RtlInitAnsiString(&Source
, MultiByteString
);
219 Status
= RtlAnsiStringToUnicodeString(&Destination
, &Source
, TRUE
);
220 if (!NT_SUCCESS(Status
))
222 return Destination
.Buffer
;
234 lpSubKeyW
= MultiByteToWideChar(lpSubKey
);
236 return ERROR_OUTOFMEMORY
;
238 rc
= RegCreateKeyW(hKey
, lpSubKeyW
, phkResult
);
244 RegDeleteKeyA(HKEY Key
,
247 if (Name
!= NULL
&& strchr(Name
, '\\') != NULL
)
248 return(ERROR_INVALID_PARAMETER
);
252 return(ERROR_SUCCESS
);
261 return RegpOpenOrCreateKey(hKey
, lpSubKey
, FALSE
, phkResult
);
273 lpSubKeyW
= MultiByteToWideChar(lpSubKey
);
275 return ERROR_OUTOFMEMORY
;
277 rc
= RegOpenKeyW(hKey
, lpSubKeyW
, phkResult
);
283 RegpOpenOrCreateValue(
285 IN LPCWSTR ValueName
,
286 IN BOOL AllowCreation
,
287 OUT PCM_KEY_VALUE
*ValueCell
,
288 OUT PHCELL_INDEX ValueCellOffset
)
291 UNICODE_STRING ValueString
;
294 ParentKey
= HKEY_TO_MEMKEY(hKey
);
295 RtlInitUnicodeString(&ValueString
, ValueName
);
297 Status
= CmiScanForValueKey(
298 ParentKey
->RegistryHive
,
303 if (AllowCreation
&& Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
305 Status
= CmiAddValueKey(
306 ParentKey
->RegistryHive
,
308 ParentKey
->KeyCellOffset
,
313 if (!NT_SUCCESS(Status
))
314 return ERROR_UNSUCCESSFUL
;
315 return ERROR_SUCCESS
;
321 IN LPCWSTR lpValueName OPTIONAL
,
324 IN
const UCHAR
* lpData
,
329 PCM_KEY_VALUE ValueCell
;
330 HCELL_INDEX ValueCellOffset
;
335 if (dwType
== REG_LINK
)
337 /* Special handling of registry links */
338 if (cbData
!= sizeof(PVOID
))
339 return STATUS_INVALID_PARAMETER
;
340 phKey
= (PHKEY
)lpData
;
341 Key
= HKEY_TO_MEMKEY(hKey
);
342 DestKey
= HKEY_TO_MEMKEY(*phKey
);
344 /* Create the link in memory */
345 Key
->DataType
= REG_LINK
;
346 Key
->LinkedKey
= DestKey
;
348 /* Create the link in registry hive (if applicable) */
349 if (Key
->RegistryHive
!= DestKey
->RegistryHive
)
350 return STATUS_SUCCESS
;
351 DPRINT1("Save link to registry\n");
352 return STATUS_NOT_IMPLEMENTED
;
355 if ((cbData
& REG_DATA_SIZE_MASK
) != cbData
)
356 return STATUS_UNSUCCESSFUL
;
358 Key
= HKEY_TO_MEMKEY(hKey
);
360 Status
= RegpOpenOrCreateValue(hKey
, lpValueName
, TRUE
, &ValueCell
, &ValueCellOffset
);
361 if (!NT_SUCCESS(Status
))
362 return ERROR_UNSUCCESSFUL
;
364 /* Get size of the allocated cellule (if any) */
365 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
366 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
368 DataCell
= HvGetCell(&Key
->RegistryHive
->Hive
, ValueCell
->DataOffset
);
370 return ERROR_UNSUCCESSFUL
;
371 DataCellSize
= -HvGetCellSize(&Key
->RegistryHive
->Hive
, DataCell
);
379 if (cbData
<= sizeof(HCELL_INDEX
))
381 /* If data size <= sizeof(HCELL_INDEX) then store data in the data offset */
382 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
384 HvFreeCell(&Key
->RegistryHive
->Hive
, ValueCell
->DataOffset
);
386 RtlCopyMemory(&ValueCell
->DataOffset
, lpData
, cbData
);
387 ValueCell
->DataSize
= (ULONG
)(cbData
| REG_DATA_IN_OFFSET
);
388 ValueCell
->DataType
= dwType
;
389 HvMarkCellDirty(&Key
->RegistryHive
->Hive
, ValueCellOffset
);
393 if (cbData
> (SIZE_T
)DataCellSize
)
395 /* New data size is larger than the current, destroy current
396 * data block and allocate a new one. */
397 HCELL_INDEX NewOffset
;
399 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
401 NewOffset
= HvAllocateCell(&Key
->RegistryHive
->Hive
, cbData
, HvStable
);
402 if (NewOffset
== HCELL_NULL
)
404 DPRINT("HvAllocateCell() failed with status 0x%08lx\n", Status
);
405 return ERROR_UNSUCCESSFUL
;
409 HvFreeCell(&Key
->RegistryHive
->Hive
, ValueCell
->DataOffset
);
411 ValueCell
->DataOffset
= NewOffset
;
412 DataCell
= HvGetCell(&Key
->RegistryHive
->Hive
, NewOffset
);
415 /* Copy new contents to cellule */
416 RtlCopyMemory(DataCell
, lpData
, cbData
);
417 ValueCell
->DataSize
= (ULONG
)(cbData
& REG_DATA_SIZE_MASK
);
418 ValueCell
->DataType
= dwType
;
419 HvMarkCellDirty(&Key
->RegistryHive
->Hive
, ValueCell
->DataOffset
);
420 HvMarkCellDirty(&Key
->RegistryHive
->Hive
, ValueCellOffset
);
423 HvMarkCellDirty(&Key
->RegistryHive
->Hive
, Key
->KeyCellOffset
);
425 DPRINT("Return status 0x%08lx\n", Status
);
432 IN LPCSTR lpValueName OPTIONAL
,
435 IN
const UCHAR
* lpData
,
438 LPWSTR lpValueNameW
= NULL
;
439 const UCHAR
* lpDataW
;
441 LONG rc
= ERROR_SUCCESS
;
443 DPRINT("RegSetValueA(%s)\n", lpValueName
);
446 lpValueNameW
= MultiByteToWideChar(lpValueName
);
448 return ERROR_OUTOFMEMORY
;
451 if ((dwType
== REG_SZ
|| dwType
== REG_EXPAND_SZ
|| dwType
== REG_MULTI_SZ
)
454 ANSI_STRING AnsiString
;
457 if (lpData
[cbData
- 1] != '\0')
459 RtlInitAnsiString(&AnsiString
, NULL
);
460 AnsiString
.Buffer
= (PSTR
)lpData
;
461 AnsiString
.Length
= (USHORT
)cbData
- 1;
462 AnsiString
.MaximumLength
= (USHORT
)cbData
;
463 RtlAnsiStringToUnicodeString (&Data
, &AnsiString
, TRUE
);
464 lpDataW
= (const UCHAR
*)Data
.Buffer
;
465 cbDataW
= Data
.MaximumLength
;
470 cbDataW
= (USHORT
)cbData
;
473 if (rc
== ERROR_SUCCESS
)
474 rc
= RegSetValueExW(hKey
, lpValueNameW
, 0, dwType
, lpDataW
, cbDataW
);
477 if (lpData
!= lpDataW
)
478 free((PVOID
)lpDataW
);
485 IN LPCWSTR lpValueName
,
486 IN PULONG lpReserved
,
489 OUT PSIZE_T lpcbData
)
491 //ParentKey = HKEY_TO_MEMKEY(RootKey);
492 PCM_KEY_VALUE ValueCell
;
493 HCELL_INDEX ValueCellOffset
;
496 rc
= RegpOpenOrCreateValue(
502 if (rc
!= ERROR_SUCCESS
)
505 DPRINT1("RegQueryValueExW(%S) not implemented\n", lpValueName
);
506 /* ValueCell and ValueCellOffset are valid */
508 return ERROR_UNSUCCESSFUL
;
514 IN LPCSTR lpValueName
,
515 IN PULONG lpReserved
,
518 OUT PSIZE_T lpcbData
)
520 LPWSTR lpValueNameW
= NULL
;
525 lpValueNameW
= MultiByteToWideChar(lpValueName
);
527 return ERROR_OUTOFMEMORY
;
530 rc
= RegQueryValueExW(hKey
, lpValueNameW
, lpReserved
, lpType
, lpData
, lpcbData
);
533 return ERROR_UNSUCCESSFUL
;
539 IN LPCWSTR lpValueName OPTIONAL
)
541 DPRINT1("RegDeleteValueW() unimplemented\n");
542 return ERROR_UNSUCCESSFUL
;
548 IN LPCSTR lpValueName OPTIONAL
)
555 lpValueNameW
= MultiByteToWideChar(lpValueName
);
557 return ERROR_OUTOFMEMORY
;
558 rc
= RegDeleteValueW(hKey
, lpValueNameW
);
562 rc
= RegDeleteValueW(hKey
, NULL
);
569 IN PEREGISTRY_HIVE HiveToConnect
,
576 Status
= CmiInitializeTempHive(HiveToConnect
);
577 if (!NT_SUCCESS(Status
))
579 DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status
);
588 if (rc
!= ERROR_SUCCESS
)
591 NewKey
->RegistryHive
= HiveToConnect
;
592 NewKey
->KeyCellOffset
= HiveToConnect
->Hive
.HiveHeader
->RootCell
;
593 NewKey
->KeyCell
= HvGetCell (&HiveToConnect
->Hive
, NewKey
->KeyCellOffset
);
598 MyExportBinaryHive (PCHAR FileName
,
599 PEREGISTRY_HIVE RootHive
)
604 /* Create new hive file */
605 File
= fopen (FileName
, "w+b");
608 printf(" Error creating/opening file\n");
612 fseek (File
, 0, SEEK_SET
);
614 RootHive
->HiveHandle
= (HANDLE
)File
;
615 ret
= HvWriteHive(&RootHive
->Hive
);
620 LIST_ENTRY CmiHiveListHead
;
623 RegInitializeRegistry(VOID
)
625 UNICODE_STRING RootKeyName
= RTL_CONSTANT_STRING(L
"\\");
627 HKEY ControlSetKey
, LinkKey
;
629 InitializeListHead(&CmiHiveListHead
);
631 Status
= CmiInitializeTempHive(&RootHive
);
632 if (!NT_SUCCESS(Status
))
634 DPRINT1("CmiInitializeTempHive() failed with status 0x%08lx\n", Status
);
638 RootKey
= CreateInMemoryStructure(
640 RootHive
.Hive
.HiveHeader
->RootCell
,
643 /* Create DEFAULT key */
647 L
"Registry\\User\\.DEFAULT");
653 L
"Registry\\Machine\\SAM");
655 /* Create SECURITY key */
659 L
"Registry\\Machine\\SECURITY");
661 /* Create SOFTWARE key */
665 L
"Registry\\Machine\\SOFTWARE");
667 /* Create SYSTEM key */
671 L
"Registry\\Machine\\SYSTEM");
673 /* Create 'ControlSet001' key */
676 L
"Registry\\Machine\\SYSTEM\\ControlSet001",