ReactOS 0.4.15-dev-7788-g1ad9096
wlregistry.c
Go to the documentation of this file.
1/*
2 * PROJECT: EFI Windows Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/windows/wlregistry.c
5 * PURPOSE: Registry support functions
6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
7 */
8
9/* INCLUDES ***************************************************************/
10
11#include <freeldr.h>
12#include "winldr.h"
13#include "registry.h"
14#include <internal/cmboot.h>
15
16#include <debug.h>
18
19// The only global var here, used to mark mem pages as NLS in WinLdrSetupMemoryLayout()
21
22static BOOLEAN
24 _In_ HKEY ControlSet,
25 _Inout_ PUNICODE_STRING AnsiFileName,
26 _Inout_ PUNICODE_STRING OemFileName,
27 _Inout_ PUNICODE_STRING LangFileName, // CaseTable
28 _Inout_ PUNICODE_STRING OemHalFileName);
29
30static BOOLEAN
32 IN OUT PLIST_ENTRY BootDriverListHead);
33
34typedef enum _BAD_HIVE_REASON
35{
41
42/* FUNCTIONS **************************************************************/
43
44static BOOLEAN
47 _In_ PCSTR DirectoryPath,
48 _In_ PCSTR HiveName,
50{
51 ULONG FileId;
52 CHAR FullHiveName[MAX_PATH];
55 ULONG HiveFileSize;
56 PVOID HiveDataPhysical;
57 PVOID HiveDataVirtual;
59
60 /* Do not setup any bad reason for now */
62
63 /* Concatenate path and filename to get the full name */
64 RtlStringCbCopyA(FullHiveName, sizeof(FullHiveName), DirectoryPath);
65 RtlStringCbCatA(FullHiveName, sizeof(FullHiveName), HiveName);
66
67 NtLdrOutputLoadMsg(FullHiveName, NULL);
68 Status = ArcOpen(FullHiveName, OpenReadOnly, &FileId);
69 if (Status != ESUCCESS)
70 {
71 WARN("Error while opening '%s', Status: %u\n", FullHiveName, Status);
72 *Reason = NoHive;
73 return FALSE;
74 }
75
76 /* Get the file length */
78 if (Status != ESUCCESS)
79 {
80 WARN("Hive file has 0 size!\n");
82 ArcClose(FileId);
83 return FALSE;
84 }
85 HiveFileSize = FileInfo.EndingAddress.LowPart;
86
87 /* Round up the size to page boundary and alloc memory */
88 HiveDataPhysical = MmAllocateMemoryWithType(
89 MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
91
92 if (HiveDataPhysical == NULL)
93 {
94 WARN("Could not alloc memory for hive!\n");
96 ArcClose(FileId);
97 return FALSE;
98 }
99
100 /* Convert address to virtual */
101 HiveDataVirtual = PaToVa(HiveDataPhysical);
102
103 /* Fill LoaderBlock's entries */
104 LoaderBlock->RegistryLength = HiveFileSize;
105 LoaderBlock->RegistryBase = HiveDataVirtual;
106
107 /* Finally read from file to the memory */
108 Status = ArcRead(FileId, HiveDataPhysical, HiveFileSize, &BytesRead);
109 if (Status != ESUCCESS)
110 {
111 WARN("Error while reading '%s', Status: %u\n", FullHiveName, Status);
113 ArcClose(FileId);
114 return FALSE;
115 }
116
117 // FIXME: HACK: Get the boot filesystem driver name now...
119
120 ArcClose(FileId);
121 return TRUE;
122}
123
126 IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
129{
130 CHAR SearchPath[1024];
131 PVOID ChunkBase;
132 PCSTR HiveName;
135
136 /* Load the corresponding text-mode setup system hive or the standard hive */
137 if (Setup)
138 {
140 HiveName = "SETUPREG.HIV";
141 }
142 else
143 {
145 RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\config\\");
146 HiveName = "SYSTEM";
147 }
148
149 TRACE("WinLdrInitSystemHive: loading hive %s%s\n", SearchPath, HiveName);
150 Success = WinLdrLoadSystemHive(LoaderBlock, SearchPath, HiveName, &Reason);
151 if (!Success)
152 {
153 /* Check whether the SYSTEM hive does not exist or is too corrupt to be read */
154 if (Reason == CorruptHive || Reason == NoHive)
155 {
156 /* Try loading the alternate hive, the main hive should be recovered later */
157 goto LoadAlternateHive;
158 }
159
160 /* We are failing for other reason, bail out */
161 UiMessageBox("Could not load %s hive!", HiveName);
162 return FALSE;
163 }
164
165 /* Import what was loaded */
166 Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength, SearchPath, FALSE);
167 if (!Success)
168 {
169 /*
170 * Importing of the SYSTEM hive failed. The scenarios that would
171 * have made this possible are the following:
172 *
173 * 1. The primary hive is corrupt beyond repair (such as when
174 * core FS structures are total toast);
175 *
176 * 2. Repairing the hive could with a LOG could not recover it
177 * to the fullest. This is the case when the hive and LOG have
178 * diverged too much, or are mismatched, or the containing healthy
179 * data in the LOG was not marked as dirty that could be copied
180 * into the primary hive;
181 *
182 * 3. LOG is bad (e.g. corrupt dirty vector);
183 *
184 * 4. LOG does not physically exist on the backing storage.
185 *
186 * 5. SYSTEM hive does not physically exist or it is a 0 bytes file
187 * (the latter case still counts as corruption).
188 *
189 * With the hope to boot the system, load the mirror counterpart
190 * of the main hive, the alternate. The kernel should be able to recover
191 * the main hive later on as soon as it starts writing to it.
192 */
193LoadAlternateHive:
194 HiveName = "SYSTEM.ALT";
195 Success = WinLdrLoadSystemHive(LoaderBlock, SearchPath, HiveName, &Reason);
196 if (!Success)
197 {
198 UiMessageBox("Could not load %s hive!", HiveName);
199 return FALSE;
200 }
201
202 /* Retry importing it again */
203 Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength, SearchPath, TRUE);
204 if (!Success)
205 {
206 UiMessageBox("Importing binary hive failed!");
207 return FALSE;
208 }
209
210 /*
211 * Acknowledge the kernel we recovered the SYSTEM hive
212 * on our side by loading the alternate variant of the hive.
213 */
214 WARN("SYSTEM hive does not exist or is corrupt and SYSTEM.ALT has been loaded!\n");
215 ChunkBase = VaToPa(LoaderBlock->RegistryBase);
216 ((PHBASE_BLOCK)ChunkBase)->BootRecover = HBOOT_BOOT_RECOVERED_BY_ALTERNATE_HIVE;
217 }
218
219 // FIXME: Load SYSTEM.SAV if GUI setup installation is still in progress
220
221 /* Initialize the 'CurrentControlSet' link */
223 {
224 UiMessageBox("Initializing CurrentControlSet link failed!");
225 return FALSE;
226 }
227
228 return TRUE;
229}
230
233{
237 DECLARE_UNICODE_STRING_SIZE(LangFileName, MAX_PATH); // CaseTable
238 DECLARE_UNICODE_STRING_SIZE(OemHalFileName, MAX_PATH);
239 CHAR SearchPath[1024];
240
241 /* Scan registry and prepare boot drivers list */
242 Success = WinLdrScanRegistry(&LoaderBlock->BootDriverListHead);
243 if (!Success)
244 {
245 UiMessageBox("Failed to load boot drivers!");
246 return FALSE;
247 }
248
249 /* Get names of NLS files */
251 &AnsiFileName,
252 &OemFileName,
253 &LangFileName,
254 &OemHalFileName);
255 if (!Success)
256 {
257 UiMessageBox("Getting NLS names from registry failed!");
258 return FALSE;
259 }
260
261 TRACE("NLS data: '%wZ' '%wZ' '%wZ' '%wZ'\n",
262 &AnsiFileName, &OemFileName, &LangFileName, &OemHalFileName);
263
264 /* Load NLS data */
266 RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\");
267 Success = WinLdrLoadNLSData(LoaderBlock,
269 &AnsiFileName,
270 &OemFileName,
271 &LangFileName,
272 &OemHalFileName);
273 TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
274
275 return TRUE;
276}
277
278
279/* PRIVATE FUNCTIONS ******************************************************/
280
281// Queries registry for those three file names
282static BOOLEAN
284 _In_ HKEY ControlSet,
285 _Inout_ PUNICODE_STRING AnsiFileName,
286 _Inout_ PUNICODE_STRING OemFileName,
287 _Inout_ PUNICODE_STRING LangFileName, // CaseTable
288 _Inout_ PUNICODE_STRING OemHalFileName)
289{
290 LONG rc;
291 HKEY hKey;
293 WCHAR szIdBuffer[80];
294
295 /* Open the CodePage key */
296 rc = RegOpenKey(ControlSet, L"Control\\NLS\\CodePage", &hKey);
297 if (rc != ERROR_SUCCESS)
298 {
299 //TRACE("Couldn't open CodePage registry key\n");
300 return FALSE;
301 }
302
303 /* Get ANSI codepage file */
304 BufferSize = sizeof(szIdBuffer);
305 rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
306 if (rc != ERROR_SUCCESS)
307 {
308 //TRACE("Couldn't get ACP NLS setting\n");
309 goto Quit;
310 }
311
312 BufferSize = AnsiFileName->MaximumLength;
313 rc = RegQueryValue(hKey, szIdBuffer, NULL,
314 (PUCHAR)AnsiFileName->Buffer, &BufferSize);
315 if (rc != ERROR_SUCCESS)
316 {
317 //TRACE("ACP NLS Setting exists, but isn't readable\n");
318 //goto Quit;
319 AnsiFileName->Length = 0;
320 RtlAppendUnicodeToString(AnsiFileName, L"c_1252.nls"); // HACK: ReactOS bug CORE-6105
321 }
322 else
323 {
324 AnsiFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
325 }
326
327 /* Get OEM codepage file */
328 BufferSize = sizeof(szIdBuffer);
329 rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
330 if (rc != ERROR_SUCCESS)
331 {
332 //TRACE("Couldn't get OEMCP NLS setting\n");
333 goto Quit;
334 }
335
336 BufferSize = OemFileName->MaximumLength;
337 rc = RegQueryValue(hKey, szIdBuffer, NULL,
338 (PUCHAR)OemFileName->Buffer, &BufferSize);
339 if (rc != ERROR_SUCCESS)
340 {
341 //TRACE("OEMCP NLS setting exists, but isn't readable\n");
342 //goto Quit;
343 OemFileName->Length = 0;
344 RtlAppendUnicodeToString(OemFileName, L"c_437.nls"); // HACK: ReactOS bug CORE-6105
345 }
346 else
347 {
348 OemFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
349 }
350
351 /* Get OEM HAL font file */
352 BufferSize = OemHalFileName->MaximumLength;
353 rc = RegQueryValue(hKey, L"OEMHAL", NULL,
354 (PUCHAR)OemHalFileName->Buffer, &BufferSize);
355 if (rc != ERROR_SUCCESS)
356 {
357 //TRACE("Couldn't get OEMHAL NLS setting\n");
358 //goto Quit;
359 RtlInitEmptyUnicodeString(OemHalFileName, NULL, 0);
360 }
361 else
362 {
363 OemHalFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
364 }
365
367
368 /* Open the Language key */
369 rc = RegOpenKey(ControlSet, L"Control\\NLS\\Language", &hKey);
370 if (rc != ERROR_SUCCESS)
371 {
372 //TRACE("Couldn't open Language registry key\n");
373 return FALSE;
374 }
375
376 /* Get the Unicode case table file */
377 BufferSize = sizeof(szIdBuffer);
378 rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
379 if (rc != ERROR_SUCCESS)
380 {
381 //TRACE("Couldn't get Language Default setting\n");
382 goto Quit;
383 }
384
385 BufferSize = LangFileName->MaximumLength;
386 rc = RegQueryValue(hKey, szIdBuffer, NULL,
387 (PUCHAR)LangFileName->Buffer, &BufferSize);
388 if (rc != ERROR_SUCCESS)
389 {
390 //TRACE("Language Default setting exists, but isn't readable\n");
391 //goto Quit;
392 LangFileName->Length = 0;
393 RtlAppendUnicodeToString(LangFileName, L"l_intl.nls");
394 }
395 else
396 {
397 LangFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
398 }
399
400Quit:
402 return (rc == ERROR_SUCCESS);
403}
404
408 _In_ PCSTR DirectoryPath,
409 _In_ PCUNICODE_STRING AnsiFileName,
410 _In_ PCUNICODE_STRING OemFileName,
411 _In_ PCUNICODE_STRING LangFileName, // CaseTable
412 _In_ PCUNICODE_STRING OemHalFileName)
413{
416 ULONG AnsiFileId = -1, OemFileId = -1, LangFileId = -1;
417 ULONG AnsiFileSize, OemFileSize, LangFileSize;
418 ULONG TotalSize;
420 PVOID NlsDataBase, NlsVirtual;
421 BOOLEAN AnsiEqualsOem = FALSE;
423
424 /* There may be a case, where OEM and ANSI pages coincide */
425 if (RtlCompareUnicodeString(AnsiFileName, OemFileName, TRUE) == 0)
426 AnsiEqualsOem = TRUE;
427
428 /* Open file with ANSI and store its size */
429 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
430 DirectoryPath, AnsiFileName);
431 Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
432 if (Status != ESUCCESS)
433 {
434 WARN("Error while opening '%s', Status: %u\n", FileName, Status);
435 goto Quit;
436 }
437
438 Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
439 if (Status != ESUCCESS)
440 goto Quit;
441 AnsiFileSize = FileInfo.EndingAddress.LowPart;
442 TRACE("AnsiFileSize: %d\n", AnsiFileSize);
443
444 /* Open OEM file and store its length */
445 if (AnsiEqualsOem)
446 {
447 OemFileSize = 0;
448 }
449 else
450 {
451 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
452 DirectoryPath, OemFileName);
453 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
454 if (Status != ESUCCESS)
455 {
456 WARN("Error while opening '%s', Status: %u\n", FileName, Status);
457 goto Quit;
458 }
459
461 if (Status != ESUCCESS)
462 goto Quit;
463 OemFileSize = FileInfo.EndingAddress.LowPart;
464 }
465 TRACE("OemFileSize: %d\n", OemFileSize);
466
467 /* Finally open the language codepage file and store its length */
468 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
469 DirectoryPath, LangFileName);
470 Status = ArcOpen(FileName, OpenReadOnly, &LangFileId);
471 if (Status != ESUCCESS)
472 {
473 WARN("Error while opening '%s', Status: %u\n", FileName, Status);
474 goto Quit;
475 }
476
477 Status = ArcGetFileInformation(LangFileId, &FileInfo);
478 if (Status != ESUCCESS)
479 goto Quit;
480 LangFileSize = FileInfo.EndingAddress.LowPart;
481 TRACE("LangFileSize: %d\n", LangFileSize);
482
483 //
484 // TODO: The OEMHAL file.
485 //
486
487 /* Sum up all three length, having in mind that every one of them
488 must start at a page boundary => thus round up each file to a page */
489 TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
490 MM_SIZE_TO_PAGES(OemFileSize) +
491 MM_SIZE_TO_PAGES(LangFileSize);
492
493 /* Store it for later marking the pages as NlsData type */
494 TotalNLSSize = TotalSize;
495
496 NlsDataBase = MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
497 if (NlsDataBase == NULL)
498 goto Quit;
499
500 NlsVirtual = PaToVa(NlsDataBase);
501 LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
502
503 LoaderBlock->NlsData->OemCodePageData =
504 (PVOID)((ULONG_PTR)NlsVirtual +
505 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
506
507 LoaderBlock->NlsData->UnicodeCodePageData =
508 (PVOID)((ULONG_PTR)NlsVirtual +
509 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
510 (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
511
512 /* ANSI and OEM data are the same - just set pointers to the same area */
513 if (AnsiEqualsOem)
514 LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
515
516 /* Now actually read the data into memory, starting with the ANSI file */
517 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
518 DirectoryPath, AnsiFileName);
520 Status = ArcRead(AnsiFileId,
521 VaToPa(LoaderBlock->NlsData->AnsiCodePageData),
522 AnsiFileSize, &BytesRead);
523 if (Status != ESUCCESS)
524 {
525 WARN("Error while reading '%s', Status: %u\n", FileName, Status);
526 goto Quit;
527 }
528
529 /* OEM now, if it isn't the same as the ANSI one */
530 if (!AnsiEqualsOem)
531 {
532 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
533 DirectoryPath, OemFileName);
535 Status = ArcRead(OemFileId,
536 VaToPa(LoaderBlock->NlsData->OemCodePageData),
537 OemFileSize, &BytesRead);
538 if (Status != ESUCCESS)
539 {
540 WARN("Error while reading '%s', Status: %u\n", FileName, Status);
541 goto Quit;
542 }
543 }
544
545 /* Finally the language file */
546 RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
547 DirectoryPath, LangFileName);
549 Status = ArcRead(LangFileId,
550 VaToPa(LoaderBlock->NlsData->UnicodeCodePageData),
551 LangFileSize, &BytesRead);
552 if (Status != ESUCCESS)
553 {
554 WARN("Error while reading '%s', Status: %u\n", FileName, Status);
555 goto Quit;
556 }
557
558 //
559 // THIS IS a HACK and should be replaced by actually loading the OEMHAL file!
560 //
561 LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
562
563 /* Convert NlsTables address to VA */
564 LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
565
566Quit:
567 if (LangFileId != -1)
568 ArcClose(LangFileId);
569 if (OemFileId != -1)
570 ArcClose(OemFileId);
571 if (AnsiFileId != -1)
572 ArcClose(AnsiFileId);
573
574 if (Status != ESUCCESS)
575 UiMessageBox("Error reading NLS file %s", FileName);
576
577 return (Status == ESUCCESS);
578}
579
580static BOOLEAN
582 IN OUT PLIST_ENTRY BootDriverListHead)
583{
585
586 /* Find all boot drivers */
589 BootLoad,
591 BootDriverListHead);
592 if (!Success)
593 goto Quit;
594
595 /* Sort by group/tag */
598 BootDriverListHead);
599 if (!Success)
600 goto Quit;
601
602 /* Remove circular dependencies (cycles) and sort */
603 Success = CmpResolveDriverDependencies(BootDriverListHead);
604 if (!Success)
605 goto Quit;
606
607Quit:
608 /* In case of failure, free the boot driver list */
609 if (!Success)
610 CmpFreeDriverList(SystemHive, BootDriverListHead);
611
612 return Success;
613}
614
646 _Inout_ PLIST_ENTRY DriverListHead,
647 _In_ BOOLEAN InsertAtHead,
648 _In_ PCWSTR DriverName,
649 _In_opt_ PCWSTR ImagePath,
650 _In_opt_ PCWSTR GroupName,
651 _In_ ULONG ErrorControl,
652 _In_ ULONG Tag)
653{
654 PBOOT_DRIVER_NODE DriverNode;
656 BOOLEAN AlreadyInserted;
658 UNICODE_STRING DriverNameU;
661 UNICODE_STRING RegistryString = {0};
662 UNICODE_STRING GroupString = {0};
663
664 /* Check whether the driver is already in the list */
665 RtlInitUnicodeString(&DriverNameU, DriverName);
666 AlreadyInserted = CmpIsDriverInList(DriverListHead,
667 &DriverNameU,
668 &DriverNode);
669 if (AlreadyInserted)
670 {
671 /* If so, we have obtained its node */
672 ASSERT(DriverNode);
673 DriverEntry = &DriverNode->ListEntry;
674 }
675 else
676 {
677 /* Allocate a driver node and initialize it */
678 DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
679 if (!DriverNode)
680 return FALSE;
681
682 RtlZeroMemory(DriverNode, sizeof(BOOT_DRIVER_NODE));
683 DriverEntry = &DriverNode->ListEntry;
684
685 /* Driver Name */
686 RtlInitEmptyUnicodeString(&DriverNode->Name,
687 CmpAllocate(DriverNameU.Length, FALSE, TAG_CM),
688 DriverNameU.Length);
689 if (!DriverNode->Name.Buffer)
690 goto Failure;
691
692 if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DriverNode->Name, &DriverNameU)))
693 goto Failure;
694 }
695
696 /* Check whether we have a valid ImagePath. If not, we need
697 * to build it like "System32\\Drivers\\blah.sys" */
698 if (ImagePath && *ImagePath)
699 {
700 /* Just copy ImagePath to the corresponding field in the structure */
701 PathLength = (USHORT)(wcslen(ImagePath)) * sizeof(WCHAR);
702 RtlInitEmptyUnicodeString(&FilePath,
704 PathLength);
705 if (!FilePath.Buffer)
706 goto Failure;
707
709 goto Failure;
710 }
711 else
712 {
713 /* We have to construct ImagePath ourselves */
714 PathLength = DriverNode->Name.Length + sizeof(L"system32\\drivers\\.sys");
715 RtlInitEmptyUnicodeString(&FilePath,
717 PathLength);
718 if (!FilePath.Buffer)
719 goto Failure;
720
721 if (!NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, L"system32\\drivers\\")) ||
724 {
725 goto Failure;
726 }
727 }
728
729 /* Registry path */
731 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
732 PathLength = RegistryPath.Length + DriverNode->Name.Length;
733 RtlInitEmptyUnicodeString(&RegistryString,
735 PathLength);
736 if (!RegistryString.Buffer)
737 goto Failure;
738
739 if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &RegistryPath)) ||
740 !NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &DriverNode->Name)))
741 {
742 goto Failure;
743 }
744
745 /* Group */
746 if (GroupName && *GroupName)
747 {
748 /*
749 * NOTE: Here we can use our own allocator as we alone maintain the
750 * group string. This is different from the other allocated strings,
751 * where we instead need to use the same (hive) allocator as the
752 * one used by CmpAddDriverToList(), for interoperability purposes.
753 */
754 RtlCreateUnicodeString(&GroupString, GroupName);
755 if (!GroupString.Buffer)
756 goto Failure;
757 }
758 else
759 {
760 RtlInitEmptyUnicodeString(&GroupString, NULL, 0);
761 }
762
763 /* Set or replace the driver node's file path */
764 if (DriverEntry->FilePath.Buffer)
765 {
766 CmpFree(DriverEntry->FilePath.Buffer,
767 DriverEntry->FilePath.MaximumLength);
768 }
769 DriverEntry->FilePath = FilePath;
770 FilePath.Buffer = NULL;
771
772 /* Set or replace the driver node's registry path */
773 if (DriverEntry->RegistryPath.Buffer)
774 {
775 CmpFree(DriverEntry->RegistryPath.Buffer,
776 DriverEntry->RegistryPath.MaximumLength);
777 }
778 DriverEntry->RegistryPath = RegistryString;
779 RegistryString.Buffer = NULL;
780
781 /* Set or replace the driver node's group */
782 if (DriverNode->Group.Buffer)
783 {
784 /*
785 * If the buffer is inside the registry hive's memory, this means that
786 * it has been set by CmpAddDriverToList() to point to some data within
787 * the hive; thus we should not free the buffer but just replace it.
788 * Otherwise, this is a buffer previously allocated by ourselves, that
789 * we can free.
790 *
791 * NOTE: This function does not have an explicit LoaderBlock input
792 * parameter pointer, since it does not need it, except for this
793 * very place. So instead, use the global WinLdrSystemBlock pointer.
794 */
795 PLOADER_PARAMETER_BLOCK LoaderBlock =
797
798 if (!LoaderBlock || !LoaderBlock->RegistryBase || !LoaderBlock->RegistryLength ||
799 ((ULONG_PTR)DriverNode->Group.Buffer <
800 (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase)) ||
801 ((ULONG_PTR)DriverNode->Group.Buffer >=
802 (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase) + LoaderBlock->RegistryLength))
803 {
804 RtlFreeUnicodeString(&DriverNode->Group);
805 }
806 }
807 DriverNode->Group = GroupString;
808 GroupString.Buffer = NULL;
809
810 /* ErrorControl and Tag */
811 DriverNode->ErrorControl = ErrorControl;
812 DriverNode->Tag = Tag;
813
814 /* Insert the entry into the list if it does not exist there already */
815 if (!AlreadyInserted)
816 {
817 if (InsertAtHead)
818 InsertHeadList(DriverListHead, &DriverEntry->Link);
819 else
820 InsertTailList(DriverListHead, &DriverEntry->Link);
821 }
822
823 return TRUE;
824
825Failure:
826 if (GroupString.Buffer)
827 RtlFreeUnicodeString(&GroupString);
828 if (RegistryString.Buffer)
829 CmpFree(RegistryString.Buffer, RegistryString.MaximumLength);
830 if (FilePath.Buffer)
831 CmpFree(FilePath.Buffer, FilePath.MaximumLength);
832
833 /* If it does not exist in the list already, free the allocated
834 * driver node, otherwise keep the original one in place. */
835 if (!AlreadyInserted)
836 {
837 if (DriverEntry->RegistryPath.Buffer)
838 {
839 CmpFree(DriverEntry->RegistryPath.Buffer,
840 DriverEntry->RegistryPath.MaximumLength);
841 }
842 if (DriverEntry->FilePath.Buffer)
843 {
844 CmpFree(DriverEntry->FilePath.Buffer,
845 DriverEntry->FilePath.MaximumLength);
846 }
847 if (DriverNode->Name.Buffer)
848 {
849 CmpFree(DriverNode->Name.Buffer,
850 DriverNode->Name.MaximumLength);
851 }
852 CmpFree(DriverNode, sizeof(BOOT_DRIVER_NODE));
853 }
854
855 return FALSE;
856}
static USHORT PathLength
PCWSTR FilePath
unsigned char BOOLEAN
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE ACPI_HANDLE ACPI_HANDLE *OutHandle ACPI_HANDLE *OutHandle void *Context void *Context ACPI_EVENT_HANDLER Handler UINT32 UINT32 ACPI_GPE_HANDLER void *Context UINT32 ACPI_NOTIFY_HANDLER void *Context ACPI_ADR_SPACE_TYPE ACPI_ADR_SPACE_HANDLER ACPI_ADR_SPACE_SETUP Setup
Definition: acpixf.h:834
#define WARN(fmt,...)
Definition: debug.h:112
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:220
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:252
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:56
PCWSTR FsGetServiceName(ULONG FileId)
Definition: fs.c:404
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:238
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
VOID UiMessageBox(_In_ PCSTR Format,...)
Definition: ui.c:359
BOOLEAN RegInitCurrentControlSet(_In_ BOOLEAN LastKnownGood)
Definition: registry.c:525
PHHIVE SystemHive
Definition: registry.c:33
BOOLEAN RegImportBinaryHive(_In_ PVOID ChunkBase, _In_ ULONG ChunkSize, _In_ PCSTR SearchPath, _In_ BOOLEAN LoadAlternate)
Imports the SYSTEM binary hive from the registry base chunk that's been provided by the loader block.
Definition: registry.c:449
HKEY CurrentControlSetKey
Definition: registry.c:34
#define HKEY_TO_HCI(hKey)
Definition: registry.h:28
#define RegCloseKey(hKey)
Definition: registry.h:49
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Definition: bootreg.c:90
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
BOOLEAN NTAPI CmpFindDrivers(_In_ PHHIVE Hive, _In_ HCELL_INDEX ControlSet, _In_ SERVICE_LOAD_TYPE LoadType, _In_opt_ PCWSTR BootFileSystem, _Inout_ PLIST_ENTRY DriverListHead)
Enumerates all drivers within the given control set and load type, present in the "Services" sub-key,...
Definition: cmboot.c:679
BOOLEAN NTAPI CmpResolveDriverDependencies(_Inout_ PLIST_ENTRY DriverListHead)
Removes potential circular dependencies (cycles) and sorts the driver list.
Definition: cmboot.c:1030
BOOLEAN NTAPI CmpSortDriverList(_In_ PHHIVE Hive, _In_ HCELL_INDEX ControlSet, _Inout_ PLIST_ENTRY DriverListHead)
Sorts the driver list, according to the drivers' group load ordering.
Definition: cmboot.c:902
VOID NTAPI CmpFreeDriverList(_In_ PHHIVE Hive, _Inout_ PLIST_ENTRY DriverListHead)
Empties the driver list and frees all allocated driver nodes in it.
Definition: cmboot.c:1224
#define TAG_CM
Definition: cmlib.h:212
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
FORCEINLINE PVOID VaToPa(PVOID Va)
Definition: conversion.h:15
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static const WCHAR SystemRoot[]
Definition: reg.c:38
#define MAX_PATH
Definition: compat.h:34
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define ULONG_PTR
Definition: config.h:101
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
@ Success
Definition: eventcreate.c:712
FxAutoRegKey hKey
Status
Definition: gdiplustypes.h:25
#define HBOOT_BOOT_RECOVERED_BY_ALTERNATE_HIVE
Definition: hivedata.h:96
struct _HBASE_BLOCK * PHBASE_BLOCK
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define TAG_WLDR_NAME
Definition: winldr.h:15
#define ASSERT(a)
Definition: mode.c:44
PVOID PVOID PWCHAR PVOID USHORT PULONG Reason
Definition: env.c:47
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define UNICODE_NULL
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625
NTSTRSAFEVAPI RtlStringCbPrintfA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCSTR pszFormat,...)
Definition: ntstrsafe.h:1148
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
@ ESUCCESS
Definition: arc.h:32
@ LoaderNlsData
Definition: arc.h:195
@ LoaderRegistryData
Definition: arc.h:193
ULONG ARC_STATUS
Definition: arc.h:4
@ OpenReadOnly
Definition: arc.h:65
#define TRACE(s)
Definition: solgame.cpp:4
Definition: arc.h:246
UNICODE_STRING Group
Definition: cmboot.h:16
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
ULONG ErrorControl
Definition: cmboot.h:19
UNICODE_STRING Name
Definition: cmboot.h:17
Definition: typedefs.h:120
ULONG RegistryLength
Definition: arc.h:547
LOADER_PARAMETER_BLOCK LoaderBlock
Definition: winldr.h:48
USHORT MaximumLength
Definition: env_spec_w32.h:370
const uint16_t * PCWSTR
Definition: typedefs.h:57
void * PVOID
Definition: typedefs.h:50
const char * PCSTR
Definition: typedefs.h:52
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define DECLARE_UNICODE_STRING_SIZE(_var, _size)
Definition: wdfcore.h:155
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4065
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
#define SearchPath
Definition: winbase.h:3835
VOID NtLdrOutputLoadMsg(_In_ PCSTR FileName, _In_opt_ PCSTR Description)
Definition: winldr.c:54
PCWSTR BootFileSystem
Definition: winldr.c:30
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
Definition: winldr.c:29
#define RegOpenKey
Definition: winreg.h:519
#define RegQueryValue
Definition: winreg.h:523
ULONG TotalNLSSize
Definition: wlregistry.c:20
static BOOLEAN WinLdrLoadSystemHive(_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ PCSTR DirectoryPath, _In_ PCSTR HiveName, _Out_ PBAD_HIVE_REASON Reason)
Definition: wlregistry.c:45
BOOLEAN WinLdrLoadNLSData(_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock, _In_ PCSTR DirectoryPath, _In_ PCUNICODE_STRING AnsiFileName, _In_ PCUNICODE_STRING OemFileName, _In_ PCUNICODE_STRING LangFileName, _In_ PCUNICODE_STRING OemHalFileName)
Definition: wlregistry.c:406
BOOLEAN WinLdrAddDriverToList(_Inout_ PLIST_ENTRY DriverListHead, _In_ BOOLEAN InsertAtHead, _In_ PCWSTR DriverName, _In_opt_ PCWSTR ImagePath, _In_opt_ PCWSTR GroupName, _In_ ULONG ErrorControl, _In_ ULONG Tag)
Inserts the specified driver entry into the driver list, or updates an existing entry with new ImageP...
Definition: wlregistry.c:645
BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot, IN BOOLEAN Setup)
Definition: wlregistry.c:125
enum _BAD_HIVE_REASON BAD_HIVE_REASON
enum _BAD_HIVE_REASON * PBAD_HIVE_REASON
static BOOLEAN WinLdrGetNLSNames(_In_ HKEY ControlSet, _Inout_ PUNICODE_STRING AnsiFileName, _Inout_ PUNICODE_STRING OemFileName, _Inout_ PUNICODE_STRING LangFileName, _Inout_ PUNICODE_STRING OemHalFileName)
Definition: wlregistry.c:283
static BOOLEAN WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead)
Definition: wlregistry.c:581
BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot)
Definition: wlregistry.c:231
_BAD_HIVE_REASON
Definition: wlregistry.c:35
@ CorruptHive
Definition: wlregistry.c:37
@ GoodHive
Definition: wlregistry.c:36
@ NoHiveAlloc
Definition: wlregistry.c:39
@ NoHive
Definition: wlregistry.c:38
@ BootLoad
Definition: cmtypes.h:996
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175