New macros InitializeUnicodeString(), RtlInitUnicodeStringFromLiteral() and UNICODE_S...
[reactos.git] / reactos / ntoskrnl / cm / registry.c
1 /* $Id: registry.c,v 1.74 2002/08/20 20:37:11 hyperion Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/registry.c
6 * PURPOSE: Registry functions
7 * PROGRAMMERS: Rex Jolliff
8 * Matt Pyne
9 * Jean Michault
10 * UPDATE HISTORY:
11 * Created 22/05/98
12 */
13
14 #include <ddk/ntddk.h>
15 #include <roscfg.h>
16 #include <limits.h>
17 #include <string.h>
18 #include <internal/pool.h>
19 #include <internal/registry.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24 #include "cm.h"
25
26 /* ------------------------------------------------- File Statics */
27
28 POBJECT_TYPE CmiKeyType = NULL;
29 PREGISTRY_HIVE CmiVolatileHive = NULL;
30 KSPIN_LOCK CmiKeyListLock;
31
32 static PKEY_OBJECT CmiRootKey = NULL;
33 static PKEY_OBJECT CmiMachineKey = NULL;
34 static PKEY_OBJECT CmiUserKey = NULL;
35 static PKEY_OBJECT CmiHardwareKey = NULL;
36
37 static GENERIC_MAPPING CmiKeyMapping =
38 {KEY_READ, KEY_WRITE, KEY_EXECUTE, KEY_ALL_ACCESS};
39
40
41 VOID
42 CmiCheckKey(BOOLEAN Verbose,
43 HANDLE Key);
44
45 static NTSTATUS
46 CmiCreateCurrentControlSetLink(VOID);
47
48 /* FUNCTIONS ****************************************************************/
49
50 VOID
51 CmiCheckSubKeys(BOOLEAN Verbose,
52 HANDLE Key)
53 {
54 OBJECT_ATTRIBUTES ObjectAttributes;
55 PKEY_NODE_INFORMATION KeyInfo;
56 WCHAR KeyBuffer[MAX_PATH];
57 UNICODE_STRING KeyPath;
58 WCHAR Name[MAX_PATH];
59 ULONG BufferSize;
60 ULONG ResultSize;
61 NTSTATUS Status;
62 HANDLE SubKey;
63 ULONG Index;
64
65 Index = 0;
66 while (TRUE)
67 {
68 BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
69 KeyInfo = ExAllocatePool(PagedPool, BufferSize);
70
71 Status = NtEnumerateKey(Key,
72 Index,
73 KeyNodeInformation,
74 KeyInfo,
75 BufferSize,
76 &ResultSize);
77 if (!NT_SUCCESS(Status))
78 {
79 ExFreePool(KeyInfo);
80 if (Status == STATUS_NO_MORE_ENTRIES)
81 Status = STATUS_SUCCESS;
82 break;
83 }
84
85 wcsncpy(Name,
86 KeyInfo->Name,
87 KeyInfo->NameLength / sizeof(WCHAR));
88
89 if (Verbose)
90 {
91 DbgPrint("Key: %S\n", Name);
92 }
93
94 /* FIXME: Check info. */
95
96 ExFreePool(KeyInfo);
97
98 wcscpy(KeyBuffer, L"\\Registry\\");
99 wcscat(KeyBuffer, Name);
100
101 RtlInitUnicodeString(&KeyPath, KeyBuffer);
102
103 InitializeObjectAttributes(&ObjectAttributes,
104 &KeyPath,
105 OBJ_CASE_INSENSITIVE,
106 NULL,
107 NULL);
108
109 Status = NtOpenKey(&SubKey,
110 KEY_ALL_ACCESS,
111 &ObjectAttributes);
112
113 assert(NT_SUCCESS(Status));
114
115 CmiCheckKey(Verbose, SubKey);
116
117 NtClose(SubKey);
118
119 Index++;
120 }
121
122 assert(NT_SUCCESS(Status));
123 }
124
125
126 VOID
127 CmiCheckValues(BOOLEAN Verbose,
128 HANDLE Key)
129 {
130 PKEY_NODE_INFORMATION ValueInfo;
131 WCHAR Name[MAX_PATH];
132 ULONG BufferSize;
133 ULONG ResultSize;
134 NTSTATUS Status;
135 ULONG Index;
136
137 Index = 0;
138 while (TRUE)
139 {
140 BufferSize = sizeof(KEY_NODE_INFORMATION) + 4096;
141 ValueInfo = ExAllocatePool(PagedPool, BufferSize);
142
143 Status = NtEnumerateValueKey(Key,
144 Index,
145 KeyNodeInformation,
146 ValueInfo,
147 BufferSize,
148 &ResultSize);
149 if (!NT_SUCCESS(Status))
150 {
151 ExFreePool(ValueInfo);
152 if (Status == STATUS_NO_MORE_ENTRIES)
153 Status = STATUS_SUCCESS;
154 break;
155 }
156
157 wcsncpy(Name,
158 ValueInfo->Name,
159 ValueInfo->NameLength / sizeof(WCHAR));
160
161 if (Verbose)
162 {
163 DbgPrint("Value: %S\n", Name);
164 }
165
166 /* FIXME: Check info. */
167
168 ExFreePool(ValueInfo);
169
170 Index++;
171 }
172
173 assert(NT_SUCCESS(Status));
174 }
175
176
177 VOID
178 CmiCheckKey(BOOLEAN Verbose,
179 HANDLE Key)
180 {
181 CmiCheckValues(Verbose, Key);
182 CmiCheckSubKeys(Verbose, Key);
183 }
184
185
186 VOID
187 CmiCheckByName(BOOLEAN Verbose,
188 PWSTR KeyName)
189 {
190 OBJECT_ATTRIBUTES ObjectAttributes;
191 WCHAR KeyPathBuffer[MAX_PATH];
192 UNICODE_STRING KeyPath;
193 NTSTATUS Status;
194 HANDLE Key;
195
196 wcscpy(KeyPathBuffer, L"\\Registry\\");
197 wcscat(KeyPathBuffer, KeyName);
198
199 RtlInitUnicodeString(&KeyPath, KeyPathBuffer);
200
201 InitializeObjectAttributes(&ObjectAttributes,
202 &KeyPath,
203 OBJ_CASE_INSENSITIVE,
204 NULL,
205 NULL);
206
207 Status = NtOpenKey(&Key,
208 KEY_ALL_ACCESS,
209 &ObjectAttributes);
210
211 if (CHECKED)
212 {
213 if (!NT_SUCCESS(Status))
214 {
215 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath, Status);
216 DbgPrint("KeyPath %S Status: %.08x", KeyPath.Buffer, Status);
217 assert(NT_SUCCESS(Status));
218 }
219 }
220
221 CmiCheckKey(Verbose, Key);
222
223 NtClose(Key);
224 }
225
226
227 VOID
228 CmiCheckRegistry(BOOLEAN Verbose)
229 {
230 if (Verbose)
231 DbgPrint("Checking registry internals\n");
232
233 CmiCheckByName(Verbose, L"Machine");
234 CmiCheckByName(Verbose, L"User");
235 }
236
237
238 VOID
239 CmInitializeRegistry(VOID)
240 {
241 OBJECT_ATTRIBUTES ObjectAttributes;
242 UNICODE_STRING RootKeyName;
243 HANDLE RootKeyHandle;
244 PKEY_OBJECT NewKey;
245 HANDLE KeyHandle;
246 NTSTATUS Status;
247
248 /* Initialize the Key object type */
249 CmiKeyType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
250 assert(CmiKeyType);
251 CmiKeyType->TotalObjects = 0;
252 CmiKeyType->TotalHandles = 0;
253 CmiKeyType->MaxObjects = LONG_MAX;
254 CmiKeyType->MaxHandles = LONG_MAX;
255 CmiKeyType->PagedPoolCharge = 0;
256 CmiKeyType->NonpagedPoolCharge = sizeof(KEY_OBJECT);
257 CmiKeyType->Mapping = &CmiKeyMapping;
258 CmiKeyType->Dump = NULL;
259 CmiKeyType->Open = NULL;
260 CmiKeyType->Close = NULL;
261 CmiKeyType->Delete = CmiObjectDelete;
262 CmiKeyType->Parse = CmiObjectParse;
263 CmiKeyType->Security = NULL;
264 CmiKeyType->QueryName = NULL;
265 CmiKeyType->OkayToClose = NULL;
266 CmiKeyType->Create = CmiObjectCreate;
267 CmiKeyType->DuplicationNotify = NULL;
268 RtlInitUnicodeString(&CmiKeyType->TypeName, L"Key");
269
270 /* Build volatile registry store */
271 Status = CmiCreateRegistryHive(NULL, &CmiVolatileHive, FALSE);
272 assert(NT_SUCCESS(Status));
273
274 /* Build the Root Key Object */
275 RtlInitUnicodeString(&RootKeyName, REG_ROOT_KEY_NAME);
276 InitializeObjectAttributes(&ObjectAttributes, &RootKeyName, 0, NULL, NULL);
277 Status = ObCreateObject(&RootKeyHandle,
278 STANDARD_RIGHTS_REQUIRED,
279 &ObjectAttributes,
280 CmiKeyType,
281 (PVOID *) &NewKey);
282 assert(NT_SUCCESS(Status));
283 CmiRootKey = NewKey;
284 Status = ObReferenceObjectByHandle(RootKeyHandle,
285 STANDARD_RIGHTS_REQUIRED,
286 CmiKeyType,
287 KernelMode,
288 (PVOID *) &CmiRootKey,
289 NULL);
290 assert(NT_SUCCESS(Status));
291 CmiRootKey->RegistryHive = CmiVolatileHive;
292 NewKey->BlockOffset = CmiVolatileHive->HiveHeader->RootKeyCell;
293 NewKey->KeyCell = CmiGetBlock(CmiVolatileHive, NewKey->BlockOffset, NULL);
294 CmiRootKey->Flags = 0;
295 CmiRootKey->NumberOfSubKeys = 0;
296 CmiRootKey->SubKeys = NULL;
297 CmiRootKey->SizeOfSubKeys = 0;
298 CmiRootKey->Name = ExAllocatePool(PagedPool, strlen("Registry"));
299 CmiRootKey->NameSize = strlen("Registry");
300 memcpy(CmiRootKey->Name, "Registry", strlen("Registry"));
301
302 KeInitializeSpinLock(&CmiKeyListLock);
303
304 /* Create initial predefined symbolic links */
305
306 /* HKEY_LOCAL_MACHINE */
307 Status = ObCreateObject(&KeyHandle,
308 STANDARD_RIGHTS_REQUIRED,
309 NULL,
310 CmiKeyType,
311 (PVOID*) &NewKey);
312 assert(NT_SUCCESS(Status));
313 Status = CmiAddSubKey(CmiVolatileHive,
314 CmiRootKey,
315 NewKey,
316 L"Machine",
317 wcslen(L"Machine") * sizeof(WCHAR),
318 0,
319 NULL,
320 0);
321 assert(NT_SUCCESS(Status));
322 NewKey->RegistryHive = CmiVolatileHive;
323 NewKey->Flags = 0;
324 NewKey->NumberOfSubKeys = 0;
325 NewKey->SubKeys = NULL;
326 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
327 NewKey->Name = ExAllocatePool(PagedPool, strlen("Machine"));
328 NewKey->NameSize = strlen("Machine");
329 memcpy(NewKey->Name, "Machine", strlen("Machine"));
330 CmiAddKeyToList(CmiRootKey, NewKey);
331 CmiMachineKey = NewKey;
332
333 /* HKEY_USERS */
334 Status = ObCreateObject(&KeyHandle,
335 STANDARD_RIGHTS_REQUIRED,
336 NULL,
337 CmiKeyType,
338 (PVOID*) &NewKey);
339 assert(NT_SUCCESS(Status));
340 Status = CmiAddSubKey(CmiVolatileHive,
341 CmiRootKey,
342 NewKey,
343 L"User",
344 wcslen(L"User") * sizeof(WCHAR),
345 0,
346 NULL,
347 0);
348 assert(NT_SUCCESS(Status));
349 NewKey->RegistryHive = CmiVolatileHive;
350 NewKey->Flags = 0;
351 NewKey->NumberOfSubKeys = 0;
352 NewKey->SubKeys = NULL;
353 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
354 NewKey->Name = ExAllocatePool(PagedPool, strlen("User"));
355 NewKey->NameSize = strlen("User");
356 memcpy(NewKey->Name, "User", strlen("User"));
357 CmiAddKeyToList(CmiRootKey, NewKey);
358 CmiUserKey = NewKey;
359
360 /* Create '\\Registry\\Machine\\HARDWARE' key. */
361 Status = ObCreateObject(&KeyHandle,
362 STANDARD_RIGHTS_REQUIRED,
363 NULL,
364 CmiKeyType,
365 (PVOID*)&NewKey);
366 assert(NT_SUCCESS(Status));
367 Status = CmiAddSubKey(CmiVolatileHive,
368 CmiMachineKey,
369 NewKey,
370 L"HARDWARE",
371 wcslen(L"HARDWARE") * sizeof(WCHAR),
372 0,
373 NULL,
374 0);
375 assert(NT_SUCCESS(Status));
376 NewKey->RegistryHive = CmiVolatileHive;
377 NewKey->Flags = 0;
378 NewKey->NumberOfSubKeys = 0;
379 NewKey->SubKeys = NULL;
380 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
381 NewKey->Name = ExAllocatePool(PagedPool, strlen("HARDWARE"));
382 NewKey->NameSize = strlen("HARDWARE");
383 memcpy(NewKey->Name, "HARDWARE", strlen("HARDWARE"));
384 CmiAddKeyToList(CmiMachineKey, NewKey);
385 CmiHardwareKey = NewKey;
386
387 /* Create '\\Registry\\Machine\\HARDWARE\\DESCRIPTION' key. */
388 Status = ObCreateObject(&KeyHandle,
389 STANDARD_RIGHTS_REQUIRED,
390 NULL,
391 CmiKeyType,
392 (PVOID*) &NewKey);
393 assert(NT_SUCCESS(Status));
394 Status = CmiAddSubKey(CmiVolatileHive,
395 CmiHardwareKey,
396 NewKey,
397 L"DESCRIPTION",
398 wcslen(L"DESCRIPTION") * sizeof(WCHAR),
399 0,
400 NULL,
401 0);
402 assert(NT_SUCCESS(Status));
403 NewKey->RegistryHive = CmiVolatileHive;
404 NewKey->Flags = 0;
405 NewKey->NumberOfSubKeys = 0;
406 NewKey->SubKeys = NULL;
407 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
408 NewKey->Name = ExAllocatePool(PagedPool, strlen("DESCRIPTION"));
409 NewKey->NameSize = strlen("DESCRIPTION");
410 memcpy(NewKey->Name, "DESCRIPTION", strlen("DESCRIPTION"));
411 CmiAddKeyToList(CmiHardwareKey, NewKey);
412
413 /* Create '\\Registry\\Machine\\HARDWARE\\DEVICEMAP' key. */
414 Status = ObCreateObject(&KeyHandle,
415 STANDARD_RIGHTS_REQUIRED,
416 NULL,
417 CmiKeyType,
418 (PVOID*) &NewKey);
419 assert(NT_SUCCESS(Status));
420 Status = CmiAddSubKey(CmiVolatileHive,
421 CmiHardwareKey,
422 NewKey,
423 L"DEVICEMAP",
424 wcslen(L"DEVICEMAP") * sizeof(WCHAR),
425 0,
426 NULL,
427 0);
428 assert(NT_SUCCESS(Status));
429 NewKey->RegistryHive = CmiVolatileHive;
430 NewKey->Flags = 0;
431 NewKey->NumberOfSubKeys = 0;
432 NewKey->SubKeys = NULL;
433 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
434 NewKey->Name = ExAllocatePool(PagedPool, strlen("DEVICEMAP"));
435 NewKey->NameSize = strlen("DEVICEMAP");
436 memcpy(NewKey->Name, "DEVICEMAP", strlen("DEVICEMAP"));
437 CmiAddKeyToList(CmiHardwareKey,NewKey);
438
439 /* Create '\\Registry\\Machine\\HARDWARE\\RESOURCEMAP' key. */
440 Status = ObCreateObject(&KeyHandle,
441 STANDARD_RIGHTS_REQUIRED,
442 NULL,
443 CmiKeyType,
444 (PVOID*) &NewKey);
445 assert(NT_SUCCESS(Status));
446 Status = CmiAddSubKey(CmiVolatileHive,
447 CmiHardwareKey,
448 NewKey,
449 L"RESOURCEMAP",
450 wcslen(L"RESOURCEMAP") * sizeof(WCHAR),
451 0,
452 NULL,
453 0);
454 assert(NT_SUCCESS(Status));
455 NewKey->RegistryHive = CmiVolatileHive;
456 NewKey->Flags = 0;
457 NewKey->NumberOfSubKeys = 0;
458 NewKey->SubKeys = NULL;
459 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
460 NewKey->Name = ExAllocatePool(PagedPool, strlen("RESOURCEMAP"));
461 NewKey->NameSize = strlen("RESOURCEMAP");
462 memcpy(NewKey->Name, "RESOURCEMAP", strlen("RESOURCEMAP"));
463 CmiAddKeyToList(CmiHardwareKey, NewKey);
464
465 /* FIXME: create remaining structure needed for default handles */
466 /* FIXME: load volatile registry data from ROSDTECT */
467 }
468
469
470 VOID
471 CmInit2(PCHAR CommandLine)
472 {
473 PCHAR p1, p2;
474 ULONG PiceStart;
475
476 /* FIXME: Store current command line */
477
478 /* Create the 'CurrentControlSet' link. */
479 CmiCreateCurrentControlSetLink();
480
481
482 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
483 PiceStart = 4;
484 p1 = (PCHAR)CommandLine;
485 while (p1 && (p2 = strchr(p1, '/')))
486 {
487 p2++;
488 if (_strnicmp(p2, "DEBUGPORT", 9) == 0)
489 {
490 p2 += 9;
491 if (*p2 == '=')
492 {
493 p2++;
494 if (_strnicmp(p2, "PICE", 4) == 0)
495 {
496 p2 += 4;
497 PiceStart = 1;
498 }
499 }
500 }
501 p1 = p2;
502 }
503
504 RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
505 L"\\Pice",
506 L"Start",
507 REG_DWORD,
508 &PiceStart,
509 sizeof(ULONG));
510
511 }
512
513
514 static NTSTATUS
515 CmiCreateCurrentControlSetLink(VOID)
516 {
517 RTL_QUERY_REGISTRY_TABLE QueryTable[5];
518 WCHAR TargetNameBuffer[80];
519 ULONG TargetNameLength;
520 UNICODE_STRING LinkName;
521 UNICODE_STRING LinkValue;
522 ULONG CurrentSet;
523 ULONG DefaultSet;
524 ULONG Failed;
525 ULONG LastKnownGood;
526 NTSTATUS Status;
527 OBJECT_ATTRIBUTES ObjectAttributes;
528 HANDLE KeyHandle;
529
530 DPRINT("CmiCreateCurrentControlSetLink() called\n");
531
532 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
533
534 QueryTable[0].Name = L"Current";
535 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
536 QueryTable[0].EntryContext = &CurrentSet;
537
538 QueryTable[1].Name = L"Default";
539 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
540 QueryTable[1].EntryContext = &DefaultSet;
541
542 QueryTable[2].Name = L"Failed";
543 QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
544 QueryTable[2].EntryContext = &Failed;
545
546 QueryTable[3].Name = L"LastKnownGood";
547 QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
548 QueryTable[3].EntryContext = &LastKnownGood;
549
550 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
551 L"\\Registry\\Machine\\SYSTEM\\Select",
552 QueryTable,
553 NULL,
554 NULL);
555 if (!NT_SUCCESS(Status))
556 {
557 return(Status);
558 }
559
560 DPRINT("Current %ld Default %ld\n", CurrentSet, DefaultSet);
561
562 swprintf(TargetNameBuffer,
563 L"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
564 CurrentSet);
565 TargetNameLength = wcslen(TargetNameBuffer) * sizeof(WCHAR);
566
567 DPRINT("Link target '%S'\n", TargetNameBuffer);
568
569 RtlInitUnicodeStringFromLiteral(&LinkName,
570 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
571 InitializeObjectAttributes(&ObjectAttributes,
572 &LinkName,
573 OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_OPENLINK,
574 NULL,
575 NULL);
576 Status = NtCreateKey(&KeyHandle,
577 KEY_ALL_ACCESS | KEY_CREATE_LINK,
578 &ObjectAttributes,
579 0,
580 NULL,
581 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK,
582 NULL);
583 if (!NT_SUCCESS(Status))
584 {
585 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
586 return(Status);
587 }
588
589 RtlInitUnicodeStringFromLiteral(&LinkValue,
590 L"SymbolicLinkValue");
591 Status=NtSetValueKey(KeyHandle,
592 &LinkValue,
593 0,
594 REG_LINK,
595 (PVOID)TargetNameBuffer,
596 TargetNameLength);
597 if (!NT_SUCCESS(Status))
598 {
599 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
600 }
601
602 NtClose(KeyHandle);
603
604 return(Status);
605 }
606
607
608 NTSTATUS
609 CmiConnectHive(PWSTR FileName,
610 PWSTR FullName,
611 PCHAR KeyName,
612 PKEY_OBJECT Parent,
613 BOOLEAN CreateNew)
614 {
615 OBJECT_ATTRIBUTES ObjectAttributes;
616 PREGISTRY_HIVE RegistryHive = NULL;
617 UNICODE_STRING uKeyName;
618 PKEY_OBJECT NewKey;
619 HANDLE KeyHandle;
620 NTSTATUS Status;
621
622 DPRINT("Called. FileName %S\n", FullName);
623
624 Status = CmiCreateRegistryHive(FileName, &RegistryHive, CreateNew);
625 if (!NT_SUCCESS(Status))
626 return(Status);
627
628 RtlInitUnicodeString(&uKeyName, FullName);
629
630 InitializeObjectAttributes(&ObjectAttributes,
631 &uKeyName,
632 0,
633 NULL,
634 NULL);
635
636 Status = ObCreateObject(&KeyHandle,
637 STANDARD_RIGHTS_REQUIRED,
638 &ObjectAttributes,
639 CmiKeyType,
640 (PVOID*)&NewKey);
641 if (!NT_SUCCESS(Status))
642 return(Status);
643
644 NewKey->RegistryHive = RegistryHive;
645 NewKey->BlockOffset = RegistryHive->HiveHeader->RootKeyCell;
646 NewKey->KeyCell = CmiGetBlock(RegistryHive, NewKey->BlockOffset, NULL);
647 NewKey->Flags = 0;
648 NewKey->NumberOfSubKeys = 0;
649 NewKey->SubKeys = ExAllocatePool(PagedPool,
650 NewKey->KeyCell->NumberOfSubKeys * sizeof(DWORD));
651
652 if ((NewKey->SubKeys == NULL) && (NewKey->KeyCell->NumberOfSubKeys != 0))
653 {
654 /* FIXME: Cleanup from CmiCreateRegistryHive() */
655 DPRINT("NumberOfSubKeys %d\n", NewKey->KeyCell->NumberOfSubKeys);
656 ZwClose(NewKey);
657 return(STATUS_INSUFFICIENT_RESOURCES);
658 }
659
660 NewKey->SizeOfSubKeys = NewKey->KeyCell->NumberOfSubKeys;
661 NewKey->Name = ExAllocatePool(PagedPool, strlen(KeyName));
662
663 if ((NewKey->Name == NULL) && (strlen(KeyName) != 0))
664 {
665 /* FIXME: Cleanup from CmiCreateRegistryHive() */
666 DPRINT("strlen(KeyName) %d\n", strlen(KeyName));
667 if (NewKey->SubKeys != NULL)
668 ExFreePool(NewKey->SubKeys);
669 ZwClose(NewKey);
670 return(STATUS_INSUFFICIENT_RESOURCES);
671 }
672
673 NewKey->NameSize = strlen(KeyName);
674 memcpy(NewKey->Name, KeyName, strlen(KeyName));
675 CmiAddKeyToList(Parent, NewKey);
676
677 VERIFY_KEY_OBJECT(NewKey);
678
679 return(STATUS_SUCCESS);
680 }
681
682
683 NTSTATUS
684 CmiInitializeHive(PWSTR FileName,
685 PWSTR FullName,
686 PCHAR KeyName,
687 PKEY_OBJECT Parent,
688 BOOLEAN CreateNew)
689 {
690 NTSTATUS Status;
691
692 DPRINT("CmiInitializeHive(%s) called\n", KeyName);
693
694 /* Try to connect the hive */
695 //Status = CmiConnectHive(FileName, FullName, KeyName, Parent, FALSE);
696 Status = CmiConnectHive(FileName, FullName, KeyName, Parent, CreateNew);
697
698 if (!NT_SUCCESS(Status))
699 {
700 DPRINT("Status %.08x\n", Status);
701 #if 0
702 WCHAR AltFileName[MAX_PATH];
703
704 CPRINT("WARNING! Registry file %S not found\n", FileName);
705
706 wcscpy(AltFileName, FileName);
707 wcscat(AltFileName, L".alt");
708
709 /* Try to connect the alternative hive */
710 Status = CmiConnectHive(AltFileName, FullName, KeyName, Parent, TRUE);
711
712 if (!NT_SUCCESS(Status))
713 {
714 CPRINT("WARNING! Alternative registry file %S not found\n", AltFileName);
715 DPRINT("Status %.08x\n", Status);
716 }
717 #endif
718 }
719
720 DPRINT("CmiInitializeHive() done\n");
721
722 return(Status);
723 }
724
725
726 NTSTATUS
727 CmiInitHives(BOOLEAN SetUpBoot)
728 {
729 NTSTATUS Status;
730
731 DPRINT("CmiInitHives() called\n");
732
733 CmiDoVerify = TRUE;
734
735 /* FIXME: Delete temporary \Registry\Machine\System */
736
737 /* Connect the SYSTEM hive */
738 /* FIXME: Don't overwrite the existing 'System' hive yet */
739 // Status = CmiInitializeHive(SYSTEM_REG_FILE, REG_SYSTEM_KEY_NAME, "System", CmiMachineKey);
740 // assert(NT_SUCCESS(Status));
741
742 /* Connect the SOFTWARE hive */
743 Status = CmiInitializeHive(SOFTWARE_REG_FILE, REG_SOFTWARE_KEY_NAME, "Software", CmiMachineKey, SetUpBoot);
744 //assert(NT_SUCCESS(Status));
745
746 /* Connect the SAM hive */
747 Status = CmiInitializeHive(SAM_REG_FILE,REG_SAM_KEY_NAME, "Sam", CmiMachineKey, SetUpBoot);
748 //assert(NT_SUCCESS(Status));
749
750 /* Connect the SECURITY hive */
751 Status = CmiInitializeHive(SEC_REG_FILE, REG_SEC_KEY_NAME, "Security", CmiMachineKey, SetUpBoot);
752 //assert(NT_SUCCESS(Status));
753
754 /* Connect the DEFAULT hive */
755 Status = CmiInitializeHive(USER_REG_FILE, REG_USER_KEY_NAME, ".Default", CmiUserKey, SetUpBoot);
756 //assert(NT_SUCCESS(Status));
757
758 /* FIXME : initialize standards symbolic links */
759
760 // CmiCheckRegistry(TRUE);
761
762 DPRINT("CmiInitHives() done\n");
763
764 return(STATUS_SUCCESS);
765 }
766
767
768 VOID
769 CmShutdownRegistry(VOID)
770 {
771 DPRINT("CmShutdownRegistry() called\n");
772
773 /* Note:
774 * Don't call UNIMPLEMENTED() here since this function is
775 * called by NtShutdownSystem().
776 */
777 }
778
779 /* EOF */