[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: freeldr/winldr/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 <debug.h>
13
14 DBG_DEFAULT_CHANNEL(WINDOWS);
15
16 // The only global var here, used to mark mem pages as NLS in WinLdrSetupMemoryLayout()
17 ULONG TotalNLSSize = 0;
18
19 static BOOLEAN
20 WinLdrGetNLSNames(LPSTR AnsiName,
21 LPSTR OemName,
22 LPSTR LangName);
23
24 static VOID
25 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
26 IN LPCSTR DirectoryPath);
27
28
29 /* FUNCTIONS **************************************************************/
30
31 BOOLEAN
32 WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
33 IN LPCSTR DirectoryPath,
34 IN LPCSTR HiveName)
35 {
36 ULONG FileId;
37 CHAR FullHiveName[256];
38 LONG Status;
39 FILEINFORMATION FileInfo;
40 ULONG HiveFileSize;
41 ULONG_PTR HiveDataPhysical;
42 PVOID HiveDataVirtual;
43 ULONG BytesRead;
44 LPCWSTR FsService;
45
46 /* Concatenate path and filename to get the full name */
47 strcpy(FullHiveName, DirectoryPath);
48 strcat(FullHiveName, HiveName);
49 //Print(L"Loading %s...\n", FullHiveName);
50 Status = ArcOpen(FullHiveName, OpenReadOnly, &FileId);
51
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
61 if (Status != ESUCCESS)
62 {
63 ArcClose(FileId);
64 UiMessageBox("Hive file has 0 size!");
65 return FALSE;
66 }
67 HiveFileSize = FileInfo.EndingAddress.LowPart;
68
69 /* Round up the size to page boundary and alloc memory */
70 HiveDataPhysical = (ULONG_PTR)MmAllocateMemoryWithType(
71 MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT,
72 LoaderRegistryData);
73
74 if (HiveDataPhysical == 0)
75 {
76 ArcClose(FileId);
77 UiMessageBox("Unable to alloc memory for a hive!");
78 return FALSE;
79 }
80
81 /* Convert address to virtual */
82 HiveDataVirtual = PaToVa((PVOID)HiveDataPhysical);
83
84 /* Fill LoaderBlock's entries */
85 LoaderBlock->RegistryLength = HiveFileSize;
86 LoaderBlock->RegistryBase = HiveDataVirtual;
87
88 /* Finally read from file to the memory */
89 Status = ArcRead(FileId, (PVOID)HiveDataPhysical, HiveFileSize, &BytesRead);
90 if (Status != ESUCCESS)
91 {
92 ArcClose(FileId);
93 UiMessageBox("Unable to read from hive file!");
94 return FALSE;
95 }
96
97 // Add boot filesystem driver to the list
98 FsService = FsGetServiceName(FileId);
99 if (FsService)
100 {
101 TRACE(" Adding filesystem service %S\n", FsService);
102 Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead,
103 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
104 NULL,
105 (LPWSTR)FsService);
106 if (!Status)
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 Status;
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 Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");
131
132 // Fail if failed...
133 if (!Status)
134 return FALSE;
135
136 // Initialize in-memory registry
137 RegInitializeRegistry();
138
139 // Import what was loaded
140 Status = RegImportBinaryHive((PCHAR)VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
141 if (!Status)
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 Status;
163
164 // Scan registry and prepare boot drivers list
165 WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, DirectoryPath);
166
167 // Get names of NLS files
168 Status = WinLdrGetNLSNames(AnsiName, OemName, LangName);
169 if (!Status)
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 Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
181 TRACE("NLS data loaded with status %d\n", Status);
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 FRLDRHKEY 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
284 BOOLEAN
285 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
286 IN LPCSTR DirectoryPath,
287 IN LPCSTR AnsiFileName,
288 IN LPCSTR OemFileName,
289 IN LPCSTR LanguageFileName)
290 {
291 CHAR FileName[255];
292 ULONG AnsiFileId;
293 ULONG OemFileId;
294 ULONG LanguageFileId;
295 ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
296 ULONG TotalSize;
297 ULONG_PTR NlsDataBase;
298 PVOID NlsVirtual;
299 BOOLEAN AnsiEqualsOem = FALSE;
300 FILEINFORMATION FileInfo;
301 ULONG BytesRead, 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
313 if (Status != ESUCCESS)
314 goto Failure;
315
316 Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
317 if (Status != ESUCCESS)
318 goto Failure;
319 AnsiFileSize = FileInfo.EndingAddress.LowPart;
320 TRACE("AnsiFileSize: %d\n", AnsiFileSize);
321 ArcClose(AnsiFileId);
322
323 /* Open OEM file and store its length */
324 if (AnsiEqualsOem)
325 {
326 OemFileSize = 0;
327 }
328 else
329 {
330 //Print(L"Loading %s...\n", Filename);
331 strcpy(FileName, DirectoryPath);
332 strcat(FileName, OemFileName);
333 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
334
335 if (Status != ESUCCESS)
336 goto Failure;
337
338 Status = ArcGetFileInformation(OemFileId, &FileInfo);
339 if (Status != ESUCCESS)
340 goto Failure;
341 OemFileSize = FileInfo.EndingAddress.LowPart;
342 ArcClose(OemFileId);
343 }
344 TRACE("OemFileSize: %d\n", OemFileSize);
345
346 /* And finally open the language codepage file and store its length */
347 //Print(L"Loading %s...\n", Filename);
348 strcpy(FileName, DirectoryPath);
349 strcat(FileName, LanguageFileName);
350 Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId);
351
352 if (Status != ESUCCESS)
353 goto Failure;
354
355 Status = ArcGetFileInformation(LanguageFileId, &FileInfo);
356 if (Status != ESUCCESS)
357 goto Failure;
358 LanguageFileSize = FileInfo.EndingAddress.LowPart;
359 ArcClose(LanguageFileId);
360 TRACE("LanguageFileSize: %d\n", LanguageFileSize);
361
362 /* Sum up all three length, having in mind that every one of them
363 must start at a page boundary => thus round up each file to a page */
364 TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
365 MM_SIZE_TO_PAGES(OemFileSize) +
366 MM_SIZE_TO_PAGES(LanguageFileSize);
367
368 /* Store it for later marking the pages as NlsData type */
369 TotalNLSSize = TotalSize;
370
371 NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
372
373 if (NlsDataBase == 0)
374 goto Failure;
375
376 NlsVirtual = PaToVa((PVOID)NlsDataBase);
377 LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
378 LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual +
379 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
380 LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual +
381 (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
382 (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
383
384 /* Ansi and OEM data are the same - just set pointers to the same area */
385 if (AnsiEqualsOem)
386 LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
387
388
389 /* Now actually read the data into memory, starting with Ansi file */
390 strcpy(FileName, DirectoryPath);
391 strcat(FileName, AnsiFileName);
392 Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
393
394 if (Status != ESUCCESS)
395 goto Failure;
396
397 Status = ArcRead(AnsiFileId, VaToPa(LoaderBlock->NlsData->AnsiCodePageData), AnsiFileSize, &BytesRead);
398
399 if (Status != ESUCCESS)
400 goto Failure;
401
402 ArcClose(AnsiFileId);
403
404 /* OEM now, if it doesn't equal Ansi of course */
405 if (!AnsiEqualsOem)
406 {
407 strcpy(FileName, DirectoryPath);
408 strcat(FileName, OemFileName);
409 Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
410
411 if (Status != ESUCCESS)
412 goto Failure;
413
414 Status = ArcRead(OemFileId, VaToPa(LoaderBlock->NlsData->OemCodePageData), OemFileSize, &BytesRead);
415
416 if (Status != ESUCCESS)
417 goto Failure;
418
419 ArcClose(OemFileId);
420 }
421
422 /* finally the language file */
423 strcpy(FileName, DirectoryPath);
424 strcat(FileName, LanguageFileName);
425 Status = ArcOpen(FileName, OpenReadOnly, &LanguageFileId);
426
427 if (Status != ESUCCESS)
428 goto Failure;
429
430 Status = ArcRead(LanguageFileId, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData), LanguageFileSize, &BytesRead);
431
432 if (Status != ESUCCESS)
433 goto Failure;
434
435 ArcClose(LanguageFileId);
436
437 //
438 // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
439 // Should go to WinLdrLoadOemHalFont(), when it will be implemented
440 //
441 LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
442
443 /* Convert NlsTables address to VA */
444 LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
445
446 return TRUE;
447
448 Failure:
449 //UiMessageBox("Error reading NLS file %s\n", Filename);
450 UiMessageBox("Error reading NLS file!");
451 return FALSE;
452 }
453
454 static VOID
455 WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
456 IN LPCSTR DirectoryPath)
457 {
458 LONG rc = 0;
459 FRLDRHKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey;
460 LPWSTR GroupNameBuffer;
461 WCHAR ServiceName[256];
462 ULONG OrderList[128];
463 ULONG BufferSize;
464 ULONG Index;
465 ULONG TagIndex;
466 LPWSTR GroupName;
467
468 ULONG ValueSize;
469 ULONG ValueType;
470 ULONG StartValue;
471 ULONG TagValue;
472 WCHAR DriverGroup[256];
473 ULONG DriverGroupSize;
474
475 CHAR ImagePath[256];
476 WCHAR TempImagePath[256];
477
478 BOOLEAN Status;
479
480 /* get 'service group order' key */
481 rc = RegOpenKey(NULL,
482 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
483 &hGroupKey);
484 if (rc != ERROR_SUCCESS) {
485
486 TRACE_CH(REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc);
487 return;
488 }
489
490 /* get 'group order list' key */
491 rc = RegOpenKey(NULL,
492 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
493 &hOrderKey);
494 if (rc != ERROR_SUCCESS) {
495
496 TRACE_CH(REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc);
497 return;
498 }
499
500 /* enumerate drivers */
501 rc = RegOpenKey(NULL,
502 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
503 &hServiceKey);
504 if (rc != ERROR_SUCCESS) {
505
506 TRACE_CH(REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc);
507 return;
508 }
509
510 /* Get the Name Group */
511 BufferSize = 4096;
512 GroupNameBuffer = FrLdrHeapAlloc(BufferSize, TAG_WLDR_NAME);
513 rc = RegQueryValue(hGroupKey, L"List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize);
514 TRACE_CH(REACTOS, "RegQueryValue(): rc %d\n", (int)rc);
515 if (rc != ERROR_SUCCESS)
516 return;
517 TRACE_CH(REACTOS, "BufferSize: %d \n", (int)BufferSize);
518 TRACE_CH(REACTOS, "GroupNameBuffer: '%S' \n", GroupNameBuffer);
519
520 /* Loop through each group */
521 GroupName = GroupNameBuffer;
522 while (*GroupName)
523 {
524 TRACE("Driver group: '%S'\n", GroupName);
525
526 /* Query the Order */
527 BufferSize = sizeof(OrderList);
528 rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize);
529 if (rc != ERROR_SUCCESS) OrderList[0] = 0;
530
531 /* enumerate all drivers */
532 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++)
533 {
534 Index = 0;
535
536 while (TRUE)
537 {
538 /* Get the Driver's Name */
539 ValueSize = sizeof(ServiceName);
540 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey);
541 TRACE("RegEnumKey(): rc %d\n", (int)rc);
542
543 /* Make sure it's valid, and check if we're done */
544 if (rc == ERROR_NO_MORE_ITEMS)
545 break;
546 if (rc != ERROR_SUCCESS)
547 {
548 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
549 return;
550 }
551 //TRACE_CH(REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName);
552
553 /* Read the Start Value */
554 ValueSize = sizeof(ULONG);
555 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
556 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
557 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
558
559 /* Read the Tag */
560 ValueSize = sizeof(ULONG);
561 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
562 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
563 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
564
565 /* Read the driver's group */
566 DriverGroupSize = sizeof(DriverGroup);
567 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
568 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
569
570 /* Make sure it should be started */
571 if ((StartValue == 0) &&
572 (TagValue == OrderList[TagIndex]) &&
573 (_wcsicmp(DriverGroup, GroupName) == 0)) {
574
575 /* Get the Driver's Location */
576 ValueSize = sizeof(TempImagePath);
577 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
578
579 /* Write the whole path if it suceeded, else prepare to fail */
580 if (rc != ERROR_SUCCESS) {
581 TRACE_CH(REACTOS, "ImagePath: not found\n");
582 TempImagePath[0] = 0;
583 sprintf(ImagePath, "%s\\system32\\drivers\\%S.sys", DirectoryPath, ServiceName);
584 } else if (TempImagePath[0] != L'\\') {
585 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
586 } else {
587 sprintf(ImagePath, "%S", TempImagePath);
588 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
589 }
590
591 TRACE("Adding boot driver: '%s'\n", ImagePath);
592
593 Status = WinLdrAddDriverToList(BootDriverListHead,
594 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
595 TempImagePath,
596 ServiceName);
597
598 if (!Status)
599 ERR("Failed to add boot driver\n");
600 }
601 else
602 {
603 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n",
604 // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName);
605 }
606
607 Index++;
608 }
609 }
610
611 Index = 0;
612 while (TRUE)
613 {
614 /* Get the Driver's Name */
615 ValueSize = sizeof(ServiceName);
616 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize, &hDriverKey);
617
618 //TRACE_CH(REACTOS, "RegEnumKey(): rc %d\n", (int)rc);
619 if (rc == ERROR_NO_MORE_ITEMS)
620 break;
621 if (rc != ERROR_SUCCESS)
622 {
623 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
624 return;
625 }
626 TRACE("Service %d: '%S'\n", (int)Index, ServiceName);
627
628 /* Read the Start Value */
629 ValueSize = sizeof(ULONG);
630 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
631 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
632 //TRACE_CH(REACTOS, " Start: %x \n", (int)StartValue);
633
634 /* Read the Tag */
635 ValueSize = sizeof(ULONG);
636 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
637 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
638 //TRACE_CH(REACTOS, " Tag: %x \n", (int)TagValue);
639
640 /* Read the driver's group */
641 DriverGroupSize = sizeof(DriverGroup);
642 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
643 //TRACE_CH(REACTOS, " Group: '%S' \n", DriverGroup);
644
645 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) {
646 if (TagValue == OrderList[TagIndex]) break;
647 }
648
649 if ((StartValue == 0) &&
650 (TagIndex > OrderList[0]) &&
651 (_wcsicmp(DriverGroup, GroupName) == 0)) {
652
653 ValueSize = sizeof(TempImagePath);
654 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
655 if (rc != ERROR_SUCCESS) {
656 TRACE_CH(REACTOS, "ImagePath: not found\n");
657 TempImagePath[0] = 0;
658 sprintf(ImagePath, "%ssystem32\\drivers\\%S.sys", DirectoryPath, ServiceName);
659 } else if (TempImagePath[0] != L'\\') {
660 sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath);
661 } else {
662 sprintf(ImagePath, "%S", TempImagePath);
663 TRACE_CH(REACTOS, "ImagePath: '%s'\n", ImagePath);
664 }
665 TRACE(" Adding boot driver: '%s'\n", ImagePath);
666
667 Status = WinLdrAddDriverToList(BootDriverListHead,
668 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
669 TempImagePath,
670 ServiceName);
671
672 if (!Status)
673 ERR(" Failed to add boot driver\n");
674 }
675 else
676 {
677 //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
678 // ServiceName, StartValue, TagValue, DriverGroup, GroupName);
679 }
680
681 Index++;
682 }
683
684 /* Move to the next group name */
685 GroupName = GroupName + wcslen(GroupName) + 1;
686 }
687
688 /* Free allocated memory */
689 FrLdrHeapFree(GroupNameBuffer, TAG_WLDR_NAME);
690 }
691
692 BOOLEAN
693 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
694 LPWSTR RegistryPath,
695 LPWSTR ImagePath,
696 LPWSTR ServiceName)
697 {
698 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry;
699 NTSTATUS Status;
700 USHORT PathLength;
701
702 BootDriverEntry = FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY), TAG_WLDR_BDE);
703
704 if (!BootDriverEntry)
705 return FALSE;
706
707 // DTE will be filled during actual load of the driver
708 BootDriverEntry->LdrEntry = NULL;
709
710 // Check - if we have a valid ImagePath, if not - we need to build it
711 // like "System32\\Drivers\\blah.sys"
712 if (ImagePath && (wcslen(ImagePath) > 0))
713 {
714 // Just copy ImagePath to the corresponding field in the structure
715 PathLength = (USHORT)wcslen(ImagePath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
716
717 BootDriverEntry->FilePath.Length = 0;
718 BootDriverEntry->FilePath.MaximumLength = PathLength;
719 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
720
721 if (!BootDriverEntry->FilePath.Buffer)
722 {
723 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
724 return FALSE;
725 }
726
727 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath);
728 if (!NT_SUCCESS(Status))
729 {
730 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
731 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
732 return FALSE;
733 }
734 }
735 else
736 {
737 // we have to construct ImagePath ourselves
738 PathLength = (USHORT)wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");
739 BootDriverEntry->FilePath.Length = 0;
740 BootDriverEntry->FilePath.MaximumLength = PathLength;
741 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
742
743 if (!BootDriverEntry->FilePath.Buffer)
744 {
745 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
746 return FALSE;
747 }
748
749 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\");
750 if (!NT_SUCCESS(Status))
751 {
752 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
753 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
754 return FALSE;
755 }
756
757 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName);
758 if (!NT_SUCCESS(Status))
759 {
760 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
761 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
762 return FALSE;
763 }
764
765 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys");
766 if (!NT_SUCCESS(Status))
767 {
768 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
769 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
770 return FALSE;
771 }
772 }
773
774 // Add registry path
775 PathLength = (USHORT)(wcslen(RegistryPath) + wcslen(ServiceName))*sizeof(WCHAR) + sizeof(UNICODE_NULL);
776 BootDriverEntry->RegistryPath.Length = 0;
777 BootDriverEntry->RegistryPath.MaximumLength = PathLength;
778 BootDriverEntry->RegistryPath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
779 if (!BootDriverEntry->RegistryPath.Buffer)
780 return FALSE;
781
782 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, RegistryPath);
783 if (!NT_SUCCESS(Status))
784 return FALSE;
785
786 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName);
787 if (!NT_SUCCESS(Status))
788 return FALSE;
789
790 // Insert entry at top of the list
791 InsertTailList(BootDriverListHead, &BootDriverEntry->Link);
792
793 return TRUE;
794 }