[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / windows / wlregistry.c
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 "registry.h"
13
14 #include <debug.h>
15 DBG_DEFAULT_CHANNEL(WINDOWS);
16
17 // The only global var here, used to mark mem pages as NLS in WinLdrSetupMemoryLayout()
18 ULONG TotalNLSSize = 0;
19
20 static BOOLEAN
21 WinLdrGetNLSNames(LPSTR AnsiName,
22 LPSTR OemName,
23 LPSTR LangName);
24
25 static VOID
26 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
27 IN LPCSTR DirectoryPath);
28
29
30 /* FUNCTIONS **************************************************************/
31
32 BOOLEAN
33 WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
34 IN LPCSTR DirectoryPath,
35 IN LPCSTR HiveName)
36 {
37 ULONG FileId;
38 CHAR FullHiveName[256];
39 ARC_STATUS Status;
40 FILEINFORMATION FileInfo;
41 ULONG HiveFileSize;
42 ULONG_PTR HiveDataPhysical;
43 PVOID HiveDataVirtual;
44 ULONG BytesRead;
45 LPCWSTR FsService;
46
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)
53 {
54 UiMessageBox("Opening hive file failed!");
55 return FALSE;
56 }
57
58 /* Get the file length */
59 Status = ArcGetFileInformation(FileId, &FileInfo);
60 if (Status != ESUCCESS)
61 {
62 ArcClose(FileId);
63 UiMessageBox("Hive file has 0 size!");
64 return FALSE;
65 }
66 HiveFileSize = FileInfo.EndingAddress.LowPart;
67
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,
71 LoaderRegistryData);
72
73 if (HiveDataPhysical == 0)
74 {
75 ArcClose(FileId);
76 UiMessageBox("Unable to alloc memory for a hive!");
77 return FALSE;
78 }
79
80 /* Convert address to virtual */
81 HiveDataVirtual = PaToVa((PVOID)HiveDataPhysical);
82
83 /* Fill LoaderBlock's entries */
84 LoaderBlock->RegistryLength = HiveFileSize;
85 LoaderBlock->RegistryBase = HiveDataVirtual;
86
87 /* Finally read from file to the memory */
88 Status = ArcRead(FileId, (PVOID)HiveDataPhysical, HiveFileSize, &BytesRead);
89 if (Status != ESUCCESS)
90 {
91 ArcClose(FileId);
92 UiMessageBox("Unable to read from hive file!");
93 return FALSE;
94 }
95
96 // Add boot filesystem driver to the list
97 FsService = FsGetServiceName(FileId);
98 if (FsService)
99 {
100 BOOLEAN Success;
101 TRACE(" Adding filesystem service %S\n", FsService);
102 Success = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead,
103 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
104 NULL,
105 (LPWSTR)FsService);
106 if (!Success)
107 TRACE(" Failed to add filesystem service\n");
108 }
109 else
110 {
111 TRACE(" No required filesystem service\n");
112 }
113
114 ArcClose(FileId);
115 return TRUE;
116 }
117
118 BOOLEAN WinLdrInitSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
119 IN LPCSTR DirectoryPath)
120 {
121 CHAR SearchPath[1024];
122 BOOLEAN Success;
123
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
126
127 // FIXME: For now we only try system
128 strcpy(SearchPath, DirectoryPath);
129 strcat(SearchPath, "SYSTEM32\\CONFIG\\");
130 Success = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");
131
132 // Fail if failed...
133 if (!Success)
134 return FALSE;
135
136 // Initialize in-memory registry
137 RegInitializeRegistry();
138
139 // Import what was loaded
140 Success = RegImportBinaryHive((PCHAR)VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
141 if (!Success)
142 {
143 UiMessageBox("Importing binary hive failed!");
144 return FALSE;
145 }
146
147 // Initialize the 'CurrentControlSet' link
148 if (RegInitCurrentControlSet(FALSE) != ERROR_SUCCESS)
149 {
150 UiMessageBox("Initializing CurrentControlSet link failed!");
151 return FALSE;
152 }
153
154 return TRUE;
155 }
156
157 BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
158 IN LPCSTR DirectoryPath)
159 {
160 CHAR SearchPath[1024];
161 CHAR AnsiName[256], OemName[256], LangName[256];
162 BOOLEAN Success;
163
164 // Scan registry and prepare boot drivers list
165 WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, DirectoryPath);
166
167 // Get names of NLS files
168 Success = WinLdrGetNLSNames(AnsiName, OemName, LangName);
169 if (!Success)
170 {
171 UiMessageBox("Getting NLS names from registry failed!");
172 return FALSE;
173 }
174
175 TRACE("NLS data %s %s %s\n", AnsiName, OemName, LangName);
176
177 // Load NLS data
178 strcpy(SearchPath, DirectoryPath);
179 strcat(SearchPath, "SYSTEM32\\");
180 Success = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
181 TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
182
183 /* TODO: Load OEM HAL font */
184
185
186 return TRUE;
187 }
188
189
190 /* PRIVATE FUNCTIONS ******************************************************/
191
192 // Queries registry for those three file names
193 static BOOLEAN
194 WinLdrGetNLSNames(LPSTR AnsiName,
195 LPSTR OemName,
196 LPSTR LangName)
197 {
198 LONG rc = ERROR_SUCCESS;
199 HKEY hKey;
200 WCHAR szIdBuffer[80];
201 WCHAR NameBuffer[80];
202 ULONG BufferSize;
203
204 /* open the codepage key */
205 rc = RegOpenKey(NULL,
206 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
207 &hKey);
208 if (rc != ERROR_SUCCESS)
209 {
210 //strcpy(szErrorOut, "Couldn't open CodePage registry key");
211 return FALSE;
212 }
213
214 /* get ANSI codepage */
215 BufferSize = sizeof(szIdBuffer);
216 rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
217 if (rc != ERROR_SUCCESS)
218 {
219 //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
220 return FALSE;
221 }
222
223 BufferSize = sizeof(NameBuffer);
224 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
225 if (rc != ERROR_SUCCESS)
226 {
227 //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
228 //return FALSE;
229 wcscpy(NameBuffer, L"c_1252.nls"); // HACK: ReactOS bug #6727
230 }
231 sprintf(AnsiName, "%S", NameBuffer);
232
233 /* get OEM codepage */
234 BufferSize = sizeof(szIdBuffer);
235 rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
236 if (rc != ERROR_SUCCESS)
237 {
238 //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
239 return FALSE;
240 }
241
242 BufferSize = sizeof(NameBuffer);
243 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
244 if (rc != ERROR_SUCCESS)
245 {
246 //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
247 //return FALSE;
248 wcscpy(NameBuffer, L"c_437.nls"); // HACK: ReactOS bug #6727
249 }
250 sprintf(OemName, "%S", NameBuffer);
251
252 /* open the language key */
253 rc = RegOpenKey(NULL,
254 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
255 &hKey);
256 if (rc != ERROR_SUCCESS)
257 {
258 //strcpy(szErrorOut, "Couldn't open Language registry key");
259 return FALSE;
260 }
261
262 /* get the Unicode case table */
263 BufferSize = sizeof(szIdBuffer);
264 rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
265 if (rc != ERROR_SUCCESS)
266 {
267 //strcpy(szErrorOut, "Couldn't get Language Default setting");
268 return FALSE;
269 }
270
271 BufferSize = sizeof(NameBuffer);
272 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
273 if (rc != ERROR_SUCCESS)
274 {
275 //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
276 return FALSE;
277 }
278 sprintf(LangName, "%S", NameBuffer);
279
280 return TRUE;
281 }
282
283 BOOLEAN
284 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
285 IN LPCSTR DirectoryPath,
286 IN LPCSTR AnsiFileName,
287 IN LPCSTR OemFileName,
288 IN LPCSTR LanguageFileName)
289 {
290 CHAR FileName[255];
291 ULONG AnsiFileId;
292 ULONG OemFileId;
293 ULONG LanguageFileId;
294 ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
295 ULONG TotalSize;
296 ULONG_PTR NlsDataBase;
297 PVOID NlsVirtual;
298 BOOLEAN AnsiEqualsOem = FALSE;
299 FILEINFORMATION FileInfo;
300 ULONG BytesRead;
301 ARC_STATUS Status;
302
303 /* There may be a case, when OEM and ANSI page coincide */
304 if (!strcmp(AnsiFileName, OemFileName))
305 AnsiEqualsOem = TRUE;
306
307 /* Open file with ANSI and store its size */
308 //Print(L"Loading %s...\n", Filename);
309 strcpy(FileName, DirectoryPath);
310 strcat(FileName, AnsiFileName);
311 Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
312 if (Status != ESUCCESS)
313 goto Failure;
314
315 Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
316 if (Status != ESUCCESS)
317 goto Failure;
318 AnsiFileSize = FileInfo.EndingAddress.LowPart;
319 TRACE("AnsiFileSize: %d\n", AnsiFileSize);
320 ArcClose(AnsiFileId);
321
322 /* Open OEM file and store its length */
323 if (AnsiEqualsOem)
324 {
325 OemFileSize = 0;
326 }
327 else
328 {
329 //Print(L"Loading %s...\n", Filename);
330 strcpy(FileName, DirectoryPath);
331 strcat(FileName, OemFileName);
332 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
333 if (Status != ESUCCESS)
334 goto Failure;
335
336 Status = ArcGetFileInformation(OemFileId, &FileInfo);
337 if (Status != ESUCCESS)
338 goto Failure;
339 OemFileSize = FileInfo.EndingAddress.LowPart;
340 ArcClose(OemFileId);
341 }
342 TRACE("OemFileSize: %d\n", OemFileSize);
343
344 /* And finally open the language codepage file and store its length */
345 //Print(L"Loading %s...\n", Filename);
346 strcpy(FileName, DirectoryPath);
347 strcat(FileName, LanguageFileName);
348 Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId);
349 if (Status != ESUCCESS)
350 goto Failure;
351
352 Status = ArcGetFileInformation(LanguageFileId, &FileInfo);
353 if (Status != ESUCCESS)
354 goto Failure;
355 LanguageFileSize = FileInfo.EndingAddress.LowPart;
356 ArcClose(LanguageFileId);
357 TRACE("LanguageFileSize: %d\n", LanguageFileSize);
358
359 /* Sum up all three length, having in mind that every one of them
360 must start at a page boundary => thus round up each file to a page */
361 TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
362 MM_SIZE_TO_PAGES(OemFileSize) +
363 MM_SIZE_TO_PAGES(LanguageFileSize);
364
365 /* Store it for later marking the pages as NlsData type */
366 TotalNLSSize = TotalSize;
367
368 NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
369
370 if (NlsDataBase == 0)
371 goto Failure;
372
373 NlsVirtual = PaToVa((PVOID)NlsDataBase);
374 LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
375 LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual +
376 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
377 LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual +
378 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
379 (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
380
381 /* Ansi and OEM data are the same - just set pointers to the same area */
382 if (AnsiEqualsOem)
383 LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
384
385
386 /* Now actually read the data into memory, starting with Ansi file */
387 strcpy(FileName, DirectoryPath);
388 strcat(FileName, AnsiFileName);
389 Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
390 if (Status != ESUCCESS)
391 goto Failure;
392
393 Status = ArcRead(AnsiFileId, VaToPa(LoaderBlock->NlsData->AnsiCodePageData), AnsiFileSize, &BytesRead);
394 if (Status != ESUCCESS)
395 goto Failure;
396
397 ArcClose(AnsiFileId);
398
399 /* OEM now, if it doesn't equal Ansi of course */
400 if (!AnsiEqualsOem)
401 {
402 strcpy(FileName, DirectoryPath);
403 strcat(FileName, OemFileName);
404 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
405 if (Status != ESUCCESS)
406 goto Failure;
407
408 Status = ArcRead(OemFileId, VaToPa(LoaderBlock->NlsData->OemCodePageData), OemFileSize, &BytesRead);
409 if (Status != ESUCCESS)
410 goto Failure;
411
412 ArcClose(OemFileId);
413 }
414
415 /* finally the language file */
416 strcpy(FileName, DirectoryPath);
417 strcat(FileName, LanguageFileName);
418 Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId);
419 if (Status != ESUCCESS)
420 goto Failure;
421
422 Status = ArcRead(LanguageFileId, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData), LanguageFileSize, &BytesRead);
423 if (Status != ESUCCESS)
424 goto Failure;
425
426 ArcClose(LanguageFileId);
427
428 //
429 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
430 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
431 //
432 LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
433
434 /* Convert NlsTables address to VA */
435 LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
436
437 return TRUE;
438
439 Failure:
440 UiMessageBox("Error reading NLS file %s", FileName);
441 return FALSE;
442 }
443
444 static VOID
445 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
446 IN LPCSTR DirectoryPath)
447 {
448 LONG rc = 0;
449 HKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey;
450 LPWSTR GroupNameBuffer;
451 WCHAR ServiceName[256];
452 ULONG OrderList[128];
453 ULONG BufferSize;
454 ULONG Index;
455 ULONG TagIndex;
456 LPWSTR GroupName;
457
458 ULONG ValueSize;
459 ULONG ValueType;
460 ULONG StartValue;
461 ULONG TagValue;
462 WCHAR DriverGroup[256];
463 ULONG DriverGroupSize;
464
465 CHAR ImagePath[256];
466 WCHAR TempImagePath[256];
467
468 BOOLEAN Success;
469
470 /* get 'service group order' key */
471 rc = RegOpenKey(NULL,
472 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
473 &hGroupKey);
474 if (rc != ERROR_SUCCESS) {
475
476 TRACE_CH(REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc);
477 return;
478 }
479
480 /* get 'group order list' key */
481 rc = RegOpenKey(NULL,
482 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
483 &hOrderKey);
484 if (rc != ERROR_SUCCESS) {
485
486 TRACE_CH(REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc);
487 return;
488 }
489
490 /* enumerate drivers */
491 rc = RegOpenKey(NULL,
492 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
493 &hServiceKey);
494 if (rc != ERROR_SUCCESS) {
495
496 TRACE_CH(REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc);
497 return;
498 }
499
500 /* Get the Name Group */
501 BufferSize = 4096;
502 GroupNameBuffer = FrLdrHeapAlloc(BufferSize, TAG_WLDR_NAME);
503 rc = RegQueryValue(hGroupKey, L"List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize);
504 TRACE_CH(REACTOS, "RegQueryValue(): rc %d\n", (int)rc);
505 if (rc != ERROR_SUCCESS)
506 return;
507 TRACE_CH(REACTOS, "BufferSize: %d \n", (int)BufferSize);
508 TRACE_CH(REACTOS, "GroupNameBuffer: '%S' \n", GroupNameBuffer);
509
510 /* Loop through each group */
511 GroupName = GroupNameBuffer;
512 while (*GroupName)
513 {
514 TRACE("Driver group: '%S'\n", GroupName);
515
516 /* Query the Order */
517 BufferSize = sizeof(OrderList);
518 rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize);
519 if (rc != ERROR_SUCCESS) OrderList[0] = 0;
520
521 /* enumerate all drivers */
522 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++)
523 {
524 Index = 0;
525
526 while (TRUE)
527 {
528 /* Get the Driver's Name */
529 ValueSize = sizeof(ServiceName);
530 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey);
531 TRACE("RegEnumKey(): rc %d\n", (int)rc);
532
533 /* Make sure it's valid, and check if we're done */
534 if (rc == ERROR_NO_MORE_ITEMS)
535 break;
536 if (rc != ERROR_SUCCESS)
537 {
538 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
539 return;
540 }
541 //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName);
542
543 /* Read the Start Value */
544 ValueSize = sizeof(ULONG);
545 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
546 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
547 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
548
549 /* Read the Tag */
550 ValueSize = sizeof(ULONG);
551 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
552 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
553 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
554
555 /* Read the driver's group */
556 DriverGroupSize = sizeof(DriverGroup);
557 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
558 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
559
560 /* Make sure it should be started */
561 if ((StartValue == 0) &&
562 (TagValue == OrderList[TagIndex]) &&
563 (_wcsicmp(DriverGroup, GroupName) == 0))
564 {
565 /* Get the Driver's Location */
566 ValueSize = sizeof(TempImagePath);
567 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
568
569 /* Write the whole path if it suceeded, else prepare to fail */
570 if (rc != ERROR_SUCCESS)
571 {
572 TRACE_CH(REACTOS, "ImagePath: not found\n");
573 TempImagePath[0] = 0;
574 sprintf(ImagePath, "%s\\system32\\drivers\\%S.sys", DirectoryPath, ServiceName);
575 }
576 else if (TempImagePath[0] != L'\\')
577 {
578 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
579 }
580 else
581 {
582 sprintf(ImagePath, "%S", TempImagePath);
583 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
584 }
585
586 TRACE("Adding boot driver: '%s'\n", ImagePath);
587
588 Success = WinLdrAddDriverToList(BootDriverListHead,
589 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
590 TempImagePath,
591 ServiceName);
592 if (!Success)
593 ERR("Failed to add boot driver\n");
594 }
595 else
596 {
597 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n",
598 // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName);
599 }
600
601 Index++;
602 }
603 }
604
605 Index = 0;
606 while (TRUE)
607 {
608 /* Get the Driver's Name */
609 ValueSize = sizeof(ServiceName);
610 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey);
611
612 //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc);
613 if (rc == ERROR_NO_MORE_ITEMS)
614 break;
615 if (rc != ERROR_SUCCESS)
616 {
617 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
618 return;
619 }
620 TRACE("Service %d: '%S'\n", (int)Index, ServiceName);
621
622 /* Read the Start Value */
623 ValueSize = sizeof(ULONG);
624 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
625 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
626 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
627
628 /* Read the Tag */
629 ValueSize = sizeof(ULONG);
630 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
631 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
632 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
633
634 /* Read the driver's group */
635 DriverGroupSize = sizeof(DriverGroup);
636 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
637 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
638
639 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++)
640 {
641 if (TagValue == OrderList[TagIndex]) break;
642 }
643
644 if ((StartValue == 0) &&
645 (TagIndex > OrderList[0]) &&
646 (_wcsicmp(DriverGroup, GroupName) == 0))
647 {
648 ValueSize = sizeof(TempImagePath);
649 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
650 if (rc != ERROR_SUCCESS)
651 {
652 TRACE_CH(REACTOS, "ImagePath: not found\n");
653 TempImagePath[0] = 0;
654 sprintf(ImagePath, "%ssystem32\\drivers\\%S.sys", DirectoryPath, ServiceName);
655 }
656 else if (TempImagePath[0] != L'\\')
657 {
658 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
659 }
660 else
661 {
662 sprintf(ImagePath, "%S", TempImagePath);
663 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
664 }
665 TRACE(" Adding boot driver: '%s'\n", ImagePath);
666
667 Success = WinLdrAddDriverToList(BootDriverListHead,
668 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
669 TempImagePath,
670 ServiceName);
671 if (!Success)
672 ERR(" Failed to add boot driver\n");
673 }
674 else
675 {
676 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
677 // ServiceName, StartValue, TagValue, DriverGroup, GroupName);
678 }
679
680 Index++;
681 }
682
683 /* Move to the next group name */
684 GroupName = GroupName + wcslen(GroupName) + 1;
685 }
686
687 /* Free allocated memory */
688 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
689 }
690
691 BOOLEAN
692 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
693 LPWSTR RegistryPath,
694 LPWSTR ImagePath,
695 LPWSTR ServiceName)
696 {
697 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry;
698 NTSTATUS Status;
699 USHORT PathLength;
700
701 BootDriverEntry = FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY), TAG_WLDR_BDE);
702
703 if (!BootDriverEntry)
704 return FALSE;
705
706 // DTE will be filled during actual load of the driver
707 BootDriverEntry->LdrEntry = NULL;
708
709 // Check - if we have a valid ImagePath, if not - we need to build it
710 // like "System32\\Drivers\\blah.sys"
711 if (ImagePath && (wcslen(ImagePath) > 0))
712 {
713 // Just copy ImagePath to the corresponding field in the structure
714 PathLength = (USHORT)wcslen(ImagePath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
715
716 BootDriverEntry->FilePath.Length = 0;
717 BootDriverEntry->FilePath.MaximumLength = PathLength;
718 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
719
720 if (!BootDriverEntry->FilePath.Buffer)
721 {
722 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
723 return FALSE;
724 }
725
726 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath);
727 if (!NT_SUCCESS(Status))
728 {
729 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
730 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
731 return FALSE;
732 }
733 }
734 else
735 {
736 // we have to construct ImagePath ourselves
737 PathLength = (USHORT)wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");
738 BootDriverEntry->FilePath.Length = 0;
739 BootDriverEntry->FilePath.MaximumLength = PathLength;
740 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
741
742 if (!BootDriverEntry->FilePath.Buffer)
743 {
744 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
745 return FALSE;
746 }
747
748 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\");
749 if (!NT_SUCCESS(Status))
750 {
751 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
752 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
753 return FALSE;
754 }
755
756 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName);
757 if (!NT_SUCCESS(Status))
758 {
759 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
760 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
761 return FALSE;
762 }
763
764 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys");
765 if (!NT_SUCCESS(Status))
766 {
767 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
768 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
769 return FALSE;
770 }
771 }
772
773 // Add registry path
774 PathLength = (USHORT)(wcslen(RegistryPath) + wcslen(ServiceName))*sizeof(WCHAR) + sizeof(UNICODE_NULL);
775 BootDriverEntry->RegistryPath.Length = 0;
776 BootDriverEntry->RegistryPath.MaximumLength = PathLength;
777 BootDriverEntry->RegistryPath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
778 if (!BootDriverEntry->RegistryPath.Buffer)
779 return FALSE;
780
781 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, RegistryPath);
782 if (!NT_SUCCESS(Status))
783 return FALSE;
784
785 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName);
786 if (!NT_SUCCESS(Status))
787 return FALSE;
788
789 // Insert entry at top of the list
790 InsertTailList(BootDriverListHead, &BootDriverEntry->Link);
791
792 return TRUE;
793 }