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