mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 21:58:49 +00:00
863 lines
25 KiB
C
863 lines
25 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: services/dd/blue/blue.c
|
|
* PURPOSE: Console (blue screen) device driver
|
|
* PROGRAMMER: Eric Kohl
|
|
* UPDATE HISTORY:
|
|
* ??? Created
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include "blue.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
// ROS Internal. Please deprecate.
|
|
NTHALAPI
|
|
BOOLEAN
|
|
NTAPI
|
|
HalQueryDisplayOwnership(
|
|
VOID
|
|
);
|
|
|
|
/* NOTES ******************************************************************/
|
|
/*
|
|
* [[character][attribute]][[character][attribute]]....
|
|
*/
|
|
|
|
|
|
/* TYPEDEFS ***************************************************************/
|
|
|
|
typedef struct _DEVICE_EXTENSION
|
|
{
|
|
PUCHAR VideoMemory; /* Pointer to video memory */
|
|
ULONG CursorSize;
|
|
INT CursorVisible;
|
|
USHORT CharAttribute;
|
|
ULONG Mode;
|
|
UCHAR ScanLines; /* Height of a text line */
|
|
USHORT Rows; /* Number of rows */
|
|
USHORT Columns; /* Number of columns */
|
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
|
|
|
typedef struct _VGA_REGISTERS
|
|
{
|
|
UCHAR CRT[24];
|
|
UCHAR Attribute[21];
|
|
UCHAR Graphics[9];
|
|
UCHAR Sequencer[5];
|
|
UCHAR Misc;
|
|
} VGA_REGISTERS, *PVGA_REGISTERS;
|
|
|
|
static const VGA_REGISTERS VidpMode3Regs =
|
|
{
|
|
/* CRT Controller Registers */
|
|
{0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x47, 0x1E, 0x00,
|
|
0x00, 0x00, 0x05, 0xF0, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3},
|
|
/* Attribute Controller Registers */
|
|
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
|
|
0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00},
|
|
/* Graphics Controller Registers */
|
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF},
|
|
/* Sequencer Registers */
|
|
{0x03, 0x00, 0x03, 0x00, 0x02},
|
|
/* Misc Output Register */
|
|
0x67
|
|
};
|
|
|
|
static const UCHAR DefaultPalette[] =
|
|
{
|
|
0, 0, 0,
|
|
0, 0, 0xC0,
|
|
0, 0xC0, 0,
|
|
0, 0xC0, 0xC0,
|
|
0xC0, 0, 0,
|
|
0xC0, 0, 0xC0,
|
|
0xC0, 0xC0, 0,
|
|
0xC0, 0xC0, 0xC0,
|
|
0x80, 0x80, 0x80,
|
|
0, 0, 0xFF,
|
|
0, 0xFF, 0,
|
|
0, 0xFF, 0xFF,
|
|
0xFF, 0, 0,
|
|
0xFF, 0, 0xFF,
|
|
0xFF, 0xFF, 0,
|
|
0xFF, 0xFF, 0xFF
|
|
};
|
|
|
|
/* FUNCTIONS **************************************************************/
|
|
|
|
static VOID FASTCALL
|
|
ScrSetRegisters(const VGA_REGISTERS *Registers)
|
|
{
|
|
UINT32 i;
|
|
|
|
/* Update misc output register */
|
|
WRITE_PORT_UCHAR(MISC, Registers->Misc);
|
|
|
|
/* Synchronous reset on */
|
|
WRITE_PORT_UCHAR(SEQ, 0x00);
|
|
WRITE_PORT_UCHAR(SEQDATA, 0x01);
|
|
|
|
/* Write sequencer registers */
|
|
for (i = 1; i < sizeof(Registers->Sequencer); i++)
|
|
{
|
|
WRITE_PORT_UCHAR(SEQ, i);
|
|
WRITE_PORT_UCHAR(SEQDATA, Registers->Sequencer[i]);
|
|
}
|
|
|
|
/* Synchronous reset off */
|
|
WRITE_PORT_UCHAR(SEQ, 0x00);
|
|
WRITE_PORT_UCHAR(SEQDATA, 0x03);
|
|
|
|
/* Deprotect CRT registers 0-7 */
|
|
WRITE_PORT_UCHAR(CRTC, 0x11);
|
|
WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[0x11] & 0x7f);
|
|
|
|
/* Write CRT registers */
|
|
for (i = 0; i < sizeof(Registers->CRT); i++)
|
|
{
|
|
WRITE_PORT_UCHAR(CRTC, i);
|
|
WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[i]);
|
|
}
|
|
|
|
/* Write graphics controller registers */
|
|
for (i = 0; i < sizeof(Registers->Graphics); i++)
|
|
{
|
|
WRITE_PORT_UCHAR(GRAPHICS, i);
|
|
WRITE_PORT_UCHAR(GRAPHICSDATA, Registers->Graphics[i]);
|
|
}
|
|
|
|
/* Write attribute controller registers */
|
|
for (i = 0; i < sizeof(Registers->Attribute); i++)
|
|
{
|
|
READ_PORT_UCHAR(STATUS);
|
|
WRITE_PORT_UCHAR(ATTRIB, i);
|
|
WRITE_PORT_UCHAR(ATTRIB, Registers->Attribute[i]);
|
|
}
|
|
|
|
/* Set the PEL mask. */
|
|
WRITE_PORT_UCHAR(PELMASK, 0xff);
|
|
}
|
|
|
|
static VOID FASTCALL
|
|
ScrAcquireOwnership(PDEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
unsigned int offset;
|
|
UCHAR data, value;
|
|
ULONG Index;
|
|
|
|
ScrSetRegisters(&VidpMode3Regs);
|
|
|
|
/* Disable screen and enable palette access. */
|
|
READ_PORT_UCHAR(STATUS);
|
|
WRITE_PORT_UCHAR(ATTRIB, 0x00);
|
|
|
|
for (Index = 0; Index < sizeof(DefaultPalette) / 3; Index++)
|
|
{
|
|
WRITE_PORT_UCHAR(PELINDEX, Index);
|
|
WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3] >> 2);
|
|
WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3 + 1] >> 2);
|
|
WRITE_PORT_UCHAR(PELDATA, DefaultPalette[Index * 3 + 2] >> 2);
|
|
}
|
|
|
|
/* Enable screen and disable palette access. */
|
|
READ_PORT_UCHAR(STATUS);
|
|
WRITE_PORT_UCHAR(ATTRIB, 0x20);
|
|
|
|
/* get current output position */
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
offset = READ_PORT_UCHAR (CRTC_DATA);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
|
|
|
|
/* switch blinking characters off */
|
|
READ_PORT_UCHAR (ATTRC_INPST1);
|
|
value = READ_PORT_UCHAR (ATTRC_WRITEREG);
|
|
WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10);
|
|
data = READ_PORT_UCHAR (ATTRC_READREG);
|
|
data = data & ~0x08;
|
|
WRITE_PORT_UCHAR (ATTRC_WRITEREG, data);
|
|
WRITE_PORT_UCHAR (ATTRC_WRITEREG, value);
|
|
READ_PORT_UCHAR (ATTRC_INPST1);
|
|
|
|
/* read screen information from crt controller */
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS);
|
|
DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1;
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS);
|
|
DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW);
|
|
data = READ_PORT_UCHAR (CRTC_DATA);
|
|
DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3));
|
|
DeviceExtension->Rows++;
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES);
|
|
DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1;
|
|
|
|
/* show blinking cursor */
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
|
|
data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
|
|
WRITE_PORT_UCHAR (CRTC_DATA,
|
|
data | ((DeviceExtension->ScanLines - 1) & 0x1F));
|
|
|
|
/* calculate number of text rows */
|
|
DeviceExtension->Rows =
|
|
DeviceExtension->Rows / DeviceExtension->ScanLines;
|
|
#ifdef BOCHS_30ROWS
|
|
DeviceExtension->Rows = 30;
|
|
#endif
|
|
|
|
DPRINT ("%d Columns %d Rows %d Scanlines\n",
|
|
DeviceExtension->Columns,
|
|
DeviceExtension->Rows,
|
|
DeviceExtension->ScanLines);
|
|
}
|
|
|
|
NTSTATUS NTAPI
|
|
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
|
|
|
static DRIVER_DISPATCH ScrCreate;
|
|
static NTSTATUS NTAPI
|
|
ScrCreate(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
PHYSICAL_ADDRESS BaseAddress;
|
|
NTSTATUS Status;
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
ScrAcquireOwnership(DeviceExtension);
|
|
|
|
/* get pointer to video memory */
|
|
BaseAddress.QuadPart = VIDMEM_BASE;
|
|
DeviceExtension->VideoMemory =
|
|
(PUCHAR)MmMapIoSpace (BaseAddress, DeviceExtension->Rows * DeviceExtension->Columns * 2, MmNonCached);
|
|
}
|
|
else
|
|
{
|
|
/* store dummy values here */
|
|
DeviceExtension->Columns = 1;
|
|
DeviceExtension->Rows = 1;
|
|
DeviceExtension->ScanLines = 1;
|
|
}
|
|
|
|
DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
|
|
DeviceExtension->CursorVisible = TRUE;
|
|
|
|
/* more initialization */
|
|
DeviceExtension->CharAttribute = 0x17; /* light grey on blue */
|
|
DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
|
|
ENABLE_WRAP_AT_EOL_OUTPUT;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
static DRIVER_DISPATCH ScrWrite;
|
|
static NTSTATUS NTAPI
|
|
ScrWrite(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
|
|
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
|
NTSTATUS Status;
|
|
char *pch = Irp->UserBuffer;
|
|
PUCHAR vidmem;
|
|
unsigned int i;
|
|
int j, offset;
|
|
int cursorx, cursory;
|
|
int rows, columns;
|
|
int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT;
|
|
|
|
if (InbvCheckDisplayOwnership())
|
|
{
|
|
/* Display is in graphics mode, we're not allowed to touch it */
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
rows = DeviceExtension->Rows;
|
|
columns = DeviceExtension->Columns;
|
|
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
offset += READ_PORT_UCHAR (CRTC_DATA);
|
|
_enable();
|
|
|
|
cursory = offset / columns;
|
|
cursorx = offset % columns;
|
|
if( processed == 0 )
|
|
{
|
|
/* raw output mode */
|
|
memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
|
|
offset += (stk->Parameters.Write.Length / 2);
|
|
}
|
|
else {
|
|
for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
|
|
{
|
|
switch (*pch)
|
|
{
|
|
case '\b':
|
|
if (cursorx > 0)
|
|
{
|
|
cursorx--;
|
|
}
|
|
else if (cursory > 0)
|
|
{
|
|
cursorx = columns - 1;
|
|
cursory--;
|
|
}
|
|
vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
|
|
vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
|
|
break;
|
|
|
|
case '\n':
|
|
cursory++;
|
|
cursorx = 0;
|
|
break;
|
|
|
|
case '\r':
|
|
cursorx = 0;
|
|
break;
|
|
|
|
case '\t':
|
|
offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
|
|
for (j = 0; j < offset; j++)
|
|
{
|
|
vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
|
|
cursorx++;
|
|
|
|
if (cursorx >= columns)
|
|
{
|
|
cursory++;
|
|
cursorx = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
|
|
vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
|
|
cursorx++;
|
|
if (cursorx >= columns)
|
|
{
|
|
cursory++;
|
|
cursorx = 0;
|
|
}
|
|
break;
|
|
}
|
|
if (cursory >= rows)
|
|
{
|
|
unsigned short *LinePtr;
|
|
|
|
memcpy (vidmem,
|
|
&vidmem[columns * 2],
|
|
columns * (rows - 1) * 2);
|
|
|
|
LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
|
|
|
|
for (j = 0; j < columns; j++)
|
|
{
|
|
LinePtr[j] = DeviceExtension->CharAttribute << 8;
|
|
}
|
|
cursory = rows - 1;
|
|
for (j = 0; j < columns; j++)
|
|
{
|
|
vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
|
|
vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Set the cursor position */
|
|
offset = (cursory * columns) + cursorx;
|
|
}
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, offset);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
offset >>= 8;
|
|
WRITE_PORT_UCHAR (CRTC_DATA, offset);
|
|
_enable();
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
static DRIVER_DISPATCH ScrIoControl;
|
|
static NTSTATUS NTAPI
|
|
ScrIoControl(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
NTSTATUS Status;
|
|
|
|
DeviceExtension = DeviceObject->DeviceExtension;
|
|
switch (stk->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
|
|
{
|
|
PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
int rows = DeviceExtension->Rows;
|
|
int columns = DeviceExtension->Columns;
|
|
unsigned int offset;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
/* read cursor position from crtc */
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
offset = READ_PORT_UCHAR (CRTC_DATA);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
|
|
_enable();
|
|
}
|
|
else
|
|
{
|
|
offset = 0;
|
|
}
|
|
|
|
pcsbi->dwSize.X = columns;
|
|
pcsbi->dwSize.Y = rows;
|
|
|
|
pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
|
|
pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
|
|
|
|
pcsbi->wAttributes = DeviceExtension->CharAttribute;
|
|
|
|
pcsbi->srWindow.Left = 0;
|
|
pcsbi->srWindow.Right = columns - 1;
|
|
pcsbi->srWindow.Top = 0;
|
|
pcsbi->srWindow.Bottom = rows - 1;
|
|
|
|
pcsbi->dwMaximumWindowSize.X = columns;
|
|
pcsbi->dwMaximumWindowSize.Y = rows;
|
|
|
|
Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
|
|
{
|
|
PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
unsigned int offset;
|
|
|
|
DeviceExtension->CharAttribute = pcsbi->wAttributes;
|
|
offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
|
|
pcsbi->dwCursorPosition.X;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, offset);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
|
|
_enable();
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_GET_CURSOR_INFO:
|
|
{
|
|
PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
pcci->dwSize = DeviceExtension->CursorSize;
|
|
pcci->bVisible = DeviceExtension->CursorVisible;
|
|
|
|
Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_SET_CURSOR_INFO:
|
|
{
|
|
PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
|
|
UCHAR data, value;
|
|
ULONG size, height;
|
|
|
|
DeviceExtension->CursorSize = pcci->dwSize;
|
|
DeviceExtension->CursorVisible = pcci->bVisible;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
height = DeviceExtension->ScanLines;
|
|
data = (pcci->bVisible) ? 0x00 : 0x20;
|
|
|
|
size = (pcci->dwSize * height) / 100;
|
|
if (size < 1)
|
|
{
|
|
size = 1;
|
|
}
|
|
|
|
data |= (UCHAR)(height - size);
|
|
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, data);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
|
|
value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
|
|
WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
|
|
|
|
_enable();
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_GET_MODE:
|
|
{
|
|
PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
pcm->dwMode = DeviceExtension->Mode;
|
|
|
|
Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_SET_MODE:
|
|
{
|
|
PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
DeviceExtension->Mode = pcm->dwMode;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
|
|
{
|
|
POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
|
|
(Buf->dwCoord.X * 2) + 1;
|
|
|
|
for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
|
|
{
|
|
vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
|
|
}
|
|
}
|
|
|
|
Buf->dwTransfered = Buf->nLength;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
|
|
{
|
|
POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
|
|
PUSHORT pAttr = (PUSHORT)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
|
|
(Buf->dwCoord.X * 2) + 1;
|
|
|
|
for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++)
|
|
{
|
|
*((char *) pAttr) = vidmem[offset + (dwCount * 2)];
|
|
}
|
|
|
|
Buf->dwTransfered = dwCount;
|
|
}
|
|
else
|
|
{
|
|
Buf->dwTransfered = 0;
|
|
}
|
|
|
|
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
|
|
{
|
|
COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
CHAR *pAttr = (CHAR *)(pCoord + 1);
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (pCoord->Y * DeviceExtension->Columns * 2) +
|
|
(pCoord->X * 2) + 1;
|
|
|
|
for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pAttr++)
|
|
{
|
|
vidmem[offset + (dwCount * 2)] = *pAttr;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
|
|
DeviceExtension->CharAttribute = (USHORT)*(PUSHORT)Irp->AssociatedIrp.SystemBuffer;
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
|
|
{
|
|
POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
|
|
(Buf->dwCoord.X * 2);
|
|
|
|
|
|
for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
|
|
{
|
|
vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
|
|
}
|
|
}
|
|
|
|
Buf->dwTransfered = Buf->nLength;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
|
|
{
|
|
POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
|
|
LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
|
|
(Buf->dwCoord.X * 2);
|
|
|
|
for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++)
|
|
{
|
|
*pChar = vidmem[offset + (dwCount * 2)];
|
|
}
|
|
|
|
Buf->dwTransfered = dwCount;
|
|
}
|
|
else
|
|
{
|
|
Buf->dwTransfered = 0;
|
|
}
|
|
|
|
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
|
|
{
|
|
COORD *pCoord;
|
|
LPSTR pChar;
|
|
PUCHAR vidmem;
|
|
int offset;
|
|
ULONG dwCount;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
pChar = (CHAR *)(pCoord + 1);
|
|
vidmem = DeviceExtension->VideoMemory;
|
|
offset = (pCoord->Y * DeviceExtension->Columns * 2) +
|
|
(pCoord->X * 2);
|
|
|
|
for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof( COORD )); dwCount++, pChar++)
|
|
{
|
|
vidmem[offset + (dwCount * 2)] = *pChar;
|
|
}
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_DRAW:
|
|
{
|
|
PCONSOLE_DRAW ConsoleDraw;
|
|
PUCHAR Src, Dest;
|
|
UINT32 SrcDelta, DestDelta, i, Offset;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
ConsoleDraw = (PCONSOLE_DRAW) MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
Src = (PUCHAR) (ConsoleDraw + 1);
|
|
SrcDelta = ConsoleDraw->SizeX * 2;
|
|
Dest = DeviceExtension->VideoMemory +
|
|
(ConsoleDraw->Y * DeviceExtension->Columns + ConsoleDraw->X) * 2;
|
|
DestDelta = DeviceExtension->Columns * 2;
|
|
|
|
for (i = 0; i < ConsoleDraw->SizeY; i++)
|
|
{
|
|
RtlCopyMemory(Dest, Src, SrcDelta);
|
|
Src += SrcDelta;
|
|
Dest += DestDelta;
|
|
}
|
|
|
|
Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) +
|
|
ConsoleDraw->CursorX;
|
|
|
|
_disable();
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, Offset);
|
|
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
|
|
WRITE_PORT_UCHAR (CRTC_DATA, Offset >> 8);
|
|
_enable();
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_CONSOLE_LOADFONT:
|
|
{
|
|
UINT32 CodePage = (UINT32)*(PULONG)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (!InbvCheckDisplayOwnership())
|
|
{
|
|
// Upload a font for the codepage if needed
|
|
ScrLoadFontTable(CodePage);
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return Status;
|
|
}
|
|
|
|
static DRIVER_DISPATCH ScrDispatch;
|
|
static NTSTATUS NTAPI
|
|
ScrDispatch(PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS Status;
|
|
|
|
switch (stk->MajorFunction)
|
|
{
|
|
case IRP_MJ_CLOSE:
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
break;
|
|
}
|
|
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
|
|
/*
|
|
* Module entry point
|
|
*/
|
|
NTSTATUS NTAPI
|
|
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen");
|
|
UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen");
|
|
|
|
DPRINT ("Screen Driver 0.0.6\n");
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
|
|
|
|
Status = IoCreateDevice (DriverObject,
|
|
sizeof(DEVICE_EXTENSION),
|
|
&DeviceName,
|
|
FILE_DEVICE_SCREEN,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
TRUE,
|
|
&DeviceObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
Status = IoCreateSymbolicLink (&SymlinkName, &DeviceName);
|
|
if (NT_SUCCESS(Status))
|
|
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
else
|
|
IoDeleteDevice (DeviceObject);
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|