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