b280250142f0458600a64cbd73600adb248914f8
[reactos.git] / boot / freeldr / freeldr / ntldr / 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 // Import what was loaded
137 Success = RegImportBinaryHive(VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
138 if (!Success)
139 {
140 UiMessageBox("Importing binary hive failed!");
141 return FALSE;
142 }
143
144 // Initialize the 'CurrentControlSet' link
145 if (RegInitCurrentControlSet(FALSE) != ERROR_SUCCESS)
146 {
147 UiMessageBox("Initializing CurrentControlSet link failed!");
148 return FALSE;
149 }
150
151 return TRUE;
152 }
153
154 BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
155 IN LPCSTR DirectoryPath)
156 {
157 CHAR SearchPath[1024];
158 CHAR AnsiName[256], OemName[256], LangName[256];
159 BOOLEAN Success;
160
161 // Scan registry and prepare boot drivers list
162 WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, DirectoryPath);
163
164 // Get names of NLS files
165 Success = WinLdrGetNLSNames(AnsiName, OemName, LangName);
166 if (!Success)
167 {
168 UiMessageBox("Getting NLS names from registry failed!");
169 return FALSE;
170 }
171
172 TRACE("NLS data %s %s %s\n", AnsiName, OemName, LangName);
173
174 // Load NLS data
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");
179
180 /* TODO: Load OEM HAL font */
181
182 return TRUE;
183 }
184
185
186 /* PRIVATE FUNCTIONS ******************************************************/
187
188 // Queries registry for those three file names
189 static BOOLEAN
190 WinLdrGetNLSNames(LPSTR AnsiName,
191 LPSTR OemName,
192 LPSTR LangName)
193 {
194 LONG rc = ERROR_SUCCESS;
195 HKEY hKey;
196 WCHAR szIdBuffer[80];
197 WCHAR NameBuffer[80];
198 ULONG BufferSize;
199
200 /* open the codepage key */
201 rc = RegOpenKey(NULL,
202 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
203 &hKey);
204 if (rc != ERROR_SUCCESS)
205 {
206 //strcpy(szErrorOut, "Couldn't open CodePage registry key");
207 return FALSE;
208 }
209
210 /* get ANSI codepage */
211 BufferSize = sizeof(szIdBuffer);
212 rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
213 if (rc != ERROR_SUCCESS)
214 {
215 //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
216 return FALSE;
217 }
218
219 BufferSize = sizeof(NameBuffer);
220 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
221 if (rc != ERROR_SUCCESS)
222 {
223 //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
224 //return FALSE;
225 wcscpy(NameBuffer, L"c_1252.nls"); // HACK: ReactOS bug CORE-6105
226 }
227 sprintf(AnsiName, "%S", NameBuffer);
228
229 /* get OEM codepage */
230 BufferSize = sizeof(szIdBuffer);
231 rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
232 if (rc != ERROR_SUCCESS)
233 {
234 //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
235 return FALSE;
236 }
237
238 BufferSize = sizeof(NameBuffer);
239 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
240 if (rc != ERROR_SUCCESS)
241 {
242 //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
243 //return FALSE;
244 wcscpy(NameBuffer, L"c_437.nls"); // HACK: ReactOS bug CORE-6105
245 }
246 sprintf(OemName, "%S", NameBuffer);
247
248 /* open the language key */
249 rc = RegOpenKey(NULL,
250 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
251 &hKey);
252 if (rc != ERROR_SUCCESS)
253 {
254 //strcpy(szErrorOut, "Couldn't open Language registry key");
255 return FALSE;
256 }
257
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)
262 {
263 //strcpy(szErrorOut, "Couldn't get Language Default setting");
264 return FALSE;
265 }
266
267 BufferSize = sizeof(NameBuffer);
268 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
269 if (rc != ERROR_SUCCESS)
270 {
271 //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
272 return FALSE;
273 }
274 sprintf(LangName, "%S", NameBuffer);
275
276 return TRUE;
277 }
278
279 BOOLEAN
280 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
281 IN LPCSTR DirectoryPath,
282 IN LPCSTR AnsiFileName,
283 IN LPCSTR OemFileName,
284 IN LPCSTR LanguageFileName)
285 {
286 CHAR FileName[255];
287 ULONG AnsiFileId;
288 ULONG OemFileId;
289 ULONG LanguageFileId;
290 ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
291 ULONG TotalSize;
292 ULONG_PTR NlsDataBase;
293 PVOID NlsVirtual;
294 BOOLEAN AnsiEqualsOem = FALSE;
295 FILEINFORMATION FileInfo;
296 ULONG BytesRead;
297 ARC_STATUS Status;
298
299 /* There may be a case, when OEM and ANSI page coincide */
300 if (!strcmp(AnsiFileName, OemFileName))
301 AnsiEqualsOem = TRUE;
302
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)
309 goto Failure;
310
311 Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
312 if (Status != ESUCCESS)
313 goto Failure;
314 AnsiFileSize = FileInfo.EndingAddress.LowPart;
315 TRACE("AnsiFileSize: %d\n", AnsiFileSize);
316 ArcClose(AnsiFileId);
317
318 /* Open OEM file and store its length */
319 if (AnsiEqualsOem)
320 {
321 OemFileSize = 0;
322 }
323 else
324 {
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)
330 goto Failure;
331
332 Status = ArcGetFileInformation(OemFileId, &FileInfo);
333 if (Status != ESUCCESS)
334 goto Failure;
335 OemFileSize = FileInfo.EndingAddress.LowPart;
336 ArcClose(OemFileId);
337 }
338 TRACE("OemFileSize: %d\n", OemFileSize);
339
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)
346 goto Failure;
347
348 Status = ArcGetFileInformation(LanguageFileId, &FileInfo);
349 if (Status != ESUCCESS)
350 goto Failure;
351 LanguageFileSize = FileInfo.EndingAddress.LowPart;
352 ArcClose(LanguageFileId);
353 TRACE("LanguageFileSize: %d\n", LanguageFileSize);
354
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);
360
361 /* Store it for later marking the pages as NlsData type */
362 TotalNLSSize = TotalSize;
363
364 NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
365
366 if (NlsDataBase == 0)
367 goto Failure;
368
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));
376
377 /* Ansi and OEM data are the same - just set pointers to the same area */
378 if (AnsiEqualsOem)
379 LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
380
381
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)
387 goto Failure;
388
389 Status = ArcRead(AnsiFileId, VaToPa(LoaderBlock->NlsData->AnsiCodePageData), AnsiFileSize, &BytesRead);
390 if (Status != ESUCCESS)
391 goto Failure;
392
393 ArcClose(AnsiFileId);
394
395 /* OEM now, if it doesn't equal Ansi of course */
396 if (!AnsiEqualsOem)
397 {
398 strcpy(FileName, DirectoryPath);
399 strcat(FileName, OemFileName);
400 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
401 if (Status != ESUCCESS)
402 goto Failure;
403
404 Status = ArcRead(OemFileId, VaToPa(LoaderBlock->NlsData->OemCodePageData), OemFileSize, &BytesRead);
405 if (Status != ESUCCESS)
406 goto Failure;
407
408 ArcClose(OemFileId);
409 }
410
411 /* finally the language file */
412 strcpy(FileName, DirectoryPath);
413 strcat(FileName, LanguageFileName);
414 Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId);
415 if (Status != ESUCCESS)
416 goto Failure;
417
418 Status = ArcRead(LanguageFileId, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData), LanguageFileSize, &BytesRead);
419 if (Status != ESUCCESS)
420 goto Failure;
421
422 ArcClose(LanguageFileId);
423
424 //
425 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
426 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
427 //
428 LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
429
430 /* Convert NlsTables address to VA */
431 LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
432
433 return TRUE;
434
435 Failure:
436 UiMessageBox("Error reading NLS file %s", FileName);
437 return FALSE;
438 }
439
440 static VOID
441 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
442 IN LPCSTR DirectoryPath)
443 {
444 LONG rc = 0;
445 HKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey;
446 LPWSTR GroupNameBuffer;
447 WCHAR ServiceName[256];
448 ULONG OrderList[128];
449 ULONG BufferSize;
450 ULONG Index;
451 ULONG TagIndex;
452 LPWSTR GroupName;
453
454 ULONG ValueSize;
455 ULONG ValueType;
456 ULONG StartValue;
457 ULONG TagValue;
458 WCHAR DriverGroup[256];
459 ULONG DriverGroupSize;
460
461 CHAR ImagePath[256];
462 WCHAR TempImagePath[256];
463
464 BOOLEAN Success;
465
466 /* get 'service group order' key */
467 rc = RegOpenKey(NULL,
468 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
469 &hGroupKey);
470 if (rc != ERROR_SUCCESS) {
471
472 TRACE_CH(REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc);
473 return;
474 }
475
476 /* get 'group order list' key */
477 rc = RegOpenKey(NULL,
478 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
479 &hOrderKey);
480 if (rc != ERROR_SUCCESS) {
481
482 TRACE_CH(REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc);
483 return;
484 }
485
486 /* enumerate drivers */
487 rc = RegOpenKey(NULL,
488 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
489 &hServiceKey);
490 if (rc != ERROR_SUCCESS) {
491
492 TRACE_CH(REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc);
493 return;
494 }
495
496 /* Get the Name Group */
497 BufferSize = 4096;
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)
502 return;
503 TRACE_CH(REACTOS, "BufferSize: %d \n", (int)BufferSize);
504 TRACE_CH(REACTOS, "GroupNameBuffer: '%S' \n", GroupNameBuffer);
505
506 /* Loop through each group */
507 GroupName = GroupNameBuffer;
508 while (*GroupName)
509 {
510 TRACE("Driver group: '%S'\n", GroupName);
511
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;
516
517 /* enumerate all drivers */
518 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++)
519 {
520 Index = 0;
521
522 while (TRUE)
523 {
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);
528
529 /* Make sure it's valid, and check if we're done */
530 if (rc == ERROR_NO_MORE_ITEMS)
531 break;
532 if (rc != ERROR_SUCCESS)
533 {
534 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
535 return;
536 }
537 //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName);
538
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);
544
545 /* Read the Tag */
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);
550
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);
555
556 /* Make sure it should be started */
557 if ((StartValue == 0) &&
558 (TagValue == OrderList[TagIndex]) &&
559 (_wcsicmp(DriverGroup, GroupName) == 0))
560 {
561 /* Get the Driver's Location */
562 ValueSize = sizeof(TempImagePath);
563 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
564
565 /* Write the whole path if it succeeded, else prepare to fail */
566 if (rc != ERROR_SUCCESS)
567 {
568 TRACE_CH(REACTOS, "ImagePath: not found\n");
569 TempImagePath[0] = 0;
570 sprintf(ImagePath, "%s\\system32\\drivers\\%S.sys", DirectoryPath, ServiceName);
571 }
572 else if (TempImagePath[0] != L'\\')
573 {
574 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
575 }
576 else
577 {
578 sprintf(ImagePath, "%S", TempImagePath);
579 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
580 }
581
582 TRACE("Adding boot driver: '%s'\n", ImagePath);
583
584 Success = WinLdrAddDriverToList(BootDriverListHead,
585 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
586 TempImagePath,
587 ServiceName);
588 if (!Success)
589 ERR("Failed to add boot driver\n");
590 }
591 else
592 {
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);
595 }
596
597 Index++;
598 }
599 }
600
601 Index = 0;
602 while (TRUE)
603 {
604 /* Get the Driver's Name */
605 ValueSize = sizeof(ServiceName);
606 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey);
607
608 //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc);
609 if (rc == ERROR_NO_MORE_ITEMS)
610 break;
611 if (rc != ERROR_SUCCESS)
612 {
613 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
614 return;
615 }
616 TRACE("Service %d: '%S'\n", (int)Index, ServiceName);
617
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);
623
624 /* Read the Tag */
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);
629
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);
634
635 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++)
636 {
637 if (TagValue == OrderList[TagIndex]) break;
638 }
639
640 if ((StartValue == 0) &&
641 (TagIndex > OrderList[0]) &&
642 (_wcsicmp(DriverGroup, GroupName) == 0))
643 {
644 ValueSize = sizeof(TempImagePath);
645 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
646 if (rc != ERROR_SUCCESS)
647 {
648 TRACE_CH(REACTOS, "ImagePath: not found\n");
649 TempImagePath[0] = 0;
650 sprintf(ImagePath, "%ssystem32\\drivers\\%S.sys", DirectoryPath, ServiceName);
651 }
652 else if (TempImagePath[0] != L'\\')
653 {
654 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
655 }
656 else
657 {
658 sprintf(ImagePath, "%S", TempImagePath);
659 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
660 }
661 TRACE(" Adding boot driver: '%s'\n", ImagePath);
662
663 Success = WinLdrAddDriverToList(BootDriverListHead,
664 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
665 TempImagePath,
666 ServiceName);
667 if (!Success)
668 ERR(" Failed to add boot driver\n");
669 }
670 else
671 {
672 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
673 // ServiceName, StartValue, TagValue, DriverGroup, GroupName);
674 }
675
676 Index++;
677 }
678
679 /* Move to the next group name */
680 GroupName = GroupName + wcslen(GroupName) + 1;
681 }
682
683 /* Free allocated memory */
684 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
685 }
686
687 BOOLEAN
688 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
689 LPWSTR RegistryPath,
690 LPWSTR ImagePath,
691 LPWSTR ServiceName)
692 {
693 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry;
694 NTSTATUS Status;
695 USHORT PathLength;
696
697 BootDriverEntry = FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY), TAG_WLDR_BDE);
698
699 if (!BootDriverEntry)
700 return FALSE;
701
702 // DTE will be filled during actual load of the driver
703 BootDriverEntry->LdrEntry = NULL;
704
705 // Check - if we have a valid ImagePath, if not - we need to build it
706 // like "System32\\Drivers\\blah.sys"
707 if (ImagePath && (ImagePath[0] != 0))
708 {
709 // Just copy ImagePath to the corresponding field in the structure
710 PathLength = (USHORT)wcslen(ImagePath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
711
712 BootDriverEntry->FilePath.Length = 0;
713 BootDriverEntry->FilePath.MaximumLength = PathLength;
714 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
715
716 if (!BootDriverEntry->FilePath.Buffer)
717 {
718 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
719 return FALSE;
720 }
721
722 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath);
723 if (!NT_SUCCESS(Status))
724 {
725 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
726 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
727 return FALSE;
728 }
729 }
730 else
731 {
732 // we have to construct ImagePath ourselves
733 PathLength = (USHORT)wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");
734 BootDriverEntry->FilePath.Length = 0;
735 BootDriverEntry->FilePath.MaximumLength = PathLength;
736 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
737
738 if (!BootDriverEntry->FilePath.Buffer)
739 {
740 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
741 return FALSE;
742 }
743
744 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\");
745 if (!NT_SUCCESS(Status))
746 {
747 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
748 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
749 return FALSE;
750 }
751
752 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName);
753 if (!NT_SUCCESS(Status))
754 {
755 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
756 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
757 return FALSE;
758 }
759
760 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys");
761 if (!NT_SUCCESS(Status))
762 {
763 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
764 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
765 return FALSE;
766 }
767 }
768
769 // Add registry path
770 PathLength = (USHORT)(wcslen(RegistryPath) + wcslen(ServiceName))*sizeof(WCHAR) + sizeof(UNICODE_NULL);
771 BootDriverEntry->RegistryPath.Length = 0;
772 BootDriverEntry->RegistryPath.MaximumLength = PathLength;
773 BootDriverEntry->RegistryPath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
774 if (!BootDriverEntry->RegistryPath.Buffer)
775 return FALSE;
776
777 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, RegistryPath);
778 if (!NT_SUCCESS(Status))
779 return FALSE;
780
781 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName);
782 if (!NT_SUCCESS(Status))
783 return FALSE;
784
785 // Insert entry at top of the list
786 InsertTailList(BootDriverListHead, &BootDriverEntry->Link);
787
788 return TRUE;
789 }