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