1 /* INCLUDES ******************************************************************/
6 #include "bootvid/bootvid.h"
9 #define TAG_OSTR 'RTSO'
12 /* GLOBALS *******************************************************************/
15 * Enable this define if you want Inbv to use coloured headless mode.
17 // #define INBV_HEADLESS_COLORS
20 * ReactOS uses the same boot screen for all the products.
21 * Also it doesn't use a parallel system thread for the
22 * rotating "progress" bar.
26 * Enable this define when ReactOS will have different SKUs
27 * (Workstation, Server, Storage Server, Cluster Server, etc...).
29 // #define REACTOS_SKUS
32 * Enable this define when Inbv will support rotating progress bar.
34 #define INBV_ROTBAR_IMPLEMENTED
36 static KSPIN_LOCK BootDriverLock
;
37 static KIRQL InbvOldIrql
;
38 static INBV_DISPLAY_STATE InbvDisplayState
= INBV_DISPLAY_STATE_DISABLED
;
39 BOOLEAN InbvBootDriverInstalled
= FALSE
;
40 static BOOLEAN InbvDisplayDebugStrings
= FALSE
;
41 static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter
= NULL
;
42 static ULONG ProgressBarLeft
= 0, ProgressBarTop
= 0;
43 static BOOLEAN ShowProgressBar
= FALSE
;
44 static INBV_PROGRESS_STATE InbvProgressState
;
45 static BT_PROGRESS_INDICATOR InbvProgressIndicator
= {0, 25, 0};
46 static INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters
= NULL
;
47 static ULONG ResourceCount
= 0;
48 static PUCHAR ResourceList
[1 + IDB_MAX_RESOURCE
]; // First entry == NULL, followed by 'ResourceCount' entries.
50 #ifdef INBV_ROTBAR_IMPLEMENTED
52 * Change this to modify progress bar behaviour
54 #define ROT_BAR_DEFAULT_MODE RB_PROGRESS_BAR
57 * Values for PltRotBarStatus:
58 * - PltRotBarStatus == 1, do palette fading-in (done elsewhere in ReactOS);
59 * - PltRotBarStatus == 2, do rotation bar animation;
60 * - PltRotBarStatus == 3, stop the animation thread.
61 * - Any other value is ignored and the animation thread continues to run.
63 typedef enum _ROT_BAR_STATUS
71 static BOOLEAN RotBarThreadActive
= FALSE
;
72 static ROT_BAR_TYPE RotBarSelection
= RB_UNSPECIFIED
;
73 static ROT_BAR_STATUS PltRotBarStatus
= 0;
74 static UCHAR RotBarBuffer
[24 * 9];
75 static UCHAR RotLineBuffer
[640 * 6];
80 * Headless terminal text colors
83 #ifdef INBV_HEADLESS_COLORS
85 // Conversion table CGA to ANSI color index
86 static const UCHAR CGA_TO_ANSI_COLOR_TABLE
[16] =
102 65, // Bright Magenta
104 67 // Bright Grey (White)
107 #define CGA_TO_ANSI_COLOR(CgaColor) \
108 CGA_TO_ANSI_COLOR_TABLE[CgaColor & 0x0F]
112 // Default colors: text in white, background in black
113 static ULONG InbvTerminalTextColor
= 37;
114 static ULONG InbvTerminalBkgdColor
= 40;
117 /* FADING FUNCTION ***********************************************************/
119 /** From include/psdk/wingdi.h **/
120 typedef struct tagRGBQUAD
126 } RGBQUAD
,*LPRGBQUAD
;
127 /*******************************/
129 static RGBQUAD MainPalette
[16];
131 #define PALETTE_FADE_STEPS 15
132 #define PALETTE_FADE_TIME (20 * 1000) /* 20 ms */
134 /** From bootvid/precomp.h **/
138 typedef struct tagBITMAPINFOHEADER
147 LONG biXPelsPerMeter
;
148 LONG biYPelsPerMeter
;
150 ULONG biClrImportant
;
151 } BITMAPINFOHEADER
, *PBITMAPINFOHEADER
;
152 /****************************/
157 VOID NTAPI
InbvAcquireLock(VOID
);
158 VOID NTAPI
InbvReleaseLock(VOID
);
163 UCHAR PaletteBitmapBuffer
[sizeof(BITMAPINFOHEADER
) + sizeof(MainPalette
)];
164 PBITMAPINFOHEADER PaletteBitmap
= (PBITMAPINFOHEADER
)PaletteBitmapBuffer
;
165 LPRGBQUAD Palette
= (LPRGBQUAD
)(PaletteBitmapBuffer
+ sizeof(BITMAPINFOHEADER
));
166 ULONG Iteration
, Index
, ClrUsed
;
169 Delay
.QuadPart
= - (PALETTE_FADE_TIME
* 10);
171 /* Check if we are installed and we own the display */
172 if (!InbvBootDriverInstalled
||
173 (InbvDisplayState
!= INBV_DISPLAY_STATE_OWNED
))
179 * Build a bitmap containing the fade-in palette. The palette entries
180 * are then processed in a loop and set using VidBitBlt function.
182 ClrUsed
= RTL_NUMBER_OF(MainPalette
);
183 RtlZeroMemory(PaletteBitmap
, sizeof(BITMAPINFOHEADER
));
184 PaletteBitmap
->biSize
= sizeof(BITMAPINFOHEADER
);
185 PaletteBitmap
->biBitCount
= 4;
186 PaletteBitmap
->biClrUsed
= ClrUsed
;
189 * Main animation loop.
191 for (Iteration
= 0; Iteration
<= PALETTE_FADE_STEPS
; ++Iteration
)
193 for (Index
= 0; Index
< ClrUsed
; Index
++)
195 Palette
[Index
].rgbRed
= (UCHAR
)
196 (MainPalette
[Index
].rgbRed
* Iteration
/ PALETTE_FADE_STEPS
);
197 Palette
[Index
].rgbGreen
= (UCHAR
)
198 (MainPalette
[Index
].rgbGreen
* Iteration
/ PALETTE_FADE_STEPS
);
199 Palette
[Index
].rgbBlue
= (UCHAR
)
200 (MainPalette
[Index
].rgbBlue
* Iteration
/ PALETTE_FADE_STEPS
);
203 /* Do the animation */
205 VidBitBlt(PaletteBitmapBuffer
, 0, 0);
209 KeDelayExecutionThread(KernelMode
, FALSE
, &Delay
);
213 /* FUNCTIONS *****************************************************************/
218 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
221 UNICODE_STRING UpString
= RTL_CONSTANT_STRING(L
"ntoskrnl.exe");
222 UNICODE_STRING MpString
= RTL_CONSTANT_STRING(L
"ntkrnlmp.exe");
223 PLIST_ENTRY NextEntry
, ListHead
;
224 PLDR_DATA_TABLE_ENTRY LdrEntry
;
225 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry
;
226 LDR_RESOURCE_INFO ResourceInfo
;
230 /* Loop the driver list */
231 ListHead
= &LoaderBlock
->LoadOrderListHead
;
232 NextEntry
= ListHead
->Flink
;
233 while (NextEntry
!= ListHead
)
236 LdrEntry
= CONTAINING_RECORD(NextEntry
,
237 LDR_DATA_TABLE_ENTRY
,
240 /* Check for a match */
241 if (RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &UpString
, TRUE
) ||
242 RtlEqualUnicodeString(&LdrEntry
->BaseDllName
, &MpString
, TRUE
))
249 /* Check if we found it */
250 if (NextEntry
!= ListHead
)
252 /* Try to find the resource */
253 ResourceInfo
.Type
= 2; // RT_BITMAP;
254 ResourceInfo
.Name
= ResourceId
;
255 ResourceInfo
.Language
= 0;
256 Status
= LdrFindResource_U(LdrEntry
->DllBase
,
260 if (NT_SUCCESS(Status
))
262 /* Access the resource */
264 Status
= LdrAccessResource(LdrEntry
->DllBase
,
268 if ((Data
) && (ResourceId
< 3))
270 KiBugCheckData
[4] ^= RtlComputeCrc32(0, Data
, Size
);
272 if (!NT_SUCCESS(Status
)) Data
= NULL
;
276 /* Return the pointer */
283 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock
,
287 BOOLEAN ResetMode
= FALSE
; // By default do not reset the video mode
290 /* Quit if we're already installed */
291 if (InbvBootDriverInstalled
) return TRUE
;
293 /* Initialize the lock and check the current display state */
294 KeInitializeSpinLock(&BootDriverLock
);
295 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
297 /* Reset the video mode in case we do not have a custom boot logo */
298 CommandLine
= (LoaderBlock
->LoadOptions
? _strupr(LoaderBlock
->LoadOptions
) : NULL
);
299 ResetMode
= (CommandLine
== NULL
) || (strstr(CommandLine
, "BOOTLOGO") == NULL
);
302 /* Initialize the video */
303 InbvBootDriverInstalled
= VidInitialize(ResetMode
);
304 if (InbvBootDriverInstalled
)
306 /* Find bitmap resources in the kernel */
307 ResourceCount
= min(Count
, RTL_NUMBER_OF(ResourceList
) - 1);
308 for (i
= 1; i
<= ResourceCount
; i
++)
311 ResourceList
[i
] = FindBitmapResource(LoaderBlock
, i
);
314 /* Set the progress bar ranges */
315 InbvSetProgressBarSubset(0, 100);
318 /* Return install state */
319 return InbvBootDriverInstalled
;
324 InbvAcquireLock(VOID
)
328 /* Check if we're at dispatch level or lower */
329 OldIrql
= KeGetCurrentIrql();
330 if (OldIrql
<= DISPATCH_LEVEL
)
332 /* Loop until the lock is free */
333 while (!KeTestSpinLock(&BootDriverLock
));
335 /* Raise IRQL to dispatch level */
336 KeRaiseIrql(DISPATCH_LEVEL
, &OldIrql
);
339 /* Acquire the lock */
340 KiAcquireSpinLock(&BootDriverLock
);
341 InbvOldIrql
= OldIrql
;
346 InbvReleaseLock(VOID
)
350 /* Capture the old IRQL */
351 OldIrql
= InbvOldIrql
;
353 /* Release the driver lock */
354 KiReleaseSpinLock(&BootDriverLock
);
356 /* If we were at dispatch level or lower, restore the old IRQL */
357 if (InbvOldIrql
<= DISPATCH_LEVEL
) KeLowerIrql(OldIrql
);
363 InbvEnableBootDriver(IN BOOLEAN Enable
)
365 /* Check if we're installed */
366 if (InbvBootDriverInstalled
)
368 /* Check for lost state */
369 if (InbvDisplayState
>= INBV_DISPLAY_STATE_LOST
) return;
371 /* Acquire the lock */
374 /* Cleanup the screen if we own it */
375 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
) VidCleanUp();
377 /* Set the new display state */
378 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
379 INBV_DISPLAY_STATE_DISABLED
;
381 /* Release the lock */
386 /* Set the new display state */
387 InbvDisplayState
= Enable
? INBV_DISPLAY_STATE_OWNED
:
388 INBV_DISPLAY_STATE_DISABLED
;
394 InbvAcquireDisplayOwnership(VOID
)
396 /* Check if we have a callback and we're just acquiring it now */
397 if ((InbvResetDisplayParameters
) &&
398 (InbvDisplayState
== INBV_DISPLAY_STATE_LOST
))
400 /* Call the callback */
401 InbvResetDisplayParameters(80, 50);
404 /* Acquire the display */
405 InbvDisplayState
= INBV_DISPLAY_STATE_OWNED
;
410 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned
)
412 /* Set the new display state */
413 InbvDisplayState
= DisplayOwned
? INBV_DISPLAY_STATE_OWNED
:
414 INBV_DISPLAY_STATE_LOST
;
419 InbvCheckDisplayOwnership(VOID
)
421 /* Return if we own it or not */
422 return InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
;
427 InbvGetDisplayState(VOID
)
429 /* Return the actual state */
430 return InbvDisplayState
;
435 InbvDisplayString(IN PCHAR String
)
437 /* Make sure we own the display */
438 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
440 /* If we're not allowed, return success anyway */
441 if (!InbvDisplayDebugStrings
) return TRUE
;
443 /* Check if a filter is installed */
444 if (InbvDisplayFilter
) InbvDisplayFilter(&String
);
446 /* Acquire the lock */
449 /* Make sure we're installed and display the string */
450 if (InbvBootDriverInstalled
) VidDisplayString((PUCHAR
)String
);
452 /* Print the string on the EMS port */
453 HeadlessDispatch(HeadlessCmdPutString
,
455 strlen(String
) + sizeof(ANSI_NULL
),
459 /* Release the lock */
466 /* We don't own it, fail */
472 InbvEnableDisplayString(IN BOOLEAN Enable
)
476 /* Get the old setting */
477 OldSetting
= InbvDisplayDebugStrings
;
480 InbvDisplayDebugStrings
= Enable
;
482 /* Return the old setting */
488 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter
)
490 /* Save the filter */
491 InbvDisplayFilter
= Filter
;
496 InbvIsBootDriverInstalled(VOID
)
498 /* Return driver state */
499 return InbvBootDriverInstalled
;
504 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback
)
506 /* Check if we're installed */
507 if (InbvBootDriverInstalled
)
509 /* Acquire the lock and cleanup if we own the screen */
511 if (InbvDisplayState
!= INBV_DISPLAY_STATE_LOST
) VidCleanUp();
513 /* Set the reset callback and display state */
514 InbvResetDisplayParameters
= Callback
;
515 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
517 /* Release the lock */
522 /* Set the reset callback and display state */
523 InbvResetDisplayParameters
= Callback
;
524 InbvDisplayState
= INBV_DISPLAY_STATE_LOST
;
530 InbvResetDisplay(VOID
)
532 /* Check if we're installed and we own it */
533 if (InbvBootDriverInstalled
&&
534 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
537 VidResetDisplay(TRUE
);
541 /* Nothing to reset */
547 InbvSetScrollRegion(IN ULONG Left
,
552 /* Just call bootvid */
553 VidSetScrollRegion(Left
, Top
, Right
, Bottom
);
558 InbvSetTextColor(IN ULONG Color
)
560 HEADLESS_CMD_SET_COLOR HeadlessSetColor
;
562 /* Set color for EMS port */
563 #ifdef INBV_HEADLESS_COLORS
564 InbvTerminalTextColor
= 30 + CGA_TO_ANSI_COLOR(Color
);
566 InbvTerminalTextColor
= 37;
568 HeadlessSetColor
.TextColor
= InbvTerminalTextColor
;
569 HeadlessSetColor
.BkgdColor
= InbvTerminalBkgdColor
;
570 HeadlessDispatch(HeadlessCmdSetColor
,
572 sizeof(HeadlessSetColor
),
576 /* Update the text color */
577 VidSetTextColor(Color
);
582 InbvSolidColorFill(IN ULONG Left
,
588 HEADLESS_CMD_SET_COLOR HeadlessSetColor
;
590 /* Make sure we own it */
591 if (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
593 /* Acquire the lock */
596 /* Check if we're installed */
597 if (InbvBootDriverInstalled
)
600 VidSolidColorFill(Left
, Top
, Right
, Bottom
, (UCHAR
)Color
);
603 /* Set color for EMS port and clear display */
604 #ifdef INBV_HEADLESS_COLORS
605 InbvTerminalBkgdColor
= 40 + CGA_TO_ANSI_COLOR(Color
);
607 InbvTerminalBkgdColor
= 40;
609 HeadlessSetColor
.TextColor
= InbvTerminalTextColor
;
610 HeadlessSetColor
.BkgdColor
= InbvTerminalBkgdColor
;
611 HeadlessDispatch(HeadlessCmdSetColor
,
613 sizeof(HeadlessSetColor
),
616 HeadlessDispatch(HeadlessCmdClearDisplay
,
620 /* Release the lock */
628 InbvUpdateProgressBar(IN ULONG Progress
)
630 ULONG FillCount
, BoundedProgress
;
632 /* Make sure the progress bar is enabled, that we own and are installed */
633 if (ShowProgressBar
&&
634 InbvBootDriverInstalled
&&
635 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
637 /* Compute fill count */
638 BoundedProgress
= (InbvProgressState
.Floor
/ 100) + Progress
;
639 FillCount
= 121 * (InbvProgressState
.Bias
* BoundedProgress
) / 1000000;
641 /* Acquire the lock */
644 /* Fill the progress bar */
645 VidSolidColorFill(ProgressBarLeft
,
647 ProgressBarLeft
+ FillCount
,
651 /* Release the lock */
658 InbvBufferToScreenBlt(IN PUCHAR Buffer
,
665 /* Check if we're installed and we own it */
666 if (InbvBootDriverInstalled
&&
667 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
670 VidBufferToScreenBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
676 InbvBitBlt(IN PUCHAR Buffer
,
680 /* Check if we're installed and we own it */
681 if (InbvBootDriverInstalled
&&
682 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
684 /* Acquire the lock */
688 VidBitBlt(Buffer
, X
, Y
);
690 /* Release the lock */
697 InbvScreenToBufferBlt(IN PUCHAR Buffer
,
704 /* Check if we're installed and we own it */
705 if (InbvBootDriverInstalled
&&
706 (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
))
709 VidScreenToBufferBlt(Buffer
, X
, Y
, Width
, Height
, Delta
);
715 InbvSetProgressBarCoordinates(IN ULONG Left
,
718 /* Update the coordinates */
719 ProgressBarLeft
= Left
;
720 ProgressBarTop
= Top
;
722 /* Enable the progress bar */
723 ShowProgressBar
= TRUE
;
728 InbvSetProgressBarSubset(IN ULONG Floor
,
732 ASSERT(Floor
< Ceiling
);
733 ASSERT(Ceiling
<= 100);
735 /* Update the progress bar state */
736 InbvProgressState
.Floor
= Floor
* 100;
737 InbvProgressState
.Ceiling
= Ceiling
* 100;
738 InbvProgressState
.Bias
= (Ceiling
* 100) - Floor
;
744 InbvIndicateProgress(VOID
)
748 /* Increase progress */
749 InbvProgressIndicator
.Count
++;
751 /* Compute new percentage */
752 Percentage
= min(100 * InbvProgressIndicator
.Count
/
753 InbvProgressIndicator
.Expected
,
755 if (Percentage
!= InbvProgressIndicator
.Percentage
)
757 /* Percentage has moved, update the progress bar */
758 InbvProgressIndicator
.Percentage
= Percentage
;
759 InbvUpdateProgressBar(Percentage
);
765 InbvGetResourceAddress(IN ULONG ResourceNumber
)
767 /* Validate the resource number */
768 if (ResourceNumber
> ResourceCount
) return NULL
;
770 /* Return the address */
771 return ResourceList
[ResourceNumber
];
776 NtDisplayString(IN PUNICODE_STRING DisplayString
)
779 UNICODE_STRING CapturedString
;
780 OEM_STRING OemString
;
781 KPROCESSOR_MODE PreviousMode
;
785 PreviousMode
= ExGetPreviousMode();
787 /* We require the TCB privilege */
788 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
789 return STATUS_PRIVILEGE_NOT_HELD
;
791 /* Capture the string */
792 Status
= ProbeAndCaptureUnicodeString(&CapturedString
, PreviousMode
, DisplayString
);
793 if (!NT_SUCCESS(Status
))
796 /* Do not display the string if it is empty */
797 if (CapturedString
.Length
== 0 || CapturedString
.Buffer
== NULL
)
799 Status
= STATUS_SUCCESS
;
804 * Convert the string since INBV understands only ANSI/OEM. Allocate the
805 * string buffer in non-paged pool because INBV passes it down to BOOTVID.
806 * We cannot perform the allocation using RtlUnicodeStringToOemString()
807 * since its allocator uses PagedPool.
809 RtlInitEmptyAnsiString((PANSI_STRING
)&OemString
, NULL
,
810 RtlUnicodeStringToOemSize(&CapturedString
));
811 OemString
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
812 OemString
.MaximumLength
,
814 if (OemString
.Buffer
== NULL
)
816 Status
= STATUS_NO_MEMORY
;
819 RtlUnicodeStringToOemString(&OemString
, &CapturedString
, FALSE
);
821 /* Display the string */
822 InbvDisplayString(OemString
.Buffer
);
824 /* Free the string buffer */
825 ExFreePoolWithTag(OemString
.Buffer
, TAG_OSTR
);
827 Status
= STATUS_SUCCESS
;
830 /* Free the captured string */
831 ReleaseCapturedUnicodeString(&CapturedString
, PreviousMode
);
836 #ifdef INBV_ROTBAR_IMPLEMENTED
843 ULONG X
, Y
, Index
, Total
;
844 LARGE_INTEGER Delay
= {{0}};
847 if (RotBarSelection
== RB_SQUARE_CELLS
)
855 X
= ProgressBarLeft
+ 2;
856 Y
= ProgressBarTop
+ 2;
859 while (InbvDisplayState
== INBV_DISPLAY_STATE_OWNED
)
862 KeDelayExecutionThread(KernelMode
, FALSE
, &Delay
);
866 /* Unknown unexpected command */
867 ASSERT(PltRotBarStatus
< RBS_STATUS_MAX
);
869 if (PltRotBarStatus
== RBS_STOP_ANIMATE
)
871 /* Stop the thread */
876 if (RotBarSelection
== RB_SQUARE_CELLS
)
878 Delay
.QuadPart
= -800000; // 80 ms
884 /* Fill previous bar position */
885 VidSolidColorFill(X
+ ((Index
- 3) * 8), Y
, (X
+ ((Index
- 3) * 8)) + 8 - 1, Y
+ 9 - 1, 0);
887 if (Index
< Total
- 1)
889 /* Draw the progress bar bit */
892 /* Appearing from the left */
893 VidBufferToScreenBlt(RotBarBuffer
+ 8 * (2 - Index
) / 2, X
, Y
, 22 - 8 * (2 - Index
), 9, 24);
895 else if (Index
>= Total
- 3)
897 /* Hiding to the right */
898 VidBufferToScreenBlt(RotBarBuffer
, X
+ ((Index
- 2) * 8), Y
, 22 - 8 * (4 - (Total
- Index
)), 9, 24);
902 VidBufferToScreenBlt(RotBarBuffer
, X
+ ((Index
- 2) * 8), Y
, 22, 9, 24);
907 else if (RotBarSelection
== RB_PROGRESS_BAR
)
909 Delay
.QuadPart
= -600000; // 60 ms
914 VidBufferToScreenBlt(RotLineBuffer
, Index
, 474, 640 - Index
, 6, 640);
918 VidBufferToScreenBlt(RotLineBuffer
+ (640 - Index
) / 2, 0, 474, Index
- 2, 6, 640);
926 PsTerminateSystemThread(STATUS_SUCCESS
);
934 PltRotBarStatus
= RBS_FADEIN
;
935 /* Perform other initialization if needed */
942 DisplayBootBitmap(IN BOOLEAN TextMode
)
944 PVOID Header
= NULL
, Footer
= NULL
, Screen
= NULL
;
946 #ifdef INBV_ROTBAR_IMPLEMENTED
947 UCHAR Buffer
[24 * 9];
948 PVOID Bar
= NULL
, LineBmp
= NULL
;
949 ROT_BAR_TYPE TempRotBarSelection
= RB_UNSPECIFIED
;
951 HANDLE ThreadHandle
= NULL
;
958 #ifdef INBV_ROTBAR_IMPLEMENTED
959 /* Check if the animation thread has already been created */
960 if (RotBarThreadActive
)
962 /* Yes, just reset the progress bar but keep the thread alive */
964 RotBarSelection
= RB_UNSPECIFIED
;
969 ShowProgressBar
= FALSE
;
971 /* Check if this is text mode */
974 /* Check the type of the OS: workstation or server */
975 if (SharedUserData
->NtProductType
== NtProductWinNt
)
977 /* Workstation; set colors */
978 InbvSetTextColor(15);
979 InbvSolidColorFill(0, 0, 639, 479, 7);
980 InbvSolidColorFill(0, 421, 639, 479, 1);
983 Header
= InbvGetResourceAddress(IDB_WKSTA_HEADER
);
984 Footer
= InbvGetResourceAddress(IDB_WKSTA_FOOTER
);
988 /* Server; set colors */
989 InbvSetTextColor(14);
990 InbvSolidColorFill(0, 0, 639, 479, 6);
991 InbvSolidColorFill(0, 421, 639, 479, 1);
994 Header
= InbvGetResourceAddress(IDB_SERVER_HEADER
);
995 Footer
= InbvGetResourceAddress(IDB_SERVER_FOOTER
);
998 /* Set the scrolling region */
999 InbvSetScrollRegion(32, 80, 631, 400);
1001 /* Make sure we have resources */
1002 if (Header
&& Footer
)
1004 /* BitBlt them on the screen */
1005 InbvBitBlt(Footer
, 0, 419);
1006 InbvBitBlt(Header
, 0, 0);
1011 /* Is the boot driver installed? */
1012 if (!InbvBootDriverInstalled
) return;
1014 /* Load the standard boot screen */
1015 Screen
= InbvGetResourceAddress(IDB_BOOT_SCREEN
);
1019 if (SharedUserData
->NtProductType
== NtProductWinNt
)
1021 #ifdef INBV_ROTBAR_IMPLEMENTED
1022 /* Workstation product, use appropriate status bar color */
1023 Bar
= InbvGetResourceAddress(IDB_BAR_WKSTA
);
1028 /* Display correct branding based on server suite */
1029 if (ExVerifySuite(StorageServer
))
1031 /* Storage Server Edition */
1032 Text
= InbvGetResourceAddress(IDB_STORAGE_SERVER
);
1034 else if (ExVerifySuite(ComputeServer
))
1036 /* Compute Cluster Edition */
1037 Text
= InbvGetResourceAddress(IDB_CLUSTER_SERVER
);
1041 /* Normal edition */
1042 Text
= InbvGetResourceAddress(IDB_SERVER_LOGO
);
1045 #ifdef INBV_ROTBAR_IMPLEMENTED
1046 /* Server product, use appropriate status bar color */
1047 Bar
= InbvGetResourceAddress(IDB_BAR_SERVER
);
1051 /* Use default status bar */
1052 Bar
= InbvGetResourceAddress(IDB_BAR_WKSTA
);
1055 /* Make sure we have a logo */
1058 PBITMAPINFOHEADER BitmapInfoHeader
;
1062 * Save the main image palette and replace it with black palette,
1063 * so that we can do fade-in effect later.
1065 BitmapInfoHeader
= (PBITMAPINFOHEADER
)Screen
;
1066 Palette
= (LPRGBQUAD
)((PUCHAR
)Screen
+ BitmapInfoHeader
->biSize
);
1067 RtlCopyMemory(MainPalette
, Palette
, sizeof(MainPalette
));
1068 RtlZeroMemory(Palette
, sizeof(MainPalette
));
1070 /* Blit the background */
1071 InbvBitBlt(Screen
, 0, 0);
1073 #ifdef INBV_ROTBAR_IMPLEMENTED
1074 /* Choose progress bar */
1075 TempRotBarSelection
= ROT_BAR_DEFAULT_MODE
;
1078 /* Set progress bar coordinates and display it */
1079 InbvSetProgressBarCoordinates(259, 352);
1082 /* Check for non-workstation products */
1083 if (SharedUserData
->NtProductType
!= NtProductWinNt
)
1085 /* Overwrite part of the logo for a server product */
1086 InbvScreenToBufferBlt(Buffer
, 413, 237, 7, 7, 8);
1087 InbvSolidColorFill(418, 230, 454, 256, 0);
1088 InbvBufferToScreenBlt(Buffer
, 413, 237, 7, 7, 8);
1090 /* In setup mode, you haven't selected a SKU yet */
1091 if (ExpInTextModeSetup
) Text
= NULL
;
1097 /* Draw the SKU text if it exits */
1098 if (Text
) InbvBitBlt(Text
, 180, 121);
1101 #ifdef INBV_ROTBAR_IMPLEMENTED
1104 /* Save previous screen pixels to buffer */
1105 InbvScreenToBufferBlt(Buffer
, 0, 0, 22, 9, 24);
1106 /* Draw the progress bar bit */
1107 InbvBitBlt(Bar
, 0, 0);
1108 /* Store it in global buffer */
1109 InbvScreenToBufferBlt(RotBarBuffer
, 0, 0, 22, 9, 24);
1110 /* Restore screen pixels */
1111 InbvBufferToScreenBlt(Buffer
, 0, 0, 22, 9, 24);
1115 * Add a rotating bottom horizontal bar when using a progress bar,
1116 * to show that ReactOS can be still alive when the bar does not
1117 * appear to progress.
1119 if (TempRotBarSelection
== RB_PROGRESS_BAR
)
1121 LineBmp
= InbvGetResourceAddress(IDB_ROTATING_LINE
);
1124 /* Draw the line and store it in global buffer */
1125 InbvBitBlt(LineBmp
, 0, 474);
1126 InbvScreenToBufferBlt(RotLineBuffer
, 0, 474, 640, 6, 640);
1131 /* Hide the simple progress bar if not used */
1132 ShowProgressBar
= FALSE
;
1136 /* Display the boot logo and fade it in */
1139 #ifdef INBV_ROTBAR_IMPLEMENTED
1140 if (!RotBarThreadActive
&& TempRotBarSelection
!= RB_UNSPECIFIED
)
1142 /* Start the animation thread */
1143 Status
= PsCreateSystemThread(&ThreadHandle
,
1150 if (NT_SUCCESS(Status
))
1152 /* The thread has started, close the handle as we don't need it */
1153 RotBarThreadActive
= TRUE
;
1154 ObCloseHandle(ThreadHandle
, KernelMode
);
1159 /* Set filter which will draw text display if needed */
1160 InbvInstallDisplayStringFilter(DisplayFilter
);
1163 #ifdef INBV_ROTBAR_IMPLEMENTED
1164 /* Do we have the animation thread? */
1165 if (RotBarThreadActive
)
1167 /* We do, initialize the progress bar */
1169 RotBarSelection
= TempRotBarSelection
;
1173 // FIXME: This was added to allow animation start before the processor hangs
1174 if (TempRotBarSelection
!= RB_UNSPECIFIED
)
1176 LARGE_INTEGER Delay
;
1177 Delay
.QuadPart
= -3000000; // 300 ms
1178 KeDelayExecutionThread(KernelMode
, FALSE
, &Delay
);
1187 DisplayFilter(PCHAR
*String
)
1189 /* Windows hack to skip first dots */
1190 static BOOLEAN DotHack
= TRUE
;
1192 /* If "." is given set *String to empty string */
1193 if(DotHack
&& strcmp(*String
, ".") == 0)
1198 /* Remove the filter */
1199 InbvInstallDisplayStringFilter(NULL
);
1203 /* Draw text screen */
1204 DisplayBootBitmap(TRUE
);
1211 FinalizeBootLogo(VOID
)
1213 /* Acquire lock and check the display state */
1215 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED
)
1217 /* Clear the screen */
1218 VidSolidColorFill(0, 0, 639, 479, 0);
1221 /* Reset progress bar and lock */
1222 #ifdef INBV_ROTBAR_IMPLEMENTED
1223 PltRotBarStatus
= RBS_STOP_ANIMATE
;
1224 RotBarThreadActive
= FALSE
;