能力值:
( LV2,RANK:10 )
|
-
-
6 楼
可以做到,但是需要你比较厉害。
蓝屏画面只支持16位色,不支持24位色和A通道。
调用流程如下:(xp下)
VOID
NTAPI
KeBugCheckEx(IN ULONG BugCheckCode,
IN ULONG_PTR BugCheckParameter1,
IN ULONG_PTR BugCheckParameter2,
IN ULONG_PTR BugCheckParameter3,
IN ULONG_PTR BugCheckParameter4)
{
/* Workaround for Windows Server 2003 Checked PCI Driver issue */
if (!((BugCheckCode == PCI_BUS_DRIVER_INTERNAL) &&
(BugCheckParameter1 == 0xDEAD0010)))
{
/* Call the internal API */
KeBugCheckWithTf(BugCheckCode,
BugCheckParameter1,
BugCheckParameter2,
BugCheckParameter3,
BugCheckParameter4,
NULL);
}
}
VOID
NTAPI
KeBugCheck(ULONG BugCheckCode)
{
/* Call the internal API */
KeBugCheckWithTf(BugCheckCode, 0, 0, 0, 0, NULL);
}
VOID
NTAPI
KeBugCheckWithTf(IN ULONG BugCheckCode,
IN ULONG_PTR BugCheckParameter1,
IN ULONG_PTR BugCheckParameter2,
IN ULONG_PTR BugCheckParameter3,
IN ULONG_PTR BugCheckParameter4,
IN PKTRAP_FRAME TrapFrame)
{
...
KiDisplayBlueScreen(MessageId,
IsHardError,
HardErrCaption,
HardErrMessage,
AnsiName);
...
}
VOID
NTAPI
KiDisplayBlueScreen(IN ULONG MessageId,
IN BOOLEAN IsHardError,
IN PCHAR HardErrCaption OPTIONAL,
IN PCHAR HardErrMessage OPTIONAL,
IN PCHAR Message)
{
CHAR AnsiName[75];
/* Check if bootvid is installed */
if (InbvIsBootDriverInstalled())
{
/* Acquire ownership and reset the display */
InbvAcquireDisplayOwnership();
InbvResetDisplay();
/* Display blue screen */
InbvSolidColorFill(0, 0, 639, 479, 4); <--- here
InbvSetTextColor(15);
InbvInstallDisplayStringFilter(NULL);
InbvEnableDisplayString(TRUE);
InbvSetScrollRegion(0, 0, 639, 479);
}
....
}
VOID
NTAPI
InbvSolidColorFill(IN ULONG Left,
IN ULONG Top,
IN ULONG Width,
IN ULONG Height,
IN ULONG Color)
{
/* Make sure we own it */
if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)
{
....
/* Check if we're installed */
if (InbvBootDriverInstalled)
{
/* Call bootvid */
VidSolidColorFill(Left, Top, Width, Height, (UCHAR)Color);
}
....
}
}
VOID
NTAPI
VidSolidColorFill(IN ULONG Left,
IN ULONG Top,
IN ULONG Right,
IN ULONG Bottom,
IN UCHAR Color)
{
int y, x;
//
// Loop along the Y-axis
//
for (y = Top; y <= Bottom; y++)
{
//
// Loop along the X-axis
//
for (x = Left; x <= Right; x++)
{
//
// Draw the pixel
//
VidpSetPixel(x, y, Color);
}
}
}
#define WRITE_REGISTER_USHORT(r, v) (*(volatile USHORT *)(r) = (v))
VOID
FORCEINLINE
VidpSetPixel(IN ULONG Left,
IN ULONG Top,
IN UCHAR Color)
{
PUSHORT PixelPosition;
//
// Calculate the pixel position
//
PixelPosition = &VgaArmBase[Left + (Top * 640)];
//
// Set our color
//
WRITE_REGISTER_USHORT(PixelPosition, VidpBuildColor(Color));
}
USHORT
FORCEINLINE
VidpBuildColor(IN UCHAR Color)
{
UCHAR Red, Green, Blue;
//
// Extract color components
//
Red = VidpVga8To16BitTransform[Color].Red;
Green = VidpVga8To16BitTransform[Color].Green;
Blue = VidpVga8To16BitTransform[Color].Blue;
//
// Build the 16-bit color mask
//
return ((Red & 0x1F) << 11) | ((Green & 0x1F) << 6) | ((Blue & 0x1F)); <--- here
}
其中
VGA_COLOR VidpVga8To16BitTransform[16] =
{
{0x00, 0x00, 0x00}, // Black
{0x00, 0x00, 0x08}, // Blue
{0x00, 0x08, 0x00}, // Green
{0x00, 0x08, 0x08}, // Cyan
{0x08, 0x00, 0x00}, // Red
{0x08, 0x00, 0x08}, // Magenta
{0x0B, 0x0D, 0x0F}, // Brown
{0x10, 0x10, 0x10}, // Light Gray
{0x08, 0x08, 0x08}, // Dark Gray
{0x00, 0x00, 0x1F}, // Light Blue
{0x00, 0x1F, 0x00}, // Light Green
{0x00, 0x1F, 0x1F}, // Light Cyan
{0x1F, 0x00, 0x00}, // Light Red
{0x1F, 0x00, 0x1F}, // Light Magenta
{0x1F, 0x1F, 0x00}, // Yellow
{0x1F, 0x1F, 0x1F}, // White
};
由此可见想要画图片,不能用它的VidpVga8To16BitTransform表
需要自己写16位颜色。
准备一张16位bmp位图,读进来,解析出颜色,然后写进去就行了
不过有几个难点
1. 你得能找到上面代码的位置,这个还不算难
2. 怎么读图片。这个比较困难,如果自己不会读,最好在3环准备一个图片格式转换工具
这样先将其他格式图片转为自己的格式,就是一个颜色的文本文件,这样就容易了。
不过还涉及到图片大小转换的问题,蓝屏指定大小与图片大小不一致时如何处理之类。
3. 显示文字,要么用原来的VidDisplayString,要么使用图片上的文本。
如果如此,必须准备3环的工具,将文本发到3环,绘到图片,导出颜色,返回内核。
总之太复杂,通常的做法是接到KeBugCheckEx直接重启,避免屏幕闪烁。不过我想你们也没这个需求。
|