[CLASS2]: Fix status code on too small as exposed by kernel32:DeviceIoControl
[reactos.git] / ntoskrnl / inbv / inbv.c
1 /* INCLUDES ******************************************************************/
2
3 #include <ntoskrnl.h>
4 #define NDEBUG
5 #include <debug.h>
6 #include "bootvid/bootvid.h"
7
8 /* GLOBALS *******************************************************************/
9
10 /*
11 * Enable this define if you want Inbv to use coloured headless mode.
12 */
13 // #define INBV_HEADLESS_COLORS
14
15 /*
16 * ReactOS uses the same boot screen for all the products.
17 * Also it doesn't use a parallel system thread for the
18 * rotating "progress" bar.
19 */
20
21 /*
22 * Enable this define when ReactOS will have different SKUs
23 * (Workstation, Server, Storage Server, Cluster Server, etc...).
24 */
25 // #define REACTOS_SKUS
26
27 /*
28 * Enable this define when Inbv will support rotating progress bar.
29 */
30 // #define INBV_ROTBAR_IMPLEMENTED
31
32 static KSPIN_LOCK BootDriverLock;
33 static KIRQL InbvOldIrql;
34 static INBV_DISPLAY_STATE InbvDisplayState = INBV_DISPLAY_STATE_DISABLED;
35 BOOLEAN InbvBootDriverInstalled = FALSE;
36 static BOOLEAN InbvDisplayDebugStrings = FALSE;
37 static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL;
38 static ULONG ProgressBarLeft = 0, ProgressBarTop = 0;
39 static BOOLEAN ShowProgressBar = FALSE;
40 static INBV_PROGRESS_STATE InbvProgressState;
41 static BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0};
42 static INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters = NULL;
43 static ULONG ResourceCount = 0;
44 static PUCHAR ResourceList[1 + IDB_CLUSTER_SERVER]; // First entry == NULL, followed by 'ResourceCount' entries.
45
46 #ifdef INBV_ROTBAR_IMPLEMENTED
47 static BOOLEAN RotBarThreadActive = FALSE;
48 static ROT_BAR_TYPE RotBarSelection;
49 static ULONG PltRotBarStatus;
50 #endif
51
52
53 /*
54 * Headless terminal text colors
55 */
56
57 #ifdef INBV_HEADLESS_COLORS
58
59 // Conversion table CGA to ANSI color index
60 static const UCHAR CGA_TO_ANSI_COLOR_TABLE[16] =
61 {
62 0, // Black
63 4, // Blue
64 2, // Green
65 6, // Cyan
66 1, // Red
67 5, // Magenta
68 3, // Brown/Yellow
69 7, // Grey/White
70
71 60, // Bright Black
72 64, // Bright Blue
73 62, // Bright Green
74 66, // Bright Cyan
75 61, // Bright Red
76 65, // Bright Magenta
77 63, // Bright Yellow
78 67 // Bright Grey (White)
79 };
80
81 #define CGA_TO_ANSI_COLOR(CgaColor) \
82 CGA_TO_ANSI_COLOR_TABLE[CgaColor & 0x0F]
83
84 #endif
85
86 // Default colors: text in white, background in black
87 static ULONG InbvTerminalTextColor = 37;
88 static ULONG InbvTerminalBkgdColor = 40;
89
90
91 /* FADING FUNCTION ***********************************************************/
92
93 /** From include/psdk/wingdi.h **/
94 typedef struct tagRGBQUAD
95 {
96 UCHAR rgbBlue;
97 UCHAR rgbGreen;
98 UCHAR rgbRed;
99 UCHAR rgbReserved;
100 } RGBQUAD,*LPRGBQUAD;
101 /*******************************/
102
103 static RGBQUAD MainPalette[16];
104
105 #define PALETTE_FADE_STEPS 15
106 #define PALETTE_FADE_TIME 20 * 1000 /* 20ms */
107
108 /** From bootvid/precomp.h **/
109 //
110 // Bitmap Header
111 //
112 typedef struct tagBITMAPINFOHEADER
113 {
114 ULONG biSize;
115 LONG biWidth;
116 LONG biHeight;
117 USHORT biPlanes;
118 USHORT biBitCount;
119 ULONG biCompression;
120 ULONG biSizeImage;
121 LONG biXPelsPerMeter;
122 LONG biYPelsPerMeter;
123 ULONG biClrUsed;
124 ULONG biClrImportant;
125 } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
126 /****************************/
127
128 //
129 // Needed prototypes
130 //
131 VOID NTAPI InbvAcquireLock(VOID);
132 VOID NTAPI InbvReleaseLock(VOID);
133
134 static VOID
135 BootLogoFadeIn(VOID)
136 {
137 UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(MainPalette)];
138 PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer;
139 LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER));
140
141 ULONG Iteration, Index, ClrUsed;
142
143 /* Check if we're installed and we own it */
144 if (InbvBootDriverInstalled &&
145 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
146 {
147 /* Acquire the lock */
148 InbvAcquireLock();
149
150 /*
151 * Build a bitmap containing the fade in palette. The palette entries
152 * are then processed in a loop and set using VidBitBlt function.
153 */
154 ClrUsed = RTL_NUMBER_OF(MainPalette);
155 RtlZeroMemory(PaletteBitmap, sizeof(BITMAPINFOHEADER));
156 PaletteBitmap->biSize = sizeof(BITMAPINFOHEADER);
157 PaletteBitmap->biBitCount = 4;
158 PaletteBitmap->biClrUsed = ClrUsed;
159
160 /*
161 * Main animation loop.
162 */
163 for (Iteration = 0; Iteration <= PALETTE_FADE_STEPS; ++Iteration)
164 {
165 for (Index = 0; Index < ClrUsed; Index++)
166 {
167 Palette[Index].rgbRed = (UCHAR)
168 (MainPalette[Index].rgbRed * Iteration / PALETTE_FADE_STEPS);
169 Palette[Index].rgbGreen = (UCHAR)
170 (MainPalette[Index].rgbGreen * Iteration / PALETTE_FADE_STEPS);
171 Palette[Index].rgbBlue = (UCHAR)
172 (MainPalette[Index].rgbBlue * Iteration / PALETTE_FADE_STEPS);
173 }
174
175 VidBitBlt(PaletteBitmapBuffer, 0, 0);
176
177 /* Wait for a bit */
178 KeStallExecutionProcessor(PALETTE_FADE_TIME);
179 }
180
181 /* Release the lock */
182 InbvReleaseLock();
183
184 /* Wait for a bit */
185 KeStallExecutionProcessor(PALETTE_FADE_TIME);
186 }
187 }
188
189 /* FUNCTIONS *****************************************************************/
190
191 PVOID
192 NTAPI
193 INIT_FUNCTION
194 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
195 IN ULONG ResourceId)
196 {
197 UNICODE_STRING UpString = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
198 UNICODE_STRING MpString = RTL_CONSTANT_STRING(L"ntkrnlmp.exe");
199 PLIST_ENTRY NextEntry, ListHead;
200 PLDR_DATA_TABLE_ENTRY LdrEntry;
201 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
202 LDR_RESOURCE_INFO ResourceInfo;
203 NTSTATUS Status;
204 PVOID Data = NULL;
205
206 /* Loop the driver list */
207 ListHead = &LoaderBlock->LoadOrderListHead;
208 NextEntry = ListHead->Flink;
209 while (NextEntry != ListHead)
210 {
211 /* Get the entry */
212 LdrEntry = CONTAINING_RECORD(NextEntry,
213 LDR_DATA_TABLE_ENTRY,
214 InLoadOrderLinks);
215
216 /* Check for a match */
217 if (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE) ||
218 RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE))
219 {
220 /* Break out */
221 break;
222 }
223 }
224
225 /* Check if we found it */
226 if (NextEntry != ListHead)
227 {
228 /* Try to find the resource */
229 ResourceInfo.Type = 2; // RT_BITMAP;
230 ResourceInfo.Name = ResourceId;
231 ResourceInfo.Language = 0;
232 Status = LdrFindResource_U(LdrEntry->DllBase,
233 &ResourceInfo,
234 RESOURCE_DATA_LEVEL,
235 &ResourceDataEntry);
236 if (NT_SUCCESS(Status))
237 {
238 /* Access the resource */
239 ULONG Size = 0;
240 Status = LdrAccessResource(LdrEntry->DllBase,
241 ResourceDataEntry,
242 &Data,
243 &Size);
244 if ((Data) && (ResourceId < 3))
245 {
246 KiBugCheckData[4] ^= RtlComputeCrc32(0, Data, Size);
247 }
248 if (!NT_SUCCESS(Status)) Data = NULL;
249 }
250 }
251
252 /* Return the pointer */
253 return Data;
254 }
255
256 BOOLEAN
257 NTAPI
258 INIT_FUNCTION
259 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
260 IN ULONG Count)
261 {
262 PCHAR CommandLine;
263 BOOLEAN ResetMode = FALSE; // By default do not reset the video mode
264 ULONG i;
265
266 /* Quit if we're already installed */
267 if (InbvBootDriverInstalled) return TRUE;
268
269 /* Initialize the lock and check the current display state */
270 KeInitializeSpinLock(&BootDriverLock);
271 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
272 {
273 /* Reset the video mode in case we do not have a custom boot logo */
274 CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL);
275 ResetMode = (CommandLine == NULL) || (strstr(CommandLine, "BOOTLOGO") == NULL);
276 }
277
278 /* Initialize the video */
279 InbvBootDriverInstalled = VidInitialize(ResetMode);
280 if (InbvBootDriverInstalled)
281 {
282 /* Find bitmap resources in the kernel */
283 ResourceCount = min(Count, RTL_NUMBER_OF(ResourceList) - 1);
284 for (i = 1; i <= ResourceCount; i++)
285 {
286 /* Do the lookup */
287 ResourceList[i] = FindBitmapResource(LoaderBlock, i);
288 }
289
290 /* Set the progress bar ranges */
291 InbvSetProgressBarSubset(0, 100);
292 }
293
294 /* Return install state */
295 return InbvBootDriverInstalled;
296 }
297
298 VOID
299 NTAPI
300 InbvAcquireLock(VOID)
301 {
302 KIRQL OldIrql;
303
304 /* Check if we're at dispatch level or lower */
305 OldIrql = KeGetCurrentIrql();
306 if (OldIrql <= DISPATCH_LEVEL)
307 {
308 /* Loop until the lock is free */
309 while (!KeTestSpinLock(&BootDriverLock));
310
311 /* Raise IRQL to dispatch level */
312 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
313 }
314
315 /* Acquire the lock */
316 KiAcquireSpinLock(&BootDriverLock);
317 InbvOldIrql = OldIrql;
318 }
319
320 VOID
321 NTAPI
322 InbvReleaseLock(VOID)
323 {
324 KIRQL OldIrql;
325
326 /* Capture the old IRQL */
327 OldIrql = InbvOldIrql;
328
329 /* Release the driver lock */
330 KiReleaseSpinLock(&BootDriverLock);
331
332 /* If we were at dispatch level or lower, restore the old IRQL */
333 if (InbvOldIrql <= DISPATCH_LEVEL) KeLowerIrql(OldIrql);
334 }
335
336 VOID
337 NTAPI
338 INIT_FUNCTION
339 InbvEnableBootDriver(IN BOOLEAN Enable)
340 {
341 /* Check if we're installed */
342 if (InbvBootDriverInstalled)
343 {
344 /* Check for lost state */
345 if (InbvDisplayState >= INBV_DISPLAY_STATE_LOST) return;
346
347 /* Acquire the lock */
348 InbvAcquireLock();
349
350 /* Cleanup the screen if we own it */
351 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) VidCleanUp();
352
353 /* Set the new display state */
354 InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED :
355 INBV_DISPLAY_STATE_DISABLED;
356
357 /* Release the lock */
358 InbvReleaseLock();
359 }
360 else
361 {
362 /* Set the new display state */
363 InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED :
364 INBV_DISPLAY_STATE_DISABLED;
365 }
366 }
367
368 VOID
369 NTAPI
370 InbvAcquireDisplayOwnership(VOID)
371 {
372 /* Check if we have a callback and we're just acquiring it now */
373 if ((InbvResetDisplayParameters) &&
374 (InbvDisplayState == INBV_DISPLAY_STATE_LOST))
375 {
376 /* Call the callback */
377 InbvResetDisplayParameters(80, 50);
378 }
379
380 /* Acquire the display */
381 InbvDisplayState = INBV_DISPLAY_STATE_OWNED;
382 }
383
384 VOID
385 NTAPI
386 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned)
387 {
388 /* Set the new display state */
389 InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED :
390 INBV_DISPLAY_STATE_LOST;
391 }
392
393 BOOLEAN
394 NTAPI
395 InbvCheckDisplayOwnership(VOID)
396 {
397 /* Return if we own it or not */
398 return InbvDisplayState != INBV_DISPLAY_STATE_LOST;
399 }
400
401 INBV_DISPLAY_STATE
402 NTAPI
403 InbvGetDisplayState(VOID)
404 {
405 /* Return the actual state */
406 return InbvDisplayState;
407 }
408
409 BOOLEAN
410 NTAPI
411 InbvDisplayString(IN PCHAR String)
412 {
413 /* Make sure we own the display */
414 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
415 {
416 /* If we're not allowed, return success anyway */
417 if (!InbvDisplayDebugStrings) return TRUE;
418
419 /* Check if a filter is installed */
420 if (InbvDisplayFilter) InbvDisplayFilter(&String);
421
422 /* Acquire the lock */
423 InbvAcquireLock();
424
425 /* Make sure we're installed and display the string */
426 if (InbvBootDriverInstalled) VidDisplayString((PUCHAR)String);
427
428 /* Print the string on the EMS port */
429 HeadlessDispatch(HeadlessCmdPutString,
430 String,
431 strlen(String) + sizeof(ANSI_NULL),
432 NULL,
433 NULL);
434
435 /* Release the lock */
436 InbvReleaseLock();
437
438 /* All done */
439 return TRUE;
440 }
441
442 /* We don't own it, fail */
443 return FALSE;
444 }
445
446 BOOLEAN
447 NTAPI
448 InbvEnableDisplayString(IN BOOLEAN Enable)
449 {
450 BOOLEAN OldSetting;
451
452 /* Get the old setting */
453 OldSetting = InbvDisplayDebugStrings;
454
455 /* Update it */
456 InbvDisplayDebugStrings = Enable;
457
458 /* Return the old setting */
459 return OldSetting;
460 }
461
462 VOID
463 NTAPI
464 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter)
465 {
466 /* Save the filter */
467 InbvDisplayFilter = Filter;
468 }
469
470 BOOLEAN
471 NTAPI
472 InbvIsBootDriverInstalled(VOID)
473 {
474 /* Return driver state */
475 return InbvBootDriverInstalled;
476 }
477
478 VOID
479 NTAPI
480 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback)
481 {
482 /* Check if we're installed */
483 if (InbvBootDriverInstalled)
484 {
485 /* Acquire the lock and cleanup if we own the screen */
486 InbvAcquireLock();
487 if (InbvDisplayState != INBV_DISPLAY_STATE_LOST) VidCleanUp();
488
489 /* Set the reset callback and display state */
490 InbvResetDisplayParameters = Callback;
491 InbvDisplayState = INBV_DISPLAY_STATE_LOST;
492
493 /* Release the lock */
494 InbvReleaseLock();
495 }
496 else
497 {
498 /* Set the reset callback and display state */
499 InbvResetDisplayParameters = Callback;
500 InbvDisplayState = INBV_DISPLAY_STATE_LOST;
501 }
502 }
503
504 BOOLEAN
505 NTAPI
506 InbvResetDisplay(VOID)
507 {
508 /* Check if we're installed and we own it */
509 if (InbvBootDriverInstalled &&
510 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
511 {
512 /* Do the reset */
513 VidResetDisplay(TRUE);
514 return TRUE;
515 }
516
517 /* Nothing to reset */
518 return FALSE;
519 }
520
521 VOID
522 NTAPI
523 InbvSetScrollRegion(IN ULONG Left,
524 IN ULONG Top,
525 IN ULONG Right,
526 IN ULONG Bottom)
527 {
528 /* Just call bootvid */
529 VidSetScrollRegion(Left, Top, Right, Bottom);
530 }
531
532 VOID
533 NTAPI
534 InbvSetTextColor(IN ULONG Color)
535 {
536 HEADLESS_CMD_SET_COLOR HeadlessSetColor;
537
538 /* Set color for EMS port */
539 #ifdef INBV_HEADLESS_COLORS
540 InbvTerminalTextColor = 30 + CGA_TO_ANSI_COLOR(Color);
541 #else
542 InbvTerminalTextColor = 37;
543 #endif
544 HeadlessSetColor.TextColor = InbvTerminalTextColor;
545 HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor;
546 HeadlessDispatch(HeadlessCmdSetColor,
547 &HeadlessSetColor,
548 sizeof(HeadlessSetColor),
549 NULL,
550 NULL);
551
552 /* Update the text color */
553 VidSetTextColor(Color);
554 }
555
556 VOID
557 NTAPI
558 InbvSolidColorFill(IN ULONG Left,
559 IN ULONG Top,
560 IN ULONG Right,
561 IN ULONG Bottom,
562 IN ULONG Color)
563 {
564 HEADLESS_CMD_SET_COLOR HeadlessSetColor;
565
566 /* Make sure we own it */
567 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
568 {
569 /* Acquire the lock */
570 InbvAcquireLock();
571
572 /* Check if we're installed */
573 if (InbvBootDriverInstalled)
574 {
575 /* Call bootvid */
576 VidSolidColorFill(Left, Top, Right, Bottom, (UCHAR)Color);
577 }
578
579 /* Set color for EMS port and clear display */
580 #ifdef INBV_HEADLESS_COLORS
581 InbvTerminalBkgdColor = 40 + CGA_TO_ANSI_COLOR(Color);
582 #else
583 InbvTerminalBkgdColor = 40;
584 #endif
585 HeadlessSetColor.TextColor = InbvTerminalTextColor;
586 HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor;
587 HeadlessDispatch(HeadlessCmdSetColor,
588 &HeadlessSetColor,
589 sizeof(HeadlessSetColor),
590 NULL,
591 NULL);
592 HeadlessDispatch(HeadlessCmdClearDisplay,
593 NULL, 0,
594 NULL, NULL);
595
596 /* Release the lock */
597 InbvReleaseLock();
598 }
599 }
600
601 VOID
602 NTAPI
603 INIT_FUNCTION
604 InbvUpdateProgressBar(IN ULONG Progress)
605 {
606 ULONG FillCount, BoundedProgress;
607
608 /* Make sure the progress bar is enabled, that we own and are installed */
609 if (ShowProgressBar &&
610 InbvBootDriverInstalled &&
611 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
612 {
613 /* Compute fill count */
614 BoundedProgress = (InbvProgressState.Floor / 100) + Progress;
615 FillCount = 121 * (InbvProgressState.Bias * BoundedProgress) / 1000000;
616
617 /* Acquire the lock */
618 InbvAcquireLock();
619
620 /* Fill the progress bar */
621 VidSolidColorFill(ProgressBarLeft,
622 ProgressBarTop,
623 ProgressBarLeft + FillCount,
624 ProgressBarTop + 12,
625 15);
626
627 /* Release the lock */
628 InbvReleaseLock();
629 }
630 }
631
632 VOID
633 NTAPI
634 InbvBufferToScreenBlt(IN PUCHAR Buffer,
635 IN ULONG X,
636 IN ULONG Y,
637 IN ULONG Width,
638 IN ULONG Height,
639 IN ULONG Delta)
640 {
641 /* Check if we're installed and we own it */
642 if (InbvBootDriverInstalled &&
643 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
644 {
645 /* Do the blit */
646 VidBufferToScreenBlt(Buffer, X, Y, Width, Height, Delta);
647 }
648 }
649
650 VOID
651 NTAPI
652 InbvBitBlt(IN PUCHAR Buffer,
653 IN ULONG X,
654 IN ULONG Y)
655 {
656 /* Check if we're installed and we own it */
657 if (InbvBootDriverInstalled &&
658 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
659 {
660 /* Acquire the lock */
661 InbvAcquireLock();
662
663 /* Do the blit */
664 VidBitBlt(Buffer, X, Y);
665
666 /* Release the lock */
667 InbvReleaseLock();
668 }
669 }
670
671 VOID
672 NTAPI
673 InbvScreenToBufferBlt(IN PUCHAR Buffer,
674 IN ULONG X,
675 IN ULONG Y,
676 IN ULONG Width,
677 IN ULONG Height,
678 IN ULONG Delta)
679 {
680 /* Check if we're installed and we own it */
681 if (InbvBootDriverInstalled &&
682 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED))
683 {
684 /* Do the blit */
685 VidScreenToBufferBlt(Buffer, X, Y, Width, Height, Delta);
686 }
687 }
688
689 VOID
690 NTAPI
691 InbvSetProgressBarCoordinates(IN ULONG Left,
692 IN ULONG Top)
693 {
694 /* Update the coordinates */
695 ProgressBarLeft = Left;
696 ProgressBarTop = Top;
697
698 /* Enable the progress bar */
699 ShowProgressBar = TRUE;
700 }
701
702 VOID
703 NTAPI
704 InbvSetProgressBarSubset(IN ULONG Floor,
705 IN ULONG Ceiling)
706 {
707 /* Sanity checks */
708 ASSERT(Floor < Ceiling);
709 ASSERT(Ceiling <= 100);
710
711 /* Update the progress bar state */
712 InbvProgressState.Floor = Floor * 100;
713 InbvProgressState.Ceiling = Ceiling * 100;
714 InbvProgressState.Bias = (Ceiling * 100) - Floor;
715 }
716
717 VOID
718 NTAPI
719 INIT_FUNCTION
720 InbvIndicateProgress(VOID)
721 {
722 ULONG Percentage;
723
724 /* Increase progress */
725 InbvProgressIndicator.Count++;
726
727 /* Compute new percentage */
728 Percentage = min(100 * InbvProgressIndicator.Count /
729 InbvProgressIndicator.Expected,
730 99);
731 if (Percentage != InbvProgressIndicator.Percentage)
732 {
733 /* Percentage has moved, update the progress bar */
734 InbvProgressIndicator.Percentage = Percentage;
735 InbvUpdateProgressBar(Percentage);
736 }
737 }
738
739 PUCHAR
740 NTAPI
741 InbvGetResourceAddress(IN ULONG ResourceNumber)
742 {
743 /* Validate the resource number */
744 if (ResourceNumber > ResourceCount) return NULL;
745
746 /* Return the address */
747 return ResourceList[ResourceNumber];
748 }
749
750 NTSTATUS
751 NTAPI
752 NtDisplayString(IN PUNICODE_STRING DisplayString)
753 {
754 OEM_STRING OemString;
755
756 /* Convert the string to OEM and display it */
757 RtlUnicodeStringToOemString(&OemString, DisplayString, TRUE);
758 InbvDisplayString(OemString.Buffer);
759 RtlFreeOemString(&OemString);
760
761 /* Return success */
762 return STATUS_SUCCESS;
763 }
764
765 VOID
766 NTAPI
767 INIT_FUNCTION
768 DisplayBootBitmap(IN BOOLEAN TextMode)
769 {
770 PVOID Header = NULL, Footer = NULL, Screen = NULL;
771
772 #ifdef INBV_ROTBAR_IMPLEMENTED
773 PVOID Bar = NULL;
774 ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED;
775 #endif
776
777 #ifdef REACTOS_SKUS
778 PVOID Text = NULL;
779 UCHAR Buffer[64];
780 #endif
781
782 #ifdef INBV_ROTBAR_IMPLEMENTED
783 /* Check if the system thread has already been created */
784 if (RotBarThreadActive)
785 {
786 /* Reset the progress bar */
787 InbvAcquireLock();
788 RotBarSelection = RB_UNSPECIFIED;
789 InbvReleaseLock();
790 }
791 #endif
792
793 ShowProgressBar = FALSE;
794
795 /* Check if this is text mode */
796 if (TextMode)
797 {
798 /* Check the type of the OS: workstation or server */
799 if (SharedUserData->NtProductType == NtProductWinNt)
800 {
801 /* Workstation; set colors */
802 InbvSetTextColor(15);
803 InbvSolidColorFill(0, 0, 639, 479, 7);
804 InbvSolidColorFill(0, 421, 639, 479, 1);
805
806 /* Get resources */
807 Header = InbvGetResourceAddress(IDB_WKSTA_HEADER);
808 Footer = InbvGetResourceAddress(IDB_WKSTA_FOOTER);
809 }
810 else
811 {
812 /* Server; set colors */
813 InbvSetTextColor(14);
814 InbvSolidColorFill(0, 0, 639, 479, 6);
815 InbvSolidColorFill(0, 421, 639, 479, 1);
816
817 /* Get resources */
818 Header = InbvGetResourceAddress(IDB_SERVER_HEADER);
819 Footer = InbvGetResourceAddress(IDB_SERVER_FOOTER);
820 }
821
822 /* Set the scrolling region */
823 InbvSetScrollRegion(32, 80, 631, 400);
824
825 /* Make sure we have resources */
826 if (Header && Footer)
827 {
828 /* BitBlt them on the screen */
829 InbvBitBlt(Footer, 0, 419);
830 InbvBitBlt(Header, 0, 0);
831 }
832 }
833 else
834 {
835 /* Is the boot driver installed? */
836 if (!InbvBootDriverInstalled) return;
837
838 /* Load the standard boot screen */
839 Screen = InbvGetResourceAddress(IDB_BOOT_SCREEN);
840
841 #ifdef REACTOS_SKUS
842 Text = NULL;
843 if (SharedUserData->NtProductType == NtProductWinNt)
844 {
845 #ifdef INBV_ROTBAR_IMPLEMENTED
846 /* Workstation product, use appropriate status bar color */
847 Bar = InbvGetResourceAddress(IDB_BAR_WKSTA);
848 #endif
849 }
850 else
851 {
852 /* Display correct branding based on server suite */
853 if (ExVerifySuite(StorageServer))
854 {
855 /* Storage Server Edition */
856 Text = InbvGetResourceAddress(IDB_STORAGE_SERVER);
857 }
858 else if (ExVerifySuite(ComputeServer))
859 {
860 /* Compute Cluster Edition */
861 Text = InbvGetResourceAddress(IDB_CLUSTER_SERVER);
862 }
863 else
864 {
865 /* Normal edition */
866 Text = InbvGetResourceAddress(IDB_SERVER_LOGO);
867 }
868
869 #ifdef INBV_ROTBAR_IMPLEMENTED
870 /* Server product, use appropriate status bar color */
871 Bar = InbvGetResourceAddress(IDB_BAR_SERVER);
872 #endif
873 }
874 #endif
875
876 /* Make sure we have a logo */
877 if (Screen)
878 {
879 PBITMAPINFOHEADER BitmapInfoHeader;
880 LPRGBQUAD Palette;
881
882 /*
883 * Save the main image palette and replace it with black palette,
884 * so that we can do fade in effect later.
885 */
886 BitmapInfoHeader = (PBITMAPINFOHEADER)Screen;
887 Palette = (LPRGBQUAD)((PUCHAR)Screen + BitmapInfoHeader->biSize);
888 RtlCopyMemory(MainPalette, Palette, sizeof(MainPalette));
889 RtlZeroMemory(Palette, sizeof(MainPalette));
890
891 /* Blit the background */
892 InbvBitBlt(Screen, 0, 0);
893
894 #ifdef INBV_ROTBAR_IMPLEMENTED
895 /* Choose progress bar */
896 TempRotBarSelection = RB_SQUARE_CELLS;
897 #endif
898
899 /* Set progress bar coordinates and display it */
900 InbvSetProgressBarCoordinates(259, 352);
901
902 #ifdef REACTOS_SKUS
903 /* Check for non-workstation products */
904 if (SharedUserData->NtProductType != NtProductWinNt)
905 {
906 /* Overwrite part of the logo for a server product */
907 InbvScreenToBufferBlt(Buffer, 413, 237, 7, 7, 8);
908 InbvSolidColorFill(418, 230, 454, 256, 0);
909 InbvBufferToScreenBlt(Buffer, 413, 237, 7, 7, 8);
910
911 /* In setup mode, you haven't selected a SKU yet */
912 if (ExpInTextModeSetup) Text = NULL;
913 }
914 #endif
915 }
916
917 #ifdef REACTOS_SKUS
918 /* Draw the SKU text if it exits */
919 if (Text) InbvBitBlt(Text, 180, 121);
920 #endif
921
922 #ifdef INBV_ROTBAR_IMPLEMENTED
923 /* Draw the progress bar bit */
924 if (Bar) InbvBitBlt(Bar, 0, 0);
925 #endif
926
927 /* Display the boot logo and fade it in */
928 BootLogoFadeIn();
929
930 /* Set filter which will draw text display if needed */
931 InbvInstallDisplayStringFilter(DisplayFilter);
932 }
933
934 #ifdef INBV_ROTBAR_IMPLEMENTED
935 /* Do we have a system thread? */
936 if (RotBarThreadActive)
937 {
938 /* We do, initialize the progress bar */
939 InbvAcquireLock();
940 RotBarSelection = TempRotBarSelection;
941 // InbvRotBarInit();
942 InbvReleaseLock();
943 }
944 #endif
945 }
946
947 VOID
948 NTAPI
949 INIT_FUNCTION
950 DisplayFilter(PCHAR *String)
951 {
952 /* Windows hack to skip first dots */
953 static BOOLEAN DotHack = TRUE;
954
955 /* If "." is given set *String to empty string */
956 if(DotHack && strcmp(*String, ".") == 0)
957 *String = "";
958
959 if(**String)
960 {
961 /* Remove the filter */
962 InbvInstallDisplayStringFilter(NULL);
963
964 DotHack = FALSE;
965
966 /* Draw text screen */
967 DisplayBootBitmap(TRUE);
968 }
969 }
970
971 VOID
972 NTAPI
973 INIT_FUNCTION
974 FinalizeBootLogo(VOID)
975 {
976 /* Acquire lock and check the display state */
977 InbvAcquireLock();
978 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED)
979 {
980 /* Clear the screen */
981 VidSolidColorFill(0, 0, 639, 479, 0);
982 }
983
984 /* Reset progress bar and lock */
985 #ifdef INBV_ROTBAR_IMPLEMENTED
986 PltRotBarStatus = 3;
987 #endif
988 InbvReleaseLock();
989 }