bootvid.c

来自「一个类似windows」· C语言 代码 · 共 673 行 · 第 1/2 页

C
673
字号
   bminfo = (PBITMAPV5HEADER) &BootimageBitmap[0];
   DPRINT("bV5Size = %d\n", bminfo->bV5Size);
   DPRINT("bV5Width = %d\n", bminfo->bV5Width);
   DPRINT("bV5Height = %d\n", bminfo->bV5Height);
   DPRINT("bV5Planes = %d\n", bminfo->bV5Planes);
   DPRINT("bV5BitCount = %d\n", bminfo->bV5BitCount);
   DPRINT("bV5Compression = %d\n", bminfo->bV5Compression);
   DPRINT("bV5SizeImage = %d\n", bminfo->bV5SizeImage);
   DPRINT("bV5XPelsPerMeter = %d\n", bminfo->bV5XPelsPerMeter);
   DPRINT("bV5YPelsPerMeter = %d\n", bminfo->bV5YPelsPerMeter);
   DPRINT("bV5ClrUsed = %d\n", bminfo->bV5ClrUsed);
   DPRINT("bV5ClrImportant = %d\n", bminfo->bV5ClrImportant);

   if (bminfo->bV5ClrUsed)
      ClrUsed = bminfo->bV5ClrUsed;
   else
      ClrUsed = 1 << bminfo->bV5BitCount;

   bfOffBits = bminfo->bV5Size + ClrUsed * sizeof(RGBQUAD);
   DPRINT("bfOffBits = %d\n", bfOffBits);
   DPRINT("size of color indices = %d\n", ClrUsed * sizeof(RGBQUAD));
   DPRINT("first byte of data = %d\n", BootimageBitmap[bfOffBits]);

   InbvSetBlackPalette();

   ImageData = ExAllocatePool(NonPagedPool, bminfo->bV5Width * bminfo->bV5Height);
   RtlZeroMemory(ImageData, bminfo->bV5Width * bminfo->bV5Height);

   /*
    * ImageData has 1 pixel per byte.
    * bootimage has 2 pixels per byte.
    */

   if (bminfo->bV5Compression == 2)
   {
      k = 0;
      j = 0;
      while ((j < bminfo->bV5SizeImage) && (k < (ULONG) (bminfo->bV5Width * bminfo->bV5Height)))
      {
         unsigned char b;

         clen = BootimageBitmap[bfOffBits + j];
         j++;

         if (clen > 0)
         {
            /* Encoded mode */

            b = BootimageBitmap[bfOffBits + j];
            j++;

            for (i = 0; i < (clen / 2); i++)
            {
               ImageData[k] = (b & 0xf0) >> 4;
               k++;
               ImageData[k] = b & 0xf;
               k++;
            }
            if ((clen & 1) > 0)
            {
               ImageData[k] = (b & 0xf0) >> 4;
               k++;
            }
         }
         else
         {
            /* Absolute mode */
            b = BootimageBitmap[bfOffBits + j];
            j++;

            if (b == 0)
            {
               /* End of line */
               if (k % bminfo->bV5Width)
               {
                  cury = k / bminfo->bV5Width;
                  k = (cury + 1) * bminfo->bV5Width;
               }
            }
            else if (b == 1)
            {
               /* End of image */
               break;
            }
            else if (b == 2)
            {
               x = BootimageBitmap[bfOffBits + j];
               j++;
               y = BootimageBitmap[bfOffBits + j];
               j++;
               curx = k % bminfo->bV5Width;
               cury = k / bminfo->bV5Width;
               k = (cury + y) * bminfo->bV5Width + (curx + x);
            }
            else
            {
               if ((j & 1) > 0)
               {
                  DPRINT("Unaligned copy!\n");
               }

               clen = b;
               for (i = 0; i < (clen / 2); i++)
               {
                  b = BootimageBitmap[bfOffBits + j];
                  j++;

                  ImageData[k] = (b & 0xf0) >> 4;
                  k++;
                  ImageData[k] = b & 0xf;
                  k++;
               }
               if ((clen & 1) > 0)
               {
                  b = BootimageBitmap[bfOffBits + j];
                  j++;
                  ImageData[k] = (b & 0xf0) >> 4;
                  k++;
               }
               /* Word align */
               j += (j & 1);
            }
         }
      }

      InbvDisplayBitmap(bminfo->bV5Width, bminfo->bV5Height, ImageData);
   }
   else
   {
      DbgPrint("Warning boot image need to be compressed using RLE4\n");
   }

   ExFreePool(ImageData);
}


static VOID FASTCALL
InbvFadeUpPalette()
{
   PBITMAPV5HEADER bminfo;
   PRGBQUAD Palette;
   ULONG i;
   unsigned char r, g, b;
   register ULONG c;
   LARGE_INTEGER Interval;
   FADER_PALETTE_ENTRY FaderPalette[16];
   FADER_PALETTE_ENTRY FaderPaletteDelta[16];
   UCHAR ClrUsed;

   RtlZeroMemory(&FaderPalette, sizeof(FaderPalette));
   RtlZeroMemory(&FaderPaletteDelta, sizeof(FaderPaletteDelta));

   bminfo = (PBITMAPV5HEADER)&BootimageBitmap[0];
   Palette = (PRGBQUAD)&BootimageBitmap[bminfo->bV5Size];

   if (bminfo->bV5ClrUsed)
      ClrUsed = bminfo->bV5ClrUsed;
   else
      ClrUsed = 1 << bminfo->bV5BitCount;

   for (i = 0; i < 16 && i < ClrUsed; i++)
   {
      FaderPaletteDelta[i].r = ((Palette[i].rgbRed << 8) / PALETTE_FADE_STEPS);
      FaderPaletteDelta[i].g = ((Palette[i].rgbGreen << 8) / PALETTE_FADE_STEPS);
      FaderPaletteDelta[i].b = ((Palette[i].rgbBlue << 8) / PALETTE_FADE_STEPS);
   }

   for (i = 0; i < PALETTE_FADE_STEPS && !ShutdownNotify; i++)
   {
      /* Disable screen and enable palette access. */
      READ_PORT_UCHAR(STATUS);
      WRITE_PORT_UCHAR(ATTRIB, 0x00);

      for (c = 0; c < ClrUsed; c++)
      {
         /* Add the delta */
         FaderPalette[c].r += FaderPaletteDelta[c].r;
         FaderPalette[c].g += FaderPaletteDelta[c].g;
         FaderPalette[c].b += FaderPaletteDelta[c].b;

         /* Get the integer values */
         r = FaderPalette[c].r >> 8;
         g = FaderPalette[c].g >> 8;
         b = FaderPalette[c].b >> 8;

         /* Don't go too far */
         if (r > Palette[c].rgbRed)
            r = Palette[c].rgbRed;
         if (g > Palette[c].rgbGreen)
            g = Palette[c].rgbGreen;
         if (b > Palette[c].rgbBlue)
            b = Palette[c].rgbBlue;

         /* Update the hardware */
         InbvSetColor(c, r, g, b);
      }

      /* Enable screen and disable palette access. */
      READ_PORT_UCHAR(STATUS);
      WRITE_PORT_UCHAR(ATTRIB, 0x20);

      /* Wait for a bit. */
      Interval.QuadPart = -PALETTE_FADE_TIME;
      KeDelayExecutionThread(KernelMode, FALSE, &Interval);
   }
}


static VOID STDCALL
InbvBitmapThreadMain(PVOID Ignored)
{
   if (InbvFindBootimage())
   {
      InbvDisplayCompressedBitmap();
      InbvFadeUpPalette();
   }
   else
   {
      DbgPrint("Warning: Cannot find boot image\n");
   }
   KeSetEvent(&ShutdownCompleteEvent, 0, FALSE);
}


static BOOLEAN STDCALL
VidInitialize(VOID)
{
   NTSTATUS Status;
   HANDLE BitmapThreadHandle;

   InbvMapVideoMemory();
   InbvInitVGAMode();

   Status = PsCreateSystemThread(
      &BitmapThreadHandle,
      THREAD_ALL_ACCESS,
      NULL,
      NULL,
      &BitmapThreadId,
      InbvBitmapThreadMain,
      NULL);

   if (!NT_SUCCESS(Status))
   {
      return FALSE;
   }

   ZwClose(BitmapThreadHandle);

   return TRUE;
}


static NTSTATUS STDCALL
VidDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status;
   NTBOOTVID_FUNCTION_TABLE* FunctionTable;

   IrpSp = IoGetCurrentIrpStackLocation(Irp);
   Status = STATUS_SUCCESS;

   switch(IrpSp->MajorFunction)
   {
      /* Opening and closing handles to the device */
      case IRP_MJ_CREATE:
      case IRP_MJ_CLOSE:
         break;

      case IRP_MJ_DEVICE_CONTROL:
         switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
         {
            case IOCTL_BOOTVID_INITIALIZE:
               VidInitialize();
               FunctionTable = (NTBOOTVID_FUNCTION_TABLE *)
                  Irp->AssociatedIrp.SystemBuffer;
               FunctionTable->ResetDisplay = VidResetDisplay;
               Irp->IoStatus.Information = sizeof(NTBOOTVID_FUNCTION_TABLE);
               break;

            case IOCTL_BOOTVID_CLEANUP:
               VidCleanUp();
               break;

            default:
               Status = STATUS_NOT_IMPLEMENTED;
               break;
         }
         break;

      /* Unsupported operations */
      default:
         Status = STATUS_NOT_IMPLEMENTED;
   }

   Irp->IoStatus.Status = Status;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);

   return Status;
}


NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
   PDEVICE_OBJECT BootVidDevice;
   UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BootVid");
   NTSTATUS Status;

   BootVidDriverObject = DriverObject;

   ShutdownNotify = 0;
   KeInitializeEvent(&ShutdownCompleteEvent, NotificationEvent, FALSE);

   /* Register driver routines */
   DriverObject->MajorFunction[IRP_MJ_CLOSE] = VidDispatch;
   DriverObject->MajorFunction[IRP_MJ_CREATE] = VidDispatch;
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VidDispatch;
   DriverObject->DriverUnload = NULL;

   DriverObject->Flags |= DO_BUFFERED_IO;

   /* Create device */
   Status = IoCreateDevice(
      DriverObject,
      0,
      &DeviceName,
      FILE_DEVICE_BOOTVID,
      0,
      FALSE,
      &BootVidDevice);

   return Status;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?