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