1 /* INCLUDES ******************************************************************/ 2 3 #include <ntoskrnl.h> 4 5 #define NDEBUG 6 #include <debug.h> 7 8 #include "inbv/logo.h" 9 10 /* See also mm/ARM3/miarm.h */ 11 #define MM_READONLY 1 // PAGE_READONLY 12 #define MM_READWRITE 4 // PAGE_WRITECOPY 13 14 #ifndef TAG_OSTR 15 #define TAG_OSTR 'RTSO' 16 #endif 17 18 /* GLOBALS *******************************************************************/ 19 20 /* 21 * Enable this define if you want Inbv to use coloured headless mode. 22 */ 23 // #define INBV_HEADLESS_COLORS 24 25 /* 26 * ReactOS uses the same boot screen for all the products. 27 * Also it doesn't use a parallel system thread for the 28 * rotating "progress" bar. 29 */ 30 31 /* 32 * Enable this define when ReactOS will have different SKUs 33 * (Workstation, Server, Storage Server, Cluster Server, etc...). 34 */ 35 // #define REACTOS_SKUS 36 37 typedef struct _INBV_PROGRESS_STATE 38 { 39 ULONG Floor; 40 ULONG Ceiling; 41 ULONG Bias; 42 } INBV_PROGRESS_STATE; 43 44 typedef struct _BT_PROGRESS_INDICATOR 45 { 46 ULONG Count; 47 ULONG Expected; 48 ULONG Percentage; 49 } BT_PROGRESS_INDICATOR, *PBT_PROGRESS_INDICATOR; 50 51 typedef enum _ROT_BAR_TYPE 52 { 53 RB_UNSPECIFIED, 54 RB_SQUARE_CELLS, 55 RB_PROGRESS_BAR 56 } ROT_BAR_TYPE; 57 58 /* 59 * BitBltAligned() alignments 60 */ 61 typedef enum _BBLT_VERT_ALIGNMENT 62 { 63 AL_VERTICAL_TOP = 0, 64 AL_VERTICAL_CENTER, 65 AL_VERTICAL_BOTTOM 66 } BBLT_VERT_ALIGNMENT; 67 68 typedef enum _BBLT_HORZ_ALIGNMENT 69 { 70 AL_HORIZONTAL_LEFT = 0, 71 AL_HORIZONTAL_CENTER, 72 AL_HORIZONTAL_RIGHT 73 } BBLT_HORZ_ALIGNMENT; 74 75 /* 76 * Enable this define when Inbv will support rotating progress bar. 77 */ 78 #define INBV_ROTBAR_IMPLEMENTED 79 80 static KSPIN_LOCK BootDriverLock; 81 static KIRQL InbvOldIrql; 82 static INBV_DISPLAY_STATE InbvDisplayState = INBV_DISPLAY_STATE_DISABLED; 83 BOOLEAN InbvBootDriverInstalled = FALSE; 84 static BOOLEAN InbvDisplayDebugStrings = FALSE; 85 static INBV_DISPLAY_STRING_FILTER InbvDisplayFilter = NULL; 86 static ULONG ProgressBarLeft = 0, ProgressBarTop = 0; 87 static ULONG ProgressBarWidth = 0, ProgressBarHeight = 0; 88 static BOOLEAN ShowProgressBar = FALSE; 89 static INBV_PROGRESS_STATE InbvProgressState; 90 static BT_PROGRESS_INDICATOR InbvProgressIndicator = {0, 25, 0}; 91 static INBV_RESET_DISPLAY_PARAMETERS InbvResetDisplayParameters = NULL; 92 static ULONG ResourceCount = 0; 93 static PUCHAR ResourceList[1 + IDB_MAX_RESOURCE]; // First entry == NULL, followed by 'ResourceCount' entries. 94 95 #ifdef INBV_ROTBAR_IMPLEMENTED 96 /* 97 * Change this to modify progress bar behaviour 98 */ 99 #define ROT_BAR_DEFAULT_MODE RB_PROGRESS_BAR 100 101 /* 102 * Values for PltRotBarStatus: 103 * - PltRotBarStatus == 1, do palette fading-in (done elsewhere in ReactOS); 104 * - PltRotBarStatus == 2, do rotation bar animation; 105 * - PltRotBarStatus == 3, stop the animation thread. 106 * - Any other value is ignored and the animation thread continues to run. 107 */ 108 typedef enum _ROT_BAR_STATUS 109 { 110 RBS_FADEIN = 1, 111 RBS_ANIMATE, 112 RBS_STOP_ANIMATE, 113 RBS_STATUS_MAX 114 } ROT_BAR_STATUS; 115 116 static BOOLEAN RotBarThreadActive = FALSE; 117 static ROT_BAR_TYPE RotBarSelection = RB_UNSPECIFIED; 118 static ROT_BAR_STATUS PltRotBarStatus = 0; 119 static UCHAR RotBarBuffer[24 * 9]; 120 static UCHAR RotLineBuffer[SCREEN_WIDTH * 6]; 121 #endif 122 123 124 /* 125 * Headless terminal text colors 126 */ 127 128 #ifdef INBV_HEADLESS_COLORS 129 130 // Conversion table CGA to ANSI color index 131 static const UCHAR CGA_TO_ANSI_COLOR_TABLE[16] = 132 { 133 0, // Black 134 4, // Blue 135 2, // Green 136 6, // Cyan 137 1, // Red 138 5, // Magenta 139 3, // Brown/Yellow 140 7, // Grey/White 141 142 60, // Bright Black 143 64, // Bright Blue 144 62, // Bright Green 145 66, // Bright Cyan 146 61, // Bright Red 147 65, // Bright Magenta 148 63, // Bright Yellow 149 67 // Bright Grey (White) 150 }; 151 152 #define CGA_TO_ANSI_COLOR(CgaColor) \ 153 CGA_TO_ANSI_COLOR_TABLE[CgaColor & 0x0F] 154 155 #endif 156 157 // Default colors: text in white, background in black 158 static ULONG InbvTerminalTextColor = 37; 159 static ULONG InbvTerminalBkgdColor = 40; 160 161 162 /* FADING FUNCTION ***********************************************************/ 163 164 /** From include/psdk/wingdi.h **/ 165 typedef struct tagRGBQUAD 166 { 167 UCHAR rgbBlue; 168 UCHAR rgbGreen; 169 UCHAR rgbRed; 170 UCHAR rgbReserved; 171 } RGBQUAD,*LPRGBQUAD; 172 /*******************************/ 173 174 static RGBQUAD MainPalette[16]; 175 176 #define PALETTE_FADE_STEPS 12 177 #define PALETTE_FADE_TIME (15 * 1000) /* 15 ms */ 178 179 /** From bootvid/precomp.h **/ 180 // 181 // Bitmap Header 182 // 183 typedef struct tagBITMAPINFOHEADER 184 { 185 ULONG biSize; 186 LONG biWidth; 187 LONG biHeight; 188 USHORT biPlanes; 189 USHORT biBitCount; 190 ULONG biCompression; 191 ULONG biSizeImage; 192 LONG biXPelsPerMeter; 193 LONG biYPelsPerMeter; 194 ULONG biClrUsed; 195 ULONG biClrImportant; 196 } BITMAPINFOHEADER, *PBITMAPINFOHEADER; 197 /****************************/ 198 199 // 200 // Needed prototypes 201 // 202 VOID NTAPI InbvAcquireLock(VOID); 203 VOID NTAPI InbvReleaseLock(VOID); 204 205 static VOID 206 BootLogoFadeIn(VOID) 207 { 208 UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(MainPalette)]; 209 PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer; 210 LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER)); 211 ULONG Iteration, Index, ClrUsed; 212 213 LARGE_INTEGER Delay; 214 Delay.QuadPart = -(PALETTE_FADE_TIME * 10); 215 216 /* Check if we are installed and we own the display */ 217 if (!InbvBootDriverInstalled || 218 (InbvDisplayState != INBV_DISPLAY_STATE_OWNED)) 219 { 220 return; 221 } 222 223 /* 224 * Build a bitmap containing the fade-in palette. The palette entries 225 * are then processed in a loop and set using VidBitBlt function. 226 */ 227 ClrUsed = RTL_NUMBER_OF(MainPalette); 228 RtlZeroMemory(PaletteBitmap, sizeof(BITMAPINFOHEADER)); 229 PaletteBitmap->biSize = sizeof(BITMAPINFOHEADER); 230 PaletteBitmap->biBitCount = 4; 231 PaletteBitmap->biClrUsed = ClrUsed; 232 233 /* 234 * Main animation loop. 235 */ 236 for (Iteration = 0; Iteration <= PALETTE_FADE_STEPS; ++Iteration) 237 { 238 for (Index = 0; Index < ClrUsed; Index++) 239 { 240 Palette[Index].rgbRed = (UCHAR) 241 (MainPalette[Index].rgbRed * Iteration / PALETTE_FADE_STEPS); 242 Palette[Index].rgbGreen = (UCHAR) 243 (MainPalette[Index].rgbGreen * Iteration / PALETTE_FADE_STEPS); 244 Palette[Index].rgbBlue = (UCHAR) 245 (MainPalette[Index].rgbBlue * Iteration / PALETTE_FADE_STEPS); 246 } 247 248 /* Do the animation */ 249 InbvAcquireLock(); 250 VidBitBlt(PaletteBitmapBuffer, 0, 0); 251 InbvReleaseLock(); 252 253 /* Wait for a bit */ 254 KeDelayExecutionThread(KernelMode, FALSE, &Delay); 255 } 256 } 257 258 static VOID 259 BitBltPalette( 260 IN PVOID Image, 261 IN BOOLEAN NoPalette, 262 IN ULONG X, 263 IN ULONG Y) 264 { 265 LPRGBQUAD Palette; 266 RGBQUAD OrigPalette[RTL_NUMBER_OF(MainPalette)]; 267 268 /* If requested, remove the palette from the image */ 269 if (NoPalette) 270 { 271 /* Get bitmap header and palette */ 272 PBITMAPINFOHEADER BitmapInfoHeader = Image; 273 Palette = (LPRGBQUAD)((PUCHAR)Image + BitmapInfoHeader->biSize); 274 275 /* Save the image original palette and remove palette information */ 276 RtlCopyMemory(OrigPalette, Palette, sizeof(OrigPalette)); 277 RtlZeroMemory(Palette, sizeof(OrigPalette)); 278 } 279 280 /* Draw the image */ 281 InbvBitBlt(Image, X, Y); 282 283 /* Restore the image original palette */ 284 if (NoPalette) 285 { 286 RtlCopyMemory(Palette, OrigPalette, sizeof(OrigPalette)); 287 } 288 } 289 290 static VOID 291 BitBltAligned( 292 IN PVOID Image, 293 IN BOOLEAN NoPalette, 294 IN BBLT_HORZ_ALIGNMENT HorizontalAlignment, 295 IN BBLT_VERT_ALIGNMENT VerticalAlignment, 296 IN ULONG MarginLeft, 297 IN ULONG MarginTop, 298 IN ULONG MarginRight, 299 IN ULONG MarginBottom) 300 { 301 PBITMAPINFOHEADER BitmapInfoHeader = Image; 302 ULONG X, Y; 303 304 /* Calculate X */ 305 switch (HorizontalAlignment) 306 { 307 case AL_HORIZONTAL_LEFT: 308 X = MarginLeft - MarginRight; 309 break; 310 311 case AL_HORIZONTAL_CENTER: 312 X = MarginLeft - MarginRight + (SCREEN_WIDTH - BitmapInfoHeader->biWidth + 1) / 2; 313 break; 314 315 case AL_HORIZONTAL_RIGHT: 316 X = MarginLeft - MarginRight + SCREEN_WIDTH - BitmapInfoHeader->biWidth; 317 break; 318 319 default: 320 /* Unknown */ 321 return; 322 } 323 324 /* Calculate Y */ 325 switch (VerticalAlignment) 326 { 327 case AL_VERTICAL_TOP: 328 Y = MarginTop - MarginBottom; 329 break; 330 331 case AL_VERTICAL_CENTER: 332 Y = MarginTop - MarginBottom + (SCREEN_HEIGHT - BitmapInfoHeader->biHeight + 1) / 2; 333 break; 334 335 case AL_VERTICAL_BOTTOM: 336 Y = MarginTop - MarginBottom + SCREEN_HEIGHT - BitmapInfoHeader->biHeight; 337 break; 338 339 default: 340 /* Unknown */ 341 return; 342 } 343 344 /* Finally draw the image */ 345 BitBltPalette(Image, NoPalette, X, Y); 346 } 347 348 /* FUNCTIONS *****************************************************************/ 349 350 CODE_SEG("INIT") 351 PVOID 352 NTAPI 353 FindBitmapResource(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 354 IN ULONG ResourceId) 355 { 356 UNICODE_STRING UpString = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); 357 UNICODE_STRING MpString = RTL_CONSTANT_STRING(L"ntkrnlmp.exe"); 358 PLIST_ENTRY NextEntry, ListHead; 359 PLDR_DATA_TABLE_ENTRY LdrEntry; 360 PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry; 361 LDR_RESOURCE_INFO ResourceInfo; 362 NTSTATUS Status; 363 PVOID Data = NULL; 364 365 /* Loop the driver list */ 366 ListHead = &LoaderBlock->LoadOrderListHead; 367 NextEntry = ListHead->Flink; 368 while (NextEntry != ListHead) 369 { 370 /* Get the entry */ 371 LdrEntry = CONTAINING_RECORD(NextEntry, 372 LDR_DATA_TABLE_ENTRY, 373 InLoadOrderLinks); 374 375 /* Check for a match */ 376 if (RtlEqualUnicodeString(&LdrEntry->BaseDllName, &UpString, TRUE) || 377 RtlEqualUnicodeString(&LdrEntry->BaseDllName, &MpString, TRUE)) 378 { 379 /* Break out */ 380 break; 381 } 382 } 383 384 /* Check if we found it */ 385 if (NextEntry != ListHead) 386 { 387 /* Try to find the resource */ 388 ResourceInfo.Type = 2; // RT_BITMAP; 389 ResourceInfo.Name = ResourceId; 390 ResourceInfo.Language = 0; 391 Status = LdrFindResource_U(LdrEntry->DllBase, 392 &ResourceInfo, 393 RESOURCE_DATA_LEVEL, 394 &ResourceDataEntry); 395 if (NT_SUCCESS(Status)) 396 { 397 /* Access the resource */ 398 ULONG Size = 0; 399 Status = LdrAccessResource(LdrEntry->DllBase, 400 ResourceDataEntry, 401 &Data, 402 &Size); 403 if ((Data) && (ResourceId < 3)) 404 { 405 KiBugCheckData[4] ^= RtlComputeCrc32(0, Data, Size); 406 } 407 if (!NT_SUCCESS(Status)) Data = NULL; 408 } 409 } 410 411 /* Return the pointer */ 412 return Data; 413 } 414 415 CODE_SEG("INIT") 416 BOOLEAN 417 NTAPI 418 InbvDriverInitialize(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 419 IN ULONG Count) 420 { 421 PCHAR CommandLine; 422 BOOLEAN ResetMode = FALSE; // By default do not reset the video mode 423 ULONG i; 424 425 /* Quit if we're already installed */ 426 if (InbvBootDriverInstalled) return TRUE; 427 428 /* Initialize the lock and check the current display state */ 429 KeInitializeSpinLock(&BootDriverLock); 430 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) 431 { 432 /* Reset the video mode in case we do not have a custom boot logo */ 433 CommandLine = (LoaderBlock->LoadOptions ? _strupr(LoaderBlock->LoadOptions) : NULL); 434 ResetMode = (CommandLine == NULL) || (strstr(CommandLine, "BOOTLOGO") == NULL); 435 } 436 437 /* Initialize the video */ 438 InbvBootDriverInstalled = VidInitialize(ResetMode); 439 if (InbvBootDriverInstalled) 440 { 441 /* Find bitmap resources in the kernel */ 442 ResourceCount = min(Count, RTL_NUMBER_OF(ResourceList) - 1); 443 for (i = 1; i <= ResourceCount; i++) 444 { 445 /* Do the lookup */ 446 ResourceList[i] = FindBitmapResource(LoaderBlock, i); 447 } 448 449 /* Set the progress bar ranges */ 450 InbvSetProgressBarSubset(0, 100); 451 } 452 453 /* Return install state */ 454 return InbvBootDriverInstalled; 455 } 456 457 VOID 458 NTAPI 459 InbvAcquireLock(VOID) 460 { 461 KIRQL OldIrql; 462 463 /* Check if we're at dispatch level or lower */ 464 OldIrql = KeGetCurrentIrql(); 465 if (OldIrql <= DISPATCH_LEVEL) 466 { 467 /* Loop until the lock is free */ 468 while (!KeTestSpinLock(&BootDriverLock)); 469 470 /* Raise IRQL to dispatch level */ 471 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 472 } 473 474 /* Acquire the lock */ 475 KiAcquireSpinLock(&BootDriverLock); 476 InbvOldIrql = OldIrql; 477 } 478 479 VOID 480 NTAPI 481 InbvReleaseLock(VOID) 482 { 483 KIRQL OldIrql; 484 485 /* Capture the old IRQL */ 486 OldIrql = InbvOldIrql; 487 488 /* Release the driver lock */ 489 KiReleaseSpinLock(&BootDriverLock); 490 491 /* If we were at dispatch level or lower, restore the old IRQL */ 492 if (InbvOldIrql <= DISPATCH_LEVEL) KeLowerIrql(OldIrql); 493 } 494 495 VOID 496 NTAPI 497 InbvEnableBootDriver(IN BOOLEAN Enable) 498 { 499 /* Check if we're installed */ 500 if (InbvBootDriverInstalled) 501 { 502 /* Check for lost state */ 503 if (InbvDisplayState >= INBV_DISPLAY_STATE_LOST) return; 504 505 /* Acquire the lock */ 506 InbvAcquireLock(); 507 508 /* Cleanup the screen if we own it */ 509 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) VidCleanUp(); 510 511 /* Set the new display state */ 512 InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED : 513 INBV_DISPLAY_STATE_DISABLED; 514 515 /* Release the lock */ 516 InbvReleaseLock(); 517 } 518 else 519 { 520 /* Set the new display state */ 521 InbvDisplayState = Enable ? INBV_DISPLAY_STATE_OWNED : 522 INBV_DISPLAY_STATE_DISABLED; 523 } 524 } 525 526 VOID 527 NTAPI 528 InbvAcquireDisplayOwnership(VOID) 529 { 530 /* Check if we have a callback and we're just acquiring it now */ 531 if ((InbvResetDisplayParameters) && 532 (InbvDisplayState == INBV_DISPLAY_STATE_LOST)) 533 { 534 /* Call the callback */ 535 InbvResetDisplayParameters(80, 50); 536 } 537 538 /* Acquire the display */ 539 InbvDisplayState = INBV_DISPLAY_STATE_OWNED; 540 } 541 542 VOID 543 NTAPI 544 InbvSetDisplayOwnership(IN BOOLEAN DisplayOwned) 545 { 546 /* Set the new display state */ 547 InbvDisplayState = DisplayOwned ? INBV_DISPLAY_STATE_OWNED : 548 INBV_DISPLAY_STATE_LOST; 549 } 550 551 BOOLEAN 552 NTAPI 553 InbvCheckDisplayOwnership(VOID) 554 { 555 /* Return if we own it or not */ 556 return InbvDisplayState != INBV_DISPLAY_STATE_LOST; 557 } 558 559 INBV_DISPLAY_STATE 560 NTAPI 561 InbvGetDisplayState(VOID) 562 { 563 /* Return the actual state */ 564 return InbvDisplayState; 565 } 566 567 BOOLEAN 568 NTAPI 569 InbvDisplayString(IN PCHAR String) 570 { 571 /* Make sure we own the display */ 572 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) 573 { 574 /* If we're not allowed, return success anyway */ 575 if (!InbvDisplayDebugStrings) return TRUE; 576 577 /* Check if a filter is installed */ 578 if (InbvDisplayFilter) InbvDisplayFilter(&String); 579 580 /* Acquire the lock */ 581 InbvAcquireLock(); 582 583 /* Make sure we're installed and display the string */ 584 if (InbvBootDriverInstalled) VidDisplayString((PUCHAR)String); 585 586 /* Print the string on the EMS port */ 587 HeadlessDispatch(HeadlessCmdPutString, 588 String, 589 strlen(String) + sizeof(ANSI_NULL), 590 NULL, 591 NULL); 592 593 /* Release the lock */ 594 InbvReleaseLock(); 595 596 /* All done */ 597 return TRUE; 598 } 599 600 /* We don't own it, fail */ 601 return FALSE; 602 } 603 604 BOOLEAN 605 NTAPI 606 InbvEnableDisplayString(IN BOOLEAN Enable) 607 { 608 BOOLEAN OldSetting; 609 610 /* Get the old setting */ 611 OldSetting = InbvDisplayDebugStrings; 612 613 /* Update it */ 614 InbvDisplayDebugStrings = Enable; 615 616 /* Return the old setting */ 617 return OldSetting; 618 } 619 620 VOID 621 NTAPI 622 InbvInstallDisplayStringFilter(IN INBV_DISPLAY_STRING_FILTER Filter) 623 { 624 /* Save the filter */ 625 InbvDisplayFilter = Filter; 626 } 627 628 BOOLEAN 629 NTAPI 630 InbvIsBootDriverInstalled(VOID) 631 { 632 /* Return driver state */ 633 return InbvBootDriverInstalled; 634 } 635 636 VOID 637 NTAPI 638 InbvNotifyDisplayOwnershipLost(IN INBV_RESET_DISPLAY_PARAMETERS Callback) 639 { 640 /* Check if we're installed */ 641 if (InbvBootDriverInstalled) 642 { 643 /* Acquire the lock and cleanup if we own the screen */ 644 InbvAcquireLock(); 645 if (InbvDisplayState != INBV_DISPLAY_STATE_LOST) VidCleanUp(); 646 647 /* Set the reset callback and display state */ 648 InbvResetDisplayParameters = Callback; 649 InbvDisplayState = INBV_DISPLAY_STATE_LOST; 650 651 /* Release the lock */ 652 InbvReleaseLock(); 653 } 654 else 655 { 656 /* Set the reset callback and display state */ 657 InbvResetDisplayParameters = Callback; 658 InbvDisplayState = INBV_DISPLAY_STATE_LOST; 659 } 660 } 661 662 BOOLEAN 663 NTAPI 664 InbvResetDisplay(VOID) 665 { 666 /* Check if we're installed and we own it */ 667 if (InbvBootDriverInstalled && 668 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) 669 { 670 /* Do the reset */ 671 VidResetDisplay(TRUE); 672 return TRUE; 673 } 674 675 /* Nothing to reset */ 676 return FALSE; 677 } 678 679 VOID 680 NTAPI 681 InbvSetScrollRegion(IN ULONG Left, 682 IN ULONG Top, 683 IN ULONG Right, 684 IN ULONG Bottom) 685 { 686 /* Just call bootvid */ 687 VidSetScrollRegion(Left, Top, Right, Bottom); 688 } 689 690 VOID 691 NTAPI 692 InbvSetTextColor(IN ULONG Color) 693 { 694 HEADLESS_CMD_SET_COLOR HeadlessSetColor; 695 696 /* Set color for EMS port */ 697 #ifdef INBV_HEADLESS_COLORS 698 InbvTerminalTextColor = 30 + CGA_TO_ANSI_COLOR(Color); 699 #else 700 InbvTerminalTextColor = 37; 701 #endif 702 HeadlessSetColor.TextColor = InbvTerminalTextColor; 703 HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor; 704 HeadlessDispatch(HeadlessCmdSetColor, 705 &HeadlessSetColor, 706 sizeof(HeadlessSetColor), 707 NULL, 708 NULL); 709 710 /* Update the text color */ 711 VidSetTextColor(Color); 712 } 713 714 VOID 715 NTAPI 716 InbvSolidColorFill(IN ULONG Left, 717 IN ULONG Top, 718 IN ULONG Right, 719 IN ULONG Bottom, 720 IN ULONG Color) 721 { 722 HEADLESS_CMD_SET_COLOR HeadlessSetColor; 723 724 /* Make sure we own it */ 725 if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) 726 { 727 /* Acquire the lock */ 728 InbvAcquireLock(); 729 730 /* Check if we're installed */ 731 if (InbvBootDriverInstalled) 732 { 733 /* Call bootvid */ 734 VidSolidColorFill(Left, Top, Right, Bottom, (UCHAR)Color); 735 } 736 737 /* Set color for EMS port and clear display */ 738 #ifdef INBV_HEADLESS_COLORS 739 InbvTerminalBkgdColor = 40 + CGA_TO_ANSI_COLOR(Color); 740 #else 741 InbvTerminalBkgdColor = 40; 742 #endif 743 HeadlessSetColor.TextColor = InbvTerminalTextColor; 744 HeadlessSetColor.BkgdColor = InbvTerminalBkgdColor; 745 HeadlessDispatch(HeadlessCmdSetColor, 746 &HeadlessSetColor, 747 sizeof(HeadlessSetColor), 748 NULL, 749 NULL); 750 HeadlessDispatch(HeadlessCmdClearDisplay, 751 NULL, 0, 752 NULL, NULL); 753 754 /* Release the lock */ 755 InbvReleaseLock(); 756 } 757 } 758 759 CODE_SEG("INIT") 760 VOID 761 NTAPI 762 InbvUpdateProgressBar(IN ULONG Progress) 763 { 764 ULONG FillCount, BoundedProgress; 765 766 /* Make sure the progress bar is enabled, that we own and are installed */ 767 if (ShowProgressBar && 768 InbvBootDriverInstalled && 769 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) 770 { 771 /* Compute fill count */ 772 BoundedProgress = (InbvProgressState.Floor / 100) + Progress; 773 FillCount = ProgressBarWidth * (InbvProgressState.Bias * BoundedProgress) / 1000000; 774 775 /* Acquire the lock */ 776 InbvAcquireLock(); 777 778 /* Fill the progress bar */ 779 VidSolidColorFill(ProgressBarLeft, 780 ProgressBarTop, 781 ProgressBarLeft + FillCount, 782 ProgressBarTop + ProgressBarHeight, 783 BV_COLOR_WHITE); 784 785 /* Release the lock */ 786 InbvReleaseLock(); 787 } 788 } 789 790 VOID 791 NTAPI 792 InbvBufferToScreenBlt(IN PUCHAR Buffer, 793 IN ULONG X, 794 IN ULONG Y, 795 IN ULONG Width, 796 IN ULONG Height, 797 IN ULONG Delta) 798 { 799 /* Check if we're installed and we own it */ 800 if (InbvBootDriverInstalled && 801 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) 802 { 803 /* Do the blit */ 804 VidBufferToScreenBlt(Buffer, X, Y, Width, Height, Delta); 805 } 806 } 807 808 VOID 809 NTAPI 810 InbvBitBlt(IN PUCHAR Buffer, 811 IN ULONG X, 812 IN ULONG Y) 813 { 814 /* Check if we're installed and we own it */ 815 if (InbvBootDriverInstalled && 816 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) 817 { 818 /* Acquire the lock */ 819 InbvAcquireLock(); 820 821 /* Do the blit */ 822 VidBitBlt(Buffer, X, Y); 823 824 /* Release the lock */ 825 InbvReleaseLock(); 826 } 827 } 828 829 VOID 830 NTAPI 831 InbvScreenToBufferBlt(OUT PUCHAR Buffer, 832 IN ULONG X, 833 IN ULONG Y, 834 IN ULONG Width, 835 IN ULONG Height, 836 IN ULONG Delta) 837 { 838 /* Check if we're installed and we own it */ 839 if (InbvBootDriverInstalled && 840 (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) 841 { 842 /* Do the blit */ 843 VidScreenToBufferBlt(Buffer, X, Y, Width, Height, Delta); 844 } 845 } 846 847 CODE_SEG("INIT") 848 VOID 849 NTAPI 850 InbvSetProgressBarCoordinates(IN ULONG Left, 851 IN ULONG Top, 852 IN ULONG Width, 853 IN ULONG Height) 854 { 855 /* Update the coordinates */ 856 ProgressBarLeft = Left; 857 ProgressBarTop = Top; 858 ProgressBarWidth = Width; 859 ProgressBarHeight = Height; 860 861 /* Enable the progress bar */ 862 ShowProgressBar = TRUE; 863 } 864 865 CODE_SEG("INIT") 866 VOID 867 NTAPI 868 InbvSetProgressBarSubset(IN ULONG Floor, 869 IN ULONG Ceiling) 870 { 871 /* Sanity checks */ 872 ASSERT(Floor < Ceiling); 873 ASSERT(Ceiling <= 100); 874 875 /* Update the progress bar state */ 876 InbvProgressState.Floor = Floor * 100; 877 InbvProgressState.Ceiling = Ceiling * 100; 878 InbvProgressState.Bias = (Ceiling * 100) - Floor; 879 } 880 881 CODE_SEG("INIT") 882 VOID 883 NTAPI 884 InbvIndicateProgress(VOID) 885 { 886 ULONG Percentage; 887 888 /* Increase progress */ 889 InbvProgressIndicator.Count++; 890 891 /* Compute new percentage */ 892 Percentage = min(100 * InbvProgressIndicator.Count / 893 InbvProgressIndicator.Expected, 894 99); 895 if (Percentage != InbvProgressIndicator.Percentage) 896 { 897 /* Percentage has moved, update the progress bar */ 898 InbvProgressIndicator.Percentage = Percentage; 899 InbvUpdateProgressBar(Percentage); 900 } 901 } 902 903 PUCHAR 904 NTAPI 905 InbvGetResourceAddress(IN ULONG ResourceNumber) 906 { 907 /* Validate the resource number */ 908 if (ResourceNumber > ResourceCount) return NULL; 909 910 /* Return the address */ 911 return ResourceList[ResourceNumber]; 912 } 913 914 NTSTATUS 915 NTAPI 916 NtDisplayString(IN PUNICODE_STRING DisplayString) 917 { 918 NTSTATUS Status; 919 UNICODE_STRING CapturedString; 920 OEM_STRING OemString; 921 ULONG OemLength; 922 KPROCESSOR_MODE PreviousMode; 923 924 PAGED_CODE(); 925 926 PreviousMode = ExGetPreviousMode(); 927 928 /* We require the TCB privilege */ 929 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) 930 return STATUS_PRIVILEGE_NOT_HELD; 931 932 /* Capture the string */ 933 Status = ProbeAndCaptureUnicodeString(&CapturedString, PreviousMode, DisplayString); 934 if (!NT_SUCCESS(Status)) 935 return Status; 936 937 /* Do not display the string if it is empty */ 938 if (CapturedString.Length == 0 || CapturedString.Buffer == NULL) 939 { 940 Status = STATUS_SUCCESS; 941 goto Quit; 942 } 943 944 /* 945 * Convert the string since INBV understands only ANSI/OEM. Allocate the 946 * string buffer in non-paged pool because INBV passes it down to BOOTVID. 947 * We cannot perform the allocation using RtlUnicodeStringToOemString() 948 * since its allocator uses PagedPool. 949 */ 950 OemLength = RtlUnicodeStringToOemSize(&CapturedString); 951 if (OemLength > MAXUSHORT) 952 { 953 Status = STATUS_BUFFER_OVERFLOW; 954 goto Quit; 955 } 956 RtlInitEmptyAnsiString((PANSI_STRING)&OemString, NULL, (USHORT)OemLength); 957 OemString.Buffer = ExAllocatePoolWithTag(NonPagedPool, OemLength, TAG_OSTR); 958 if (OemString.Buffer == NULL) 959 { 960 Status = STATUS_NO_MEMORY; 961 goto Quit; 962 } 963 Status = RtlUnicodeStringToOemString(&OemString, &CapturedString, FALSE); 964 if (!NT_SUCCESS(Status)) 965 { 966 ExFreePoolWithTag(OemString.Buffer, TAG_OSTR); 967 goto Quit; 968 } 969 970 /* Display the string */ 971 InbvDisplayString(OemString.Buffer); 972 973 /* Free the string buffer */ 974 ExFreePoolWithTag(OemString.Buffer, TAG_OSTR); 975 976 Status = STATUS_SUCCESS; 977 978 Quit: 979 /* Free the captured string */ 980 ReleaseCapturedUnicodeString(&CapturedString, PreviousMode); 981 982 return Status; 983 } 984 985 #ifdef INBV_ROTBAR_IMPLEMENTED 986 static 987 VOID 988 NTAPI 989 InbvRotationThread( 990 _In_ PVOID Context) 991 { 992 ULONG X, Y, Index, Total; 993 LARGE_INTEGER Delay = {{0}}; 994 995 InbvAcquireLock(); 996 if (RotBarSelection == RB_SQUARE_CELLS) 997 { 998 Index = 0; 999 } 1000 else 1001 { 1002 Index = 32; 1003 } 1004 X = ProgressBarLeft + 2; 1005 Y = ProgressBarTop + 2; 1006 InbvReleaseLock(); 1007 1008 while (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) 1009 { 1010 /* Wait for a bit */ 1011 KeDelayExecutionThread(KernelMode, FALSE, &Delay); 1012 1013 InbvAcquireLock(); 1014 1015 /* Unknown unexpected command */ 1016 ASSERT(PltRotBarStatus < RBS_STATUS_MAX); 1017 1018 if (PltRotBarStatus == RBS_STOP_ANIMATE) 1019 { 1020 /* Stop the thread */ 1021 InbvReleaseLock(); 1022 break; 1023 } 1024 1025 if (RotBarSelection == RB_SQUARE_CELLS) 1026 { 1027 Delay.QuadPart = -800000; // 80 ms 1028 Total = 18; 1029 Index %= Total; 1030 1031 if (Index >= 3) 1032 { 1033 /* Fill previous bar position */ 1034 VidSolidColorFill(X + ((Index - 3) * 8), Y, (X + ((Index - 3) * 8)) + 8 - 1, Y + 9 - 1, BV_COLOR_BLACK); 1035 } 1036 if (Index < Total - 1) 1037 { 1038 /* Draw the progress bar bit */ 1039 if (Index < 2) 1040 { 1041 /* Appearing from the left */ 1042 VidBufferToScreenBlt(RotBarBuffer + 8 * (2 - Index) / 2, X, Y, 22 - 8 * (2 - Index), 9, 24); 1043 } 1044 else if (Index >= Total - 3) 1045 { 1046 /* Hiding to the right */ 1047 VidBufferToScreenBlt(RotBarBuffer, X + ((Index - 2) * 8), Y, 22 - 8 * (4 - (Total - Index)), 9, 24); 1048 } 1049 else 1050 { 1051 VidBufferToScreenBlt(RotBarBuffer, X + ((Index - 2) * 8), Y, 22, 9, 24); 1052 } 1053 } 1054 Index++; 1055 } 1056 else if (RotBarSelection == RB_PROGRESS_BAR) 1057 { 1058 Delay.QuadPart = -600000; // 60 ms 1059 Total = SCREEN_WIDTH; 1060 Index %= Total; 1061 1062 /* Right part */ 1063 VidBufferToScreenBlt(RotLineBuffer, Index, SCREEN_HEIGHT-6, SCREEN_WIDTH - Index, 6, SCREEN_WIDTH); 1064 if (Index > 0) 1065 { 1066 /* Left part */ 1067 VidBufferToScreenBlt(RotLineBuffer + (SCREEN_WIDTH - Index) / 2, 0, SCREEN_HEIGHT-6, Index - 2, 6, SCREEN_WIDTH); 1068 } 1069 Index += 32; 1070 } 1071 1072 InbvReleaseLock(); 1073 } 1074 1075 PsTerminateSystemThread(STATUS_SUCCESS); 1076 } 1077 1078 CODE_SEG("INIT") 1079 VOID 1080 NTAPI 1081 InbvRotBarInit(VOID) 1082 { 1083 PltRotBarStatus = RBS_FADEIN; 1084 /* Perform other initialization if needed */ 1085 } 1086 #endif 1087 1088 CODE_SEG("INIT") 1089 VOID 1090 NTAPI 1091 DisplayBootBitmap(IN BOOLEAN TextMode) 1092 { 1093 PVOID BootCopy = NULL, BootProgress = NULL, BootLogo = NULL, Header = NULL, Footer = NULL; 1094 1095 #ifdef INBV_ROTBAR_IMPLEMENTED 1096 UCHAR Buffer[24 * 9]; 1097 PVOID Bar = NULL, LineBmp = NULL; 1098 ROT_BAR_TYPE TempRotBarSelection = RB_UNSPECIFIED; 1099 NTSTATUS Status; 1100 HANDLE ThreadHandle = NULL; 1101 #endif 1102 1103 #ifdef REACTOS_SKUS 1104 PVOID Text = NULL; 1105 #endif 1106 1107 #ifdef INBV_ROTBAR_IMPLEMENTED 1108 /* Check if the animation thread has already been created */ 1109 if (RotBarThreadActive) 1110 { 1111 /* Yes, just reset the progress bar but keep the thread alive */ 1112 InbvAcquireLock(); 1113 RotBarSelection = RB_UNSPECIFIED; 1114 InbvReleaseLock(); 1115 } 1116 #endif 1117 1118 ShowProgressBar = FALSE; 1119 1120 /* Check if this is text mode */ 1121 if (TextMode) 1122 { 1123 /* 1124 * Make the kernel resource section temporarily writable, 1125 * as we are going to change the bitmaps' palette in place. 1126 */ 1127 MmChangeKernelResourceSectionProtection(MM_READWRITE); 1128 1129 /* Check the type of the OS: workstation or server */ 1130 if (SharedUserData->NtProductType == NtProductWinNt) 1131 { 1132 /* Workstation; set colors */ 1133 InbvSetTextColor(BV_COLOR_WHITE); 1134 InbvSolidColorFill(0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, BV_COLOR_DARK_GRAY); 1135 InbvSolidColorFill(0, VID_FOOTER_BG_TOP, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, BV_COLOR_RED); 1136 1137 /* Get resources */ 1138 Header = InbvGetResourceAddress(IDB_WKSTA_HEADER); 1139 Footer = InbvGetResourceAddress(IDB_WKSTA_FOOTER); 1140 } 1141 else 1142 { 1143 /* Server; set colors */ 1144 InbvSetTextColor(BV_COLOR_LIGHT_CYAN); 1145 InbvSolidColorFill(0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, BV_COLOR_CYAN); 1146 InbvSolidColorFill(0, VID_FOOTER_BG_TOP, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, BV_COLOR_RED); 1147 1148 /* Get resources */ 1149 Header = InbvGetResourceAddress(IDB_SERVER_HEADER); 1150 Footer = InbvGetResourceAddress(IDB_SERVER_FOOTER); 1151 } 1152 1153 /* Set the scrolling region */ 1154 InbvSetScrollRegion(VID_SCROLL_AREA_LEFT, VID_SCROLL_AREA_TOP, 1155 VID_SCROLL_AREA_RIGHT, VID_SCROLL_AREA_BOTTOM); 1156 1157 /* Make sure we have resources */ 1158 if (Header && Footer) 1159 { 1160 /* BitBlt them on the screen */ 1161 BitBltAligned(Footer, 1162 TRUE, 1163 AL_HORIZONTAL_CENTER, 1164 AL_VERTICAL_BOTTOM, 1165 0, 0, 0, 59); 1166 BitBltAligned(Header, 1167 FALSE, 1168 AL_HORIZONTAL_CENTER, 1169 AL_VERTICAL_TOP, 1170 0, 0, 0, 0); 1171 } 1172 1173 /* Restore the kernel resource section protection to be read-only */ 1174 MmChangeKernelResourceSectionProtection(MM_READONLY); 1175 } 1176 else 1177 { 1178 /* Is the boot driver installed? */ 1179 if (!InbvBootDriverInstalled) return; 1180 1181 /* 1182 * Make the kernel resource section temporarily writable, 1183 * as we are going to change the bitmaps' palette in place. 1184 */ 1185 MmChangeKernelResourceSectionProtection(MM_READWRITE); 1186 1187 /* Load boot screen logo */ 1188 BootLogo = InbvGetResourceAddress(IDB_LOGO_DEFAULT); 1189 1190 #ifdef REACTOS_SKUS 1191 Text = NULL; 1192 if (SharedUserData->NtProductType == NtProductWinNt) 1193 { 1194 #ifdef INBV_ROTBAR_IMPLEMENTED 1195 /* Workstation product, use appropriate status bar color */ 1196 Bar = InbvGetResourceAddress(IDB_BAR_WKSTA); 1197 #endif 1198 } 1199 else 1200 { 1201 /* Display correct branding based on server suite */ 1202 if (ExVerifySuite(StorageServer)) 1203 { 1204 /* Storage Server Edition */ 1205 Text = InbvGetResourceAddress(IDB_STORAGE_SERVER); 1206 } 1207 else if (ExVerifySuite(ComputeServer)) 1208 { 1209 /* Compute Cluster Edition */ 1210 Text = InbvGetResourceAddress(IDB_CLUSTER_SERVER); 1211 } 1212 else 1213 { 1214 /* Normal edition */ 1215 Text = InbvGetResourceAddress(IDB_SERVER_LOGO); 1216 } 1217 1218 #ifdef INBV_ROTBAR_IMPLEMENTED 1219 /* Server product, use appropriate status bar color */ 1220 Bar = InbvGetResourceAddress(IDB_BAR_DEFAULT); 1221 #endif 1222 } 1223 #else 1224 /* Use default status bar */ 1225 Bar = InbvGetResourceAddress(IDB_BAR_WKSTA); 1226 #endif 1227 1228 /* Make sure we have a logo */ 1229 if (BootLogo) 1230 { 1231 /* Save the main image palette for implementing the fade-in effect */ 1232 PBITMAPINFOHEADER BitmapInfoHeader = BootLogo; 1233 LPRGBQUAD Palette = (LPRGBQUAD)((PUCHAR)BootLogo + BitmapInfoHeader->biSize); 1234 RtlCopyMemory(MainPalette, Palette, sizeof(MainPalette)); 1235 1236 /* Draw the logo at the center of the screen */ 1237 BitBltAligned(BootLogo, 1238 TRUE, 1239 AL_HORIZONTAL_CENTER, 1240 AL_VERTICAL_CENTER, 1241 0, 0, 0, 34); 1242 1243 #ifdef INBV_ROTBAR_IMPLEMENTED 1244 /* Choose progress bar */ 1245 TempRotBarSelection = ROT_BAR_DEFAULT_MODE; 1246 #endif 1247 1248 /* Set progress bar coordinates and display it */ 1249 InbvSetProgressBarCoordinates(VID_PROGRESS_BAR_LEFT, 1250 VID_PROGRESS_BAR_TOP, 1251 VID_PROGRESS_BAR_WIDTH, 1252 VID_PROGRESS_BAR_HEIGHT); 1253 1254 #ifdef REACTOS_SKUS 1255 /* Check for non-workstation products */ 1256 if (SharedUserData->NtProductType != NtProductWinNt) 1257 { 1258 /* Overwrite part of the logo for a server product */ 1259 InbvScreenToBufferBlt(Buffer, VID_SKU_SAVE_AREA_LEFT, 1260 VID_SKU_SAVE_AREA_TOP, 7, 7, 8); 1261 InbvSolidColorFill(VID_SKU_AREA_LEFT, VID_SKU_AREA_TOP, 1262 VID_SKU_AREA_RIGHT, VID_SKU_AREA_BOTTOM, BV_COLOR_BLACK); 1263 InbvBufferToScreenBlt(Buffer, VID_SKU_SAVE_AREA_LEFT, 1264 VID_SKU_SAVE_AREA_TOP, 7, 7, 8); 1265 1266 /* In setup mode, you haven't selected a SKU yet */ 1267 if (ExpInTextModeSetup) Text = NULL; 1268 } 1269 #endif 1270 } 1271 1272 /* Load and draw progress bar bitmap */ 1273 BootProgress = InbvGetResourceAddress(IDB_PROGRESS_BAR); 1274 BitBltAligned(BootProgress, 1275 TRUE, 1276 AL_HORIZONTAL_CENTER, 1277 AL_VERTICAL_CENTER, 1278 0, 118, 0, 0); 1279 1280 /* Load and draw copyright text bitmap */ 1281 BootCopy = InbvGetResourceAddress(IDB_COPYRIGHT); 1282 BitBltAligned(BootCopy, 1283 TRUE, 1284 AL_HORIZONTAL_LEFT, 1285 AL_VERTICAL_BOTTOM, 1286 22, 0, 0, 20); 1287 1288 #ifdef REACTOS_SKUS 1289 /* Draw the SKU text if it exits */ 1290 if (Text) 1291 BitBltPalette(Text, TRUE, VID_SKU_TEXT_LEFT, VID_SKU_TEXT_TOP); 1292 #endif 1293 1294 #ifdef INBV_ROTBAR_IMPLEMENTED 1295 if ((TempRotBarSelection == RB_SQUARE_CELLS) && Bar) 1296 { 1297 /* Save previous screen pixels to buffer */ 1298 InbvScreenToBufferBlt(Buffer, 0, 0, 22, 9, 24); 1299 /* Draw the progress bar bit */ 1300 BitBltPalette(Bar, TRUE, 0, 0); 1301 /* Store it in global buffer */ 1302 InbvScreenToBufferBlt(RotBarBuffer, 0, 0, 22, 9, 24); 1303 /* Restore screen pixels */ 1304 InbvBufferToScreenBlt(Buffer, 0, 0, 22, 9, 24); 1305 } 1306 1307 /* 1308 * Add a rotating bottom horizontal bar when using a progress bar, 1309 * to show that ReactOS can be still alive when the bar does not 1310 * appear to progress. 1311 */ 1312 if (TempRotBarSelection == RB_PROGRESS_BAR) 1313 { 1314 LineBmp = InbvGetResourceAddress(IDB_ROTATING_LINE); 1315 if (LineBmp) 1316 { 1317 /* Draw the line and store it in global buffer */ 1318 BitBltPalette(LineBmp, TRUE, 0, SCREEN_HEIGHT-6); 1319 InbvScreenToBufferBlt(RotLineBuffer, 0, SCREEN_HEIGHT-6, SCREEN_WIDTH, 6, SCREEN_WIDTH); 1320 } 1321 } 1322 else 1323 { 1324 /* Hide the simple progress bar if not used */ 1325 ShowProgressBar = FALSE; 1326 } 1327 #endif 1328 1329 /* Restore the kernel resource section protection to be read-only */ 1330 MmChangeKernelResourceSectionProtection(MM_READONLY); 1331 1332 /* Display the boot logo and fade it in */ 1333 BootLogoFadeIn(); 1334 1335 #ifdef INBV_ROTBAR_IMPLEMENTED 1336 if (!RotBarThreadActive && TempRotBarSelection != RB_UNSPECIFIED) 1337 { 1338 /* Start the animation thread */ 1339 Status = PsCreateSystemThread(&ThreadHandle, 1340 0, 1341 NULL, 1342 NULL, 1343 NULL, 1344 InbvRotationThread, 1345 NULL); 1346 if (NT_SUCCESS(Status)) 1347 { 1348 /* The thread has started, close the handle as we don't need it */ 1349 RotBarThreadActive = TRUE; 1350 ObCloseHandle(ThreadHandle, KernelMode); 1351 } 1352 } 1353 #endif 1354 1355 /* Set filter which will draw text display if needed */ 1356 InbvInstallDisplayStringFilter(DisplayFilter); 1357 } 1358 1359 #ifdef INBV_ROTBAR_IMPLEMENTED 1360 /* Do we have the animation thread? */ 1361 if (RotBarThreadActive) 1362 { 1363 /* We do, initialize the progress bar */ 1364 InbvAcquireLock(); 1365 RotBarSelection = TempRotBarSelection; 1366 InbvRotBarInit(); 1367 InbvReleaseLock(); 1368 } 1369 #endif 1370 } 1371 1372 CODE_SEG("INIT") 1373 VOID 1374 NTAPI 1375 DisplayFilter(PCHAR *String) 1376 { 1377 /* Windows hack to skip first dots */ 1378 static BOOLEAN DotHack = TRUE; 1379 1380 /* If "." is given set *String to empty string */ 1381 if (DotHack && strcmp(*String, ".") == 0) 1382 *String = ""; 1383 1384 if (**String) 1385 { 1386 /* Remove the filter */ 1387 InbvInstallDisplayStringFilter(NULL); 1388 1389 DotHack = FALSE; 1390 1391 /* Draw text screen */ 1392 DisplayBootBitmap(TRUE); 1393 } 1394 } 1395 1396 CODE_SEG("INIT") 1397 VOID 1398 NTAPI 1399 FinalizeBootLogo(VOID) 1400 { 1401 /* Acquire lock and check the display state */ 1402 InbvAcquireLock(); 1403 if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED) 1404 { 1405 /* Clear the screen */ 1406 VidSolidColorFill(0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1, BV_COLOR_BLACK); 1407 } 1408 1409 /* Reset progress bar and lock */ 1410 #ifdef INBV_ROTBAR_IMPLEMENTED 1411 PltRotBarStatus = RBS_STOP_ANIMATE; 1412 RotBarThreadActive = FALSE; 1413 #endif 1414 InbvReleaseLock(); 1415 } 1416