ReactOS 0.4.16-dev-122-g325d74c
bootmgr.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI Boot Manager
4 * FILE: boot/environ/app/bootmgr/bootmgr.cla
5 * PURPOSE: Boot Manager Entrypoint
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include "bootmgr.h"
12
13/* DATA VARIABLES ************************************************************/
14
15DEFINE_GUID(GUID_WINDOWS_BOOTMGR,
16 0x9DEA862C,
17 0x5CDD,
18 0x4E70,
19 0xAC, 0xC1, 0xF3, 0x2B, 0x34, 0x4D, 0x47, 0x95);
20
25
29
33
39
40/* FUNCTIONS *****************************************************************/
41
44 _In_ HANDLE BcdHandle,
45 _In_ PGUID ObjectId,
47 )
48{
50 HANDLE ObjectHandle;
51 ULONG ElementSize, ElementCount, i, OptionsSize;
54 PBCD_ELEMENT BcdElements;
55 PBL_BCD_OPTION Options, Option, PreviousOption, DeviceOptions;
56 PBCD_DEVICE_OPTION DeviceOption;
57 GUID DeviceId;
59
60 /* Open the BCD object requested */
61 ObjectHandle = NULL;
62 BcdElements = NULL;
63 Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle);
64 if (!NT_SUCCESS(Status))
65 {
66 goto Quickie;
67 }
68
69 /* Do the initial enumeration to get the size needed */
70 ElementSize = 0;
72 ObjectHandle,
73 NULL,
74 &ElementSize,
75 &ElementCount);
77 {
78 /* If we got success, that doesn't make any sense */
79 if (NT_SUCCESS(Status))
80 {
82 }
83
84 /* Bail out */
85 goto Quickie;
86 }
87
88 /* Allocate a large-enough buffer */
89 BcdElements = BlMmAllocateHeap(ElementSize);
90 if (!BcdElements)
91 {
93 goto Quickie;
94 }
95
96 /* Now do the real enumeration to fill out the elements buffer */
98 ObjectHandle,
99 BcdElements,
100 &ElementSize,
101 &ElementCount);
102 if (!NT_SUCCESS(Status))
103 {
104 goto Quickie;
105 }
106
107 /* Go through each BCD option to add the sizes up */
108 OptionsSize = 0;
109 for (i = 0; i < ElementCount; i++)
110 {
111 OptionsSize += BcdElements[i].Header->Size + sizeof(BL_BCD_OPTION);
112 }
113
114 /* Allocate the required BCD option list */
115 Options = BlMmAllocateHeap(OptionsSize);
116 if (!Options)
117 {
119 goto Quickie;
120 }
121
122 /* Zero it out */
123 RtlZeroMemory(Options, OptionsSize);
124
125 /* Start going through each option */
126 PreviousOption = NULL;
127 Option = Options;
128 for (i = 0; i < ElementCount; i++)
129 {
130 /* Read the header and type */
131 Header = BcdElements[i].Header;
132 Type.PackedValue = Header->Type;
133
134 /* Check if this option isn't already present */
135 if (!MiscGetBootOption(Options, Type.PackedValue))
136 {
137 /* It's a new option. Did we have an existing one? */
138 if (PreviousOption)
139 {
140 /* Link it to this new one */
141 PreviousOption->NextEntryOffset = (ULONG_PTR)Option -
143 }
144
145 /* Capture the type, size, data, and offset */
146 Option->Type = Type.PackedValue;
147 Option->DataSize = Header->Size;
148 RtlCopyMemory(Option + 1, BcdElements[i].Body, Header->Size);
149 Option->DataOffset = sizeof(BL_BCD_OPTION);
150
151 /* Check if this was a device */
152 if (Type.Format == BCD_TYPE_DEVICE)
153 {
154 /* Grab its GUID */
155 DeviceOption = (PBCD_DEVICE_OPTION)(Option + 1);
156 DeviceId = DeviceOption->AssociatedEntry;
157
158 /* Look up the options for that GUID */
159 Status = BmGetOptionList(BcdHandle, &DeviceId, &DeviceOptions);
160 if (NT_SUCCESS(Status))
161 {
162 /* Device data is after the device option */
163 DeviceData = (PVOID)((ULONG_PTR)DeviceOption + Header->Size);
164
165 /* Copy it */
167 DeviceOptions,
168 BlGetBootOptionListSize(DeviceOptions));
169
170 /* Don't need this anymore */
171 BlMmFreeHeap(DeviceOptions);
172
173 /* Write the offset of the device options */
174 Option->ListOffset = (ULONG_PTR)DeviceData -
175 (ULONG_PTR)Option;
176 }
177 }
178
179 /* Save the previous option and go to the next one */
180 PreviousOption = Option;
181 Option = (PBL_BCD_OPTION)((ULONG_PTR)Option +
182 BlGetBootOptionSize(Option));
183 }
184 }
185
186 /* Return the pointer back, we've made it! */
189
190Quickie:
191 /* Did we allocate a local buffer? Free it if so */
192 if (BcdElements)
193 {
194 BlMmFreeHeap(BcdElements);
195 }
196
197 /* Was the key open? Close it if so */
198 if (ObjectHandle)
199 {
200 BiCloseKey(ObjectHandle);
201 }
202
203 /* Return the option list parsing status */
204 return Status;
205}
206
209 _In_ HANDLE BcdHandle
210 )
211{
214
215 /* Get the boot option list */
217 if (!NT_SUCCESS(Status))
218 {
219 return Status;
220 }
221
222 /* Append the options, free the local buffer, and return success */
225 return STATUS_SUCCESS;
226}
227
230 _In_ PUNICODE_STRING ApplicationDirectoryPath
231 )
232{
234 SIZE_T i, AppPathLength;
235 PWCHAR ApplicationPath, PathCopy;
236
237 /* Clear the incoming string */
238 ApplicationDirectoryPath->Length = 0;
239 ApplicationDirectoryPath->MaximumLength = 0;
240 ApplicationDirectoryPath->Buffer = 0;
241
242 /* Get the boot application path */
243 ApplicationPath = NULL;
246 &ApplicationPath);
247 if (NT_SUCCESS(Status))
248 {
249 /* Calculate the length of the application path */
250 for (i = wcslen(ApplicationPath) - 1; i > 0; i--)
251 {
252 /* Keep going until the path separator */
253 if (ApplicationPath[i] == OBJ_NAME_PATH_SEPARATOR)
254 {
255 break;
256 }
257 }
258
259 /* Check if we have space for one more character */
260 Status = RtlSIZETAdd(i, 1, &AppPathLength);
261 if (NT_SUCCESS(Status))
262 {
263 /* Check if it's safe to multiply by two */
264 Status = RtlSIZETMult(AppPathLength, sizeof(WCHAR), &AppPathLength);
265 if (NT_SUCCESS(Status))
266 {
267 /* Allocate a copy for the string */
268 PathCopy = BlMmAllocateHeap(AppPathLength);
269 if (PathCopy)
270 {
271 /* NULL-terminate it */
272 RtlCopyMemory(PathCopy,
273 ApplicationPath,
274 AppPathLength - sizeof(UNICODE_NULL));
275 PathCopy[AppPathLength] = UNICODE_NULL;
276
277 /* Finally, initialize the outgoing string */
278 RtlInitUnicodeString(ApplicationDirectoryPath, PathCopy);
279 }
280 else
281 {
282 /* No memory, fail */
284 }
285 }
286 }
287 }
288
289 /* Check if we had an application path */
290 if (ApplicationPath)
291 {
292 /* No longer need this, free it */
293 BlMmFreeHeap(ApplicationPath);
294 }
295
296 /* All done! */
297 return Status;
298}
299
302 VOID
303 )
304{
305 PWCHAR FinalPath;
307 PWCHAR BcdDirectory;
308 UNICODE_STRING BcdPath;
309 ULONG FinalSize;
311
312 /* Initialize everything for failure */
313 BcdPath.MaximumLength = 0;
314 BcdPath.Buffer = NULL;
315 BcdDirectory = NULL;
316 FinalPath = NULL;
317 FileHandle = -1;
318 DeviceHandle = -1;
319
320 /* Try to open the boot device */
323 0,
324 &DeviceHandle);
325 if (!NT_SUCCESS(Status))
326 {
327 EfiPrintf(L"Device open failed: %lx\r\n", Status);
328 goto Quickie;
329 }
330
331 /* Get the directory path */
333 BcdDirectory = BcdPath.Buffer;
334 if (!NT_SUCCESS(Status))
335 {
336 goto Quickie;
337 }
338
339 /* Add the BCD file name to it */
340 FinalSize = BcdPath.MaximumLength + sizeof(L"\\BCD") - sizeof(UNICODE_NULL);
341 if (FinalSize < BcdPath.MaximumLength)
342 {
343 goto Quickie;
344 }
345
346 /* Allocate space for the final path */
347 FinalPath = BlMmAllocateHeap(FinalSize);
348 if (!FinalPath)
349 {
350 goto Quickie;
351 }
352
353 /* Build it */
354 RtlZeroMemory(FinalPath, FinalSize);
355 RtlCopyMemory(FinalPath, BcdDirectory, BcdPath.MaximumLength);
356 wcsncat(FinalPath, L"\\BCD", FinalSize / sizeof(WCHAR));
357
358 /* Try to open the file */
360 FinalPath,
362 &FileHandle);
363 if (!NT_SUCCESS(Status))
364 {
365 BootDirectory = BcdDirectory;
366 goto Quickie;
367 }
368
369 /* Save the boot directory */
370 BootDirectory = L"\\EFI\\Boot"; /* Should be EFI\\ReactOS\\Boot */
371
372Quickie:
373 /* Free all the allocations we made */
374 if (BcdDirectory)
375 {
376 Status = BlMmFreeHeap(BcdDirectory);
377 }
378 if (FinalPath)
379 {
380 Status = BlMmFreeHeap(FinalPath);
381 }
382
383 /* Close the BCD file */
384 if (FileHandle != -1)
385 {
387 }
388
389 /* Close the boot device */
390 if (DeviceHandle != -1)
391 {
393 }
394
395 /* Return back to the caller */
396 return Status;
397}
398
401 VOID
402 )
403{
404 /* Don't yet handled boot.ini */
405 return STATUS_NOT_FOUND;
406}
407
408ULONG
410 _In_ NTSTATUS ErrorStatus,
411 _Out_ PULONG ErrorResourceId
412 )
413{
415
416 /* Assume no message for now, check for known status message */
417 Result = 0;
418 switch (ErrorStatus)
419 {
420 /* Convert each status to a resource ID */
422 *ErrorResourceId = 9017;
423 Result = 1;
424 break;
426 *ErrorResourceId = 9018;
427 break;
429 *ErrorResourceId = 9016;
430 break;
431 case 0xC0000428:
432 *ErrorResourceId = 9019;
433 Result = 2;
434 break;
436 *ErrorResourceId = 9013;
437 break;
438 }
439
440 /* Return the type of message */
441 return Result;
442}
443
444VOID
446 VOID
447 )
448{
449 /* Check if a boot error is present */
451 {
452 /* Purge it */
455 }
456
457 /* Zero out the packed buffer */
461}
462
463VOID
466 _In_ NTSTATUS ErrorStatus,
467 _In_ ULONG ErrorMsgId,
469 _In_ ULONG HelpMsgId
470 )
471{
472 PWCHAR ErrorMsgString;
473
474 /* Check if we already had an error */
476 {
477 /* Purge it */
478 BmErrorPurge();
479 }
480
481 /* Find the string for this error ID */
482 ErrorMsgString = BlResourceFindMessage(ErrorMsgId);
483 if (ErrorMsgString)
484 {
485 /* Fill out the error buffer */
488 BmpErrorBuffer.ErrorString = ErrorMsgString;
491 BmpErrorBuffer.ErrorStatus = ErrorStatus;
492 BmpErrorBuffer.HelpMsgId = HelpMsgId;
494 }
495}
496
497VOID
500 _In_ ULONG_PTR Parameter1,
501 _In_ ULONG_PTR Parameter2,
502 _In_ ULONG_PTR Parameter3,
503 _In_ ULONG_PTR Parameter4
504 )
505{
507 NTSTATUS ErrorStatus;
508 WCHAR FormatString[256];
509 ULONG ErrorResourceId, ErrorHelpId;
510 BOOLEAN Restart, NoError;
511
512 /* Assume no buffer for now */
513 Buffer = NULL;
514
515 /* Check what error code is being raised */
516 switch (ErrorCode)
517 {
518 /* Error reading the BCD */
520
521 /* Check if we have a name for the BCD file */
522 if (Parameter1)
523 {
524 /* Check if the name fits into our buffer */
525 FileName = (PWCHAR)Parameter1;
526 if (wcslen(FileName) < sizeof(BmpFileNameBuffer))
527 {
528 /* Copy it in there */
531 FileName,
533 }
534 }
535
536 /* If we don't have a buffer, use an empty one */
537 if (!Buffer)
538 {
540 }
541
542 /* The NTSTATUS code is in parameter 2*/
543 ErrorStatus = (NTSTATUS)Parameter2;
544
545 /* Build the error string */
547 L"\nAn error occurred (%08x) while attempting "
548 L"to read the boot configuration data file %s\n",
549 ErrorStatus,
550 Buffer);
551
552 /* Select the resource ID message */
553 ErrorResourceId = 9002;
554 break;
555
557
558 /* File name is in parameter 1 */
559 FileName = (PWCHAR)Parameter1;
560
561 /* The NTSTATUS code is in parameter 2*/
562 ErrorStatus = (NTSTATUS)Parameter2;
563
564 /* Build the error string */
566 L"\nNo valid entries found in the boot configuration data file %s\n",
567 FileName);
568
569 /* Select the resource ID message */
570 ErrorResourceId = 9007;
571 break;
572
574
575 /* File name isin parameter 1 */
576 FileName = (PWCHAR)Parameter1;
577
578 /* The NTSTATUS code is in parameter 2*/
579 ErrorStatus = (NTSTATUS)Parameter2;
580
581 /* Build the error string */
583 L"\nThe boot configuration file %s is invalid (%08x).\n",
584 FileName,
585 ErrorStatus);
586
587 /* Select the resource ID message */
588 ErrorResourceId = 9015;
589 break;
590
592
593 /* The NTSTATUS code is in parameter 1*/
594 ErrorStatus = (NTSTATUS)Parameter1;
595
596 /* Build the error string */
598 L"\nThe boot manager experienced an error (%08x).\n",
599 ErrorStatus);
600
601 /* Select the resource ID message */
602 ErrorResourceId = 9005;
603 break;
604
605 default:
606
607 /* The rest is not yet handled */
608 EfiPrintf(L"Unexpected fatal error: %lx\r\n", ErrorCode);
609 while (1);
610 break;
611 }
612
613 /* Check if the BCD option for restart is set */
616 &Restart);
617 if (Restart)
618 {
619 /* Yes, so no error should be shown since we'll auto-restart */
620 NoError = TRUE;
621 }
622 else
623 {
624 /* Check if the option for not showing errors is set in the BCD */
627 &NoError);
628 }
629
630 /* Do we want an error? */
631 if (!NoError)
632 {
633 /* Yep, print it and then raise an error */
635 BlStatusError(1, ErrorCode, Parameter1, Parameter2, Parameter3);
636 }
637
638 /* Get the help message ID */
639 ErrorHelpId = BmpFatalErrorMessageFilter(ErrorStatus, &ErrorResourceId);
640 BmpErrorLog(ErrorCode, ErrorStatus, ErrorResourceId, Buffer, ErrorHelpId);
641}
642
646 _Out_ PWCHAR* FullPath
647 )
648{
650 SIZE_T BootDirLength, PathLength;
651
652 /* Compute the length of the directory, and add a NUL */
653 BootDirLength = wcslen(BootDirectory);
654 Status = RtlSIZETAdd(BootDirLength, 1, &BootDirLength);
655 if (!NT_SUCCESS(Status))
656 {
657 goto Quickie;
658 }
659
660 /* Add the length of the file, make sure it fits */
662 Status = RtlSIZETAdd(PathLength, BootDirLength, &PathLength);
663 if (!NT_SUCCESS(Status))
664 {
665 goto Quickie;
666 }
667
668 /* Convert to bytes */
669 Status = RtlSIZETMult(PathLength, sizeof(WCHAR), &PathLength);
670 if (!NT_SUCCESS(Status))
671 {
672 goto Quickie;
673 }
674
675 /* Allocate the full path */
676 *FullPath = BlMmAllocateHeap(PathLength);
677 if (*FullPath)
678 {
679 /* Copy the directory followed by the file name */
680 wcsncpy(*FullPath, BootDirectory, PathLength / sizeof(WCHAR));
681 wcsncat(*FullPath, FileName, PathLength / sizeof(WCHAR));
682 }
683 else
684 {
685 /* Bail out since we have no memory */
687 }
688
689Quickie:
690 /* Return to caller */
691 return Status;
692}
693
694VOID
697 )
698{
699 /* Check if boot.ini data needs to be freed */
700 if (BmBootIniUsed)
701 {
702 EfiPrintf(L"Boot.ini not handled\r\n");
703 }
704
705 /* Dereference the hive and close the key */
708}
709
713 )
714{
716 PBL_DEVICE_DESCRIPTOR BcdDevice;
717 PWCHAR BcdPath, FullPath, PathBuffer;
718 BOOLEAN HavePath;
719 SIZE_T PathLength, FullSize;
720 PVOID FinalBuffer;
721 UNICODE_STRING BcdString;
722
723 /* Initialize variables */
724 PathBuffer = NULL;
725 BcdDevice = NULL;
726 BcdPath = NULL;
727 HavePath = FALSE;
728
729 /* Check if a boot.ini file exists */
731 if (NT_SUCCESS(Status))
732 {
734 }
735
736 /* Check on which device the BCD is */
739 &BcdDevice,
740 NULL);
741 if (!NT_SUCCESS(Status))
742 {
743 /* It's not on a custom device, so it must be where we are */
746 &BcdDevice,
747 NULL);
748 if (!NT_SUCCESS(Status))
749 {
750 /* This BCD option is required */
751 goto Quickie;
752 }
753 }
754
755 /* Next, check what file contains the BCD */
758 &BcdPath);
759 if (NT_SUCCESS(Status))
760 {
761 /* We don't handle custom BCDs yet */
762 EfiPrintf(L"Custom BCD Not handled: %s\r\n", BcdPath);
764 goto Quickie;
765 }
766
767 /* Now check if the BCD is on a remote share */
768 if (BcdDevice->DeviceType == UdpDevice)
769 {
770 /* Nope. Nope. Nope */
771 EfiPrintf(L"UDP device Not handled\r\n");
773 goto Quickie;
774 }
775
776 /* Otherwise, compute the hardcoded path of the BCD */
777 Status = BmpFwGetFullPath(L"\\BCD", &FullPath);
778 if (!NT_SUCCESS(Status))
779 {
780 /* User the raw path */
781 PathBuffer = BcdPath;
782 }
783 else
784 {
785 /* Use the path we got */
786 PathBuffer = FullPath;
787 HavePath = TRUE;
788 }
789
790 /* Check if we failed to get the BCD path */
791 if (!NT_SUCCESS(Status))
792 {
793 goto Quickie;
794 }
795
796 /* Add a NUL to the path, make sure it'll fit */
797 PathLength = wcslen(PathBuffer);
798 Status = RtlSIZETAdd(PathLength, 1, &PathLength);
799 if (!NT_SUCCESS(Status))
800 {
801 goto Quickie;
802 }
803
804 /* Convert to bytes */
805 Status = RtlSIZETMult(PathLength, sizeof(WCHAR), &PathLength);
806 if (!NT_SUCCESS(Status))
807 {
808 goto Quickie;
809 }
810
811 /* Now add the size of the path to the device path, check if it fits */
812 Status = RtlSIZETAdd(PathLength, BcdDevice->Size, &FullSize);
813 if (!NT_SUCCESS(Status))
814 {
815 goto Quickie;
816 }
817
818 /* Allocate a final structure to hold both entities */
819 FinalBuffer = BlMmAllocateHeap(FullSize);
820 if (!FinalBuffer)
821 {
823 goto Quickie;
824 }
825
826 /* Copy the device path and file path into the final buffer */
827 RtlCopyMemory(FinalBuffer, BcdDevice, BcdDevice->Size);
828 RtlCopyMemory((PVOID)((ULONG_PTR)FinalBuffer + BcdDevice->Size),
829 PathBuffer,
830 PathLength);
831
832 /* Now tell the BCD engine to open the store */
833 BcdString.Length = FullSize;
834 BcdString.MaximumLength = FullSize;
835 BcdString.Buffer = FinalBuffer;
836 Status = BcdOpenStoreFromFile(&BcdString, Handle);
837
838 /* Free our final buffer */
839 BlMmFreeHeap(FinalBuffer);
840
841Quickie:
842 /* Did we allocate a device? */
843 if (BcdDevice)
844 {
845 /* Free it */
846 BlMmFreeHeap(BcdDevice);
847 }
848
849 /* Is this the failure path? */
850 if (!NT_SUCCESS(Status))
851 {
852 /* Raise a fatal error */
854 (ULONG_PTR)PathBuffer,
855 Status,
856 0,
857 0);
858 }
859
860 /* Did we get an allocated path? */
861 if ((PathBuffer) && (HavePath))
862 {
863 /* Free it */
864 BlMmFreeHeap(PathBuffer);
865 }
866
867 /* Return back to the caller */
868 return Status;
869}
870
871typedef struct _BL_BSD_LOG_OBJECT
872{
879
882
883VOID
885 _In_ PBL_DEVICE_DESCRIPTOR LogDevice,
886 _In_ PWCHAR LogPath,
888 )
889{
891
892 /* Don't initialize twice */
894 {
895 return;
896 }
897
898 /* Set invalid IDs for now */
901
902 /* Open the BSD device */
903 Status = BlpDeviceOpen(LogDevice,
905 0,
907 if (!NT_SUCCESS(Status))
908 {
909 /* Welp that didn't work */
910 goto FailurePath;
911 }
912
913 /* Now open the BSD itself */
915 LogPath,
918 if (!NT_SUCCESS(Status))
919 {
920 /* D'oh */
921 goto FailurePath;
922 }
923
924 /* The BSD is open. Start doing stuff to it */
925 EfiPrintf(L"Unimplemented BSD path\r\n");
927
928FailurePath:
929 /* Close the BSD if we had it open */
930 if (BsdpLogObject.FileId != -1)
931 {
933 }
934
935 /* Close the device if we had it open */
936 if (BsdpLogObject.DeviceId != -1)
937 {
939 }
940
941 /* Set BSD object to its uninitialized state */
948}
949
950VOID
952 VOID
953 )
954{
956 PBL_DEVICE_DESCRIPTOR BsdDevice;
957 PWCHAR BsdPath;
958 ULONG Flags;
959 BOOLEAN PreserveBsd;
960
961 /* Initialize locals */
962 BsdPath = NULL;
963 BsdDevice = NULL;
964 Flags = 0;
965
966 /* Check if the BSD is stored in a custom device */
969 &BsdDevice,
970 NULL);
971 if (!NT_SUCCESS(Status))
972 {
973 /* Nope, use the boot device */
974 BsdDevice = BlpBootDevice;
975 }
976
977 /* Check if the path is custom as well */
980 &BsdPath);
981 if (!NT_SUCCESS(Status))
982 {
983 /* Nope, use our default path */
984 Status = BmpFwGetFullPath(L"\\bootstat.dat", &BsdPath);
985 if (!NT_SUCCESS(Status))
986 {
987 BsdPath = NULL;
988 }
989
990 /* Set preserve flag */
991 Flags = 1;
992 }
993 else
994 {
995 /* Set preserve flag */
996 Flags = 1;
997 }
998
999 /* Finally, check if the BSD should be preserved */
1002 &PreserveBsd);
1003 if (!(NT_SUCCESS(Status)) || !(PreserveBsd))
1004 {
1005 /* We failed to read, or we were asked not to preserve it */
1006 Flags = 0;
1007 }
1008
1009 /* Initialize the log */
1010 BlBsdInitializeLog(BsdDevice, BsdPath, Flags);
1011
1012 /* Free the BSD device descriptor if we had one */
1013 if (BsdDevice)
1014 {
1015 BlMmFreeHeap(BsdDevice);
1016 }
1017
1018 /* Free the BSD path if we had one */
1019 if ((Flags) && (BsdPath))
1020 {
1021 BlMmFreeHeap(BsdPath);
1022 }
1023}
1024
1025VOID
1027 VOID
1028 )
1029{
1032 BL_ADDRESS_RANGE AddressRange;
1033
1034 /* Select the range below 1MB */
1035 AddressRange.Maximum = 0xFFFFF;
1036 AddressRange.Minimum = 0;
1037
1038 /* Allocate one reserved page with the "below 1MB" attribute */
1041 1,
1043 0,
1045 &AddressRange,
1047 if (!NT_SUCCESS(Status))
1048 {
1049 /* Print a message on error, but keep going */
1050 BlStatusPrint(L"BmFwMemoryInitialize: Failed to allocate a page below 1MB. Status: 0x%08x\r\n",
1051 Status);
1052 }
1053}
1054
1058 )
1059{
1060 /* Not yet supported */
1062}
1063
1066 _In_ PWCHAR XmlTag
1067 )
1068{
1069 /* Sigh */
1070 EfiPrintf(L"XML: %s\r\n", XmlTag);
1072}
1073
1076 _In_ PWCHAR Stylesheet
1077 )
1078{
1079 /* Reset the cursor type */
1081
1082 /* Nope, not doing any XML stuff */
1083 return STATUS_SUCCESS;
1084}
1085
1088 VOID
1089 )
1090{
1091 /* Check if we're booted by UEFI off the DVD directly */
1095 {
1096 /* Windows actually bypasses integrity checks in this case. Works for us */
1097 return STATUS_SUCCESS;
1098 }
1099
1100 /* Our binaries aren't signed, so always return failure */
1101 return 0xC0000428;
1102}
1103
1106 VOID
1107 )
1108{
1110 BOOLEAN SecureBootEnabled;
1111
1112 /* Is SecureBoot enabled? */
1113 Status = BlSecureBootIsEnabled(&SecureBootEnabled);
1114 if ((NT_SUCCESS(Status)) && (SecureBootEnabled))
1115 {
1116 EfiPrintf(L"SB not implemented revok\r\n");
1118 }
1119 else
1120 {
1121 /* Nothing to do without SecureBoot */
1123 }
1124
1125 /* Return revocation result back to caller */
1126 return Status;
1127}
1128
1131 _Out_ PHANDLE BcdResumeHandle
1132 )
1133{
1135 BOOLEAN AttemptResume;
1136
1137 /* Should we attempt to resume from hibernation? */
1140 &AttemptResume);
1141 if (!NT_SUCCESS(Status))
1142 {
1143 /* Nope. Is automatic restart on crash enabled? */
1144 AttemptResume = FALSE;
1147 &AttemptResume);
1148 AttemptResume = (NT_SUCCESS(Status) && (AttemptResume));
1149 }
1150
1151 /* Don't do anything if there's no need to resume anything */
1152 if (!AttemptResume)
1153 {
1154 return STATUS_SUCCESS;
1155 }
1156
1157 /* Not yet implemented */
1158 EfiPrintf(L"Resume not supported\r\n");
1160}
1161
1164 VOID
1165 )
1166{
1167 BL_PD_DATA_BLOB BadMemoryData;
1169
1170 /* Try to get the memory data from the memtest application */
1171 BadMemoryData.BlobSize = 0;
1172 BadMemoryData.Data = NULL;
1173 BadMemoryData.DataSize = 0;
1174 Status = BlPdQueryData(&BadMemoryGuid, NULL, &BadMemoryData);
1176 {
1177 /* No results, or some other error */
1178 return Status;
1179 }
1180
1181 /* Not yet implemented */
1182 EfiPrintf(L"Bad page list persistence not implemented\r\n");
1184}
1185
1188 _In_ HANDLE BcdHandle,
1189 _In_ PGUID ObjectId,
1191 )
1192{
1193 HANDLE ObjectHandle;
1195
1196 /* Open the object */
1197 Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle);
1198 if (NT_SUCCESS(Status))
1199 {
1200 /* Delete the element */
1201 BcdDeleteElement(ObjectHandle, Type);
1202
1203 /* Close the object and set success */
1204 BiCloseKey(ObjectHandle);
1206 }
1207
1208 /* Return the result */
1209 return Status;
1210}
1211
1214 _In_ HANDLE BcdHandle,
1215 _In_ PGUID ObjectId,
1217 )
1218{
1220 HANDLE ObjectHandle;
1221
1222 /* Open the BCD object */
1223 Status = BcdOpenObject(BcdHandle, ObjectId, &ObjectHandle);
1224 if (NT_SUCCESS(Status))
1225 {
1226 /* Make sure the caller passed this argument in */
1227 if (!Description)
1228 {
1229 /* Fail otherwise */
1231 }
1232 else
1233 {
1234 /* Query the description from the BCD interface */
1235 Status = BiGetObjectDescription(ObjectHandle, Description);
1236 }
1237
1238 /* Close the object key */
1239 BiCloseKey(ObjectHandle);
1240 }
1241
1242 /* Return the result back */
1243 return Status;
1244}
1245
1248 _In_ HANDLE BcdHandle,
1249 _In_ PGUID SequenceList,
1251 _Out_ PBL_LOADED_APPLICATION_ENTRY* BootSequence,
1252 _Out_ PULONG SequenceCount
1253 )
1254{
1256 ULONG BootIndex, i, OptionSize;
1261 BOOLEAN HavePath, IsWinPe, SoftReboot;
1262 PWCHAR LoaderPath;
1263
1264 /* Initialize locals */
1265 Options = NULL;
1266 BootIndex = 0;
1268
1269 /* Loop through every element in the sequence */
1270 for (i = 0; i < *SequenceCount; i++)
1271 {
1272 /* Assume failure */
1273 BootEntry = NULL;
1274
1275 /* Get the options for the sequence element */
1276 Status = BmGetOptionList(BcdHandle, SequenceList, &Options);
1277 if (!NT_SUCCESS(Status))
1278 {
1279 EfiPrintf(L"option list failed: %lx\r\n", Status);
1280 goto LoopQuickie;
1281 }
1282
1283 /* Make sure there's at least a path and description */
1286 {
1288 EfiPrintf(L"missing list failed: %lx\r\n", Status);
1289 goto LoopQuickie;
1290 }
1291
1292 /* Get the size of the BCD options and allocate a large enough entry */
1293 OptionSize = BlGetBootOptionListSize(Options);
1294 BootEntry = BlMmAllocateHeap(sizeof(*BootEntry) + OptionSize);
1295 if (!BootEntry)
1296 {
1298 goto Quickie;
1299 }
1300
1301 /* Save it as part of the sequence */
1302 BootSequence[BootIndex] = BootEntry;
1303
1304 /* Initialize it, and copy the BCD data */
1305 RtlZeroMemory(BootEntry, sizeof(*BootEntry));
1306 BootEntry->Guid = *SequenceList;
1307 BootEntry->BcdData = (PBL_BCD_OPTION)(BootEntry + 1);
1308 BootEntry->Flags = Flags;
1309 RtlCopyMemory(BootEntry->BcdData, Options, OptionSize);
1310
1311 /* Get the object descriptor to find out what kind of entry it is */
1312 Status = BmGetEntryDescription(BcdHandle,
1313 &BootEntry->Guid,
1314 &Description);
1315 if (!NT_SUCCESS(Status))
1316 {
1317 EfiPrintf(L"missing desc failed: %lx\r\n", Status);
1318 goto LoopQuickie;
1319 }
1320
1321 /* Check if a path was given or not */
1323 TRUE : FALSE;
1324
1325 /* Now select based on what type of object this is -- must be an app */
1326 ObjectType.PackedValue = Description.Type;
1327 if (ObjectType.Application.ObjectCode == BCD_OBJECT_TYPE_APPLICATION)
1328 {
1329 /* Then select based on what kind of app it is */
1330 switch (ObjectType.Application.ApplicationCode)
1331 {
1332 /* Another boot manager */
1334 BootEntry->Flags |= BCD_APPLICATION_TYPE_BOOTMGR;
1335 break;
1336
1337 /* An OS loader */
1339 BootEntry->Flags |= BL_APPLICATION_ENTRY_WINLOAD;
1340
1341 /* Do we have a path for it? */
1342 if (!HavePath)
1343 {
1344 /* We'll try to make one up. Is this WinPE? */
1345 IsWinPe = FALSE;
1348 &IsWinPe);
1349 if (!(NT_SUCCESS(Status)) && (Status != STATUS_NOT_FOUND))
1350 {
1351 goto Quickie;
1352 }
1353
1354 /* Use the appropriate path for WinPE or local install */
1355 LoaderPath = IsWinPe ?
1356 L"\\Windows\\System32\\boot\\winload.efi" :
1357 L"\\Windows\\System32\\winload.efi";
1358
1359 /* Add the path to the boot entry */
1360 Status = BlAppendBootOptionString(BootEntry,
1362 LoaderPath);
1363 if (!NT_SUCCESS(Status))
1364 {
1365 goto Quickie;
1366 }
1367
1368 /* We have a path now */
1369 HavePath = TRUE;
1370 }
1371 break;
1372
1373 /* A hibernate-resume application */
1376 break;
1377
1378 /* An older OS NTLDR */
1380 BootEntry->Flags |= BL_APPLICATION_ENTRY_NTLDR;
1381 break;
1382
1383 /* An older OS SETUPLDR */
1386 break;
1387
1388 /* A 3rd party/Win9x boot sector */
1391 break;
1392
1393 /* Something else entirely */
1394 default:
1395 break;
1396 }
1397 }
1398
1399 /* We better have a path by now */
1400 if (!HavePath)
1401 {
1403 goto LoopQuickie;
1404 }
1405
1406 /* Check if this is a real mode startup.com */
1407 if ((ObjectType.Application.ObjectCode == BCD_OBJECT_TYPE_APPLICATION) &&
1408 (ObjectType.Application.ImageCode == BCD_IMAGE_TYPE_REAL_MODE) &&
1409 (ObjectType.Application.ApplicationCode == BCD_APPLICATION_TYPE_STARTUPCOM))
1410 {
1411 /* Check if PXE soft reboot will occur */
1414 &SoftReboot);
1415 if ((NT_SUCCESS(Status)) && (SoftReboot))
1416 {
1417 /* Then it's a valid startup.com entry */
1418 BootEntry->Flags |= BL_APPLICATION_ENTRY_STARTUP;
1419 }
1420 }
1421
1422LoopQuickie:
1423 /* All done with this entry -- did we have BCD options? */
1424 if (Options)
1425 {
1426 /* Free them, they're part of the entry now */
1428 Options = NULL;
1429 }
1430
1431 /* Did we fail anywhere? */
1432 if (!NT_SUCCESS(Status))
1433 {
1434 /* Yep -- did we fail with an active boot entry? */
1435 if (BootEntry)
1436 {
1437 /* Destroy it */
1438 BlDestroyBootEntry(BootEntry);
1439 BootSequence[BootIndex] = NULL;
1440 }
1441 }
1442 else
1443 {
1444 /* It worked, so populate the next index now */
1445 BootIndex++;
1446 }
1447
1448 /* And move to the next GUID in the sequence list */
1449 SequenceList++;
1450 }
1451
1452Quickie:
1453 /* All done now -- did we have any BCD options? */
1454 if (Options)
1455 {
1456 /* Free them */
1458 }
1459
1460 /* Return the status */
1461 return Status;
1462}
1463
1466 _In_ HANDLE BcdHandle,
1467 _In_ PGUID SequenceList,
1468 _In_ ULONG SequenceListCount,
1470 _Out_ PBL_LOADED_APPLICATION_ENTRY** BootSequence,
1471 _Out_ PULONG SequenceCount
1472 )
1473{
1475 ULONG Count = SequenceListCount;
1477
1478 /* Allocate the sequence list */
1479 Sequence = BlMmAllocateHeap(SequenceListCount * sizeof(*Sequence));
1480 if (!Sequence)
1481 {
1482 return STATUS_NO_MEMORY;
1483 }
1484
1485 /* Populate the sequence list */
1486 Status = BmpPopulateBootEntryList(BcdHandle,
1487 SequenceList,
1488 Flags,
1489 Sequence,
1490 &Count);
1491 if (!NT_SUCCESS(Status))
1492 {
1493 /* Free the list on failure */
1494 BlMmFreeHeap(Sequence);
1495 }
1496 else
1497 {
1498 /* Otherwise, set success and return the list and count */
1500 *BootSequence = Sequence;
1501 *SequenceCount = Count;
1502 }
1503
1504 /* All done */
1505 return Status;
1506}
1507
1510 _In_ HANDLE BcdHandle,
1511 _Out_ PBL_LOADED_APPLICATION_ENTRY **BootSequence,
1512 _Out_ PULONG SequenceCount
1513 )
1514{
1516 ULONG BootIndex, BootIniCount, BootEntryCount, BcdCount;
1518 PGUID DisplayOrder;
1519 GUID DefaultObject;
1520 BOOLEAN UseDisplayList;
1521
1522 /* Initialize locals */
1523 BootIndex = 0;
1524
1525 /* First try to get the display list, if any */
1526 UseDisplayList = TRUE;
1529 &DisplayOrder,
1530 &BcdCount);
1531 if (!NT_SUCCESS(Status))
1532 {
1533 /* No list, get the default entry instead */
1536 &DefaultObject);
1537 if (NT_SUCCESS(Status))
1538 {
1539 /* Set the array to just our entry */
1540 UseDisplayList = FALSE;
1541 BcdCount = 1;
1542 DisplayOrder = &DefaultObject;
1543 }
1544 else
1545 {
1546 /* No default list either, return success but no entries */
1547 *BootSequence = NULL;
1548 *SequenceCount = 0;
1550 DisplayOrder = NULL;
1551 goto Quickie;
1552 }
1553 }
1554
1555 /* Check if boot.ini was used */
1556 BootIniCount = 0;
1557 if (BmBootIniUsed)
1558 {
1559 /* Get the entries from it */
1560 EfiPrintf(L"Boot.ini not supported\r\n");
1561 BootIniCount = 0;//BmBootIniGetEntryCount();
1562 }
1563
1564 /* Allocate an array large enough for the combined boot entries */
1565 BootEntryCount = BootIniCount + BcdCount;
1566 Sequence = BlMmAllocateHeap(BootEntryCount * sizeof(*Sequence));
1567 if (!Sequence)
1568 {
1570 goto Quickie;
1571 }
1572
1573 /* Zero it out */
1574 RtlZeroMemory(Sequence, BootEntryCount * sizeof(*Sequence));
1575
1576 /* Check if we had BCD entries */
1577 if (BcdCount)
1578 {
1579 /* Populate the list of bootable entries */
1580 Status = BmpPopulateBootEntryList(BcdHandle,
1581 DisplayOrder,
1583 Sequence,
1584 &BcdCount);
1585 if (!NT_SUCCESS(Status))
1586 {
1587 /* Bail out */
1588 goto Quickie;
1589 }
1590 }
1591
1592 /* Check if we had boot.ini entries */
1593 if (BootIniCount)
1594 {
1595 /* TODO */
1596 EfiPrintf(L"Boot.ini not supported\r\n");
1597 }
1598
1599 /* Return success and the sequence + count populated */
1601 *BootSequence = Sequence;
1602 *SequenceCount = BootIniCount + BcdCount;
1603
1604Quickie:
1605 /* Check if we had allocated a GUID list */
1606 if ((UseDisplayList) && (DisplayOrder))
1607 {
1608 /* Free it */
1609 BlMmFreeHeap(DisplayOrder);
1610 }
1611
1612 /* Check if this is the failure path */
1613 if (!(NT_SUCCESS(Status)) && (Sequence))
1614 {
1615 /* Loop the remaining boot entries */
1616 while (BootIndex < BootEntryCount)
1617 {
1618 /* Check if it had been allocated */
1619 if (Sequence[BootIndex])
1620 {
1621 /* Free it */
1622 BlMmFreeHeap(Sequence[BootIndex]);
1623 }
1624
1625 /* Next*/
1626 BootIndex++;
1627 }
1628
1629 /* Free the whole sequence now */
1630 BlMmFreeHeap(Sequence);
1631 }
1632
1633 /* All done, return the result */
1634 return Status;
1635}
1636
1637VOID
1641 _Out_ PBL_LOADED_APPLICATION_ENTRY* DefaultEntry,
1642 _Out_ PULONG DefaultIndex
1643 )
1644{
1645 GUID DefaultObject;
1647 ULONG BootIndex;
1648
1649 /* Assume no default */
1650 *DefaultEntry = *Sequence;
1651 *DefaultIndex = 0;
1652
1653 /* Nothing to do if there's just one entry */
1654 if (Count == 1)
1655 {
1656 return;
1657 }
1658
1659 /* Get the default object, bail out if there isn't one */
1662 &DefaultObject);
1663 if (!(NT_SUCCESS(Status)) || !(Count))
1664 {
1665 return;
1666 }
1667
1668 /* Scan the boot sequence */
1669 for (BootIndex = 0; BootIndex < Count; BootIndex++)
1670 {
1671 /* Find one that matches the default */
1672 if (RtlEqualMemory(&Sequence[BootIndex]->Guid,
1673 &DefaultObject,
1674 sizeof(GUID)))
1675 {
1676 /* Return it */
1677 *DefaultEntry = Sequence[BootIndex];
1678 *DefaultIndex = BootIndex;
1679 return;
1680 }
1681 }
1682}
1683
1687 )
1688{
1690 BOOLEAN EmsEnabled;
1691 ULONGLONG BootMenuPolicy;
1692 ULONG OptionId;
1693
1694 /* Check if EMS is enabled */
1697 &EmsEnabled);
1698 if ((NT_SUCCESS(Status)) && (EmsEnabled))
1699 {
1700 /* No boot menu */
1701 return MenuPolicyLegacy;
1702 }
1703
1704 /* Check what entry we are looking at */
1705 if (!BootEntry)
1706 {
1707 /* No entry, pick the selected one */
1708 BootEntry = BmpSelectedBootEntry;
1709 }
1710
1711 /* Do we still not have an entry? */
1712 if (!BootEntry)
1713 {
1714 /* Show the menu */
1715 return MenuPolicyStandard;
1716 }
1717
1718 /* Check if this is an OS loader */
1719 BootMenuPolicy = 0;
1720 if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
1721 {
1722 /* Use the correct option ID */
1724 }
1725 else
1726 {
1727 /* Check if this is an OS resumer */
1728 if (!(BootEntry->Flags & BL_APPLICATION_ENTRY_WINRESUME))
1729 {
1730 /* Nope, so no reason for a menu */
1731 return MenuPolicyLegacy;
1732 }
1733
1734 /* Use the correct option ID */
1736 }
1737
1738 /* Check the option ID for the boot menu policy */
1739 Status = BlGetBootOptionInteger(BootEntry->BcdData,
1740 OptionId,
1741 &BootMenuPolicy);
1742 if (NT_SUCCESS(Status))
1743 {
1744 /* We have one, return it */
1745 return BootMenuPolicy;
1746 }
1747
1748 /* No policy, so assume no menu */
1749 return MenuPolicyLegacy;
1750}
1751
1752VOID
1754 _Out_ PL_MENU_STATUS MenuStatus
1755 )
1756{
1757 /* For now, don't support key input at all */
1758 MenuStatus->AsULong = 0;
1759 MenuStatus->OemKey = UNICODE_NULL;
1760 MenuStatus->BootIndex = -1;
1761}
1762
1765 _In_ HANDLE BcdHandle,
1766 _In_ PWCHAR ActionKey
1767 )
1768{
1769 EfiPrintf(L"Custom actions not yet handled\r\n");
1771}
1772
1773VOID
1775 _In_ HANDLE BcdHandle,
1777 _Out_ PBOOLEAN ExitBootManager
1778 )
1779{
1780 BL_MENU_STATUS MenuStatus;
1781
1782 /* Don't exit */
1783 *ExitBootManager = FALSE;
1784
1785 /* If the legacy menu must be shown, or if we have a boot entry */
1786 if ((BmGetBootMenuPolicy(BootEntry) != MenuPolicyStandard) || (BootEntry))
1787 {
1788 /* Check if any key has been pressed */
1789 BmDisplayGetBootMenuStatus(&MenuStatus);
1790 if (MenuStatus.AnyKey)
1791 {
1792 /* Was the exit key pressed? */
1793 if (MenuStatus.Exit)
1794 {
1795 /* Don't display a menu, and exit */
1796 *ExitBootManager = TRUE;
1798 }
1799 else if (MenuStatus.OemKey)
1800 {
1801 /* Process the OEM key action */
1802 BmProcessCustomAction(BcdHandle, &MenuStatus.KeyValue);
1803 }
1804 else
1805 {
1806 /* Process other keys */
1807 EfiPrintf(L"TODO\r\n");
1808 }
1809 }
1810 }
1811}
1812
1815 _In_ HANDLE BcdHandle,
1816 _Out_ PBL_LOADED_APPLICATION_ENTRY* SelectedBootEntry,
1817 _Out_ PULONG EntryIndex,
1818 _Out_ PBOOLEAN ExitBootManager
1819 )
1820{
1823 PBL_LOADED_APPLICATION_ENTRY Entry, SelectedEntry;
1824 ULONG Count, BootIndex, SelectedIndex;
1825 // BOOLEAN FoundFailedEntry;
1827
1828 /* Initialize locals */
1829 BootIndex = 0;
1830 Count = 0;
1831 Sequence = NULL;
1832 SelectedEntry = NULL;
1833
1834 /* Enumerate all the boot entries */
1835 Status = BmEnumerateBootEntries(BcdHandle, &Sequence, &Count);
1836 if (!NT_SUCCESS(Status))
1837 {
1838 /* Bail out if we failed */
1839 goto Quickie;
1840 }
1841
1842 /* Check if there are no entries */
1843 if (!Count)
1844 {
1845 /* This is fatal -- kill the system */
1848 goto Quickie;
1849 }
1850
1851 /* Check if we don't yet have an array of failed boot entries */
1853 {
1854 /* Allocate it */
1857 {
1858 /* Zero it out */
1860 }
1861 }
1862
1863 /* Check if we have a hardcoded boot override */
1865 {
1866 EfiPrintf(L"Hard-coded boot override mode not supported\r\n");
1867 }
1868
1869 /* Log the OS count */
1870 //BlLogEtwWrite(BOOT_BOOTMGR_MULTI_OS_COUNT);
1871
1872 /* Check if the display is already active and cached */
1874 {
1875 /* Check if we should display a boot menu */
1879 if (!NT_SUCCESS(Status))
1880 {
1881 /* Assume not */
1883 }
1884 }
1885
1886 /* Check if there's only one entry to boot anyway */
1887 if (Count == 1)
1888 {
1889 /* Read it */
1890 SelectedEntry = *Sequence;
1891
1892 /* Process it */
1893 BmpProcessBootEntry(BcdHandle, SelectedEntry, ExitBootManager);
1894
1895 /* Check if we're not displaying a boot menu */
1896 if (!BmpDisplayBootMenu)
1897 {
1898 /* Now we are */
1900
1901 /* Return the entry and its index back */
1902 *EntryIndex = 0;
1903 *SelectedBootEntry = SelectedEntry;
1905 goto Quickie;
1906 }
1907 }
1908 else
1909 {
1910 /* Get the default boot entry */
1911 BmpGetDefaultBootEntry(Sequence, Count, &SelectedEntry, &SelectedIndex);
1912
1913 /* Check if we have a failed boot entry array allocated */
1914 //FoundFailedEntry = FALSE;
1916 {
1917 /* Check if the default entry failed to boot */
1918 if (BmpFailedBootEntries[SelectedIndex])
1919 {
1920 /* Loop through the current boot sequence */
1921 for (SelectedIndex = 0; SelectedIndex < Count; SelectedIndex++)
1922 {
1923 /* Check if there's no sequence for this index, or it failed */
1924 while (!(Sequence[SelectedIndex]) ||
1925 (BmpFailedBootEntries[SelectedIndex]))
1926 {
1927 /* Remember that this is a failed entry */
1928 SelectedEntry = Sequence[SelectedIndex];
1929 //FoundFailedEntry = TRUE;
1931 }
1932 }
1933 }
1934 }
1935
1936 /* Check if the entry is an OS loader */
1937 if (SelectedEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
1938 {
1939 // todo
1940 EfiPrintf(L"todo path\r\n");
1941 }
1942
1943 /* Check if there's no timeout */
1946 &Timeout);
1947 if ((NT_SUCCESS(Status) && !(Timeout)))
1948 {
1949 /* There isn't, so just process the default entry right away */
1950 BmpProcessBootEntry(BcdHandle, SelectedEntry, ExitBootManager);
1951
1952 /* Check if we're not displaying a boot menu */
1953 if (!BmpDisplayBootMenu)
1954 {
1955 /* Now we are */
1957
1958 /* Return the entry and its index back */
1959 *EntryIndex = 0;
1960 *SelectedBootEntry = SelectedEntry;
1962 goto Quickie;
1963 }
1964
1965 /* Remove the timeout for this boot instance */
1968 }
1969 }
1970
1971 /* Here is where we display the menu and list of tools */
1972 EfiPrintf(L"Tool selection not yet implemented\r\n");
1973 EfiStall(10000000);
1974 *SelectedBootEntry = NULL;
1975
1976Quickie:
1977 /* We are done -- did we have a sequence? */
1978 if (Sequence)
1979 {
1980 /* Do we have any boot entries we parsed? */
1981 while (BootIndex < Count)
1982 {
1983 /* Get the current boot entry */
1984 Entry = Sequence[BootIndex];
1985
1986 /* Did we fail, or is is not the selected one? */
1987 if ((Entry) && ((Entry != SelectedEntry) || !(NT_SUCCESS(Status))))
1988 {
1989 /* Destroy it, as it won't be needed */
1991 }
1992 else if (Entry == SelectedEntry)
1993 {
1994 /* It's the selected one, return its index */
1995 *EntryIndex = BootIndex;
1996 }
1997
1998 /* Move to the next entry */
1999 BootIndex++;
2000 }
2001
2002 /* Free the sequence of entries */
2003 BlMmFreeHeap(Sequence);
2004 }
2005
2006 /* Return the selection result */
2007 return Status;
2008}
2009
2013 _In_ ULONG LaunchCode
2014 )
2015{
2017 PBL_LOADED_APPLICATION_ENTRY RecoveryEntry;
2018 HANDLE BcdHandle;
2019 PGUID RecoverySequence;
2020 ULONG Count, i, RecoveryIndex, SequenceCount;
2022
2023 /* Initialize locals */
2024 RecoveryIndex = 0;
2025 Sequence = NULL;
2026 RecoverySequence = NULL;
2027 Count = 0;
2028 BcdHandle = NULL;
2029
2030 /* Open the BCD*/
2031 Status = BmOpenDataStore(&BcdHandle);
2032 if (!NT_SUCCESS(Status))
2033 {
2034 goto Quickie;
2035 }
2036
2037 /* Get the recovery sequence list */
2038 Status = BlGetBootOptionGuidList(BootEntry->BcdData,
2040 &RecoverySequence,
2041 &SequenceCount);
2042 if (!NT_SUCCESS(Status))
2043 {
2044 goto Quickie;
2045 }
2046
2047 /* Get the sequence of boot entries out of it */
2048 Status = BmGetBootSequence(BcdHandle,
2049 RecoverySequence,
2050 SequenceCount,
2052 &Sequence,
2053 &Count);
2054 if (!NT_SUCCESS(Status))
2055 {
2056 goto Quickie;
2057 }
2058
2059 /* Was the BCD open? */
2060 if (BcdHandle)
2061 {
2062 /* Close it */
2063 BmCloseDataStore(BcdHandle);
2064 }
2065
2066 /* Now go over every entry in the sequence */
2067 for (i = 0; i < Count; ++i)
2068 {
2069 /* Check the code for this recovery launch */
2070 if (LaunchCode == 2 || LaunchCode == 5)
2071 {
2072 /* Remove the override if there is one, and set it to 4 */
2074 BlAppendBootOptionInteger(Sequence[i],
2076 4);
2077 }
2078 else if (LaunchCode == 3)
2079 {
2080 /* Remove the override if there is one, and set it to 10 */
2082 BlAppendBootOptionInteger(Sequence[i],
2084 10);
2085 }
2086
2087 /* Launch the boot entry for this part of the recovery sequence */
2088 Status = BmpLaunchBootEntry(Sequence[i], NULL, LaunchCode, FALSE);
2089 if (!NT_SUCCESS(Status))
2090 {
2091 break;
2092 }
2093 }
2094
2095Quickie:
2096 /* Did we have a sequence of entries? */
2097 if (Sequence)
2098 {
2099 /* Loop through each one */
2100 for (RecoveryIndex = 0; RecoveryIndex < Count; RecoveryIndex++)
2101 {
2102 /* Does this index have an allocated boot entry? */
2103 RecoveryEntry = Sequence[RecoveryIndex];
2104 if (RecoveryEntry)
2105 {
2106 /* Destroy it */
2107 BlDestroyBootEntry(RecoveryEntry);
2108 }
2109 }
2110
2111 /* Free the sequence itself */
2112 BlMmFreeHeap(Sequence);
2113 }
2114
2115 /* Was there a sequence list? */
2116 if (RecoverySequence)
2117 {
2118 /* Free it */
2119 BlMmFreeHeap(RecoverySequence);
2120 }
2121
2122 /* Return back to caller */
2123 return Status;
2124}
2125
2126ULONG
2129 _In_ ULONG LaunchCode
2130 )
2131{
2132 ULONG BootError;
2134 BOOLEAN Restart, NoError;
2135
2136 /* Assume we'll just reboot */
2137 BootError = Reboot;
2138
2139 /* Should we reboot? */
2142 &Restart);
2143 if ((NT_SUCCESS(Status)) && (Restart))
2144 {
2145 return BootError;
2146 }
2147
2148 /* Should we not show errors, and thus, reboot? */
2151 &NoError);
2152 if ((NT_SUCCESS(Status)) && (NoError))
2153 {
2154 return BootError;
2155 }
2156
2157 /* Is there an internal boot error? */
2159 {
2160 /* Return it -- but it's a pointer? */
2161 return (ULONG_PTR)BmpInternalBootError; // ???
2162 }
2163
2164 /* Otherwise, show the menu to see what to do */
2165 EfiPrintf(L"Error menu not yet implemented\r\n");
2166 return BootError;
2167}
2168
2172 )
2173{
2174 ULONG NextOffset, DataOffset, ListOffset;
2175 PBL_BCD_OPTION Option, ListOption;
2176 BcdElementType ElementType;
2177 PBCD_DEVICE_OPTION BcdDevice;
2178
2179 /* Starting at offset 0, loop every BCD option */
2180 NextOffset = 0;
2181 do
2182 {
2183 /* Get the current option, and its offset */
2184 Option = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + NextOffset);
2185 NextOffset = Option->NextEntryOffset;
2186
2187 /* If it's empty, ignore it */
2188 if (Option->Empty)
2189 {
2190 continue;
2191 }
2192
2193 /* If it's not a device option, ignore it */
2194 ElementType.PackedValue = Option->Type;
2195 if (ElementType.Format != BCD_TYPE_DEVICE)
2196 {
2197 continue;
2198 }
2199
2200 /* Get the data offset */
2201 DataOffset = Option->DataOffset;
2202
2203 /* Extract the device out of it */
2204 BcdDevice = (PBCD_DEVICE_OPTION)((ULONG_PTR)BootEntry->BcdData + DataOffset);
2205
2206 /* If the device is already fully specified, no need to build it */
2207 if (!(BcdDevice->DeviceDescriptor.Flags & 1))
2208 {
2209 continue;
2210 }
2211
2212 /* Otherwise, check if there's any list options as well */
2213 ListOption = NULL;
2214 ListOffset = Option->ListOffset;
2215 if (Option->ListOffset)
2216 {
2217 ListOption = (PBL_BCD_OPTION)((ULONG_PTR)BootEntry->BcdData + ListOffset);
2218 }
2219
2220 /* And now call BlCreateDevice to build the full device descriptor */
2221 EfiPrintf(L"Unspecified devices not yet supported: %p\r\n", ListOption);
2222 return STATUS_NOT_SUPPORTED;
2223 } while (NextOffset != 0);
2224
2225 /* Devices created successfully */
2226 return STATUS_SUCCESS;
2227}
2228
2232 _Out_ PULONG LaunchCode,
2234 )
2235{
2236 PWCHAR AppPath;
2238 PBL_DEVICE_DESCRIPTOR AppDevice;
2239 BL_RETURN_ARGUMENTS ReturnArgs;
2241 ULONG AppHandle;
2242
2243 /* Get the application path */
2244 Status = BlGetBootOptionString(BootEntry->BcdData,
2246 &AppPath);
2247 if (!NT_SUCCESS(Status))
2248 {
2249 /* If we couldn't find one, set this to NULL */
2250 AppPath = NULL;
2251 }
2252
2253 /* Check if this is a PXE startup.com */
2254 if (BootEntry->Flags & BL_APPLICATION_ENTRY_STARTUP)
2255 {
2256#if BL_NET_SUPPORT
2257 /* Do soft reboot to launch it */
2258 Status = BlNetSoftReboot(BootEntry);
2259#else
2260 EfiPrintf(L"Net boot not supported\r\n");
2262#endif
2263 /* Nothing else for us to do */
2264 goto Quickie;
2265 }
2266
2267 /* Loop as long as boot was not cancelled */
2268 do
2269 {
2270 /* Load the boot application */
2271 Status = BlImgLoadBootApplication(BootEntry, &AppHandle);
2272
2273 /* Did we not find it? */
2274 if (Status == STATUS_NOT_FOUND)
2275 {
2276 /* Get the device for the boot application */
2277 Status = BlGetBootOptionDevice(BootEntry->BcdData,
2279 &AppDevice,
2280 NULL);
2281 if (!NT_SUCCESS(Status))
2282 {
2283 /* Force re-enumeration */
2284 Status = BlFwEnumerateDevice(AppDevice);
2285 }
2286
2287 /* Did re-enumeration work? */
2288 if (!NT_SUCCESS(Status))
2289 {
2290 /* Nope, raise a fatal error */
2292 (ULONG_PTR)AppPath,
2293 Status,
2294 0,
2295 0);
2296 goto Quickie;
2297 }
2298
2299 /* Yes, try booting it again */
2300 Status = BlImgLoadBootApplication(BootEntry, &AppHandle);
2301 }
2302
2303 /* Was boot cancelled?*/
2304 if (Status == STATUS_CANCELLED)
2305 {
2306 /* Should we display the menu, or is there no launch sequence? */
2307 if ((BmGetBootMenuPolicy(BootEntry) != MenuPolicyStandard) ||
2308 !(MiscGetBootOption(BootEntry->BcdData,
2310 {
2311 /* Bail out, the menu will take care of it */
2312 goto Quickie;
2313 }
2314
2315 /* No menu and there's a sequence, launch it */
2316 *LaunchCode = 4;
2317 *Recover = TRUE;
2318 goto Quickie;
2319 }
2320
2321 /* STATUS_FVE_LOCKED_VOLUME -- bitlocker volume is locked */
2323 {
2324 /* Launch recovery mode */
2325 *LaunchCode = 4;
2326 *Recover = TRUE;
2327 goto Quickie;
2328 }
2329
2330 /* Was there some other error launching the boot application? */
2331 if (!NT_SUCCESS(Status))
2332 {
2333 /* Raise a fatal error */
2335 (ULONG_PTR)AppPath,
2336 Status,
2337 0,
2338 0);
2339 goto Quickie;
2340 }
2341
2342 /* Zero out the return arguments */
2343 RtlZeroMemory(&ReturnArgs, sizeof(ReturnArgs));
2344
2345 /* Log to ETW this launch */
2346 //BmpLogApplicationLaunchEvent(&BootEntry->Guid, AppPath);
2347
2348 /* Launch the boot application*/
2349 Status = BlImgStartBootApplication(AppHandle, &ReturnArgs);
2350
2351#if BL_BITLOCKER_SUPPORT
2352 /* Bitlocker stuff */
2353 BlFveSecureBootCheckpointAppReturn(BootEntry, &ReturnArgs);
2354#endif
2355
2356 /* Log in the boot status log the launch */
2357 //BlBsdLogEntry(1, 0x12, &BootEntry->Guid, 0x14);
2358
2359 /* Unloac the boot application if we've returned */
2360 BlImgUnloadBootApplication(AppHandle);
2361
2362 /* Keep going unless STATUS_RESTART_BOOT_APPLICATION */
2363 } while (Status != 0xC0000453);
2364
2365 /* We've come back. Assume we need to launch the recovery sequence */
2366 *Recover = TRUE;
2367
2368 /* Why did we get back? */
2369 if (ReturnArgs.Flags & 1)
2370 {
2371 /* Flag 1 -- should we display advanced options? */
2372 Status = BlGetBootOptionBoolean(BootEntry->BcdData,
2375 if ((NT_SUCCESS(Status)) && (AdvancedOptions))
2376 {
2377 /* Yes, so return with code 2 */
2378 *LaunchCode = 2;
2379 }
2380 else
2381 {
2382 /* No, return with code 1 */
2383 *LaunchCode = 1;
2384 }
2385 }
2386 else if (ReturnArgs.Flags & 4)
2387 {
2388 /* Flag 4 -- unknown */
2389 *LaunchCode = 1;
2390 }
2391 else if (ReturnArgs.Flags & 8)
2392 {
2393 /* Flag 5 -- unknown */
2394 *LaunchCode = 5;
2395 }
2396 else if (ReturnArgs.Flags & 0x10)
2397 {
2398 /* Flag 6 -- unknown */
2399 *LaunchCode = 6;
2400 }
2401 else if (ReturnArgs.Flags & 0x20)
2402 {
2403 /* Flag 7 -- unknown */
2404 *LaunchCode = 7;
2405 }
2406 else if (ReturnArgs.Flags & BL_RETURN_ARGUMENTS_NO_PAE_FLAG)
2407 {
2408 /* PAE is not supported -- refuse to boot */
2409 *Recover = FALSE;
2411 }
2412
2413Quickie:
2414 /* All done, did we have an application path? */
2415 if (AppPath)
2416 {
2417 /* Free it */
2418 BlMmFreeHeap(AppPath);
2419 }
2420
2421 /* Back to the caller now */
2422 return Status;
2423}
2424
2428 _Out_ PULONG EntryIndex,
2429 _In_ ULONG LaunchCode,
2430 _In_ BOOLEAN LaunchWinRe
2431 )
2432{
2433 HANDLE BcdHandle;
2435 GUID ObjectId;
2436 BOOLEAN DoRecovery, AutoRecovery, DoSequence, RestartOnFailure;
2438 BOOLEAN AdvancedOneTime, EditOneTime;
2439
2440 /* Check if this is the OS loader */
2441 if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
2442 {
2443 /* Check if one-time advanced options should be shown */
2444 if (MiscGetBootOption(BootEntry->BcdData,
2446 {
2447 /* Open the BCD */
2448 BcdHandle = NULL;
2449 Status = BmOpenDataStore(BcdHandle);
2450 if (NT_SUCCESS(Status))
2451 {
2452 /* Delete the option from the BCD, so it doesn't happen again */
2453 ObjectId = BootEntry->Guid;
2454 BmPurgeOption(BcdHandle,
2455 &ObjectId,
2457 BmCloseDataStore(BcdHandle);
2458 }
2459 }
2460
2461 /* Check if one-time options editor should be shown */
2462 if (MiscGetBootOption(BootEntry->BcdData,
2464 {
2465 /* Open the BCD */
2466 BcdHandle = NULL;
2467 Status = BmOpenDataStore(BcdHandle);
2468 if (NT_SUCCESS(Status))
2469 {
2470 /* Delete the option from the BCD, so it doesn't happen again */
2471 ObjectId = BootEntry->Guid;
2472 BmPurgeOption(BcdHandle,
2473 &ObjectId,
2475 BmCloseDataStore(BcdHandle);
2476 }
2477 }
2478 }
2479
2480TryAgain:
2481 /* Disable recovery mode */
2482 DoRecovery = FALSE;
2483
2484 /* Store globally which entry we are trying to boot */
2485 BmpSelectedBootEntry = BootEntry;
2486
2487 /* Create any devices that aren't yet fully defined for this boot entry */
2488 Status = BmpCreateDevices(BootEntry);
2489 if (!NT_SUCCESS(Status))
2490 {
2491 /* That failed -- can we launch the recovery environment? */
2492 if (!LaunchWinRe)
2493 {
2494 return Status;
2495 }
2496
2497 /* Yes, so return with the WinRe launch code */
2498 LaunchCode = 2;
2499 goto Quickie;
2500 }
2501
2502 /* Is this an OS loader/ */
2503 if (BootEntry->Flags & BL_APPLICATION_ENTRY_WINLOAD)
2504 {
2505 /* Is the one-time advanced options menu option present? */
2506 Status = BlGetBootOptionBoolean(BootEntry->BcdData,
2508 &AdvancedOneTime);
2509 if (NT_SUCCESS(Status))
2510 {
2511 /* Is it turned on? */
2512 if (AdvancedOneTime)
2513 {
2514 /* Set the option this once */
2515 BlAppendBootOptionBoolean(BootEntry,
2517 TRUE);
2518 }
2519 else
2520 {
2521 /* It's not, so disable the option if active */
2522 BlRemoveBootOption(BootEntry->BcdData,
2524 }
2525
2526 /* Remove the one-time option. We've already purged it earlier */
2527 BlRemoveBootOption(BootEntry->BcdData,
2529 }
2530
2531 /* Is the one-time options editor menu option present? */
2532 Status = BlGetBootOptionBoolean(BootEntry->BcdData,
2534 &EditOneTime);
2535 if (NT_SUCCESS(Status))
2536 {
2537 /* Is it turned on? */
2538 if (EditOneTime)
2539 {
2540 /* Set the option this once */
2541 BlAppendBootOptionBoolean(BootEntry,
2543 TRUE);
2544 }
2545 else
2546 {
2547 /* It's not, so disable the option if active */
2548 BlRemoveBootOption(BootEntry->BcdData,
2550 }
2551
2552 /* Remove the one-time option. We've already purged it earlier */
2553 BlRemoveBootOption(BootEntry->BcdData,
2555 }
2556 }
2557
2558 /* BCD handling done, transfer execution to this entry */
2559 Status = BmpTransferExecution(BootEntry, &LaunchCode, &DoRecovery);
2560 if (!LaunchWinRe)
2561 {
2562 return Status;
2563 }
2564
2565 /* Check if boot was successful, or cancelled and we're not doing WinRE */
2566 if (((NT_SUCCESS(Status)) || (Status == STATUS_CANCELLED)) && !(DoRecovery))
2567 {
2568 return Status;
2569 }
2570
2571 /* Boot failed -- are we doing recovery? */
2572 if (!DoRecovery)
2573 {
2574 /* Nope, bail out */
2575 LaunchCode = 2;
2576 goto Quickie;
2577 }
2578
2579Quickie:
2580 /* Get the recovery sequence */
2582 {
2583 /* Check if the launch depends on auto-recovery being enabled or not */
2584 if ((LaunchCode == 3) || (LaunchCode == 5) || (LaunchCode == 6))
2585 {
2586 Status = BlGetBootOptionBoolean(BootEntry->BcdData,
2588 &AutoRecovery);
2589 if (NT_SUCCESS(Status))
2590 {
2591 /* Override the setting */
2592 DoRecovery = AutoRecovery;
2593 }
2594 }
2595 }
2596 else
2597 {
2598 /* There's no recovery setting */
2599 DoRecovery = FALSE;
2600 }
2601
2602 /* Check if we should restart on failure */
2603 RestartOnFailure = FALSE;
2606 &RestartOnFailure);
2607
2608 /* Do the sequence if recovery is on, unless we should restart instead */
2609 DoSequence = RestartOnFailure ? FALSE : DoRecovery;
2610 while (1)
2611 {
2612 /* Are we doing the recovery sequence? */
2613 if (DoSequence)
2614 {
2615 /* Because of automatic recovery? */
2616 if (AutoRecovery)
2617 {
2618#if BL_BITLOCKER_SUPPORT
2619 /* Do bitlocker stuff */
2620 BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, TRUE);
2621#endif
2622 }
2623
2624 /* Launch the recovery sequence*/
2625 Status = BmLaunchRecoverySequence(BootEntry, LaunchCode);
2626
2627 /* Was it launched automatically? */
2628 if (AutoRecovery)
2629 {
2630#if BL_BITLOCKER_SUPPORT
2631 /* Do bitlocker stuff */
2632 BlFveRegisterBootEntryForTrustedWimBoot(BootEntry, FALSE);
2633#endif
2634
2635 /* No need to do this again */
2636 AutoRecovery = FALSE;
2637 }
2638
2639 /* Did the recovery sequence work? */
2640 if (NT_SUCCESS(Status))
2641 {
2642 /* All good */
2643 return STATUS_SUCCESS;
2644 }
2645
2646 /* Remove the sequence, don't do it again */
2648 }
2649
2650 /* Recovery sequence also failed, show fatal error */
2652 {
2654 }
2655
2656 /* Display the error menu */
2657 ErrorCode = BmDisplayDumpError(BootEntry, LaunchCode);
2658 BmErrorPurge();
2659
2660 /* See what the user wants to do */
2661 switch (ErrorCode)
2662 {
2663 case TryAgain:
2664 /* Try again */
2665 goto TryAgain;
2666
2667 case NextOs:
2668 /* Boot the next entry*/
2669 break;
2670
2671 case OsSelection:
2672 /* Cancel the boot*/
2673 return STATUS_CANCELLED;
2674
2675 case RecoverOem:
2676 /* Custom OEM recovery -- open the BCD */
2677 Status = BmOpenDataStore(BcdHandle);
2678 if (NT_SUCCESS(Status))
2679 {
2680 /* See what the custom sequence is */
2681 Status = BmProcessCustomAction(BcdHandle, NULL);
2682 }
2683
2684 /* All done, close the BCD */
2685 if (BcdHandle)
2686 {
2687 BmCloseDataStore(BcdHandle);
2688 }
2689 return Status;
2690
2691 case AdvancedOptions:
2692 /* Show the advanced options next iteration */
2693 BlAppendBootOptionBoolean(BootEntry,
2695 TRUE);
2696 goto TryAgain;
2697
2698 case BootOptions:
2699 /* Show the options editor next iteration */
2700 BlAppendBootOptionBoolean(BootEntry,
2702 TRUE);
2703 goto TryAgain;
2704
2705 case Recover:
2706 /* Try the recovery sequence next time*/
2707 DoSequence = TRUE;
2708 LaunchCode = 1;
2709 goto TryAgain;
2710
2711 default:
2712 /* Something unknown */
2713 return STATUS_CANCELLED;
2714 }
2715 }
2716
2717 /* We are booting the next OS, so return success as to not kill the boot */
2718 return STATUS_SUCCESS;
2719}
2720
2721/*++
2722 * @name BmMain
2723 *
2724 * The BmMain function implements the Windows Boot Application entrypoint for
2725 * the Boot Manager.
2726 *
2727 * @param BootParameters
2728 * Pointer to the Boot Application Parameter Block.
2729 *
2730 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
2731 * otherwise.
2732 *
2733 *--*/
2735NTAPI
2738 )
2739{
2740 NTSTATUS Status, LibraryStatus;
2741 BL_LIBRARY_PARAMETERS LibraryParameters;
2742 PBL_RETURN_ARGUMENTS ReturnArguments;
2743 PGUID AppIdentifier;
2744 HANDLE BcdHandle, ResumeBcdHandle;
2745 PBL_BCD_OPTION EarlyOptions;
2746 PWCHAR Stylesheet;
2747 BOOLEAN XmlLoaded, DisableIntegrity, TestSigning, PersistBootSequence;
2748 BOOLEAN RebootOnError, CustomActions;
2749 ULONG SequenceId;
2751 PGUID SequenceList;
2752 ULONG SequenceListCount;
2753 PBL_LOADED_APPLICATION_ENTRY* BootSequence;
2754 ULONG BootIndex;
2755 BOOLEAN ExitBootManager;
2756 BOOLEAN BootFailed;
2757 BOOLEAN BootOk;
2758 ULONG SequenceCount;
2759 BOOLEAN GetEntry;
2760 EfiPrintf(L"ReactOS UEFI Boot Manager Initializing...\r\n");
2761
2762 /* Reading the BCD can change this later on */
2763 RebootOnError = FALSE;
2764
2765 /* Save the start/end-of-POST time */
2766#if defined(_M_IX86) || defined(_M_X64)
2768#else
2769 EfiPrintf(L"No time source defined for this platform\r\n");
2771#endif
2773
2774 /* Setup the boot library parameters for this application */
2775 BlSetupDefaultParameters(&LibraryParameters);
2776 LibraryParameters.TranslationType = BlNone;
2777 LibraryParameters.LibraryFlags = 0x400 | 0x8;
2778 LibraryParameters.MinimumAllocationCount = 16;
2779 LibraryParameters.MinimumHeapSize = 512 * 1024;
2780
2781 /* Initialize the boot library */
2782 Status = BlInitializeLibrary(BootParameters, &LibraryParameters);
2783 if (!NT_SUCCESS(Status))
2784 {
2785 /* Check for failure due to invalid application entry */
2787 {
2788 /* Specifically print out what happened */
2789 EfiPrintf(L"BlInitializeLibrary failed 0x%x\r\n", Status);
2790 }
2791
2792 /* Go to exit path */
2793 goto Quickie;
2794 }
2795
2796 /* Get the application identifier */
2797 AppIdentifier = BlGetApplicationIdentifier();
2798 if (!AppIdentifier)
2799 {
2800 /* None was given, so set our default one */
2801 AppIdentifier = (PGUID)&GUID_WINDOWS_BOOTMGR;
2802 }
2803
2804 /* Save our identifier */
2805 BmApplicationIdentifier = *AppIdentifier;
2806
2807 /* Initialize the file system to open a handle to our root boot directory */
2809
2810 /* Load and initialize the boot configuration database (BCD) */
2811 Status = BmOpenDataStore(&BcdHandle);
2812 if (NT_SUCCESS(Status))
2813 {
2814 /* Copy the boot options */
2816 if (NT_SUCCESS(Status))
2817 {
2818 /* Update them */
2820 if (!NT_SUCCESS(Status))
2821 {
2822 /* Log a fatal error */
2824 (ULONG_PTR)L"\\BCD",
2825 Status,
2826 0,
2827 0);
2828 }
2829 }
2830 }
2831
2832#ifdef _SECURE_BOOT
2833 /* Initialize the secure boot machine policy */
2834 Status = BmSecureBootInitializeMachinePolicy();
2835 if (!NT_SUCCESS(Status))
2836 {
2837 BmFatalErrorEx(BL_FATAL_ERROR_SECURE_BOOT, Status, 0, 0, 0);
2838 }
2839#endif
2840
2841 /* Copy the library parameters and add the re-initialization flag */
2842 RtlCopyMemory(&LibraryParameters,
2844 sizeof(LibraryParameters));
2845 LibraryParameters.LibraryFlags |= (BL_LIBRARY_FLAG_REINITIALIZE_ALL |
2847
2848 /* Now that we've parsed the BCD, re-initialize the library */
2849 LibraryStatus = BlInitializeLibrary(BootParameters, &LibraryParameters);
2850 if (!NT_SUCCESS(LibraryStatus) && (NT_SUCCESS(Status)))
2851 {
2852 Status = LibraryStatus;
2853 }
2854
2855 /* Initialize firmware-specific memory regions */
2857
2858 /* Initialize the boot status data log (BSD) */
2860
2861 /* Find our XSL stylesheet */
2862 Stylesheet = BlResourceFindHtml();
2863 if (!Stylesheet)
2864 {
2865 /* Awe, no XML. This is actually fatal lol. Can't boot without XML. */
2867 EfiPrintf(L"BlResourceFindMessage failed 0x%x\r\n", STATUS_NOT_FOUND);
2868 goto Quickie;
2869 }
2870
2871 /* Initialize the XML Engine (as a side-effect, resets cursor) */
2872 Status = BlXmiInitialize(Stylesheet);
2873 if (!NT_SUCCESS(Status))
2874 {
2875 EfiPrintf(L"\r\nBlXmiInitialize failed 0x%x\r\n", Status);
2876 goto Failure;
2877 }
2878 XmlLoaded = TRUE;
2879
2880 /* Check if there's an active bitmap visible */
2882 {
2883 /* Nope, make the screen black using BGFX */
2884 if (!NT_SUCCESS(BmpBgDisplayClearScreen(0xFF000000)))
2885 {
2886 /* BGFX isn't active, use standard display */
2888 }
2889 }
2890
2891#ifdef _BIT_LOCKER_
2892 /* Bitlocker will take over screen UI if enabled */
2893 FveDisplayScreen = BmFveDisplayScreen;
2894#endif
2895
2896 /* Check if any bypass options are enabled */
2898 &DisableIntegrity,
2899 &TestSigning);
2900 if (!DisableIntegrity)
2901 {
2902 /* Integrity checks are enabled, so validate our signature */
2904 if (!NT_SUCCESS(Status))
2905 {
2906 /* Signature invalid, fail boot */
2907 goto Failure;
2908 }
2909 }
2910
2911
2912 /* TEST MODE */
2913 EfiPrintf(L"Performing memory allocator tests...\r\n");
2914 {
2916 PHYSICAL_ADDRESS PhysicalAddress, PhysicalAddress2;
2917
2918 /* Allocate 1 physical page */
2921 if (Status != STATUS_SUCCESS)
2922 {
2923 EfiPrintf(L"FAIL: Allocation status: %lx at address: %llx\r\n", Status, PhysicalAddress.QuadPart);
2924 EfiStall(100000000);
2925 }
2926
2927 /* Write some data */
2928 *(PULONG)((ULONG_PTR)PhysicalAddress.QuadPart) = 0x55555151;
2929
2930 /* Free it */
2932 if (Status != STATUS_SUCCESS)
2933 {
2934 EfiPrintf(L"FAIL: Memory free status: %lx\r\n", Status);
2935 EfiStall(100000000);
2936 }
2937
2938 /* Allocate a page again */
2939 PhysicalAddress2.QuadPart = 0;
2940 Status = BlMmAllocatePhysicalPages(&PhysicalAddress2, BlLoaderData, 1, 0, 1);
2941 if (Status != STATUS_SUCCESS)
2942 {
2943 EfiPrintf(L"FAIL: Allocation status: %lx at address: %llx\r\n", Status, PhysicalAddress2.QuadPart);
2944 EfiStall(100000000);
2945 }
2946
2947 /* It should've given us the same page, since we freed it */
2948 if (PhysicalAddress.QuadPart != PhysicalAddress2.QuadPart)
2949 {
2950 EfiPrintf(L"FAIL: Non-matching addresses: %llx %llx\r\n", PhysicalAddress.QuadPart, PhysicalAddress2.QuadPart);
2951 EfiStall(100000000);
2952 }
2953
2954 /* The data should still be there, since zero-ing is not on for bootmgr */
2955 if (*(PULONG)((ULONG_PTR)PhysicalAddress2.QuadPart) != 0x55555151)
2956 {
2957 EfiPrintf(L"FAIL: Non-matching data: %lx %lx\r\n", 0x55555151, *(PULONG)((ULONG_PTR)PhysicalAddress2.QuadPart));
2958 EfiStall(100000000);
2959 }
2960
2961 /* And free the second page again */
2963 if (Status != STATUS_SUCCESS)
2964 {
2965 EfiPrintf(L"FAIL: Memory free status: %lx\r\n", Status);
2966 EfiStall(100000000);
2967 }
2968 }
2969
2970 /* Write out the first XML tag */
2971 BlXmiWrite(L"<bootmgr/>");
2972
2973 /* Check for factory reset */
2975
2976 /* Load the revocation list */
2978 if (!NT_SUCCESS(Status))
2979 {
2980 goto Failure;
2981 }
2982
2983 /* Register our custom progress routine */
2985
2986 /* Display state is not currently cached */
2988
2989 /* Check if we need to resume from hibernate */
2990 Status = BmResumeFromHibernate(&ResumeBcdHandle);
2991 if (!NT_SUCCESS(Status))
2992 {
2993 goto Failure;
2994 }
2995
2996#ifdef BL_NET_SUPPORT
2997 /* Register multicast printing routine */
2998 BlUtlRegisterMulticastRoutine();
2999#endif
3000
3001 /* Check if restart on failure is enabled */
3004 &RebootOnError);
3005
3006 /* Check if the boot sequence is persisted */
3009 &PersistBootSequence);
3010 if (!NT_SUCCESS(Status))
3011 {
3012 /* It usually is */
3013 PersistBootSequence = TRUE;
3014 }
3015
3016 /* Check if there's custom actions to take */
3019 &CustomActions);
3020 if ((NT_SUCCESS(Status)) && (CustomActions))
3021 {
3022 /* We don't support this yet */
3023 EfiPrintf(L"Not implemented\r\n");
3025 goto Failure;
3026 }
3027
3028 //BlResourceFindMessage(BM_MSG_TEST);
3029
3030 /* At last, enter the boot selection stage */
3031 SequenceId = 0;
3032 GetEntry = FALSE;
3033 BootFailed = FALSE;
3034 SequenceList = NULL;
3035 BootSequence = NULL;
3036 SequenceCount = 0;
3037 while (1)
3038 {
3039 /* We don't have a boot entry nor a sequence ID */
3040 BootEntry = NULL;
3041 BootOk = FALSE;
3042
3043 /* Do we have a hardcoded boot sequence set? */
3044 if (!(BootSequence) && !(GetEntry))
3045 {
3046 /* Not yet, read the BCD to see if one is there */
3049 &SequenceList,
3050 &SequenceListCount);
3051 if (NT_SUCCESS(Status))
3052 {
3053 /* A GUID list for the boot sequence is set. Extract it */
3054 Status = BmGetBootSequence(BcdHandle,
3055 SequenceList,
3056 SequenceListCount,
3058 &BootSequence,
3059 &SequenceCount);
3060 if (NT_SUCCESS(Status))
3061 {
3062 /* Don't get stuck in a loop repeating this sequence */
3065
3066 /* But do check if we should persist it */
3067 if (PersistBootSequence)
3068 {
3069 /* Yes -- so go select an entry now */
3070 GetEntry = TRUE;
3071 }
3072 else
3073 {
3074 /* We shouldn't, so wipe it from the BCD too */
3075 Status = BmPurgeOption(BcdHandle,
3078 if (!NT_SUCCESS(Status))
3079 {
3080 /* Well that failed */
3081 goto LoopQuickie;
3082 }
3083 }
3084 }
3085 }
3086 else
3087 {
3088 /* No boot entry sequence for us */
3089 BootSequence = NULL;
3090 }
3091 }
3092
3093 /* Do we have a sequence active, and are we still processing it? */
3094 if ((BootSequence) && ((GetEntry) || (SequenceId < SequenceCount)))
3095 {
3096 /* Extract the next entry in the sequence */
3097 BootEntry = BootSequence[SequenceId];
3098 BootSequence[SequenceId] = NULL;
3099
3100 /* Move to the next entry for next time */
3101 SequenceId++;
3102
3103 /* Unless there won't be a a next time? */
3104 if (SequenceId == SequenceCount)
3105 {
3106 /* Clean up, it's the last entry */
3107 BlMmFreeHeap(BootSequence);
3108 BootSequence = NULL;
3109 }
3110 }
3111 else
3112 {
3113 /* Get the selected boot entry from the user */
3114 ExitBootManager = FALSE;
3115 Status = BmpGetSelectedBootEntry(BcdHandle,
3116 &BootEntry,
3117 &BootIndex,
3118 &ExitBootManager);
3119 if (!(NT_SUCCESS(Status)) || (ExitBootManager))
3120 {
3121 /* Selection failed, or user wants to exit */
3122 goto LoopQuickie;
3123 }
3124 }
3125
3126 /* Did we have a BCD open? */
3127 if (BcdHandle)
3128 {
3129 /* Close it, we'll be opening a new one */
3130 BmCloseDataStore(BcdHandle);
3131 BcdHandle = NULL;
3132 }
3133
3134 /* Launch the selected entry */
3135 Status = BmpLaunchBootEntry(BootEntry, &BootIndex, 0, TRUE);
3136 if (NT_SUCCESS(Status))
3137 {
3138 /* Boot worked, uncache display and process the bad memory list */
3141 }
3142 else
3143 {
3144 /* Boot failed -- was it user driven? */
3145 if (Status != STATUS_CANCELLED)
3146 {
3147 /* Nope, remember that booting failed */
3148 BootFailed = TRUE;
3149 goto LoopQuickie;
3150 }
3151
3152 /* Yes -- the display is still valid */
3154 }
3155
3156 /* Reopen the BCD */
3157 Status = BmOpenDataStore(&BcdHandle);
3158 if (!NT_SUCCESS(Status))
3159 {
3160 break;
3161 }
3162
3163 /* Put the BCD options back into our entry */
3165
3166 /* Update our options one more time */
3168 if (NT_SUCCESS(Status))
3169 {
3170 /* Boot was 100% OK */
3171 BootOk = TRUE;
3172 }
3173
3174LoopQuickie:
3175 /* Did we have a boot entry? */
3176 if (BootEntry)
3177 {
3178 /* We can destroy it now */
3179 BlDestroyBootEntry(BootEntry);
3180 }
3181
3182 /* Is this the success path? */
3183 if (NT_SUCCESS(Status))
3184 {
3185 /* Did we actually boot something? */
3186 if (!BootOk)
3187 {
3188 /* Bope, fail out */
3189 break;
3190 }
3191 }
3192
3193 /* This is the failure path... should we reboot? */
3194 if (RebootOnError)
3195 {
3196 break;
3197 }
3198 };
3199
3200Failure:
3201 if (!BootFailed)
3202 {
3203 /* Check if we got here due to an internal error */
3205 {
3206 /* If XML is available, display the error */
3207 if (XmlLoaded)
3208 {
3209 //BmDisplayDumpError(0, 0);
3210 //BmErrorPurge();
3211 }
3212
3213 /* Don't do a fatal error -- return back to firmware */
3214 goto Quickie;
3215 }
3216 }
3217
3218 /* Log a general fatal error once we're here */
3220
3221Quickie:
3222 /* Check if we should reboot */
3223 if ((RebootOnError) ||
3225 {
3226 /* Reboot the box */
3227 BlFwReboot();
3229 }
3230 else
3231 {
3232 /* Return back to the caller with the error argument encoded */
3233 ReturnArguments = (PVOID)((ULONG_PTR)BootParameters + BootParameters->ReturnArgumentsOffset);
3234 ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION;
3235 ReturnArguments->Status = Status;
3236
3237 /* Tear down the boot library */
3239 }
3240
3241 /* Return back status */
3242 return Status;
3243}
3244
static USHORT PathLength
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
Type
Definition: Type.h:7
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS BcdDeleteElement(_In_ HANDLE ObjectHandle, _In_ ULONG Type)
Definition: bcd.c:560
@ BcdOSLoaderBoolean_WinPEMode
Definition: bcd.h:119
@ BcdOSLoaderInteger_BootMenuPolicy
Definition: bcd.h:156
@ BcdOSLoaderBoolean_DisableCrashAutoReboot
Definition: bcd.h:120
@ BcdOSLoaderBoolean_OptionsEditOneTime
Definition: bcd.h:158
@ BcdOSLoaderBoolean_EmsEnabled
Definition: bcd.h:153
@ BcdOSLoaderBoolean_AdvancedOptionsOneTime
Definition: bcd.h:157
#define BCD_IMAGE_TYPE_REAL_MODE
Definition: bcd.h:32
#define BCD_APPLICATION_TYPE_NTLDR
Definition: bcd.h:39
#define BCD_APPLICATION_TYPE_BOOTSECTOR
Definition: bcd.h:41
@ BcdBootMgrBoolean_ProcessCustomActionsFirst
Definition: bcd.h:194
@ BcdBootMgrBoolean_NoErrorDisplay
Definition: bcd.h:191
@ BcdBootMgrBoolean_AttemptResume
Definition: bcd.h:187
@ BcdBootMgrObjectList_DisplayOrder
Definition: bcd.h:183
@ BcdBootMgrBoolean_PersistBootSequence
Definition: bcd.h:196
@ BcdBootMgrString_BcdFilePath
Definition: bcd.h:193
@ BcdBootMgrBoolean_DisplayBootMenu
Definition: bcd.h:190
@ BcdBootMgrObject_DefaultObject
Definition: bcd.h:185
@ BcdBootMgrInteger_Timeout
Definition: bcd.h:186
@ BcdBootMgrObjectList_BootSequence
Definition: bcd.h:184
@ BcdBootMgrDevice_BcdDevice
Definition: bcd.h:192
#define BCD_APPLICATION_TYPE_RESUME
Definition: bcd.h:37
struct _BCD_DEVICE_OPTION * PBCD_DEVICE_OPTION
#define BCD_APPLICATION_TYPE_BOOTMGR
Definition: bcd.h:35
@ BcdResumeInteger_BootMenuPolicy
Definition: bcd.h:206
#define BCD_OBJECT_TYPE_APPLICATION
Definition: bcd.h:44
#define BCD_APPLICATION_TYPE_OSLOADER
Definition: bcd.h:36
NTSTATUS BcdOpenObject(_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _Out_ PHANDLE ObjectHandle)
Definition: bcd.c:506
#define BCD_TYPE_DEVICE
Definition: bcd.h:21
#define BCD_APPLICATION_TYPE_STARTUPCOM
Definition: bcd.h:42
#define BCD_APPLICATION_TYPE_SETUPLDR
Definition: bcd.h:40
NTSTATUS BcdOpenStoreFromFile(_In_ PUNICODE_STRING FileName, _In_ PHANDLE StoreHandle)
Definition: bcd.c:1322
NTSTATUS BiGetObjectDescription(_In_ HANDLE ObjectHandle, _Out_ PBCD_OBJECT_DESCRIPTION Description)
Definition: bcd.c:1178
@ BcdLibraryBoolean_AutoRecoveryEnabled
Definition: bcd.h:57
@ BcdLibraryBoolean_PreserveBsdLog
Definition: bcd.h:85
@ BcdLibraryString_Description
Definition: bcd.h:52
@ BcdLibraryDevice_ApplicationDevice
Definition: bcd.h:50
@ BcdLibraryBoolean_DisplayOptionsEdit
Definition: bcd.h:82
@ BcdLibraryObjectList_RecoverySequence
Definition: bcd.h:56
@ BcdLibraryDevice_BsdLogDevice
Definition: bcd.h:83
@ BcdLibraryString_BsdLogPath
Definition: bcd.h:84
@ BcdLibraryBoolean_DisplayAdvancedOptions
Definition: bcd.h:81
@ BcdLibraryInteger_DisplayMessageOverride
Definition: bcd.h:96
@ BcdLibraryString_ApplicationPath
Definition: bcd.h:51
@ BcdLibraryBoolean_RestartOnFailure
Definition: bcd.h:98
@ BcdStartupBoolean_PxeSoftReboot
Definition: bcd.h:224
NTSTATUS BcdEnumerateAndUnpackElements(_In_ HANDLE BcdHandle, _In_ HANDLE ObjectHandle, _Out_opt_ PBCD_ELEMENT Elements, _Inout_ PULONG ElementSize, _Out_ PULONG ElementCount)
Definition: bcd.c:1241
GUID * PGUID
Definition: bdasup.h:12
NTSTATUS BlDisplaySetCursorType(_In_ ULONG Type)
Definition: display.c:969
NTSTATUS BlSecureBootIsEnabled(_Out_ PBOOLEAN SecureBootEnabled)
Definition: firmware.c:732
struct _BL_BCD_OPTION * PBL_BCD_OPTION
#define BL_APPLICATION_FLAG_CONVERTED_FROM_EFI
Definition: bl.h:51
NTSTATUS BlGetBootOptionBoolean(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PBOOLEAN Value)
Definition: bcdopt.c:504
#define BL_APPLICATION_ENTRY_FIXED_SEQUENCE
Definition: bl.h:80
PWCHAR BlResourceFindMessage(_In_ ULONG MsgId)
Definition: resource.c:349
#define BL_DEVICE_READ_ACCESS
Definition: bl.h:152
NTSTATUS BlMmAllocatePhysicalPages(_Inout_ PPHYSICAL_ADDRESS Address, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONGLONG PageCount, _In_ ULONG Attributes, _In_ ULONG Alignment)
NTSTATUS MmPapAllocatePhysicalPagesInRange(_Inout_ PPHYSICAL_ADDRESS BaseAddress, _In_ BL_MEMORY_TYPE MemoryType, _In_ ULONGLONG Pages, _In_ ULONG Attributes, _In_ ULONG Alignment, _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, _In_opt_ PBL_ADDRESS_RANGE Range, _In_ ULONG RangeType)
Definition: pagealloc.c:438
NTSTATUS BlFileOpen(_In_ ULONG DeviceId, _In_ PWCHAR FileName, _In_ ULONG Flags, _Out_ PULONG FileId)
Definition: file.c:477
VOID BlImgQueryCodeIntegrityBootOptions(_In_ PBL_LOADED_APPLICATION_ENTRY ApplicationEntry, _Out_ PBOOLEAN IntegrityChecksDisabled, _Out_ PBOOLEAN TestSigning)
Definition: image.c:651
@ BlApplicationReserved
Definition: bl.h:321
@ BlLoaderData
Definition: bl.h:313
VOID BlDestroyBootEntry(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry)
Definition: bootlib.c:442
NTSTATUS BlInitializeLibrary(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootAppParameters, _In_ PBL_LIBRARY_PARAMETERS LibraryParameters)
Definition: bootlib.c:355
VOID EfiPrintf(_In_ PWCHAR Format,...)
Definition: firmware.c:126
NTSTATUS BlUtlRegisterProgressRoutine(VOID)
Definition: util.c:244
#define BL_FILE_WRITE_ACCESS
Definition: bl.h:148
NTSTATUS BlGetBootOptionGuidList(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PGUID *Value, _In_ PULONG Count)
Definition: bcdopt.c:266
#define BL_DEVICE_WRITE_ACCESS
Definition: bl.h:153
@ BlNone
Definition: bl.h:230
#define BL_APPLICATION_ENTRY_DISPLAY_ORDER
Definition: bl.h:79
VOID BiDereferenceHive(_In_ HANDLE KeyHandle)
Definition: bootreg.c:117
#define BL_APPLICATION_ENTRY_RECOVERY
Definition: bl.h:81
NTSTATUS BlGetBootOptionDevice(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PBL_DEVICE_DESCRIPTOR *Value, _In_opt_ PBL_BCD_OPTION *ExtraOptions)
Definition: bcdopt.c:321
PVOID BlMmAllocateHeap(_In_ SIZE_T Size)
Definition: heapalloc.c:569
NTSTATUS BlpDeviceOpen(_In_ PBL_DEVICE_DESCRIPTOR Device, _In_ ULONG Flags, _In_ ULONG Unknown, _Out_ PULONG DeviceId)
Definition: device.c:2111
NTSTATUS BlDeviceClose(_In_ ULONG DeviceId)
Definition: device.c:2073
NTSTATUS BlReplaceBootOptions(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ PBL_BCD_OPTION NewOptions)
Definition: bcdopt.c:824
#define BL_RETURN_ARGUMENTS_NO_PAE_FLAG
Definition: bl.h:66
NTSTATUS BlMmFreePhysicalPages(_In_ PHYSICAL_ADDRESS Address)
Definition: pagealloc.c:1187
BL_MEMORY_DESCRIPTOR_LIST MmMdlUnmappedAllocated
Definition: pagealloc.c:38
PBL_DEVICE_DESCRIPTOR BlpBootDevice
Definition: bootlib.c:16
ULONG BlGetBootOptionSize(_In_ PBL_BCD_OPTION BcdOption)
Definition: bcdopt.c:115
#define BL_LIBRARY_FLAG_REINITIALIZE
Definition: bl.h:128
#define BL_MM_REQUEST_DEFAULT_TYPE
Definition: bl.h:121
@ BootOptions
Definition: bl.h:898
@ Recover
Definition: bl.h:892
@ RecoverOem
Definition: bl.h:893
@ AdvancedOptions
Definition: bl.h:897
@ Reboot
Definition: bl.h:891
@ NextOs
Definition: bl.h:895
@ TryAgain
Definition: bl.h:896
@ OsSelection
Definition: bl.h:894
#define BL_APPLICATION_ENTRY_SETUPLDR
Definition: bl.h:76
PWCHAR BlResourceFindHtml(VOID)
Definition: resource.c:305
VOID BiCloseKey(_In_ HANDLE KeyHandle)
Definition: bootreg.c:141
ULONG BlpApplicationFlags
Definition: bootlib.c:21
NTSTATUS BlSecureBootCheckForFactoryReset(VOID)
Definition: firmware.c:759
NTSTATUS BlAppendBootOptionInteger(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ ULONG OptionId, _In_ ULONGLONG Value)
Definition: bcdopt.c:657
NTSTATUS BlGetBootOptionGuid(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PGUID Value)
Definition: bcdopt.c:228
NTSTATUS BlFwEnumerateDevice(_In_ PBL_DEVICE_DESCRIPTOR Device)
Definition: firmware.c:2375
NTSTATUS BlAppendBootOptions(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ PBL_BCD_OPTION Options)
Definition: bcdopt.c:737
@ UdpDevice
Definition: bl.h:250
#define BL_APPLICATION_ENTRY_BOOTSECTOR
Definition: bl.h:77
NTSTATUS BlPdQueryData(_In_ const GUID *DataGuid, _In_ PVOID Unknown, _Inout_ PBL_PD_DATA_BLOB DataBlob)
Definition: bootlib.c:457
NTSTATUS EfiStall(_In_ ULONG StallTime)
Definition: firmware.c:1003
#define BL_APPLICATION_ENTRY_NTLDR
Definition: bl.h:73
VOID BlRemoveBootOption(_In_ PBL_BCD_OPTION List, _In_ ULONG Type)
Definition: bcdopt.c:801
PGUID BlGetApplicationIdentifier(VOID)
Definition: bootlib.c:414
FORCEINLINE VOID BlSetupDefaultParameters(_Out_ PBL_LIBRARY_PARAMETERS LibraryParameters)
Definition: bl.h:1354
@ LocalDevice
Definition: bl.h:261
@ CdRomDevice
Definition: bl.h:263
BL_LIBRARY_PARAMETERS BlpLibraryParameters
Definition: bootlib.c:15
VOID BlDestroyLibrary(VOID)
Definition: bootlib.c:405
BOOLEAN BlDisplayValidOemBitmap(VOID)
Definition: display.c:880
#define BL_LIBRARY_FLAG_REINITIALIZE_ALL
Definition: bl.h:129
NTSTATUS BlImgLoadBootApplication(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _Out_ PULONG AppHandle)
Definition: image.c:1324
NTSTATUS BlCopyBootOptions(_In_ PBL_BCD_OPTION OptionList, _Out_ PBL_BCD_OPTION *CopiedOptions)
Definition: bcdopt.c:597
@ MenuPolicyLegacy
Definition: bl.h:217
@ MenuPolicyStandard
Definition: bl.h:218
NTSTATUS BlAppendBootOptionString(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ ULONG OptionId, _In_ PWCHAR OptionString)
Definition: bcdopt.c:689
#define BL_FILE_READ_ACCESS
Definition: bl.h:147
NTSTATUS BlGetBootOptionString(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PWCHAR *Value)
Definition: bcdopt.c:146
VOID BlFwReboot(VOID)
Definition: fwutil.c:14
@ BlMemoryBelow1MB
Definition: bl.h:369
#define BL_APPLICATION_ENTRY_WINRESUME
Definition: bl.h:75
BL_LOADED_APPLICATION_ENTRY BlpApplicationEntry
Definition: bootlib.c:19
NTSTATUS BlFileClose(_In_ ULONG FileId)
Definition: file.c:220
#define BL_APPLICATION_ENTRY_STARTUP
Definition: bl.h:71
PBL_BCD_OPTION MiscGetBootOption(_In_ PBL_BCD_OPTION List, _In_ ULONG Type)
Definition: bcdopt.c:17
struct _BL_BCD_OPTION BL_BCD_OPTION
NTSTATUS BlMmFreeHeap(_In_ PVOID Buffer)
Definition: heapalloc.c:663
#define BL_APPLICATION_ENTRY_WINLOAD
Definition: bl.h:70
VOID BlStatusPrint(_In_ PCWCH Format,...)
Definition: debug.c:75
enum _BL_MENU_POLICY BL_MENU_POLICY
NTSTATUS BlImgUnloadBootApplication(_In_ ULONG AppHandle)
Definition: image.c:2021
NTSTATUS BlImgStartBootApplication(_In_ ULONG AppHandle, _Inout_ PBL_RETURN_ARGUMENTS ReturnArguments)
VOID BlStatusError(_In_ ULONG ErrorCode, _In_ ULONG Parameter1, _In_ ULONG_PTR Parameter2, _In_ ULONG_PTR Parameter3, _In_ ULONG_PTR Parameter4)
Definition: debug.c:121
NTSTATUS BlAppendBootOptionBoolean(_In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, _In_ ULONG OptionId, _In_ BOOLEAN Value)
Definition: bcdopt.c:625
NTSTATUS BlGetBootOptionInteger(_In_ PBL_BCD_OPTION List, _In_ ULONG Type, _Out_ PULONGLONG Value)
Definition: bcdopt.c:467
NTSTATUS BlDisplayClearScreen(VOID)
Definition: display.c:943
ULONG BlGetBootOptionListSize(_In_ PBL_BCD_OPTION BcdOption)
Definition: bcdopt.c:79
#define BL_RETURN_ARGUMENTS_VERSION
Definition: bl.h:63
#define BL_APPLICATION_ENTRY_REBOOT_ON_ERROR
Definition: bl.h:72
#define BL_FATAL_ERROR_NO_PAE
Definition: bootmgr.h:60
#define BL_FATAL_ERROR_BCD_READ
Definition: bootmgr.h:55
#define BL_FATAL_ERROR_GENERIC
Definition: bootmgr.h:58
#define BL_FATAL_ERROR_BCD_PARSE
Definition: bootmgr.h:59
#define BL_FATAL_ERROR_BCD_ENTRIES
Definition: bootmgr.h:57
#define BL_FATAL_ERROR_APP_LOAD
Definition: bootmgr.h:56
Definition: bufpool.h:45
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define NTSTATUS
Definition: precomp.h:21
static const WCHAR Description[]
Definition: oid.c:1266
#define swprintf
Definition: precomp.h:40
#define ULONG_PTR
Definition: config.h:101
VOID BmpInitializeBootStatusDataLog(VOID)
Definition: bootmgr.c:951
NTSTATUS BmpProcessBadMemory(VOID)
Definition: bootmgr.c:1163
VOID BmpProcessBootEntry(_In_ HANDLE BcdHandle, _In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _Out_ PBOOLEAN ExitBootManager)
Definition: bootmgr.c:1774
NTSTATUS BmpBgDisplayClearScreen(_In_ ULONG Color)
Definition: bootmgr.c:1056
NTSTATUS NTAPI BmMain(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters)
Definition: bootmgr.c:2736
BL_BSD_LOG_OBJECT BsdpLogObject
Definition: bootmgr.c:880
VOID BmErrorPurge(VOID)
Definition: bootmgr.c:445
NTSTATUS BlXmiWrite(_In_ PWCHAR XmlTag)
Definition: bootmgr.c:1065
NTSTATUS BmGetBootSequence(_In_ HANDLE BcdHandle, _In_ PGUID SequenceList, _In_ ULONG SequenceListCount, _In_ ULONG Flags, _Out_ PBL_LOADED_APPLICATION_ENTRY **BootSequence, _Out_ PULONG SequenceCount)
Definition: bootmgr.c:1465
NTSTATUS BmpFwGetFullPath(_In_ PWCHAR FileName, _Out_ PWCHAR *FullPath)
Definition: bootmgr.c:644
struct _BL_BSD_LOG_OBJECT BL_BSD_LOG_OBJECT
NTSTATUS BmpCreateDevices(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry)
Definition: bootmgr.c:2170
PWCHAR ParentFileName
Definition: bootmgr.c:32
NTSTATUS BmFwVerifySelfIntegrity(VOID)
Definition: bootmgr.c:1087
BL_BOOT_ERROR BmpErrorBuffer
Definition: bootmgr.c:26
NTSTATUS BmFwInitializeBootDirectoryPath(VOID)
Definition: bootmgr.c:301
VOID BmCloseDataStore(_In_ HANDLE Handle)
Definition: bootmgr.c:695
PWCHAR BootDirectory
Definition: bootmgr.c:24
BL_MENU_POLICY BmGetBootMenuPolicy(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry)
Definition: bootmgr.c:1685
BL_PACKED_BOOT_ERROR BmpPackedBootError
Definition: bootmgr.c:28
PBL_LOADED_APPLICATION_ENTRY * BmpFailedBootEntries
Definition: bootmgr.c:35
NTSTATUS BlXmiInitialize(_In_ PWCHAR Stylesheet)
Definition: bootmgr.c:1075
VOID BmFatalErrorEx(_In_ ULONG ErrorCode, _In_ ULONG_PTR Parameter1, _In_ ULONG_PTR Parameter2, _In_ ULONG_PTR Parameter3, _In_ ULONG_PTR Parameter4)
Definition: bootmgr.c:498
VOID BmDisplayGetBootMenuStatus(_Out_ PL_MENU_STATUS MenuStatus)
Definition: bootmgr.c:1753
PBL_LOADED_APPLICATION_ENTRY BmpSelectedBootEntry
Definition: bootmgr.c:36
BOOLEAN BmBootIniUsed
Definition: bootmgr.c:30
NTSTATUS BmpLaunchBootEntry(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _Out_ PULONG EntryIndex, _In_ ULONG LaunchCode, _In_ BOOLEAN LaunchWinRe)
Definition: bootmgr.c:2426
NTSTATUS BmOpenDataStore(_Out_ PHANDLE Handle)
Definition: bootmgr.c:711
NTSTATUS BmFwRegisterRevocationList(VOID)
Definition: bootmgr.c:1105
NTSTATUS BmEnumerateBootEntries(_In_ HANDLE BcdHandle, _Out_ PBL_LOADED_APPLICATION_ENTRY **BootSequence, _Out_ PULONG SequenceCount)
Definition: bootmgr.c:1509
NTSTATUS BmOpenBootIni(VOID)
Definition: bootmgr.c:400
NTSTATUS BmGetOptionList(_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _In_ PBL_BCD_OPTION *OptionList)
Definition: bootmgr.c:43
ULONG BmpFatalErrorMessageFilter(_In_ NTSTATUS ErrorStatus, _Out_ PULONG ErrorResourceId)
Definition: bootmgr.c:409
VOID BmpGetDefaultBootEntry(_In_ PBL_LOADED_APPLICATION_ENTRY *Sequence, _In_ ULONG Count, _Out_ PBL_LOADED_APPLICATION_ENTRY *DefaultEntry, _Out_ PULONG DefaultIndex)
Definition: bootmgr.c:1638
NTSTATUS BmpPopulateBootEntryList(_In_ HANDLE BcdHandle, _In_ PGUID SequenceList, _In_ ULONG Flags, _Out_ PBL_LOADED_APPLICATION_ENTRY *BootSequence, _Out_ PULONG SequenceCount)
Definition: bootmgr.c:1247
BOOLEAN BmpDisplayBootMenu
Definition: bootmgr.c:38
BOOLEAN BmDisplayStateCached
Definition: bootmgr.c:34
NTSTATUS BmpTransferExecution(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _Out_ PULONG LaunchCode, _Out_ PBOOLEAN Recover)
Definition: bootmgr.c:2230
ULONG BmDisplayDumpError(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _In_ ULONG LaunchCode)
Definition: bootmgr.c:2127
NTSTATUS BmPurgeOption(_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _In_ ULONG Type)
Definition: bootmgr.c:1187
ULONGLONG ApplicationStartTime
Definition: bootmgr.c:21
struct _BL_BSD_LOG_OBJECT * PBL_BSD_LOG_OBJECT
NTSTATUS BmpUpdateApplicationOptions(_In_ HANDLE BcdHandle)
Definition: bootmgr.c:208
NTSTATUS BmProcessCustomAction(_In_ HANDLE BcdHandle, _In_ PWCHAR ActionKey)
Definition: bootmgr.c:1764
NTSTATUS BmpFwGetApplicationDirectoryPath(_In_ PUNICODE_STRING ApplicationDirectoryPath)
Definition: bootmgr.c:229
BOOLEAN BmBootEntryOverridePresent
Definition: bootmgr.c:37
VOID BlBsdInitializeLog(_In_ PBL_DEVICE_DESCRIPTOR LogDevice, _In_ PWCHAR LogPath, _In_ ULONG Flags)
Definition: bootmgr.c:884
ULONGLONG PostTime
Definition: bootmgr.c:22
NTSTATUS BmResumeFromHibernate(_Out_ PHANDLE BcdResumeHandle)
Definition: bootmgr.c:1130
BOOLEAN BsdpLogObjectInitialized
Definition: bootmgr.c:881
GUID BmApplicationIdentifier
Definition: bootmgr.c:23
VOID BmFwMemoryInitialize(VOID)
Definition: bootmgr.c:1026
VOID BmpErrorLog(_In_ ULONG ErrorCode, _In_ NTSTATUS ErrorStatus, _In_ ULONG ErrorMsgId, _In_ PWCHAR FileName, _In_ ULONG HelpMsgId)
Definition: bootmgr.c:464
NTSTATUS BmLaunchRecoverySequence(_In_ PBL_LOADED_APPLICATION_ENTRY BootEntry, _In_ ULONG LaunchCode)
Definition: bootmgr.c:2011
NTSTATUS BmGetEntryDescription(_In_ HANDLE BcdHandle, _In_ PGUID ObjectId, _Out_ PBCD_OBJECT_DESCRIPTION Description)
Definition: bootmgr.c:1213
NTSTATUS BmpGetSelectedBootEntry(_In_ HANDLE BcdHandle, _Out_ PBL_LOADED_APPLICATION_ENTRY *SelectedBootEntry, _Out_ PULONG EntryIndex, _Out_ PBOOLEAN ExitBootManager)
Definition: bootmgr.c:1814
WCHAR BmpFileNameBuffer[128]
Definition: bootmgr.c:31
PBL_BOOT_ERROR BmpInternalBootError
Definition: bootmgr.c:27
struct _FileName FileName
Definition: fatprocs.h:897
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
DWORD FormatString(DWORD dwFlags, HINSTANCE hInstance, DWORD dwStringId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list *Arguments)
Definition: fontview.c:34
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
PPC_QUAL unsigned long long __rdtsc(void)
Definition: intrin_ppc.h:688
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
ObjectType
Definition: metafile.c:81
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
int Count
Definition: noreturn.cpp:7
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define UNICODE_NULL
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_INVALID_IMAGE_WIN_64
Definition: ntstatus.h:901
#define STATUS_FVE_LOCKED_VOLUME
Definition: ntstatus.h:1454
#define STATUS_IMAGE_CHECKSUM_MISMATCH
Definition: ntstatus.h:677
#define STATUS_INVALID_PARAMETER_9
Definition: ntstatus.h:483
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_FILE_INVALID
Definition: ntstatus.h:388
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
#define L(x)
Definition: ntvdm.h:50
static ULONG Timeout
Definition: ping.c:61
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
@ Restart
Definition: sacdrv.h:269
_CRTIMP wchar_t *__cdecl wcsncat(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
ULONG PackedValue
Definition: bcd.h:234
ULONG Format
Definition: bcd.h:238
base of all file and directory entries
Definition: entries.h:83
BL_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: bcd.h:298
GUID AssociatedEntry
Definition: bcd.h:297
PBCD_ELEMENT_HEADER Header
Definition: bcd.h:291
ULONGLONG Maximum
Definition: bl.h:1015
ULONGLONG Minimum
Definition: bl.h:1014
ULONG DataSize
Definition: bl.h:848
ULONG ListOffset
Definition: bl.h:849
ULONG Empty
Definition: bl.h:851
ULONG NextEntryOffset
Definition: bl.h:850
ULONG Type
Definition: bl.h:846
ULONG DataOffset
Definition: bl.h:847
ULONG HelpMsgId
Definition: bootmgr.h:44
ULONG Unknown1
Definition: bootmgr.h:41
NTSTATUS ErrorStatus
Definition: bootmgr.h:40
ULONG ErrorCode
Definition: bootmgr.h:39
ULONG Unknown2
Definition: bootmgr.h:45
PWCHAR ErrorString
Definition: bootmgr.h:42
PWCHAR FileName
Definition: bootmgr.h:43
DEVICE_TYPE DeviceType
Definition: bl.h:950
BL_LOCAL_DEVICE Local
Definition: bl.h:956
ULONG MinimumHeapSize
Definition: bl.h:760
ULONG LibraryFlags
Definition: bl.h:757
ULONG MinimumAllocationCount
Definition: bl.h:759
ULONG TranslationType
Definition: bl.h:758
Definition: bl.h:864
ULONG Flags
Definition: bl.h:865
PBL_BCD_OPTION BcdData
Definition: bl.h:867
GUID Guid
Definition: bl.h:866
BL_LOCAL_DEVICE_TYPE Type
Definition: bl.h:925
ULONG OemKey
Definition: bl.h:879
WCHAR KeyValue
Definition: bl.h:886
ULONG Exit
Definition: bl.h:880
ULONG AnyKey
Definition: bl.h:876
PBL_BOOT_ERROR BootError
Definition: bootmgr.h:50
ULONG DataSize
Definition: bl.h:1346
ULONG BlobSize
Definition: bl.h:1347
PVOID Data
Definition: bl.h:1345
ULONG Version
Definition: bl.h:816
NTSTATUS Status
Definition: bl.h:817
USHORT MaximumLength
Definition: env_spec_w32.h:370
static PCWSTR OptionList[]
Definition: tasklist.c:12
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_Must_inspect_result_ _In_ WDFOBJECT _In_ CONST GUID * Guid
Definition: wdfobject.h:762
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
__wchar_t WCHAR
Definition: xmlstorage.h:180