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)
9 /* INCLUDES ***************************************************************/
15 DBG_DEFAULT_CHANNEL(WINDOWS
);
17 // The only global var here, used to mark mem pages as NLS in WinLdrSetupMemoryLayout()
18 ULONG TotalNLSSize
= 0;
21 WinLdrGetNLSNames(LPSTR AnsiName
,
26 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead
,
27 IN LPCSTR DirectoryPath
);
30 /* FUNCTIONS **************************************************************/
33 WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
34 IN LPCSTR DirectoryPath
,
38 CHAR FullHiveName
[256];
40 FILEINFORMATION FileInfo
;
42 ULONG_PTR HiveDataPhysical
;
43 PVOID HiveDataVirtual
;
47 /* Concatenate path and filename to get the full name */
48 strcpy(FullHiveName
, DirectoryPath
);
49 strcat(FullHiveName
, HiveName
);
50 //Print(L"Loading %s...\n", FullHiveName);
51 Status
= ArcOpen(FullHiveName
, OpenReadOnly
, &FileId
);
52 if (Status
!= ESUCCESS
)
54 UiMessageBox("Opening hive file failed!");
58 /* Get the file length */
59 Status
= ArcGetFileInformation(FileId
, &FileInfo
);
60 if (Status
!= ESUCCESS
)
63 UiMessageBox("Hive file has 0 size!");
66 HiveFileSize
= FileInfo
.EndingAddress
.LowPart
;
68 /* Round up the size to page boundary and alloc memory */
69 HiveDataPhysical
= (ULONG_PTR
)MmAllocateMemoryWithType(
70 MM_SIZE_TO_PAGES(HiveFileSize
+ MM_PAGE_SIZE
- 1) << MM_PAGE_SHIFT
,
73 if (HiveDataPhysical
== 0)
76 UiMessageBox("Unable to alloc memory for a hive!");
80 /* Convert address to virtual */
81 HiveDataVirtual
= PaToVa((PVOID
)HiveDataPhysical
);
83 /* Fill LoaderBlock's entries */
84 LoaderBlock
->RegistryLength
= HiveFileSize
;
85 LoaderBlock
->RegistryBase
= HiveDataVirtual
;
87 /* Finally read from file to the memory */
88 Status
= ArcRead(FileId
, (PVOID
)HiveDataPhysical
, HiveFileSize
, &BytesRead
);
89 if (Status
!= ESUCCESS
)
92 UiMessageBox("Unable to read from hive file!");
96 // Add boot filesystem driver to the list
97 FsService
= FsGetServiceName(FileId
);
101 TRACE(" Adding filesystem service %S\n", FsService
);
102 Success
= WinLdrAddDriverToList(&LoaderBlock
->BootDriverListHead
,
103 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
107 TRACE(" Failed to add filesystem service\n");
111 TRACE(" No required filesystem service\n");
118 BOOLEAN
WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
119 IN LPCSTR DirectoryPath
)
121 CHAR SearchPath
[1024];
124 // There is a simple logic here: try to load usual hive (system), if it
125 // fails, then give system.alt a try, and finally try a system.sav
127 // FIXME: For now we only try system
128 strcpy(SearchPath
, DirectoryPath
);
129 strcat(SearchPath
, "SYSTEM32\\CONFIG\\");
130 Success
= WinLdrLoadSystemHive(LoaderBlock
, SearchPath
, "SYSTEM");
136 // Import what was loaded
137 Success
= RegImportBinaryHive(VaToPa(LoaderBlock
->RegistryBase
), LoaderBlock
->RegistryLength
);
140 UiMessageBox("Importing binary hive failed!");
144 // Initialize the 'CurrentControlSet' link
145 if (RegInitCurrentControlSet(FALSE
) != ERROR_SUCCESS
)
147 UiMessageBox("Initializing CurrentControlSet link failed!");
154 BOOLEAN
WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
155 IN LPCSTR DirectoryPath
)
157 CHAR SearchPath
[1024];
158 CHAR AnsiName
[256], OemName
[256], LangName
[256];
161 // Scan registry and prepare boot drivers list
162 WinLdrScanRegistry(&LoaderBlock
->BootDriverListHead
, DirectoryPath
);
164 // Get names of NLS files
165 Success
= WinLdrGetNLSNames(AnsiName
, OemName
, LangName
);
168 UiMessageBox("Getting NLS names from registry failed!");
172 TRACE("NLS data %s %s %s\n", AnsiName
, OemName
, LangName
);
175 strcpy(SearchPath
, DirectoryPath
);
176 strcat(SearchPath
, "SYSTEM32\\");
177 Success
= WinLdrLoadNLSData(LoaderBlock
, SearchPath
, AnsiName
, OemName
, LangName
);
178 TRACE("NLS data loading %s\n", Success
? "successful" : "failed");
180 /* TODO: Load OEM HAL font */
186 /* PRIVATE FUNCTIONS ******************************************************/
188 // Queries registry for those three file names
190 WinLdrGetNLSNames(LPSTR AnsiName
,
194 LONG rc
= ERROR_SUCCESS
;
196 WCHAR szIdBuffer
[80];
197 WCHAR NameBuffer
[80];
200 /* open the codepage key */
201 rc
= RegOpenKey(NULL
,
202 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
204 if (rc
!= ERROR_SUCCESS
)
206 //strcpy(szErrorOut, "Couldn't open CodePage registry key");
210 /* get ANSI codepage */
211 BufferSize
= sizeof(szIdBuffer
);
212 rc
= RegQueryValue(hKey
, L
"ACP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
213 if (rc
!= ERROR_SUCCESS
)
215 //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
219 BufferSize
= sizeof(NameBuffer
);
220 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
221 if (rc
!= ERROR_SUCCESS
)
223 //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
225 wcscpy(NameBuffer
, L
"c_1252.nls"); // HACK: ReactOS bug CORE-6105
227 sprintf(AnsiName
, "%S", NameBuffer
);
229 /* get OEM codepage */
230 BufferSize
= sizeof(szIdBuffer
);
231 rc
= RegQueryValue(hKey
, L
"OEMCP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
232 if (rc
!= ERROR_SUCCESS
)
234 //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
238 BufferSize
= sizeof(NameBuffer
);
239 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
240 if (rc
!= ERROR_SUCCESS
)
242 //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
244 wcscpy(NameBuffer
, L
"c_437.nls"); // HACK: ReactOS bug CORE-6105
246 sprintf(OemName
, "%S", NameBuffer
);
248 /* open the language key */
249 rc
= RegOpenKey(NULL
,
250 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
252 if (rc
!= ERROR_SUCCESS
)
254 //strcpy(szErrorOut, "Couldn't open Language registry key");
258 /* get the Unicode case table */
259 BufferSize
= sizeof(szIdBuffer
);
260 rc
= RegQueryValue(hKey
, L
"Default", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
261 if (rc
!= ERROR_SUCCESS
)
263 //strcpy(szErrorOut, "Couldn't get Language Default setting");
267 BufferSize
= sizeof(NameBuffer
);
268 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
269 if (rc
!= ERROR_SUCCESS
)
271 //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
274 sprintf(LangName
, "%S", NameBuffer
);
280 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
281 IN LPCSTR DirectoryPath
,
282 IN LPCSTR AnsiFileName
,
283 IN LPCSTR OemFileName
,
284 IN LPCSTR LanguageFileName
)
289 ULONG LanguageFileId
;
290 ULONG AnsiFileSize
, OemFileSize
, LanguageFileSize
;
292 ULONG_PTR NlsDataBase
;
294 BOOLEAN AnsiEqualsOem
= FALSE
;
295 FILEINFORMATION FileInfo
;
299 /* There may be a case, when OEM and ANSI page coincide */
300 if (!strcmp(AnsiFileName
, OemFileName
))
301 AnsiEqualsOem
= TRUE
;
303 /* Open file with ANSI and store its size */
304 //Print(L"Loading %s...\n", Filename);
305 strcpy(FileName
, DirectoryPath
);
306 strcat(FileName
, AnsiFileName
);
307 Status
= ArcOpen(FileName
, OpenReadOnly
, &AnsiFileId
);
308 if (Status
!= ESUCCESS
)
311 Status
= ArcGetFileInformation(AnsiFileId
, &FileInfo
);
312 if (Status
!= ESUCCESS
)
314 AnsiFileSize
= FileInfo
.EndingAddress
.LowPart
;
315 TRACE("AnsiFileSize: %d\n", AnsiFileSize
);
316 ArcClose(AnsiFileId
);
318 /* Open OEM file and store its length */
325 //Print(L"Loading %s...\n", Filename);
326 strcpy(FileName
, DirectoryPath
);
327 strcat(FileName
, OemFileName
);
328 Status
= ArcOpen(FileName
, OpenReadOnly
, &OemFileId
);
329 if (Status
!= ESUCCESS
)
332 Status
= ArcGetFileInformation(OemFileId
, &FileInfo
);
333 if (Status
!= ESUCCESS
)
335 OemFileSize
= FileInfo
.EndingAddress
.LowPart
;
338 TRACE("OemFileSize: %d\n", OemFileSize
);
340 /* And finally open the language codepage file and store its length */
341 //Print(L"Loading %s...\n", Filename);
342 strcpy(FileName
, DirectoryPath
);
343 strcat(FileName
, LanguageFileName
);
344 Status
= ArcOpen(FileName
, OpenReadOnly
, &LanguageFileId
);
345 if (Status
!= ESUCCESS
)
348 Status
= ArcGetFileInformation(LanguageFileId
, &FileInfo
);
349 if (Status
!= ESUCCESS
)
351 LanguageFileSize
= FileInfo
.EndingAddress
.LowPart
;
352 ArcClose(LanguageFileId
);
353 TRACE("LanguageFileSize: %d\n", LanguageFileSize
);
355 /* Sum up all three length, having in mind that every one of them
356 must start at a page boundary => thus round up each file to a page */
357 TotalSize
= MM_SIZE_TO_PAGES(AnsiFileSize
) +
358 MM_SIZE_TO_PAGES(OemFileSize
) +
359 MM_SIZE_TO_PAGES(LanguageFileSize
);
361 /* Store it for later marking the pages as NlsData type */
362 TotalNLSSize
= TotalSize
;
364 NlsDataBase
= (ULONG_PTR
)MmAllocateMemoryWithType(TotalSize
*MM_PAGE_SIZE
, LoaderNlsData
);
366 if (NlsDataBase
== 0)
369 NlsVirtual
= PaToVa((PVOID
)NlsDataBase
);
370 LoaderBlock
->NlsData
->AnsiCodePageData
= NlsVirtual
;
371 LoaderBlock
->NlsData
->OemCodePageData
= (PVOID
)((PUCHAR
)NlsVirtual
+
372 (MM_SIZE_TO_PAGES(AnsiFileSize
) << MM_PAGE_SHIFT
));
373 LoaderBlock
->NlsData
->UnicodeCodePageData
= (PVOID
)((PUCHAR
)NlsVirtual
+
374 (MM_SIZE_TO_PAGES(AnsiFileSize
) << MM_PAGE_SHIFT
) +
375 (MM_SIZE_TO_PAGES(OemFileSize
) << MM_PAGE_SHIFT
));
377 /* Ansi and OEM data are the same - just set pointers to the same area */
379 LoaderBlock
->NlsData
->OemCodePageData
= LoaderBlock
->NlsData
->AnsiCodePageData
;
382 /* Now actually read the data into memory, starting with Ansi file */
383 strcpy(FileName
, DirectoryPath
);
384 strcat(FileName
, AnsiFileName
);
385 Status
= ArcOpen(FileName
, OpenReadOnly
, &AnsiFileId
);
386 if (Status
!= ESUCCESS
)
389 Status
= ArcRead(AnsiFileId
, VaToPa(LoaderBlock
->NlsData
->AnsiCodePageData
), AnsiFileSize
, &BytesRead
);
390 if (Status
!= ESUCCESS
)
393 ArcClose(AnsiFileId
);
395 /* OEM now, if it doesn't equal Ansi of course */
398 strcpy(FileName
, DirectoryPath
);
399 strcat(FileName
, OemFileName
);
400 Status
= ArcOpen(FileName
, OpenReadOnly
, &OemFileId
);
401 if (Status
!= ESUCCESS
)
404 Status
= ArcRead(OemFileId
, VaToPa(LoaderBlock
->NlsData
->OemCodePageData
), OemFileSize
, &BytesRead
);
405 if (Status
!= ESUCCESS
)
411 /* finally the language file */
412 strcpy(FileName
, DirectoryPath
);
413 strcat(FileName
, LanguageFileName
);
414 Status
= ArcOpen(FileName
, OpenReadOnly
, &LanguageFileId
);
415 if (Status
!= ESUCCESS
)
418 Status
= ArcRead(LanguageFileId
, VaToPa(LoaderBlock
->NlsData
->UnicodeCodePageData
), LanguageFileSize
, &BytesRead
);
419 if (Status
!= ESUCCESS
)
422 ArcClose(LanguageFileId
);
425 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
426 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
428 LoaderBlock
->OemFontFile
= VaToPa(LoaderBlock
->NlsData
->UnicodeCodePageData
);
430 /* Convert NlsTables address to VA */
431 LoaderBlock
->NlsData
= PaToVa(LoaderBlock
->NlsData
);
436 UiMessageBox("Error reading NLS file %s", FileName
);
441 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead
,
442 IN LPCSTR DirectoryPath
)
445 HKEY hGroupKey
, hOrderKey
, hServiceKey
, hDriverKey
;
446 LPWSTR GroupNameBuffer
;
447 WCHAR ServiceName
[256];
448 ULONG OrderList
[128];
458 WCHAR DriverGroup
[256];
459 ULONG DriverGroupSize
;
462 WCHAR TempImagePath
[256];
466 /* get 'service group order' key */
467 rc
= RegOpenKey(NULL
,
468 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
470 if (rc
!= ERROR_SUCCESS
) {
472 TRACE_CH(REACTOS
, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc
);
476 /* get 'group order list' key */
477 rc
= RegOpenKey(NULL
,
478 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
480 if (rc
!= ERROR_SUCCESS
) {
482 TRACE_CH(REACTOS
, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc
);
486 /* enumerate drivers */
487 rc
= RegOpenKey(NULL
,
488 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
490 if (rc
!= ERROR_SUCCESS
) {
492 TRACE_CH(REACTOS
, "Failed to open the 'Services' key (rc %d)\n", (int)rc
);
496 /* Get the Name Group */
498 GroupNameBuffer
= FrLdrHeapAlloc(BufferSize
, TAG_WLDR_NAME
);
499 rc
= RegQueryValue(hGroupKey
, L
"List", NULL
, (PUCHAR
)GroupNameBuffer
, &BufferSize
);
500 TRACE_CH(REACTOS
, "RegQueryValue(): rc %d\n", (int)rc
);
501 if (rc
!= ERROR_SUCCESS
)
503 TRACE_CH(REACTOS
, "BufferSize: %d \n", (int)BufferSize
);
504 TRACE_CH(REACTOS
, "GroupNameBuffer: '%S' \n", GroupNameBuffer
);
506 /* Loop through each group */
507 GroupName
= GroupNameBuffer
;
510 TRACE("Driver group: '%S'\n", GroupName
);
512 /* Query the Order */
513 BufferSize
= sizeof(OrderList
);
514 rc
= RegQueryValue(hOrderKey
, GroupName
, NULL
, (PUCHAR
)OrderList
, &BufferSize
);
515 if (rc
!= ERROR_SUCCESS
) OrderList
[0] = 0;
517 /* enumerate all drivers */
518 for (TagIndex
= 1; TagIndex
<= OrderList
[0]; TagIndex
++)
524 /* Get the Driver's Name */
525 ValueSize
= sizeof(ServiceName
);
526 rc
= RegEnumKey(hServiceKey
, Index
, ServiceName
, &ValueSize
, &hDriverKey
);
527 TRACE("RegEnumKey(): rc %d\n", (int)rc
);
529 /* Make sure it's valid, and check if we're done */
530 if (rc
== ERROR_NO_MORE_ITEMS
)
532 if (rc
!= ERROR_SUCCESS
)
534 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
537 //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName);
539 /* Read the Start Value */
540 ValueSize
= sizeof(ULONG
);
541 rc
= RegQueryValue(hDriverKey
, L
"Start", &ValueType
, (PUCHAR
)&StartValue
, &ValueSize
);
542 if (rc
!= ERROR_SUCCESS
) StartValue
= (ULONG
)-1;
543 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
546 ValueSize
= sizeof(ULONG
);
547 rc
= RegQueryValue(hDriverKey
, L
"Tag", &ValueType
, (PUCHAR
)&TagValue
, &ValueSize
);
548 if (rc
!= ERROR_SUCCESS
) TagValue
= (ULONG
)-1;
549 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
551 /* Read the driver's group */
552 DriverGroupSize
= sizeof(DriverGroup
);
553 rc
= RegQueryValue(hDriverKey
, L
"Group", NULL
, (PUCHAR
)DriverGroup
, &DriverGroupSize
);
554 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
556 /* Make sure it should be started */
557 if ((StartValue
== 0) &&
558 (TagValue
== OrderList
[TagIndex
]) &&
559 (_wcsicmp(DriverGroup
, GroupName
) == 0))
561 /* Get the Driver's Location */
562 ValueSize
= sizeof(TempImagePath
);
563 rc
= RegQueryValue(hDriverKey
, L
"ImagePath", NULL
, (PUCHAR
)TempImagePath
, &ValueSize
);
565 /* Write the whole path if it succeeded, else prepare to fail */
566 if (rc
!= ERROR_SUCCESS
)
568 TRACE_CH(REACTOS
, "ImagePath: not found\n");
569 TempImagePath
[0] = 0;
570 sprintf(ImagePath
, "%s\\system32\\drivers\\%S.sys", DirectoryPath
, ServiceName
);
572 else if (TempImagePath
[0] != L
'\\')
574 sprintf(ImagePath
, "%s%S", DirectoryPath
, TempImagePath
);
578 sprintf(ImagePath
, "%S", TempImagePath
);
579 TRACE_CH(REACTOS
, "ImagePath: '%s'\n", ImagePath
);
582 TRACE("Adding boot driver: '%s'\n", ImagePath
);
584 Success
= WinLdrAddDriverToList(BootDriverListHead
,
585 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
589 ERR("Failed to add boot driver\n");
593 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n",
594 // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName);
604 /* Get the Driver's Name */
605 ValueSize
= sizeof(ServiceName
);
606 rc
= RegEnumKey(hServiceKey
, Index
, ServiceName
, &ValueSize
, &hDriverKey
);
608 //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc);
609 if (rc
== ERROR_NO_MORE_ITEMS
)
611 if (rc
!= ERROR_SUCCESS
)
613 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
616 TRACE("Service %d: '%S'\n", (int)Index
, ServiceName
);
618 /* Read the Start Value */
619 ValueSize
= sizeof(ULONG
);
620 rc
= RegQueryValue(hDriverKey
, L
"Start", &ValueType
, (PUCHAR
)&StartValue
, &ValueSize
);
621 if (rc
!= ERROR_SUCCESS
) StartValue
= (ULONG
)-1;
622 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
625 ValueSize
= sizeof(ULONG
);
626 rc
= RegQueryValue(hDriverKey
, L
"Tag", &ValueType
, (PUCHAR
)&TagValue
, &ValueSize
);
627 if (rc
!= ERROR_SUCCESS
) TagValue
= (ULONG
)-1;
628 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
630 /* Read the driver's group */
631 DriverGroupSize
= sizeof(DriverGroup
);
632 rc
= RegQueryValue(hDriverKey
, L
"Group", NULL
, (PUCHAR
)DriverGroup
, &DriverGroupSize
);
633 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
635 for (TagIndex
= 1; TagIndex
<= OrderList
[0]; TagIndex
++)
637 if (TagValue
== OrderList
[TagIndex
]) break;
640 if ((StartValue
== 0) &&
641 (TagIndex
> OrderList
[0]) &&
642 (_wcsicmp(DriverGroup
, GroupName
) == 0))
644 ValueSize
= sizeof(TempImagePath
);
645 rc
= RegQueryValue(hDriverKey
, L
"ImagePath", NULL
, (PUCHAR
)TempImagePath
, &ValueSize
);
646 if (rc
!= ERROR_SUCCESS
)
648 TRACE_CH(REACTOS
, "ImagePath: not found\n");
649 TempImagePath
[0] = 0;
650 sprintf(ImagePath
, "%ssystem32\\drivers\\%S.sys", DirectoryPath
, ServiceName
);
652 else if (TempImagePath
[0] != L
'\\')
654 sprintf(ImagePath
, "%s%S", DirectoryPath
, TempImagePath
);
658 sprintf(ImagePath
, "%S", TempImagePath
);
659 TRACE_CH(REACTOS
, "ImagePath: '%s'\n", ImagePath
);
661 TRACE(" Adding boot driver: '%s'\n", ImagePath
);
663 Success
= WinLdrAddDriverToList(BootDriverListHead
,
664 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
668 ERR(" Failed to add boot driver\n");
672 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
673 // ServiceName, StartValue, TagValue, DriverGroup, GroupName);
679 /* Move to the next group name */
680 GroupName
= GroupName
+ wcslen(GroupName
) + 1;
683 /* Free allocated memory */
684 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
689 InsertInBootDriverList(
690 PLIST_ENTRY BootDriverListHead
,
691 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry
)
693 PBOOT_DRIVER_LIST_ENTRY DriverEntry
;
694 PLIST_ENTRY ListEntry
;
696 ASSERT(BootDriverEntry
->FilePath
.Buffer
!= NULL
);
697 ASSERT(BootDriverEntry
->RegistryPath
.Buffer
!= NULL
);
699 for (ListEntry
= BootDriverListHead
->Flink
;
700 ListEntry
!= BootDriverListHead
;
701 ListEntry
= ListEntry
->Flink
)
703 DriverEntry
= CONTAINING_RECORD(ListEntry
,
704 BOOT_DRIVER_LIST_ENTRY
,
706 if ((DriverEntry
->FilePath
.Buffer
!= NULL
) &&
707 RtlEqualUnicodeString(&BootDriverEntry
->FilePath
,
708 &DriverEntry
->FilePath
,
714 if ((DriverEntry
->RegistryPath
.Buffer
!= NULL
) &&
715 RtlEqualUnicodeString(&BootDriverEntry
->RegistryPath
,
716 &DriverEntry
->RegistryPath
,
723 InsertTailList(BootDriverListHead
, &BootDriverEntry
->Link
);
728 WinLdrAddDriverToList(LIST_ENTRY
*BootDriverListHead
,
733 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry
;
737 BootDriverEntry
= FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY
), TAG_WLDR_BDE
);
739 if (!BootDriverEntry
)
742 // DTE will be filled during actual load of the driver
743 BootDriverEntry
->LdrEntry
= NULL
;
745 // Check - if we have a valid ImagePath, if not - we need to build it
746 // like "System32\\Drivers\\blah.sys"
747 if (ImagePath
&& (ImagePath
[0] != 0))
749 // Just copy ImagePath to the corresponding field in the structure
750 PathLength
= (USHORT
)wcslen(ImagePath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
752 BootDriverEntry
->FilePath
.Length
= 0;
753 BootDriverEntry
->FilePath
.MaximumLength
= PathLength
;
754 BootDriverEntry
->FilePath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
756 if (!BootDriverEntry
->FilePath
.Buffer
)
758 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_BDE
);
762 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, ImagePath
);
763 if (!NT_SUCCESS(Status
))
765 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
766 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_BDE
);
772 // we have to construct ImagePath ourselves
773 PathLength
= (USHORT
)wcslen(ServiceName
)*sizeof(WCHAR
) + sizeof(L
"system32\\drivers\\.sys");
774 BootDriverEntry
->FilePath
.Length
= 0;
775 BootDriverEntry
->FilePath
.MaximumLength
= PathLength
;
776 BootDriverEntry
->FilePath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
778 if (!BootDriverEntry
->FilePath
.Buffer
)
780 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
784 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, L
"system32\\drivers\\");
785 if (!NT_SUCCESS(Status
))
787 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
788 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
792 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, ServiceName
);
793 if (!NT_SUCCESS(Status
))
795 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
796 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
800 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, L
".sys");
801 if (!NT_SUCCESS(Status
))
803 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
804 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
810 PathLength
= (USHORT
)(wcslen(RegistryPath
) + wcslen(ServiceName
))*sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
811 BootDriverEntry
->RegistryPath
.Length
= 0;
812 BootDriverEntry
->RegistryPath
.MaximumLength
= PathLength
;
813 BootDriverEntry
->RegistryPath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
814 if (!BootDriverEntry
->RegistryPath
.Buffer
)
817 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->RegistryPath
, RegistryPath
);
818 if (!NT_SUCCESS(Status
))
821 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->RegistryPath
, ServiceName
);
822 if (!NT_SUCCESS(Status
))
825 // Insert entry into the list
826 if (!InsertInBootDriverList(BootDriverListHead
, BootDriverEntry
))
828 // It was already there, so delete our entry
829 if (BootDriverEntry
->FilePath
.Buffer
) FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
830 if (BootDriverEntry
->RegistryPath
.Buffer
) FrLdrHeapFree(BootDriverEntry
->RegistryPath
.Buffer
, TAG_WLDR_NAME
);
831 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_BDE
);