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