Create the AHCI branch for Aman's work
[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
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 suceeded, 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 BOOLEAN
689 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
690 LPWSTR RegistryPath,
691 LPWSTR ImagePath,
692 LPWSTR ServiceName)
693 {
694 PBOOT_DRIVER_LIST_ENTRY BootDriverEntry;
695 NTSTATUS Status;
696 USHORT PathLength;
697
698 BootDriverEntry = FrLdrHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY), TAG_WLDR_BDE);
699
700 if (!BootDriverEntry)
701 return FALSE;
702
703 // DTE will be filled during actual load of the driver
704 BootDriverEntry->LdrEntry = NULL;
705
706 // Check - if we have a valid ImagePath, if not - we need to build it
707 // like "System32\\Drivers\\blah.sys"
708 if (ImagePath && (wcslen(ImagePath) > 0))
709 {
710 // Just copy ImagePath to the corresponding field in the structure
711 PathLength = (USHORT)wcslen(ImagePath) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
712
713 BootDriverEntry->FilePath.Length = 0;
714 BootDriverEntry->FilePath.MaximumLength = PathLength;
715 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
716
717 if (!BootDriverEntry->FilePath.Buffer)
718 {
719 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
720 return FALSE;
721 }
722
723 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath);
724 if (!NT_SUCCESS(Status))
725 {
726 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
727 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_BDE);
728 return FALSE;
729 }
730 }
731 else
732 {
733 // we have to construct ImagePath ourselves
734 PathLength = (USHORT)wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");
735 BootDriverEntry->FilePath.Length = 0;
736 BootDriverEntry->FilePath.MaximumLength = PathLength;
737 BootDriverEntry->FilePath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
738
739 if (!BootDriverEntry->FilePath.Buffer)
740 {
741 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
742 return FALSE;
743 }
744
745 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\");
746 if (!NT_SUCCESS(Status))
747 {
748 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
749 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
750 return FALSE;
751 }
752
753 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName);
754 if (!NT_SUCCESS(Status))
755 {
756 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
757 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
758 return FALSE;
759 }
760
761 Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys");
762 if (!NT_SUCCESS(Status))
763 {
764 FrLdrHeapFree(BootDriverEntry->FilePath.Buffer, TAG_WLDR_NAME);
765 FrLdrHeapFree(BootDriverEntry, TAG_WLDR_NAME);
766 return FALSE;
767 }
768 }
769
770 // Add registry path
771 PathLength = (USHORT)(wcslen(RegistryPath) + wcslen(ServiceName))*sizeof(WCHAR) + sizeof(UNICODE_NULL);
772 BootDriverEntry->RegistryPath.Length = 0;
773 BootDriverEntry->RegistryPath.MaximumLength = PathLength;
774 BootDriverEntry->RegistryPath.Buffer = FrLdrHeapAlloc(PathLength, TAG_WLDR_NAME);
775 if (!BootDriverEntry->RegistryPath.Buffer)
776 return FALSE;
777
778 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, RegistryPath);
779 if (!NT_SUCCESS(Status))
780 return FALSE;
781
782 Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName);
783 if (!NT_SUCCESS(Status))
784 return FALSE;
785
786 // Insert entry at top of the list
787 InsertTailList(BootDriverListHead, &BootDriverEntry->Link);
788
789 return TRUE;
790 }