ReactOS  0.4.15-dev-5459-gb85f005
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>
17 DBG_DEFAULT_CHANNEL(WINDOWS);
18 
19 // The only global var here, used to mark mem pages as NLS in WinLdrSetupMemoryLayout()
21 
22 static 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 
30 static BOOLEAN
32  IN OUT PLIST_ENTRY BootDriverListHead);
33 
34 
35 /* FUNCTIONS **************************************************************/
36 
37 static BOOLEAN
39  IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
40  IN PCSTR DirectoryPath,
41  IN PCSTR HiveName)
42 {
43  ULONG FileId;
44  CHAR FullHiveName[MAX_PATH];
47  ULONG HiveFileSize;
48  PVOID HiveDataPhysical;
49  PVOID HiveDataVirtual;
51 
52  /* Concatenate path and filename to get the full name */
53  RtlStringCbCopyA(FullHiveName, sizeof(FullHiveName), DirectoryPath);
54  RtlStringCbCatA(FullHiveName, sizeof(FullHiveName), HiveName);
55 
56  NtLdrOutputLoadMsg(FullHiveName, NULL);
57  Status = ArcOpen(FullHiveName, OpenReadOnly, &FileId);
58  if (Status != ESUCCESS)
59  {
60  WARN("Error while opening '%s', Status: %u\n", FullHiveName, Status);
61  return FALSE;
62  }
63 
64  /* Get the file length */
66  if (Status != ESUCCESS)
67  {
68  WARN("Hive file has 0 size!\n");
69  ArcClose(FileId);
70  return FALSE;
71  }
72  HiveFileSize = FileInfo.EndingAddress.LowPart;
73 
74  /* Round up the size to page boundary and alloc memory */
75  HiveDataPhysical = MmAllocateMemoryWithType(
76  MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
78 
79  if (HiveDataPhysical == NULL)
80  {
81  WARN("Could not alloc memory for hive!\n");
82  ArcClose(FileId);
83  return FALSE;
84  }
85 
86  /* Convert address to virtual */
87  HiveDataVirtual = PaToVa(HiveDataPhysical);
88 
89  /* Fill LoaderBlock's entries */
90  LoaderBlock->RegistryLength = HiveFileSize;
91  LoaderBlock->RegistryBase = HiveDataVirtual;
92 
93  /* Finally read from file to the memory */
94  Status = ArcRead(FileId, HiveDataPhysical, HiveFileSize, &BytesRead);
95  if (Status != ESUCCESS)
96  {
97  WARN("Error while reading '%s', Status: %u\n", FullHiveName, Status);
98  ArcClose(FileId);
99  return FALSE;
100  }
101 
102  // FIXME: HACK: Get the boot filesystem driver name now...
104 
105  ArcClose(FileId);
106  return TRUE;
107 }
108 
109 BOOLEAN
111  IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
113  IN BOOLEAN Setup)
114 {
115  CHAR SearchPath[1024];
116  PCSTR HiveName;
118 
119  if (Setup)
120  {
122  HiveName = "SETUPREG.HIV";
123  }
124  else
125  {
126  // There is a simple logic here: try to load usual hive (system), if it
127  // fails, then give system.alt a try, and finally try a system.sav
128 
129  // FIXME: For now we only try system
131  RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\config\\");
132  HiveName = "SYSTEM";
133  }
134 
135  TRACE("WinLdrInitSystemHive: loading hive %s%s\n", SearchPath, HiveName);
136  Success = WinLdrLoadSystemHive(LoaderBlock, SearchPath, HiveName);
137  if (!Success)
138  {
139  UiMessageBox("Could not load %s hive!", HiveName);
140  return FALSE;
141  }
142 
143  /* Import what was loaded */
144  Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
145  if (!Success)
146  {
147  UiMessageBox("Importing binary hive failed!");
148  return FALSE;
149  }
150 
151  /* Initialize the 'CurrentControlSet' link */
153  {
154  UiMessageBox("Initializing CurrentControlSet link failed!");
155  return FALSE;
156  }
157 
158  return TRUE;
159 }
160 
163 {
165  DECLARE_UNICODE_STRING_SIZE(AnsiFileName, MAX_PATH);
167  DECLARE_UNICODE_STRING_SIZE(LangFileName, MAX_PATH); // CaseTable
168  DECLARE_UNICODE_STRING_SIZE(OemHalFileName, MAX_PATH);
169  CHAR SearchPath[1024];
170 
171  /* Scan registry and prepare boot drivers list */
172  Success = WinLdrScanRegistry(&LoaderBlock->BootDriverListHead);
173  if (!Success)
174  {
175  UiMessageBox("Failed to load boot drivers!");
176  return FALSE;
177  }
178 
179  /* Get names of NLS files */
181  &AnsiFileName,
182  &OemFileName,
183  &LangFileName,
184  &OemHalFileName);
185  if (!Success)
186  {
187  UiMessageBox("Getting NLS names from registry failed!");
188  return FALSE;
189  }
190 
191  TRACE("NLS data: '%wZ' '%wZ' '%wZ' '%wZ'\n",
192  &AnsiFileName, &OemFileName, &LangFileName, &OemHalFileName);
193 
194  /* Load NLS data */
196  RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\");
197  Success = WinLdrLoadNLSData(LoaderBlock,
198  SearchPath,
199  &AnsiFileName,
200  &OemFileName,
201  &LangFileName,
202  &OemHalFileName);
203  TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
204 
205  return TRUE;
206 }
207 
208 
209 /* PRIVATE FUNCTIONS ******************************************************/
210 
211 // Queries registry for those three file names
212 static BOOLEAN
214  _In_ HKEY ControlSet,
215  _Inout_ PUNICODE_STRING AnsiFileName,
216  _Inout_ PUNICODE_STRING OemFileName,
217  _Inout_ PUNICODE_STRING LangFileName, // CaseTable
218  _Inout_ PUNICODE_STRING OemHalFileName)
219 {
220  LONG rc;
221  HKEY hKey;
223  WCHAR szIdBuffer[80];
224 
225  /* Open the CodePage key */
226  rc = RegOpenKey(ControlSet, L"Control\\NLS\\CodePage", &hKey);
227  if (rc != ERROR_SUCCESS)
228  {
229  //TRACE("Couldn't open CodePage registry key\n");
230  return FALSE;
231  }
232 
233  /* Get ANSI codepage file */
234  BufferSize = sizeof(szIdBuffer);
235  rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
236  if (rc != ERROR_SUCCESS)
237  {
238  //TRACE("Couldn't get ACP NLS setting\n");
239  goto Quit;
240  }
241 
242  BufferSize = AnsiFileName->MaximumLength;
243  rc = RegQueryValue(hKey, szIdBuffer, NULL,
244  (PUCHAR)AnsiFileName->Buffer, &BufferSize);
245  if (rc != ERROR_SUCCESS)
246  {
247  //TRACE("ACP NLS Setting exists, but isn't readable\n");
248  //goto Quit;
249  AnsiFileName->Length = 0;
250  RtlAppendUnicodeToString(AnsiFileName, L"c_1252.nls"); // HACK: ReactOS bug CORE-6105
251  }
252  else
253  {
254  AnsiFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
255  }
256 
257  /* Get OEM codepage file */
258  BufferSize = sizeof(szIdBuffer);
259  rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
260  if (rc != ERROR_SUCCESS)
261  {
262  //TRACE("Couldn't get OEMCP NLS setting\n");
263  goto Quit;
264  }
265 
266  BufferSize = OemFileName->MaximumLength;
267  rc = RegQueryValue(hKey, szIdBuffer, NULL,
268  (PUCHAR)OemFileName->Buffer, &BufferSize);
269  if (rc != ERROR_SUCCESS)
270  {
271  //TRACE("OEMCP NLS setting exists, but isn't readable\n");
272  //goto Quit;
273  OemFileName->Length = 0;
274  RtlAppendUnicodeToString(OemFileName, L"c_437.nls"); // HACK: ReactOS bug CORE-6105
275  }
276  else
277  {
278  OemFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
279  }
280 
281  /* Get OEM HAL font file */
282  BufferSize = OemHalFileName->MaximumLength;
283  rc = RegQueryValue(hKey, L"OEMHAL", NULL,
284  (PUCHAR)OemHalFileName->Buffer, &BufferSize);
285  if (rc != ERROR_SUCCESS)
286  {
287  //TRACE("Couldn't get OEMHAL NLS setting\n");
288  //goto Quit;
289  RtlInitEmptyUnicodeString(OemHalFileName, NULL, 0);
290  }
291  else
292  {
293  OemHalFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
294  }
295 
296  RegCloseKey(hKey);
297 
298  /* Open the Language key */
299  rc = RegOpenKey(ControlSet, L"Control\\NLS\\Language", &hKey);
300  if (rc != ERROR_SUCCESS)
301  {
302  //TRACE("Couldn't open Language registry key\n");
303  return FALSE;
304  }
305 
306  /* Get the Unicode case table file */
307  BufferSize = sizeof(szIdBuffer);
308  rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
309  if (rc != ERROR_SUCCESS)
310  {
311  //TRACE("Couldn't get Language Default setting\n");
312  goto Quit;
313  }
314 
315  BufferSize = LangFileName->MaximumLength;
316  rc = RegQueryValue(hKey, szIdBuffer, NULL,
317  (PUCHAR)LangFileName->Buffer, &BufferSize);
318  if (rc != ERROR_SUCCESS)
319  {
320  //TRACE("Language Default setting exists, but isn't readable\n");
321  //goto Quit;
322  LangFileName->Length = 0;
323  RtlAppendUnicodeToString(LangFileName, L"l_intl.nls");
324  }
325  else
326  {
327  LangFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
328  }
329 
330 Quit:
331  RegCloseKey(hKey);
332  return (rc == ERROR_SUCCESS);
333 }
334 
335 BOOLEAN
337  _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock,
338  _In_ PCSTR DirectoryPath,
339  _In_ PCUNICODE_STRING AnsiFileName,
340  _In_ PCUNICODE_STRING OemFileName,
341  _In_ PCUNICODE_STRING LangFileName, // CaseTable
342  _In_ PCUNICODE_STRING OemHalFileName)
343 {
346  ULONG AnsiFileId = -1, OemFileId = -1, LangFileId = -1;
347  ULONG AnsiFileSize, OemFileSize, LangFileSize;
348  ULONG TotalSize;
350  PVOID NlsDataBase, NlsVirtual;
351  BOOLEAN AnsiEqualsOem = FALSE;
353 
354  /* There may be a case, where OEM and ANSI pages coincide */
355  if (RtlCompareUnicodeString(AnsiFileName, OemFileName, TRUE) == 0)
356  AnsiEqualsOem = TRUE;
357 
358  /* Open file with ANSI and store its size */
359  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
360  DirectoryPath, AnsiFileName);
361  Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
362  if (Status != ESUCCESS)
363  {
364  WARN("Error while opening '%s', Status: %u\n", FileName, Status);
365  goto Quit;
366  }
367 
368  Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
369  if (Status != ESUCCESS)
370  goto Quit;
371  AnsiFileSize = FileInfo.EndingAddress.LowPart;
372  TRACE("AnsiFileSize: %d\n", AnsiFileSize);
373 
374  /* Open OEM file and store its length */
375  if (AnsiEqualsOem)
376  {
377  OemFileSize = 0;
378  }
379  else
380  {
381  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
382  DirectoryPath, OemFileName);
383  Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
384  if (Status != ESUCCESS)
385  {
386  WARN("Error while opening '%s', Status: %u\n", FileName, Status);
387  goto Quit;
388  }
389 
390  Status = ArcGetFileInformation(OemFileId, &FileInfo);
391  if (Status != ESUCCESS)
392  goto Quit;
393  OemFileSize = FileInfo.EndingAddress.LowPart;
394  }
395  TRACE("OemFileSize: %d\n", OemFileSize);
396 
397  /* Finally open the language codepage file and store its length */
398  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
399  DirectoryPath, LangFileName);
400  Status = ArcOpen(FileName, OpenReadOnly, &LangFileId);
401  if (Status != ESUCCESS)
402  {
403  WARN("Error while opening '%s', Status: %u\n", FileName, Status);
404  goto Quit;
405  }
406 
407  Status = ArcGetFileInformation(LangFileId, &FileInfo);
408  if (Status != ESUCCESS)
409  goto Quit;
410  LangFileSize = FileInfo.EndingAddress.LowPart;
411  TRACE("LangFileSize: %d\n", LangFileSize);
412 
413  //
414  // TODO: The OEMHAL file.
415  //
416 
417  /* Sum up all three length, having in mind that every one of them
418  must start at a page boundary => thus round up each file to a page */
419  TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
420  MM_SIZE_TO_PAGES(OemFileSize) +
421  MM_SIZE_TO_PAGES(LangFileSize);
422 
423  /* Store it for later marking the pages as NlsData type */
424  TotalNLSSize = TotalSize;
425 
426  NlsDataBase = MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
427  if (NlsDataBase == NULL)
428  goto Quit;
429 
430  NlsVirtual = PaToVa(NlsDataBase);
431  LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
432 
433  LoaderBlock->NlsData->OemCodePageData =
434  (PVOID)((ULONG_PTR)NlsVirtual +
435  (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
436 
437  LoaderBlock->NlsData->UnicodeCodePageData =
438  (PVOID)((ULONG_PTR)NlsVirtual +
439  (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
440  (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
441 
442  /* ANSI and OEM data are the same - just set pointers to the same area */
443  if (AnsiEqualsOem)
444  LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
445 
446  /* Now actually read the data into memory, starting with the ANSI file */
447  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
448  DirectoryPath, AnsiFileName);
450  Status = ArcRead(AnsiFileId,
451  VaToPa(LoaderBlock->NlsData->AnsiCodePageData),
452  AnsiFileSize, &BytesRead);
453  if (Status != ESUCCESS)
454  {
455  WARN("Error while reading '%s', Status: %u\n", FileName, Status);
456  goto Quit;
457  }
458 
459  /* OEM now, if it isn't the same as the ANSI one */
460  if (!AnsiEqualsOem)
461  {
462  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
463  DirectoryPath, OemFileName);
465  Status = ArcRead(OemFileId,
466  VaToPa(LoaderBlock->NlsData->OemCodePageData),
467  OemFileSize, &BytesRead);
468  if (Status != ESUCCESS)
469  {
470  WARN("Error while reading '%s', Status: %u\n", FileName, Status);
471  goto Quit;
472  }
473  }
474 
475  /* Finally the language file */
476  RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
477  DirectoryPath, LangFileName);
479  Status = ArcRead(LangFileId,
480  VaToPa(LoaderBlock->NlsData->UnicodeCodePageData),
481  LangFileSize, &BytesRead);
482  if (Status != ESUCCESS)
483  {
484  WARN("Error while reading '%s', Status: %u\n", FileName, Status);
485  goto Quit;
486  }
487 
488  //
489  // THIS IS a HACK and should be replaced by actually loading the OEMHAL file!
490  //
491  LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
492 
493  /* Convert NlsTables address to VA */
494  LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
495 
496 Quit:
497  if (LangFileId != -1)
498  ArcClose(LangFileId);
499  if (OemFileId != -1)
500  ArcClose(OemFileId);
501  if (AnsiFileId != -1)
502  ArcClose(AnsiFileId);
503 
504  if (Status != ESUCCESS)
505  UiMessageBox("Error reading NLS file %s", FileName);
506 
507  return (Status == ESUCCESS);
508 }
509 
510 static BOOLEAN
512  IN OUT PLIST_ENTRY BootDriverListHead)
513 {
515 
516  /* Find all boot drivers */
519  BootLoad,
521  BootDriverListHead);
522  if (!Success)
523  goto Quit;
524 
525  /* Sort by group/tag */
528  BootDriverListHead);
529  if (!Success)
530  goto Quit;
531 
532  /* Remove circular dependencies (cycles) and sort */
533  Success = CmpResolveDriverDependencies(BootDriverListHead);
534  if (!Success)
535  goto Quit;
536 
537 Quit:
538  /* In case of failure, free the boot driver list */
539  if (!Success)
540  CmpFreeDriverList(SystemHive, BootDriverListHead);
541 
542  return Success;
543 }
544 
574 BOOLEAN
576  _Inout_ PLIST_ENTRY DriverListHead,
577  _In_ BOOLEAN InsertAtHead,
578  _In_ PCWSTR DriverName,
579  _In_opt_ PCWSTR ImagePath,
580  _In_opt_ PCWSTR GroupName,
581  _In_ ULONG ErrorControl,
582  _In_ ULONG Tag)
583 {
584  PBOOT_DRIVER_NODE DriverNode;
586  BOOLEAN AlreadyInserted;
588  UNICODE_STRING DriverNameU;
590  UNICODE_STRING FilePath = {0};
591  UNICODE_STRING RegistryString = {0};
592  UNICODE_STRING GroupString = {0};
593 
594  /* Check whether the driver is already in the list */
595  RtlInitUnicodeString(&DriverNameU, DriverName);
596  AlreadyInserted = CmpIsDriverInList(DriverListHead,
597  &DriverNameU,
598  &DriverNode);
599  if (AlreadyInserted)
600  {
601  /* If so, we have obtained its node */
602  ASSERT(DriverNode);
603  DriverEntry = &DriverNode->ListEntry;
604  }
605  else
606  {
607  /* Allocate a driver node and initialize it */
608  DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
609  if (!DriverNode)
610  return FALSE;
611 
612  RtlZeroMemory(DriverNode, sizeof(BOOT_DRIVER_NODE));
613  DriverEntry = &DriverNode->ListEntry;
614 
615  /* Driver Name */
616  RtlInitEmptyUnicodeString(&DriverNode->Name,
617  CmpAllocate(DriverNameU.Length, FALSE, TAG_CM),
618  DriverNameU.Length);
619  if (!DriverNode->Name.Buffer)
620  goto Failure;
621 
622  if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&DriverNode->Name, &DriverNameU)))
623  goto Failure;
624  }
625 
626  /* Check whether we have a valid ImagePath. If not, we need
627  * to build it like "System32\\Drivers\\blah.sys" */
628  if (ImagePath && *ImagePath)
629  {
630  /* Just copy ImagePath to the corresponding field in the structure */
631  PathLength = (USHORT)(wcslen(ImagePath)) * sizeof(WCHAR);
632  RtlInitEmptyUnicodeString(&FilePath,
634  PathLength);
635  if (!FilePath.Buffer)
636  goto Failure;
637 
638  if (!NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, ImagePath)))
639  goto Failure;
640  }
641  else
642  {
643  /* We have to construct ImagePath ourselves */
644  PathLength = DriverNode->Name.Length + sizeof(L"system32\\drivers\\.sys");
645  RtlInitEmptyUnicodeString(&FilePath,
647  PathLength);
648  if (!FilePath.Buffer)
649  goto Failure;
650 
651  if (!NT_SUCCESS(RtlAppendUnicodeToString(&FilePath, L"system32\\drivers\\")) ||
654  {
655  goto Failure;
656  }
657  }
658 
659  /* Registry path */
661  L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
662  PathLength = RegistryPath.Length + DriverNode->Name.Length;
663  RtlInitEmptyUnicodeString(&RegistryString,
665  PathLength);
666  if (!RegistryString.Buffer)
667  goto Failure;
668 
669  if (!NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &RegistryPath)) ||
670  !NT_SUCCESS(RtlAppendUnicodeStringToString(&RegistryString, &DriverNode->Name)))
671  {
672  goto Failure;
673  }
674 
675  /* Group */
676  if (GroupName && *GroupName)
677  {
678  /*
679  * NOTE: Here we can use our own allocator as we alone maintain the
680  * group string. This is different from the other allocated strings,
681  * where we instead need to use the same (hive) allocator as the
682  * one used by CmpAddDriverToList(), for interoperability purposes.
683  */
684  RtlCreateUnicodeString(&GroupString, GroupName);
685  if (!GroupString.Buffer)
686  goto Failure;
687  }
688  else
689  {
690  RtlInitEmptyUnicodeString(&GroupString, NULL, 0);
691  }
692 
693  /* Set or replace the driver node's file path */
694  if (DriverEntry->FilePath.Buffer)
695  {
696  CmpFree(DriverEntry->FilePath.Buffer,
697  DriverEntry->FilePath.MaximumLength);
698  }
699  DriverEntry->FilePath = FilePath;
700  FilePath.Buffer = NULL;
701 
702  /* Set or replace the driver node's registry path */
703  if (DriverEntry->RegistryPath.Buffer)
704  {
705  CmpFree(DriverEntry->RegistryPath.Buffer,
706  DriverEntry->RegistryPath.MaximumLength);
707  }
708  DriverEntry->RegistryPath = RegistryString;
709  RegistryString.Buffer = NULL;
710 
711  /* Set or replace the driver node's group */
712  if (DriverNode->Group.Buffer)
713  {
714  /*
715  * If the buffer is inside the registry hive's memory, this means that
716  * it has been set by CmpAddDriverToList() to point to some data within
717  * the hive; thus we should not free the buffer but just replace it.
718  * Otherwise, this is a buffer previously allocated by ourselves, that
719  * we can free.
720  *
721  * NOTE: This function does not have an explicit LoaderBlock input
722  * parameter pointer, since it does not need it, except for this
723  * very place. So instead, use the global WinLdrSystemBlock pointer.
724  */
725  PLOADER_PARAMETER_BLOCK LoaderBlock =
727 
728  if (!LoaderBlock || !LoaderBlock->RegistryBase || !LoaderBlock->RegistryLength ||
729  ((ULONG_PTR)DriverNode->Group.Buffer <
730  (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase)) ||
731  ((ULONG_PTR)DriverNode->Group.Buffer >=
732  (ULONG_PTR)VaToPa(LoaderBlock->RegistryBase) + LoaderBlock->RegistryLength))
733  {
734  RtlFreeUnicodeString(&DriverNode->Group);
735  }
736  }
737  DriverNode->Group = GroupString;
738  GroupString.Buffer = NULL;
739 
740  /* ErrorControl and Tag */
741  DriverNode->ErrorControl = ErrorControl;
742  DriverNode->Tag = Tag;
743 
744  /* Insert the entry into the list if it does not exist there already */
745  if (!AlreadyInserted)
746  {
747  if (InsertAtHead)
748  InsertHeadList(DriverListHead, &DriverEntry->Link);
749  else
750  InsertTailList(DriverListHead, &DriverEntry->Link);
751  }
752 
753  return TRUE;
754 
755 Failure:
756  if (GroupString.Buffer)
757  RtlFreeUnicodeString(&GroupString);
758  if (RegistryString.Buffer)
759  CmpFree(RegistryString.Buffer, RegistryString.MaximumLength);
760  if (FilePath.Buffer)
761  CmpFree(FilePath.Buffer, FilePath.MaximumLength);
762 
763  /* If it does not exist in the list already, free the allocated
764  * driver node, otherwise keep the original one in place. */
765  if (!AlreadyInserted)
766  {
767  if (DriverEntry->RegistryPath.Buffer)
768  {
769  CmpFree(DriverEntry->RegistryPath.Buffer,
770  DriverEntry->RegistryPath.MaximumLength);
771  }
772  if (DriverEntry->FilePath.Buffer)
773  {
774  CmpFree(DriverEntry->FilePath.Buffer,
775  DriverEntry->FilePath.MaximumLength);
776  }
777  if (DriverNode->Name.Buffer)
778  {
779  CmpFree(DriverNode->Name.Buffer,
780  DriverNode->Name.MaximumLength);
781  }
782  CmpFree(DriverNode, sizeof(BOOT_DRIVER_NODE));
783  }
784 
785  return FALSE;
786 }
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
BOOT_DRIVER_LIST_ENTRY ListEntry
Definition: cmboot.h:15
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
#define ERROR_SUCCESS
Definition: deptool.c:10
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: arc.h:32
#define TRUE
Definition: types.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
BOOLEAN RegImportBinaryHive(_In_ PVOID ChunkBase, _In_ ULONG ChunkSize)
Definition: registry.c:66
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG ErrorControl
Definition: cmboot.h:19
char CHAR
Definition: xmlstorage.h:175
BOOLEAN RegInitCurrentControlSet(_In_ BOOLEAN LastKnownGood)
Definition: registry.c:112
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:575
#define WARN(fmt,...)
Definition: debug.h:112
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Definition: bootreg.c:90
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:213
PHHIVE SystemHive
Definition: registry.c:32
ULONG ARC_STATUS
Definition: arc.h:4
#define InsertTailList(ListHead, Entry)
static USHORT PathLength
_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:859
PCWSTR FilePath
#define SearchPath
Definition: winbase.h:3771
uint32_t ULONG_PTR
Definition: typedefs.h:65
Definition: arc.h:198
NTSTRSAFEAPI RtlStringCbCopyA(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:156
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
#define L(x)
Definition: ntvdm.h:50
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
HKEY CurrentControlSetKey
Definition: registry.c:33
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
long LONG
Definition: pedump.c:60
BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot)
Definition: wlregistry.c:161
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 UiMessageBox(PCSTR Format,...)
Definition: ui.c:363
PCWSTR FsGetServiceName(ULONG FileId)
Definition: fs.c:402
unsigned char BOOLEAN
#define _In_
Definition: ms_sal.h:308
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:336
BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR SystemRoot, IN BOOLEAN Setup)
Definition: wlregistry.c:110
void * PVOID
Definition: retypes.h:9
LOADER_PARAMETER_BLOCK LoaderBlock
Definition: winldr.h:48
PCWSTR BootFileSystem
Definition: winldr.c:30
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
Status
Definition: gdiplustypes.h:24
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define TAG_WLDR_NAME
Definition: winldr.h:15
UNICODE_STRING Name
Definition: cmboot.h:17
#define TRACE(s)
Definition: solgame.cpp:4
#define ASSERT(a)
Definition: mode.c:44
static const WCHAR SystemRoot[]
Definition: reg.c:38
__wchar_t WCHAR
Definition: xmlstorage.h:180
VOID NtLdrOutputLoadMsg(_In_ PCSTR FileName, _In_opt_ PCSTR Description)
Definition: winldr.c:54
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
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:832
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
#define MAX_PATH
Definition: compat.h:34
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define DECLARE_UNICODE_STRING_SIZE(_var, _size)
Definition: wdfcore.h:155
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
#define TAG_CM
Definition: cmlib.h:205
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
PVOID MmAllocateMemoryWithType(SIZE_T MemorySize, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:31
Definition: typedefs.h:119
static BOOLEAN WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead)
Definition: wlregistry.c:511
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4061
BOOLEAN NTAPI CmpResolveDriverDependencies(_Inout_ PLIST_ENTRY DriverListHead)
Removes potential circular dependencies (cycles) and sorts the driver list.
Definition: cmboot.c:1030
UNICODE_STRING Group
Definition: cmboot.h:16
DBG_DEFAULT_CHANNEL(WINDOWS)
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
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:213
unsigned short USHORT
Definition: pedump.c:61
FxAutoRegKey hKey
static BOOLEAN WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN PCSTR DirectoryPath, IN PCSTR HiveName)
Definition: wlregistry.c:38
ULONG TotalNLSSize
Definition: wlregistry.c:20
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define NULL
Definition: types.h:112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
ARC_STATUS ArcClose(ULONG FileId)
Definition: fs.c:218
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:250
#define OUT
Definition: typedefs.h:40
struct FileInfo FileInfo
FORCEINLINE PVOID PaToVa(PVOID Pa)
Definition: conversion.h:22
#define RegQueryValue
Definition: winreg.h:523
ARC_STATUS ArcOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fs.c:56
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
FORCEINLINE PVOID VaToPa(PVOID Va)
Definition: conversion.h:15
const char * PCSTR
Definition: typedefs.h:52
#define RegOpenKey
Definition: winreg.h:519
#define RegCloseKey(hKey)
Definition: registry.h:47
#define HKEY_TO_HCI(hKey)
Definition: registry.h:28
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
ULONG RegistryLength
Definition: arc.h:500
PLOADER_SYSTEM_BLOCK WinLdrSystemBlock
Definition: winldr.c:29
NTSTRSAFEAPI RtlStringCbCatA(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCSTR pszSrc)
Definition: ntstrsafe.h:625