2 * PROJECT: ReactOS Console Text-Mode Device Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Driver Management Functions.
5 * COPYRIGHT: Copyright 1999 Boudewijn Dekker
6 * Copyright 1999-2019 Eric Kohl
7 * Copyright 2006 Filip Navara
10 /* INCLUDES ******************************************************************/
13 #include <ndk/inbvfuncs.h>
18 /* NOTES ******************************************************************/
20 * [[character][attribute]][[character][attribute]]....
23 /* TYPEDEFS ***************************************************************/
25 typedef struct _DEVICE_EXTENSION
27 PUCHAR VideoMemory
; /* Pointer to video memory */
32 UCHAR ScanLines
; /* Height of a text line */
33 USHORT Rows
; /* Number of rows */
34 USHORT Columns
; /* Number of columns */
35 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
37 typedef struct _VGA_REGISTERS
44 } VGA_REGISTERS
, *PVGA_REGISTERS
;
46 static const VGA_REGISTERS VidpMode3Regs
=
48 /* CRT Controller Registers */
49 {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x47, 0x1E, 0x00,
50 0x00, 0x00, 0x05, 0xF0, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3},
51 /* Attribute Controller Registers */
52 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
53 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00},
54 /* Graphics Controller Registers */
55 {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00, 0xFF},
56 /* Sequencer Registers */
57 {0x03, 0x00, 0x03, 0x00, 0x02},
58 /* Misc Output Register */
62 static const UCHAR DefaultPalette
[] =
82 /* FUNCTIONS **************************************************************/
86 ScrSetRegisters(const VGA_REGISTERS
*Registers
)
90 /* Update misc output register */
91 WRITE_PORT_UCHAR(MISC
, Registers
->Misc
);
93 /* Synchronous reset on */
94 WRITE_PORT_UCHAR(SEQ
, 0x00);
95 WRITE_PORT_UCHAR(SEQDATA
, 0x01);
97 /* Write sequencer registers */
98 for (i
= 1; i
< sizeof(Registers
->Sequencer
); i
++)
100 WRITE_PORT_UCHAR(SEQ
, i
);
101 WRITE_PORT_UCHAR(SEQDATA
, Registers
->Sequencer
[i
]);
104 /* Synchronous reset off */
105 WRITE_PORT_UCHAR(SEQ
, 0x00);
106 WRITE_PORT_UCHAR(SEQDATA
, 0x03);
108 /* Deprotect CRT registers 0-7 */
109 WRITE_PORT_UCHAR(CRTC
, 0x11);
110 WRITE_PORT_UCHAR(CRTCDATA
, Registers
->CRT
[0x11] & 0x7f);
112 /* Write CRT registers */
113 for (i
= 0; i
< sizeof(Registers
->CRT
); i
++)
115 WRITE_PORT_UCHAR(CRTC
, i
);
116 WRITE_PORT_UCHAR(CRTCDATA
, Registers
->CRT
[i
]);
119 /* Write graphics controller registers */
120 for (i
= 0; i
< sizeof(Registers
->Graphics
); i
++)
122 WRITE_PORT_UCHAR(GRAPHICS
, i
);
123 WRITE_PORT_UCHAR(GRAPHICSDATA
, Registers
->Graphics
[i
]);
126 /* Write attribute controller registers */
127 for (i
= 0; i
< sizeof(Registers
->Attribute
); i
++)
129 READ_PORT_UCHAR(STATUS
);
130 WRITE_PORT_UCHAR(ATTRIB
, i
);
131 WRITE_PORT_UCHAR(ATTRIB
, Registers
->Attribute
[i
]);
134 /* Set the PEL mask */
135 WRITE_PORT_UCHAR(PELMASK
, 0xff);
141 _In_ PDEVICE_EXTENSION DeviceExtension
)
147 ScrSetRegisters(&VidpMode3Regs
);
149 /* Disable screen and enable palette access */
150 READ_PORT_UCHAR(STATUS
);
151 WRITE_PORT_UCHAR(ATTRIB
, 0x00);
153 for (Index
= 0; Index
< sizeof(DefaultPalette
) / 3; Index
++)
155 WRITE_PORT_UCHAR(PELINDEX
, Index
);
156 WRITE_PORT_UCHAR(PELDATA
, DefaultPalette
[Index
* 3] >> 2);
157 WRITE_PORT_UCHAR(PELDATA
, DefaultPalette
[Index
* 3 + 1] >> 2);
158 WRITE_PORT_UCHAR(PELDATA
, DefaultPalette
[Index
* 3 + 2] >> 2);
161 /* Enable screen and disable palette access */
162 READ_PORT_UCHAR(STATUS
);
163 WRITE_PORT_UCHAR(ATTRIB
, 0x20);
165 /* Get current output position */
166 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
167 offset
= READ_PORT_UCHAR(CRTC_DATA
);
168 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
169 offset
+= (READ_PORT_UCHAR(CRTC_DATA
) << 8);
171 /* Switch blinking characters off */
172 READ_PORT_UCHAR(ATTRC_INPST1
);
173 value
= READ_PORT_UCHAR(ATTRC_WRITEREG
);
174 WRITE_PORT_UCHAR(ATTRC_WRITEREG
, 0x10);
175 data
= READ_PORT_UCHAR(ATTRC_READREG
);
177 WRITE_PORT_UCHAR(ATTRC_WRITEREG
, data
);
178 WRITE_PORT_UCHAR(ATTRC_WRITEREG
, value
);
179 READ_PORT_UCHAR(ATTRC_INPST1
);
181 /* Read screen information from CRT controller */
182 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_COLUMNS
);
183 DeviceExtension
->Columns
= READ_PORT_UCHAR(CRTC_DATA
) + 1;
184 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_ROWS
);
185 DeviceExtension
->Rows
= READ_PORT_UCHAR(CRTC_DATA
);
186 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_OVERFLOW
);
187 data
= READ_PORT_UCHAR(CRTC_DATA
);
188 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
189 DeviceExtension
->Rows
++;
190 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_SCANLINES
);
191 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR(CRTC_DATA
) & 0x1F) + 1;
193 /* Show blinking cursor */
194 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORSTART
);
195 WRITE_PORT_UCHAR(CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
196 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSOREND
);
197 data
= READ_PORT_UCHAR(CRTC_DATA
) & 0xE0;
198 WRITE_PORT_UCHAR(CRTC_DATA
,
199 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
201 /* Calculate number of text rows */
202 DeviceExtension
->Rows
=
203 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
205 DeviceExtension
->Rows
= 30;
208 /* Upload a default font for the default codepage 437 */
209 ScrLoadFontTable(437);
211 DPRINT("%d Columns %d Rows %d Scanlines\n",
212 DeviceExtension
->Columns
,
213 DeviceExtension
->Rows
,
214 DeviceExtension
->ScanLines
);
217 static DRIVER_DISPATCH ScrCreate
;
221 _In_ PDEVICE_OBJECT DeviceObject
,
224 #define FOREGROUND_LIGHTGRAY (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
226 PDEVICE_EXTENSION DeviceExtension
;
227 PHYSICAL_ADDRESS BaseAddress
;
230 DeviceExtension
= DeviceObject
->DeviceExtension
;
232 if (!InbvCheckDisplayOwnership())
234 ScrAcquireOwnership(DeviceExtension
);
236 /* Get a pointer to the video memory */
237 BaseAddress
.QuadPart
= VIDMEM_BASE
;
238 DeviceExtension
->VideoMemory
=
239 (PUCHAR
)MmMapIoSpace(BaseAddress
, DeviceExtension
->Rows
* DeviceExtension
->Columns
* 2, MmNonCached
);
243 /* Store dummy values */
244 DeviceExtension
->Columns
= 1;
245 DeviceExtension
->Rows
= 1;
246 DeviceExtension
->ScanLines
= 1;
249 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
250 DeviceExtension
->CursorVisible
= TRUE
;
252 /* More initialization */
253 DeviceExtension
->CharAttribute
= BACKGROUND_BLUE
| FOREGROUND_LIGHTGRAY
;
254 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
255 ENABLE_WRAP_AT_EOL_OUTPUT
;
257 Status
= STATUS_SUCCESS
;
259 Irp
->IoStatus
.Status
= Status
;
260 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
264 static DRIVER_DISPATCH ScrWrite
;
268 _In_ PDEVICE_OBJECT DeviceObject
,
271 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
272 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
274 PCHAR pch
= Irp
->UserBuffer
;
278 USHORT cursorx
, cursory
;
279 USHORT rows
, columns
;
280 BOOLEAN processed
= !!(DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
);
282 if (InbvCheckDisplayOwnership())
284 /* Display is in graphics mode, we're not allowed to touch it */
285 Status
= STATUS_SUCCESS
;
287 Irp
->IoStatus
.Status
= Status
;
288 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
293 vidmem
= DeviceExtension
->VideoMemory
;
294 rows
= DeviceExtension
->Rows
;
295 columns
= DeviceExtension
->Columns
;
298 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
299 offset
= READ_PORT_UCHAR(CRTC_DATA
)<<8;
300 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
301 offset
+= READ_PORT_UCHAR(CRTC_DATA
);
304 cursory
= (USHORT
)(offset
/ columns
);
305 cursorx
= (USHORT
)(offset
% columns
);
308 /* Raw output mode */
309 // FIXME: Does the buffer only contains chars? or chars + attributes?
310 // FIXME2: Fix buffer overflow.
311 RtlCopyMemory(&vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)],
312 pch
, stk
->Parameters
.Write
.Length
);
313 offset
+= (stk
->Parameters
.Write
.Length
/ 2);
317 /* Cooked output mode */
318 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
328 else if (cursory
> 0)
330 cursorx
= columns
- 1;
333 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
334 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
349 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
350 for (j
= 0; j
< offset
; j
++)
352 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
355 if (cursorx
>= columns
)
366 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
367 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
369 if (cursorx
>= columns
)
378 /* Scroll up the contents of the screen if we are at the end */
383 RtlCopyMemory(vidmem
,
384 &vidmem
[columns
* 2],
385 columns
* (rows
- 1) * 2);
387 LinePtr
= (PUSHORT
)&vidmem
[columns
* (rows
- 1) * 2];
389 for (j
= 0; j
< columns
; j
++)
391 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
394 for (j
= 0; j
< columns
; j
++)
396 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
397 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
402 /* Set the cursor position */
403 offset
= (cursory
* columns
) + cursorx
;
406 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
407 WRITE_PORT_UCHAR(CRTC_DATA
, offset
);
408 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
410 WRITE_PORT_UCHAR(CRTC_DATA
, offset
);
413 Status
= STATUS_SUCCESS
;
415 Irp
->IoStatus
.Status
= Status
;
416 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
421 static DRIVER_DISPATCH ScrIoControl
;
425 _In_ PDEVICE_OBJECT DeviceObject
,
429 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
430 PDEVICE_EXTENSION DeviceExtension
;
432 DeviceExtension
= DeviceObject
->DeviceExtension
;
433 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
435 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
437 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
438 USHORT rows
= DeviceExtension
->Rows
;
439 USHORT columns
= DeviceExtension
->Columns
;
442 if (!InbvCheckDisplayOwnership())
444 /* read cursor position from crtc */
446 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
447 offset
= READ_PORT_UCHAR(CRTC_DATA
);
448 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
449 offset
+= (READ_PORT_UCHAR(CRTC_DATA
) << 8);
457 pcsbi
->dwSize
.X
= columns
;
458 pcsbi
->dwSize
.Y
= rows
;
460 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
461 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
463 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
465 pcsbi
->srWindow
.Left
= 0;
466 pcsbi
->srWindow
.Right
= columns
- 1;
467 pcsbi
->srWindow
.Top
= 0;
468 pcsbi
->srWindow
.Bottom
= rows
- 1;
470 pcsbi
->dwMaximumWindowSize
.X
= columns
;
471 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
473 Irp
->IoStatus
.Information
= sizeof(CONSOLE_SCREEN_BUFFER_INFO
);
474 Status
= STATUS_SUCCESS
;
478 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
480 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
483 if ( pcsbi
->dwCursorPosition
.X
< 0 || pcsbi
->dwCursorPosition
.X
>= DeviceExtension
->Columns
||
484 pcsbi
->dwCursorPosition
.Y
< 0 || pcsbi
->dwCursorPosition
.Y
>= DeviceExtension
->Rows
)
486 Irp
->IoStatus
.Information
= 0;
487 Status
= STATUS_INVALID_PARAMETER
;
491 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
493 Offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
494 pcsbi
->dwCursorPosition
.X
;
496 if (!InbvCheckDisplayOwnership())
499 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
500 WRITE_PORT_UCHAR(CRTC_DATA
, Offset
);
501 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
502 WRITE_PORT_UCHAR(CRTC_DATA
, Offset
>> 8);
506 Irp
->IoStatus
.Information
= 0;
507 Status
= STATUS_SUCCESS
;
511 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
513 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
515 pcci
->dwSize
= DeviceExtension
->CursorSize
;
516 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
518 Irp
->IoStatus
.Information
= sizeof(CONSOLE_CURSOR_INFO
);
519 Status
= STATUS_SUCCESS
;
523 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
525 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
529 DeviceExtension
->CursorSize
= pcci
->dwSize
;
530 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
532 if (!InbvCheckDisplayOwnership())
534 height
= DeviceExtension
->ScanLines
;
535 data
= (pcci
->bVisible
) ? 0x00 : 0x20;
537 size
= (pcci
->dwSize
* height
) / 100;
541 data
|= (UCHAR
)(height
- size
);
544 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORSTART
);
545 WRITE_PORT_UCHAR(CRTC_DATA
, data
);
546 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSOREND
);
547 value
= READ_PORT_UCHAR(CRTC_DATA
) & 0xE0;
548 WRITE_PORT_UCHAR(CRTC_DATA
, value
| (height
- 1));
552 Irp
->IoStatus
.Information
= 0;
553 Status
= STATUS_SUCCESS
;
557 case IOCTL_CONSOLE_GET_MODE
:
559 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
561 pcm
->dwMode
= DeviceExtension
->Mode
;
563 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
564 Status
= STATUS_SUCCESS
;
568 case IOCTL_CONSOLE_SET_MODE
:
570 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
572 DeviceExtension
->Mode
= pcm
->dwMode
;
574 Irp
->IoStatus
.Information
= 0;
575 Status
= STATUS_SUCCESS
;
579 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
581 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
585 ULONG nMaxLength
= Buf
->nLength
;
587 if ( Buf
->dwCoord
.X
< 0 || Buf
->dwCoord
.X
>= DeviceExtension
->Columns
||
588 Buf
->dwCoord
.Y
< 0 || Buf
->dwCoord
.Y
>= DeviceExtension
->Rows
)
590 Buf
->dwTransfered
= 0;
591 Irp
->IoStatus
.Information
= 0;
592 Status
= STATUS_SUCCESS
;
596 if (!InbvCheckDisplayOwnership())
598 vidmem
= DeviceExtension
->VideoMemory
;
599 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
600 (Buf
->dwCoord
.X
* 2) + 1;
602 nMaxLength
= min(nMaxLength
,
603 (DeviceExtension
->Rows
- Buf
->dwCoord
.Y
)
604 * DeviceExtension
->Columns
- Buf
->dwCoord
.X
);
606 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++)
608 vidmem
[offset
+ (dwCount
* 2)] = (char)Buf
->wAttribute
;
612 Buf
->dwTransfered
= nMaxLength
;
614 Irp
->IoStatus
.Information
= 0;
615 Status
= STATUS_SUCCESS
;
619 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
621 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
622 PUSHORT pAttr
= (PUSHORT
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
628 if ( Buf
->dwCoord
.X
< 0 || Buf
->dwCoord
.X
>= DeviceExtension
->Columns
||
629 Buf
->dwCoord
.Y
< 0 || Buf
->dwCoord
.Y
>= DeviceExtension
->Rows
)
631 Buf
->dwTransfered
= 0;
632 Irp
->IoStatus
.Information
= 0;
633 Status
= STATUS_SUCCESS
;
637 if (!InbvCheckDisplayOwnership())
639 vidmem
= DeviceExtension
->VideoMemory
;
640 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
641 (Buf
->dwCoord
.X
* 2) + 1;
643 nMaxLength
= min(stk
->Parameters
.DeviceIoControl
.OutputBufferLength
,
644 (DeviceExtension
->Rows
- Buf
->dwCoord
.Y
)
645 * DeviceExtension
->Columns
- Buf
->dwCoord
.X
);
647 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++, pAttr
++)
649 *((PCHAR
)pAttr
) = vidmem
[offset
+ (dwCount
* 2)];
652 Buf
->dwTransfered
= dwCount
;
656 Buf
->dwTransfered
= 0;
659 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
660 Status
= STATUS_SUCCESS
;
664 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
666 PCOORD pCoord
= (PCOORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
667 PCHAR pAttr
= (PCHAR
)(pCoord
+ 1);
673 if ( pCoord
->X
< 0 || pCoord
->X
>= DeviceExtension
->Columns
||
674 pCoord
->Y
< 0 || pCoord
->Y
>= DeviceExtension
->Rows
)
676 Irp
->IoStatus
.Information
= 0;
677 Status
= STATUS_SUCCESS
;
681 if (!InbvCheckDisplayOwnership())
683 vidmem
= DeviceExtension
->VideoMemory
;
684 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
687 nMaxLength
= min(stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(COORD
),
688 (DeviceExtension
->Rows
- pCoord
->Y
)
689 * DeviceExtension
->Columns
- pCoord
->X
);
691 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++, pAttr
++)
693 vidmem
[offset
+ (dwCount
* 2)] = *pAttr
;
697 Irp
->IoStatus
.Information
= 0;
698 Status
= STATUS_SUCCESS
;
702 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
703 DeviceExtension
->CharAttribute
= (USHORT
)*(PUSHORT
)Irp
->AssociatedIrp
.SystemBuffer
;
704 Irp
->IoStatus
.Information
= 0;
705 Status
= STATUS_SUCCESS
;
708 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
710 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
714 ULONG nMaxLength
= Buf
->nLength
;
716 if ( Buf
->dwCoord
.X
< 0 || Buf
->dwCoord
.X
>= DeviceExtension
->Columns
||
717 Buf
->dwCoord
.Y
< 0 || Buf
->dwCoord
.Y
>= DeviceExtension
->Rows
)
719 Buf
->dwTransfered
= 0;
720 Irp
->IoStatus
.Information
= 0;
721 Status
= STATUS_SUCCESS
;
725 if (!InbvCheckDisplayOwnership())
727 vidmem
= DeviceExtension
->VideoMemory
;
728 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
729 (Buf
->dwCoord
.X
* 2);
731 nMaxLength
= min(nMaxLength
,
732 (DeviceExtension
->Rows
- Buf
->dwCoord
.Y
)
733 * DeviceExtension
->Columns
- Buf
->dwCoord
.X
);
735 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++)
737 vidmem
[offset
+ (dwCount
* 2)] = (char)Buf
->cCharacter
;
741 Buf
->dwTransfered
= nMaxLength
;
743 Irp
->IoStatus
.Information
= 0;
744 Status
= STATUS_SUCCESS
;
748 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
750 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
751 PCHAR pChar
= (PCHAR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
757 if ( Buf
->dwCoord
.X
< 0 || Buf
->dwCoord
.X
>= DeviceExtension
->Columns
||
758 Buf
->dwCoord
.Y
< 0 || Buf
->dwCoord
.Y
>= DeviceExtension
->Rows
)
760 Buf
->dwTransfered
= 0;
761 Irp
->IoStatus
.Information
= 0;
762 Status
= STATUS_SUCCESS
;
766 if (!InbvCheckDisplayOwnership())
768 vidmem
= DeviceExtension
->VideoMemory
;
769 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
770 (Buf
->dwCoord
.X
* 2);
772 nMaxLength
= min(stk
->Parameters
.DeviceIoControl
.OutputBufferLength
,
773 (DeviceExtension
->Rows
- Buf
->dwCoord
.Y
)
774 * DeviceExtension
->Columns
- Buf
->dwCoord
.X
);
776 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++, pChar
++)
778 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
781 Buf
->dwTransfered
= dwCount
;
785 Buf
->dwTransfered
= 0;
788 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
789 Status
= STATUS_SUCCESS
;
793 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
795 PCOORD pCoord
= (PCOORD
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
796 PCHAR pChar
= (PCHAR
)(pCoord
+ 1);
802 if ( pCoord
->X
< 0 || pCoord
->X
>= DeviceExtension
->Columns
||
803 pCoord
->Y
< 0 || pCoord
->Y
>= DeviceExtension
->Rows
)
805 Irp
->IoStatus
.Information
= 0;
806 Status
= STATUS_SUCCESS
;
810 if (!InbvCheckDisplayOwnership())
812 vidmem
= DeviceExtension
->VideoMemory
;
813 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
816 nMaxLength
= min(stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof(COORD
),
817 (DeviceExtension
->Rows
- pCoord
->Y
)
818 * DeviceExtension
->Columns
- pCoord
->X
);
820 for (dwCount
= 0; dwCount
< nMaxLength
; dwCount
++, pChar
++)
822 vidmem
[offset
+ (dwCount
* 2)] = *pChar
;
826 Irp
->IoStatus
.Information
= 0;
827 Status
= STATUS_SUCCESS
;
831 case IOCTL_CONSOLE_DRAW
:
833 PCONSOLE_DRAW ConsoleDraw
;
835 UINT32 SrcDelta
, DestDelta
, i
, Offset
;
837 if (!InbvCheckDisplayOwnership())
839 ConsoleDraw
= (PCONSOLE_DRAW
) MmGetSystemAddressForMdl(Irp
->MdlAddress
);
840 Src
= (PUCHAR
) (ConsoleDraw
+ 1);
841 SrcDelta
= ConsoleDraw
->SizeX
* 2;
842 Dest
= DeviceExtension
->VideoMemory
+
843 (ConsoleDraw
->Y
* DeviceExtension
->Columns
+ ConsoleDraw
->X
) * 2;
844 DestDelta
= DeviceExtension
->Columns
* 2;
846 for (i
= 0; i
< ConsoleDraw
->SizeY
; i
++)
848 RtlCopyMemory(Dest
, Src
, SrcDelta
);
853 Offset
= (ConsoleDraw
->CursorY
* DeviceExtension
->Columns
) +
854 ConsoleDraw
->CursorX
;
857 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSLO
);
858 WRITE_PORT_UCHAR(CRTC_DATA
, Offset
);
859 WRITE_PORT_UCHAR(CRTC_COMMAND
, CRTC_CURSORPOSHI
);
860 WRITE_PORT_UCHAR(CRTC_DATA
, Offset
>> 8);
864 Irp
->IoStatus
.Information
= 0;
865 Status
= STATUS_SUCCESS
;
869 case IOCTL_CONSOLE_LOADFONT
:
871 ULONG CodePage
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
873 if (!InbvCheckDisplayOwnership())
875 /* Upload a font for the codepage if needed */
876 ScrLoadFontTable(CodePage
);
879 Irp
->IoStatus
.Information
= 0;
880 Status
= STATUS_SUCCESS
;
885 Status
= STATUS_NOT_IMPLEMENTED
;
888 Irp
->IoStatus
.Status
= Status
;
889 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
894 static DRIVER_DISPATCH ScrDispatch
;
898 _In_ PDEVICE_OBJECT DeviceObject
,
902 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
904 switch (stk
->MajorFunction
)
907 Status
= STATUS_SUCCESS
;
911 Status
= STATUS_NOT_IMPLEMENTED
;
915 Irp
->IoStatus
.Status
= Status
;
916 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
926 _In_ PDRIVER_OBJECT DriverObject
,
927 _In_ PUNICODE_STRING RegistryPath
)
930 PDEVICE_OBJECT DeviceObject
;
931 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\BlueScreen");
932 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\??\\BlueScreen");
934 DPRINT("Screen Driver 0.0.6\n");
936 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
937 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
938 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
939 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
940 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
942 Status
= IoCreateDevice(DriverObject
,
943 sizeof(DEVICE_EXTENSION
),
946 FILE_DEVICE_SECURE_OPEN
,
949 if (!NT_SUCCESS(Status
))
954 Status
= IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
955 if (NT_SUCCESS(Status
))
956 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
958 IoDeleteDevice(DeviceObject
);