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 */
187 /* PRIVATE FUNCTIONS ******************************************************/
189 // Queries registry for those three file names
191 WinLdrGetNLSNames(LPSTR AnsiName
,
195 LONG rc
= ERROR_SUCCESS
;
197 WCHAR szIdBuffer
[80];
198 WCHAR NameBuffer
[80];
201 /* open the codepage key */
202 rc
= RegOpenKey(NULL
,
203 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
205 if (rc
!= ERROR_SUCCESS
)
207 //strcpy(szErrorOut, "Couldn't open CodePage registry key");
211 /* get ANSI codepage */
212 BufferSize
= sizeof(szIdBuffer
);
213 rc
= RegQueryValue(hKey
, L
"ACP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
214 if (rc
!= ERROR_SUCCESS
)
216 //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
220 BufferSize
= sizeof(NameBuffer
);
221 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
222 if (rc
!= ERROR_SUCCESS
)
224 //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
226 wcscpy(NameBuffer
, L
"c_1252.nls"); // HACK: ReactOS bug CORE-6105
228 sprintf(AnsiName
, "%S", NameBuffer
);
230 /* get OEM codepage */
231 BufferSize
= sizeof(szIdBuffer
);
232 rc
= RegQueryValue(hKey
, L
"OEMCP", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
233 if (rc
!= ERROR_SUCCESS
)
235 //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
239 BufferSize
= sizeof(NameBuffer
);
240 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
241 if (rc
!= ERROR_SUCCESS
)
243 //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
245 wcscpy(NameBuffer
, L
"c_437.nls"); // HACK: ReactOS bug CORE-6105
247 sprintf(OemName
, "%S", NameBuffer
);
249 /* open the language key */
250 rc
= RegOpenKey(NULL
,
251 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
253 if (rc
!= ERROR_SUCCESS
)
255 //strcpy(szErrorOut, "Couldn't open Language registry key");
259 /* get the Unicode case table */
260 BufferSize
= sizeof(szIdBuffer
);
261 rc
= RegQueryValue(hKey
, L
"Default", NULL
, (PUCHAR
)szIdBuffer
, &BufferSize
);
262 if (rc
!= ERROR_SUCCESS
)
264 //strcpy(szErrorOut, "Couldn't get Language Default setting");
268 BufferSize
= sizeof(NameBuffer
);
269 rc
= RegQueryValue(hKey
, szIdBuffer
, NULL
, (PUCHAR
)NameBuffer
, &BufferSize
);
270 if (rc
!= ERROR_SUCCESS
)
272 //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
275 sprintf(LangName
, "%S", NameBuffer
);
281 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock
,
282 IN LPCSTR DirectoryPath
,
283 IN LPCSTR AnsiFileName
,
284 IN LPCSTR OemFileName
,
285 IN LPCSTR LanguageFileName
)
290 ULONG LanguageFileId
;
291 ULONG AnsiFileSize
, OemFileSize
, LanguageFileSize
;
293 ULONG_PTR NlsDataBase
;
295 BOOLEAN AnsiEqualsOem
= FALSE
;
296 FILEINFORMATION FileInfo
;
300 /* There may be a case, when OEM and ANSI page coincide */
301 if (!strcmp(AnsiFileName
, OemFileName
))
302 AnsiEqualsOem
= TRUE
;
304 /* Open file with ANSI and store its size */
305 //Print(L"Loading %s...\n", Filename);
306 strcpy(FileName
, DirectoryPath
);
307 strcat(FileName
, AnsiFileName
);
308 Status
= ArcOpen(FileName
, OpenReadOnly
, &AnsiFileId
);
309 if (Status
!= ESUCCESS
)
312 Status
= ArcGetFileInformation(AnsiFileId
, &FileInfo
);
313 if (Status
!= ESUCCESS
)
315 AnsiFileSize
= FileInfo
.EndingAddress
.LowPart
;
316 TRACE("AnsiFileSize: %d\n", AnsiFileSize
);
317 ArcClose(AnsiFileId
);
319 /* Open OEM file and store its length */
326 //Print(L"Loading %s...\n", Filename);
327 strcpy(FileName
, DirectoryPath
);
328 strcat(FileName
, OemFileName
);
329 Status
= ArcOpen(FileName
, OpenReadOnly
, &OemFileId
);
330 if (Status
!= ESUCCESS
)
333 Status
= ArcGetFileInformation(OemFileId
, &FileInfo
);
334 if (Status
!= ESUCCESS
)
336 OemFileSize
= FileInfo
.EndingAddress
.LowPart
;
339 TRACE("OemFileSize: %d\n", OemFileSize
);
341 /* And finally open the language codepage file and store its length */
342 //Print(L"Loading %s...\n", Filename);
343 strcpy(FileName
, DirectoryPath
);
344 strcat(FileName
, LanguageFileName
);
345 Status
= ArcOpen(FileName
, OpenReadOnly
, &LanguageFileId
);
346 if (Status
!= ESUCCESS
)
349 Status
= ArcGetFileInformation(LanguageFileId
, &FileInfo
);
350 if (Status
!= ESUCCESS
)
352 LanguageFileSize
= FileInfo
.EndingAddress
.LowPart
;
353 ArcClose(LanguageFileId
);
354 TRACE("LanguageFileSize: %d\n", LanguageFileSize
);
356 /* Sum up all three length, having in mind that every one of them
357 must start at a page boundary => thus round up each file to a page */
358 TotalSize
= MM_SIZE_TO_PAGES(AnsiFileSize
) +
359 MM_SIZE_TO_PAGES(OemFileSize
) +
360 MM_SIZE_TO_PAGES(LanguageFileSize
);
362 /* Store it for later marking the pages as NlsData type */
363 TotalNLSSize
= TotalSize
;
365 NlsDataBase
= (ULONG_PTR
)MmAllocateMemoryWithType(TotalSize
*MM_PAGE_SIZE
, LoaderNlsData
);
367 if (NlsDataBase
== 0)
370 NlsVirtual
= PaToVa((PVOID
)NlsDataBase
);
371 LoaderBlock
->NlsData
->AnsiCodePageData
= NlsVirtual
;
372 LoaderBlock
->NlsData
->OemCodePageData
= (PVOID
)((PUCHAR
)NlsVirtual
+
373 (MM_SIZE_TO_PAGES(AnsiFileSize
) << MM_PAGE_SHIFT
));
374 LoaderBlock
->NlsData
->UnicodeCodePageData
= (PVOID
)((PUCHAR
)NlsVirtual
+
375 (MM_SIZE_TO_PAGES(AnsiFileSize
) << MM_PAGE_SHIFT
) +
376 (MM_SIZE_TO_PAGES(OemFileSize
) << MM_PAGE_SHIFT
));
378 /* Ansi and OEM data are the same - just set pointers to the same area */
380 LoaderBlock
->NlsData
->OemCodePageData
= LoaderBlock
->NlsData
->AnsiCodePageData
;
383 /* Now actually read the data into memory, starting with Ansi file */
384 strcpy(FileName
, DirectoryPath
);
385 strcat(FileName
, AnsiFileName
);
386 Status
= ArcOpen(FileName
, OpenReadOnly
, &AnsiFileId
);
387 if (Status
!= ESUCCESS
)
390 Status
= ArcRead(AnsiFileId
, VaToPa(LoaderBlock
->NlsData
->AnsiCodePageData
), AnsiFileSize
, &BytesRead
);
391 if (Status
!= ESUCCESS
)
394 ArcClose(AnsiFileId
);
396 /* OEM now, if it doesn't equal Ansi of course */
399 strcpy(FileName
, DirectoryPath
);
400 strcat(FileName
, OemFileName
);
401 Status
= ArcOpen(FileName
, OpenReadOnly
, &OemFileId
);
402 if (Status
!= ESUCCESS
)
405 Status
= ArcRead(OemFileId
, VaToPa(LoaderBlock
->NlsData
->OemCodePageData
), OemFileSize
, &BytesRead
);
406 if (Status
!= ESUCCESS
)
412 /* finally the language file */
413 strcpy(FileName
, DirectoryPath
);
414 strcat(FileName
, LanguageFileName
);
415 Status
= ArcOpen(FileName
, OpenReadOnly
, &LanguageFileId
);
416 if (Status
!= ESUCCESS
)
419 Status
= ArcRead(LanguageFileId
, VaToPa(LoaderBlock
->NlsData
->UnicodeCodePageData
), LanguageFileSize
, &BytesRead
);
420 if (Status
!= ESUCCESS
)
423 ArcClose(LanguageFileId
);
426 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
427 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
429 LoaderBlock
->OemFontFile
= VaToPa(LoaderBlock
->NlsData
->UnicodeCodePageData
);
431 /* Convert NlsTables address to VA */
432 LoaderBlock
->NlsData
= PaToVa(LoaderBlock
->NlsData
);
437 UiMessageBox("Error reading NLS file %s", FileName
);
442 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead
,
443 IN LPCSTR DirectoryPath
)
446 HKEY hGroupKey
, hOrderKey
, hServiceKey
, hDriverKey
;
447 LPWSTR GroupNameBuffer
;
448 WCHAR ServiceName
[256];
449 ULONG OrderList
[128];
459 WCHAR DriverGroup
[256];
460 ULONG DriverGroupSize
;
463 WCHAR TempImagePath
[256];
467 /* get 'service group order' key */
468 rc
= RegOpenKey(NULL
,
469 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
471 if (rc
!= ERROR_SUCCESS
) {
473 TRACE_CH(REACTOS
, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc
);
477 /* get 'group order list' key */
478 rc
= RegOpenKey(NULL
,
479 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
481 if (rc
!= ERROR_SUCCESS
) {
483 TRACE_CH(REACTOS
, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc
);
487 /* enumerate drivers */
488 rc
= RegOpenKey(NULL
,
489 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
491 if (rc
!= ERROR_SUCCESS
) {
493 TRACE_CH(REACTOS
, "Failed to open the 'Services' key (rc %d)\n", (int)rc
);
497 /* Get the Name Group */
499 GroupNameBuffer
= FrLdrHeapAlloc(BufferSize
, TAG_WLDR_NAME
);
500 rc
= RegQueryValue(hGroupKey
, L
"List", NULL
, (PUCHAR
)GroupNameBuffer
, &BufferSize
);
501 TRACE_CH(REACTOS
, "RegQueryValue(): rc %d\n", (int)rc
);
502 if (rc
!= ERROR_SUCCESS
)
504 TRACE_CH(REACTOS
, "BufferSize: %d \n", (int)BufferSize
);
505 TRACE_CH(REACTOS
, "GroupNameBuffer: '%S' \n", GroupNameBuffer
);
507 /* Loop through each group */
508 GroupName
= GroupNameBuffer
;
511 TRACE("Driver group: '%S'\n", GroupName
);
513 /* Query the Order */
514 BufferSize
= sizeof(OrderList
);
515 rc
= RegQueryValue(hOrderKey
, GroupName
, NULL
, (PUCHAR
)OrderList
, &BufferSize
);
516 if (rc
!= ERROR_SUCCESS
) OrderList
[0] = 0;
518 /* enumerate all drivers */
519 for (TagIndex
= 1; TagIndex
<= OrderList
[0]; TagIndex
++)
525 /* Get the Driver's Name */
526 ValueSize
= sizeof(ServiceName
);
527 rc
= RegEnumKey(hServiceKey
, Index
, ServiceName
, &ValueSize
, &hDriverKey
);
528 TRACE("RegEnumKey(): rc %d\n", (int)rc
);
530 /* Make sure it's valid, and check if we're done */
531 if (rc
== ERROR_NO_MORE_ITEMS
)
533 if (rc
!= ERROR_SUCCESS
)
535 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
538 //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName);
540 /* Read the Start Value */
541 ValueSize
= sizeof(ULONG
);
542 rc
= RegQueryValue(hDriverKey
, L
"Start", &ValueType
, (PUCHAR
)&StartValue
, &ValueSize
);
543 if (rc
!= ERROR_SUCCESS
) StartValue
= (ULONG
)-1;
544 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
547 ValueSize
= sizeof(ULONG
);
548 rc
= RegQueryValue(hDriverKey
, L
"Tag", &ValueType
, (PUCHAR
)&TagValue
, &ValueSize
);
549 if (rc
!= ERROR_SUCCESS
) TagValue
= (ULONG
)-1;
550 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
552 /* Read the driver's group */
553 DriverGroupSize
= sizeof(DriverGroup
);
554 rc
= RegQueryValue(hDriverKey
, L
"Group", NULL
, (PUCHAR
)DriverGroup
, &DriverGroupSize
);
555 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
557 /* Make sure it should be started */
558 if ((StartValue
== 0) &&
559 (TagValue
== OrderList
[TagIndex
]) &&
560 (_wcsicmp(DriverGroup
, GroupName
) == 0))
562 /* Get the Driver's Location */
563 ValueSize
= sizeof(TempImagePath
);
564 rc
= RegQueryValue(hDriverKey
, L
"ImagePath", NULL
, (PUCHAR
)TempImagePath
, &ValueSize
);
566 /* Write the whole path if it suceeded, else prepare to fail */
567 if (rc
!= ERROR_SUCCESS
)
569 TRACE_CH(REACTOS
, "ImagePath: not found\n");
570 TempImagePath
[0] = 0;
571 sprintf(ImagePath
, "%s\\system32\\drivers\\%S.sys", DirectoryPath
, ServiceName
);
573 else if (TempImagePath
[0] != L
'\\')
575 sprintf(ImagePath
, "%s%S", DirectoryPath
, TempImagePath
);
579 sprintf(ImagePath
, "%S", TempImagePath
);
580 TRACE_CH(REACTOS
, "ImagePath: '%s'\n", ImagePath
);
583 TRACE("Adding boot driver: '%s'\n", ImagePath
);
585 Success
= WinLdrAddDriverToList(BootDriverListHead
,
586 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
590 ERR("Failed to add boot driver\n");
594 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n",
595 // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName);
605 /* Get the Driver's Name */
606 ValueSize
= sizeof(ServiceName
);
607 rc
= RegEnumKey(hServiceKey
, Index
, ServiceName
, &ValueSize
, &hDriverKey
);
609 //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc);
610 if (rc
== ERROR_NO_MORE_ITEMS
)
612 if (rc
!= ERROR_SUCCESS
)
614 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
617 TRACE("Service %d: '%S'\n", (int)Index
, ServiceName
);
619 /* Read the Start Value */
620 ValueSize
= sizeof(ULONG
);
621 rc
= RegQueryValue(hDriverKey
, L
"Start", &ValueType
, (PUCHAR
)&StartValue
, &ValueSize
);
622 if (rc
!= ERROR_SUCCESS
) StartValue
= (ULONG
)-1;
623 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
626 ValueSize
= sizeof(ULONG
);
627 rc
= RegQueryValue(hDriverKey
, L
"Tag", &ValueType
, (PUCHAR
)&TagValue
, &ValueSize
);
628 if (rc
!= ERROR_SUCCESS
) TagValue
= (ULONG
)-1;
629 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
631 /* Read the driver's group */
632 DriverGroupSize
= sizeof(DriverGroup
);
633 rc
= RegQueryValue(hDriverKey
, L
"Group", NULL
, (PUCHAR
)DriverGroup
, &DriverGroupSize
);
634 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
636 for (TagIndex
= 1; TagIndex
<= OrderList
[0]; TagIndex
++)
638 if (TagValue
== OrderList
[TagIndex
]) break;
641 if ((StartValue
== 0) &&
642 (TagIndex
> OrderList
[0]) &&
643 (_wcsicmp(DriverGroup
, GroupName
) == 0))
645 ValueSize
= sizeof(TempImagePath
);
646 rc
= RegQueryValue(hDriverKey
, L
"ImagePath", NULL
, (PUCHAR
)TempImagePath
, &ValueSize
);
647 if (rc
!= ERROR_SUCCESS
)
649 TRACE_CH(REACTOS
, "ImagePath: not found\n");
650 TempImagePath
[0] = 0;
651 sprintf(ImagePath
, "%ssystem32\\drivers\\%S.sys", DirectoryPath
, ServiceName
);
653 else if (TempImagePath
[0] != L
'\\')
655 sprintf(ImagePath
, "%s%S", DirectoryPath
, TempImagePath
);
659 sprintf(ImagePath
, "%S", TempImagePath
);
660 TRACE_CH(REACTOS
, "ImagePath: '%s'\n", ImagePath
);
662 TRACE(" Adding boot driver: '%s'\n", ImagePath
);
664 Success
= WinLdrAddDriverToList(BootDriverListHead
,
665 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
669 ERR(" Failed to add boot driver\n");
673 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
674 // ServiceName, StartValue, TagValue, DriverGroup, GroupName);
680 /* Move to the next group name */
681 GroupName
= GroupName
+ wcslen(GroupName
) + 1;
684 /* Free allocated memory */
685 FrLdrHeapFree(GroupNameBuffer
, TAG_WLDR_NAME
);
689 WinLdrAddDriverToList(LIST_ENTRY
*BootDriverListHead
,
694 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry
;
698 BootDriverEntry
= FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY
), TAG_WLDR_BDE
);
700 if (!BootDriverEntry
)
703 // DTE will be filled during actual load of the driver
704 BootDriverEntry
->LdrEntry
= NULL
;
706 // Check - if we have a valid ImagePath, if not - we need to build it
707 // like "System32\\Drivers\\blah.sys"
708 if (ImagePath
&& (wcslen(ImagePath
) > 0))
710 // Just copy ImagePath to the corresponding field in the structure
711 PathLength
= (USHORT
)wcslen(ImagePath
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
713 BootDriverEntry
->FilePath
.Length
= 0;
714 BootDriverEntry
->FilePath
.MaximumLength
= PathLength
;
715 BootDriverEntry
->FilePath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
717 if (!BootDriverEntry
->FilePath
.Buffer
)
719 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_BDE
);
723 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, ImagePath
);
724 if (!NT_SUCCESS(Status
))
726 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
727 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_BDE
);
733 // we have to construct ImagePath ourselves
734 PathLength
= (USHORT
)wcslen(ServiceName
)*sizeof(WCHAR
) + sizeof(L
"system32\\drivers\\.sys");
735 BootDriverEntry
->FilePath
.Length
= 0;
736 BootDriverEntry
->FilePath
.MaximumLength
= PathLength
;
737 BootDriverEntry
->FilePath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
739 if (!BootDriverEntry
->FilePath
.Buffer
)
741 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
745 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, L
"system32\\drivers\\");
746 if (!NT_SUCCESS(Status
))
748 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
749 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
753 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, ServiceName
);
754 if (!NT_SUCCESS(Status
))
756 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
757 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
761 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->FilePath
, L
".sys");
762 if (!NT_SUCCESS(Status
))
764 FrLdrHeapFree(BootDriverEntry
->FilePath
.Buffer
, TAG_WLDR_NAME
);
765 FrLdrHeapFree(BootDriverEntry
, TAG_WLDR_NAME
);
771 PathLength
= (USHORT
)(wcslen(RegistryPath
) + wcslen(ServiceName
))*sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
772 BootDriverEntry
->RegistryPath
.Length
= 0;
773 BootDriverEntry
->RegistryPath
.MaximumLength
= PathLength
;
774 BootDriverEntry
->RegistryPath
.Buffer
= FrLdrHeapAlloc(PathLength
, TAG_WLDR_NAME
);
775 if (!BootDriverEntry
->RegistryPath
.Buffer
)
778 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->RegistryPath
, RegistryPath
);
779 if (!NT_SUCCESS(Status
))
782 Status
= RtlAppendUnicodeToString(&BootDriverEntry
->RegistryPath
, ServiceName
);
783 if (!NT_SUCCESS(Status
))
786 // Insert entry at top of the list
787 InsertTailList(BootDriverListHead
, &BootDriverEntry
->Link
);