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