[BLUE] Improve includes.
[reactos.git] / drivers / setup / blue / blue.c
1 /*
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
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include "blue.h"
13 #include <ndk/inbvfuncs.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 /* NOTES ******************************************************************/
19 /*
20 * [[character][attribute]][[character][attribute]]....
21 */
22
23 /* TYPEDEFS ***************************************************************/
24
25 typedef struct _DEVICE_EXTENSION
26 {
27 PUCHAR VideoMemory; /* Pointer to video memory */
28 ULONG CursorSize;
29 INT CursorVisible;
30 USHORT CharAttribute;
31 ULONG Mode;
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;
36
37 typedef struct _VGA_REGISTERS
38 {
39 UCHAR CRT[24];
40 UCHAR Attribute[21];
41 UCHAR Graphics[9];
42 UCHAR Sequencer[5];
43 UCHAR Misc;
44 } VGA_REGISTERS, *PVGA_REGISTERS;
45
46 static const VGA_REGISTERS VidpMode3Regs =
47 {
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 */
59 0x67
60 };
61
62 static const UCHAR DefaultPalette[] =
63 {
64 0, 0, 0,
65 0, 0, 0xC0,
66 0, 0xC0, 0,
67 0, 0xC0, 0xC0,
68 0xC0, 0, 0,
69 0xC0, 0, 0xC0,
70 0xC0, 0xC0, 0,
71 0xC0, 0xC0, 0xC0,
72 0x80, 0x80, 0x80,
73 0, 0, 0xFF,
74 0, 0xFF, 0,
75 0, 0xFF, 0xFF,
76 0xFF, 0, 0,
77 0xFF, 0, 0xFF,
78 0xFF, 0xFF, 0,
79 0xFF, 0xFF, 0xFF
80 };
81
82 /* FUNCTIONS **************************************************************/
83
84 static VOID
85 FASTCALL
86 ScrSetRegisters(const VGA_REGISTERS *Registers)
87 {
88 UINT32 i;
89
90 /* Update misc output register */
91 WRITE_PORT_UCHAR(MISC, Registers->Misc);
92
93 /* Synchronous reset on */
94 WRITE_PORT_UCHAR(SEQ, 0x00);
95 WRITE_PORT_UCHAR(SEQDATA, 0x01);
96
97 /* Write sequencer registers */
98 for (i = 1; i < sizeof(Registers->Sequencer); i++)
99 {
100 WRITE_PORT_UCHAR(SEQ, i);
101 WRITE_PORT_UCHAR(SEQDATA, Registers->Sequencer[i]);
102 }
103
104 /* Synchronous reset off */
105 WRITE_PORT_UCHAR(SEQ, 0x00);
106 WRITE_PORT_UCHAR(SEQDATA, 0x03);
107
108 /* Deprotect CRT registers 0-7 */
109 WRITE_PORT_UCHAR(CRTC, 0x11);
110 WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[0x11] & 0x7f);
111
112 /* Write CRT registers */
113 for (i = 0; i < sizeof(Registers->CRT); i++)
114 {
115 WRITE_PORT_UCHAR(CRTC, i);
116 WRITE_PORT_UCHAR(CRTCDATA, Registers->CRT[i]);
117 }
118
119 /* Write graphics controller registers */
120 for (i = 0; i < sizeof(Registers->Graphics); i++)
121 {
122 WRITE_PORT_UCHAR(GRAPHICS, i);
123 WRITE_PORT_UCHAR(GRAPHICSDATA, Registers->Graphics[i]);
124 }
125
126 /* Write attribute controller registers */
127 for (i = 0; i < sizeof(Registers->Attribute); i++)
128 {
129 READ_PORT_UCHAR(STATUS);
130 WRITE_PORT_UCHAR(ATTRIB, i);
131 WRITE_PORT_UCHAR(ATTRIB, Registers->Attribute[i]);
132 }
133
134 /* Set the PEL mask */
135 WRITE_PORT_UCHAR(PELMASK, 0xff);
136 }
137
138 static VOID
139 FASTCALL
140 ScrAcquireOwnership(
141 _In_ PDEVICE_EXTENSION DeviceExtension)
142 {
143 ULONG offset;
144 UCHAR data, value;
145 ULONG Index;
146
147 ScrSetRegisters(&VidpMode3Regs);
148
149 /* Disable screen and enable palette access */
150 READ_PORT_UCHAR(STATUS);
151 WRITE_PORT_UCHAR(ATTRIB, 0x00);
152
153 for (Index = 0; Index < sizeof(DefaultPalette) / 3; Index++)
154 {
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);
159 }
160
161 /* Enable screen and disable palette access */
162 READ_PORT_UCHAR(STATUS);
163 WRITE_PORT_UCHAR(ATTRIB, 0x20);
164
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);
170
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);
176 data = data & ~0x08;
177 WRITE_PORT_UCHAR(ATTRC_WRITEREG, data);
178 WRITE_PORT_UCHAR(ATTRC_WRITEREG, value);
179 READ_PORT_UCHAR(ATTRC_INPST1);
180
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;
192
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));
200
201 /* Calculate number of text rows */
202 DeviceExtension->Rows =
203 DeviceExtension->Rows / DeviceExtension->ScanLines;
204 #ifdef BOCHS_30ROWS
205 DeviceExtension->Rows = 30;
206 #endif
207
208 /* Upload a default font for the default codepage 437 */
209 ScrLoadFontTable(437);
210
211 DPRINT("%d Columns %d Rows %d Scanlines\n",
212 DeviceExtension->Columns,
213 DeviceExtension->Rows,
214 DeviceExtension->ScanLines);
215 }
216
217 static DRIVER_DISPATCH ScrCreate;
218 static NTSTATUS
219 NTAPI
220 ScrCreate(
221 _In_ PDEVICE_OBJECT DeviceObject,
222 _In_ PIRP Irp)
223 {
224 #define FOREGROUND_LIGHTGRAY (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
225
226 PDEVICE_EXTENSION DeviceExtension;
227 PHYSICAL_ADDRESS BaseAddress;
228 NTSTATUS Status;
229
230 DeviceExtension = DeviceObject->DeviceExtension;
231
232 if (!InbvCheckDisplayOwnership())
233 {
234 ScrAcquireOwnership(DeviceExtension);
235
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);
240 }
241 else
242 {
243 /* Store dummy values */
244 DeviceExtension->Columns = 1;
245 DeviceExtension->Rows = 1;
246 DeviceExtension->ScanLines = 1;
247 }
248
249 DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
250 DeviceExtension->CursorVisible = TRUE;
251
252 /* More initialization */
253 DeviceExtension->CharAttribute = BACKGROUND_BLUE | FOREGROUND_LIGHTGRAY;
254 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
255 ENABLE_WRAP_AT_EOL_OUTPUT;
256
257 Status = STATUS_SUCCESS;
258
259 Irp->IoStatus.Status = Status;
260 IoCompleteRequest(Irp, IO_NO_INCREMENT);
261 return Status;
262 }
263
264 static DRIVER_DISPATCH ScrWrite;
265 static NTSTATUS
266 NTAPI
267 ScrWrite(
268 _In_ PDEVICE_OBJECT DeviceObject,
269 _In_ PIRP Irp)
270 {
271 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
272 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
273 NTSTATUS Status;
274 PCHAR pch = Irp->UserBuffer;
275 PUCHAR vidmem;
276 ULONG i;
277 ULONG j, offset;
278 USHORT cursorx, cursory;
279 USHORT rows, columns;
280 BOOLEAN processed = !!(DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT);
281
282 if (InbvCheckDisplayOwnership())
283 {
284 /* Display is in graphics mode, we're not allowed to touch it */
285 Status = STATUS_SUCCESS;
286
287 Irp->IoStatus.Status = Status;
288 IoCompleteRequest(Irp, IO_NO_INCREMENT);
289
290 return Status;
291 }
292
293 vidmem = DeviceExtension->VideoMemory;
294 rows = DeviceExtension->Rows;
295 columns = DeviceExtension->Columns;
296
297 _disable();
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);
302 _enable();
303
304 cursory = (USHORT)(offset / columns);
305 cursorx = (USHORT)(offset % columns);
306 if (!processed)
307 {
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);
314 }
315 else
316 {
317 /* Cooked output mode */
318 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
319 {
320 switch (*pch)
321 {
322 case '\b':
323 {
324 if (cursorx > 0)
325 {
326 cursorx--;
327 }
328 else if (cursory > 0)
329 {
330 cursorx = columns - 1;
331 cursory--;
332 }
333 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
334 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
335 break;
336 }
337
338 case '\n':
339 cursory++;
340 cursorx = 0;
341 break;
342
343 case '\r':
344 cursorx = 0;
345 break;
346
347 case '\t':
348 {
349 offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
350 for (j = 0; j < offset; j++)
351 {
352 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
353 cursorx++;
354
355 if (cursorx >= columns)
356 {
357 cursory++;
358 cursorx = 0;
359 }
360 }
361 break;
362 }
363
364 default:
365 {
366 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
367 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
368 cursorx++;
369 if (cursorx >= columns)
370 {
371 cursory++;
372 cursorx = 0;
373 }
374 break;
375 }
376 }
377
378 /* Scroll up the contents of the screen if we are at the end */
379 if (cursory >= rows)
380 {
381 PUSHORT LinePtr;
382
383 RtlCopyMemory(vidmem,
384 &vidmem[columns * 2],
385 columns * (rows - 1) * 2);
386
387 LinePtr = (PUSHORT)&vidmem[columns * (rows - 1) * 2];
388
389 for (j = 0; j < columns; j++)
390 {
391 LinePtr[j] = DeviceExtension->CharAttribute << 8;
392 }
393 cursory = rows - 1;
394 for (j = 0; j < columns; j++)
395 {
396 vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
397 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
398 }
399 }
400 }
401
402 /* Set the cursor position */
403 offset = (cursory * columns) + cursorx;
404 }
405 _disable();
406 WRITE_PORT_UCHAR(CRTC_COMMAND, CRTC_CURSORPOSLO);
407 WRITE_PORT_UCHAR(CRTC_DATA, offset);
408 WRITE_PORT_UCHAR(CRTC_COMMAND, CRTC_CURSORPOSHI);
409 offset >>= 8;
410 WRITE_PORT_UCHAR(CRTC_DATA, offset);
411 _enable();
412
413 Status = STATUS_SUCCESS;
414
415 Irp->IoStatus.Status = Status;
416 IoCompleteRequest(Irp, IO_NO_INCREMENT);
417
418 return Status;
419 }
420
421 static DRIVER_DISPATCH ScrIoControl;
422 static NTSTATUS
423 NTAPI
424 ScrIoControl(
425 _In_ PDEVICE_OBJECT DeviceObject,
426 _In_ PIRP Irp)
427 {
428 NTSTATUS Status;
429 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
430 PDEVICE_EXTENSION DeviceExtension;
431
432 DeviceExtension = DeviceObject->DeviceExtension;
433 switch (stk->Parameters.DeviceIoControl.IoControlCode)
434 {
435 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
436 {
437 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
438 USHORT rows = DeviceExtension->Rows;
439 USHORT columns = DeviceExtension->Columns;
440 ULONG offset;
441
442 if (!InbvCheckDisplayOwnership())
443 {
444 /* read cursor position from crtc */
445 _disable();
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);
450 _enable();
451 }
452 else
453 {
454 offset = 0;
455 }
456
457 pcsbi->dwSize.X = columns;
458 pcsbi->dwSize.Y = rows;
459
460 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
461 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
462
463 pcsbi->wAttributes = DeviceExtension->CharAttribute;
464
465 pcsbi->srWindow.Left = 0;
466 pcsbi->srWindow.Right = columns - 1;
467 pcsbi->srWindow.Top = 0;
468 pcsbi->srWindow.Bottom = rows - 1;
469
470 pcsbi->dwMaximumWindowSize.X = columns;
471 pcsbi->dwMaximumWindowSize.Y = rows;
472
473 Irp->IoStatus.Information = sizeof(CONSOLE_SCREEN_BUFFER_INFO);
474 Status = STATUS_SUCCESS;
475 break;
476 }
477
478 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
479 {
480 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
481 ULONG Offset;
482
483 if ( pcsbi->dwCursorPosition.X < 0 || pcsbi->dwCursorPosition.X >= DeviceExtension->Columns ||
484 pcsbi->dwCursorPosition.Y < 0 || pcsbi->dwCursorPosition.Y >= DeviceExtension->Rows )
485 {
486 Irp->IoStatus.Information = 0;
487 Status = STATUS_INVALID_PARAMETER;
488 break;
489 }
490
491 DeviceExtension->CharAttribute = pcsbi->wAttributes;
492
493 Offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
494 pcsbi->dwCursorPosition.X;
495
496 if (!InbvCheckDisplayOwnership())
497 {
498 _disable();
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);
503 _enable();
504 }
505
506 Irp->IoStatus.Information = 0;
507 Status = STATUS_SUCCESS;
508 break;
509 }
510
511 case IOCTL_CONSOLE_GET_CURSOR_INFO:
512 {
513 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
514
515 pcci->dwSize = DeviceExtension->CursorSize;
516 pcci->bVisible = DeviceExtension->CursorVisible;
517
518 Irp->IoStatus.Information = sizeof(CONSOLE_CURSOR_INFO);
519 Status = STATUS_SUCCESS;
520 break;
521 }
522
523 case IOCTL_CONSOLE_SET_CURSOR_INFO:
524 {
525 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
526 UCHAR data, value;
527 ULONG size, height;
528
529 DeviceExtension->CursorSize = pcci->dwSize;
530 DeviceExtension->CursorVisible = pcci->bVisible;
531
532 if (!InbvCheckDisplayOwnership())
533 {
534 height = DeviceExtension->ScanLines;
535 data = (pcci->bVisible) ? 0x00 : 0x20;
536
537 size = (pcci->dwSize * height) / 100;
538 if (size < 1)
539 size = 1;
540
541 data |= (UCHAR)(height - size);
542
543 _disable();
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));
549 _enable();
550 }
551
552 Irp->IoStatus.Information = 0;
553 Status = STATUS_SUCCESS;
554 break;
555 }
556
557 case IOCTL_CONSOLE_GET_MODE:
558 {
559 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
560
561 pcm->dwMode = DeviceExtension->Mode;
562
563 Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
564 Status = STATUS_SUCCESS;
565 break;
566 }
567
568 case IOCTL_CONSOLE_SET_MODE:
569 {
570 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
571
572 DeviceExtension->Mode = pcm->dwMode;
573
574 Irp->IoStatus.Information = 0;
575 Status = STATUS_SUCCESS;
576 break;
577 }
578
579 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
580 {
581 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
582 PUCHAR vidmem;
583 int offset;
584 ULONG dwCount;
585 ULONG nMaxLength = Buf->nLength;
586
587 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns ||
588 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows )
589 {
590 Buf->dwTransfered = 0;
591 Irp->IoStatus.Information = 0;
592 Status = STATUS_SUCCESS;
593 break;
594 }
595
596 if (!InbvCheckDisplayOwnership())
597 {
598 vidmem = DeviceExtension->VideoMemory;
599 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
600 (Buf->dwCoord.X * 2) + 1;
601
602 nMaxLength = min(nMaxLength,
603 (DeviceExtension->Rows - Buf->dwCoord.Y)
604 * DeviceExtension->Columns - Buf->dwCoord.X);
605
606 for (dwCount = 0; dwCount < nMaxLength; dwCount++)
607 {
608 vidmem[offset + (dwCount * 2)] = (char)Buf->wAttribute;
609 }
610 }
611
612 Buf->dwTransfered = nMaxLength;
613
614 Irp->IoStatus.Information = 0;
615 Status = STATUS_SUCCESS;
616 break;
617 }
618
619 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
620 {
621 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
622 PUSHORT pAttr = (PUSHORT)MmGetSystemAddressForMdl(Irp->MdlAddress);
623 PUCHAR vidmem;
624 int offset;
625 ULONG dwCount;
626 ULONG nMaxLength;
627
628 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns ||
629 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows )
630 {
631 Buf->dwTransfered = 0;
632 Irp->IoStatus.Information = 0;
633 Status = STATUS_SUCCESS;
634 break;
635 }
636
637 if (!InbvCheckDisplayOwnership())
638 {
639 vidmem = DeviceExtension->VideoMemory;
640 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
641 (Buf->dwCoord.X * 2) + 1;
642
643 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength,
644 (DeviceExtension->Rows - Buf->dwCoord.Y)
645 * DeviceExtension->Columns - Buf->dwCoord.X);
646
647 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pAttr++)
648 {
649 *((PCHAR)pAttr) = vidmem[offset + (dwCount * 2)];
650 }
651
652 Buf->dwTransfered = dwCount;
653 }
654 else
655 {
656 Buf->dwTransfered = 0;
657 }
658
659 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
660 Status = STATUS_SUCCESS;
661 break;
662 }
663
664 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
665 {
666 PCOORD pCoord = (PCOORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
667 PCHAR pAttr = (PCHAR)(pCoord + 1);
668 PUCHAR vidmem;
669 int offset;
670 ULONG dwCount;
671 ULONG nMaxLength;
672
673 if ( pCoord->X < 0 || pCoord->X >= DeviceExtension->Columns ||
674 pCoord->Y < 0 || pCoord->Y >= DeviceExtension->Rows )
675 {
676 Irp->IoStatus.Information = 0;
677 Status = STATUS_SUCCESS;
678 break;
679 }
680
681 if (!InbvCheckDisplayOwnership())
682 {
683 vidmem = DeviceExtension->VideoMemory;
684 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
685 (pCoord->X * 2) + 1;
686
687 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof(COORD),
688 (DeviceExtension->Rows - pCoord->Y)
689 * DeviceExtension->Columns - pCoord->X);
690
691 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pAttr++)
692 {
693 vidmem[offset + (dwCount * 2)] = *pAttr;
694 }
695 }
696
697 Irp->IoStatus.Information = 0;
698 Status = STATUS_SUCCESS;
699 break;
700 }
701
702 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
703 DeviceExtension->CharAttribute = (USHORT)*(PUSHORT)Irp->AssociatedIrp.SystemBuffer;
704 Irp->IoStatus.Information = 0;
705 Status = STATUS_SUCCESS;
706 break;
707
708 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
709 {
710 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
711 PUCHAR vidmem;
712 int offset;
713 ULONG dwCount;
714 ULONG nMaxLength = Buf->nLength;
715
716 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns ||
717 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows )
718 {
719 Buf->dwTransfered = 0;
720 Irp->IoStatus.Information = 0;
721 Status = STATUS_SUCCESS;
722 break;
723 }
724
725 if (!InbvCheckDisplayOwnership())
726 {
727 vidmem = DeviceExtension->VideoMemory;
728 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
729 (Buf->dwCoord.X * 2);
730
731 nMaxLength = min(nMaxLength,
732 (DeviceExtension->Rows - Buf->dwCoord.Y)
733 * DeviceExtension->Columns - Buf->dwCoord.X);
734
735 for (dwCount = 0; dwCount < nMaxLength; dwCount++)
736 {
737 vidmem[offset + (dwCount * 2)] = (char)Buf->cCharacter;
738 }
739 }
740
741 Buf->dwTransfered = nMaxLength;
742
743 Irp->IoStatus.Information = 0;
744 Status = STATUS_SUCCESS;
745 break;
746 }
747
748 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
749 {
750 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
751 PCHAR pChar = (PCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
752 PUCHAR vidmem;
753 int offset;
754 ULONG dwCount;
755 ULONG nMaxLength;
756
757 if ( Buf->dwCoord.X < 0 || Buf->dwCoord.X >= DeviceExtension->Columns ||
758 Buf->dwCoord.Y < 0 || Buf->dwCoord.Y >= DeviceExtension->Rows )
759 {
760 Buf->dwTransfered = 0;
761 Irp->IoStatus.Information = 0;
762 Status = STATUS_SUCCESS;
763 break;
764 }
765
766 if (!InbvCheckDisplayOwnership())
767 {
768 vidmem = DeviceExtension->VideoMemory;
769 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
770 (Buf->dwCoord.X * 2);
771
772 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength,
773 (DeviceExtension->Rows - Buf->dwCoord.Y)
774 * DeviceExtension->Columns - Buf->dwCoord.X);
775
776 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pChar++)
777 {
778 *pChar = vidmem[offset + (dwCount * 2)];
779 }
780
781 Buf->dwTransfered = dwCount;
782 }
783 else
784 {
785 Buf->dwTransfered = 0;
786 }
787
788 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
789 Status = STATUS_SUCCESS;
790 break;
791 }
792
793 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
794 {
795 PCOORD pCoord = (PCOORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
796 PCHAR pChar = (PCHAR)(pCoord + 1);
797 PUCHAR vidmem;
798 int offset;
799 ULONG dwCount;
800 ULONG nMaxLength;
801
802 if ( pCoord->X < 0 || pCoord->X >= DeviceExtension->Columns ||
803 pCoord->Y < 0 || pCoord->Y >= DeviceExtension->Rows )
804 {
805 Irp->IoStatus.Information = 0;
806 Status = STATUS_SUCCESS;
807 break;
808 }
809
810 if (!InbvCheckDisplayOwnership())
811 {
812 vidmem = DeviceExtension->VideoMemory;
813 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
814 (pCoord->X * 2);
815
816 nMaxLength = min(stk->Parameters.DeviceIoControl.OutputBufferLength - sizeof(COORD),
817 (DeviceExtension->Rows - pCoord->Y)
818 * DeviceExtension->Columns - pCoord->X);
819
820 for (dwCount = 0; dwCount < nMaxLength; dwCount++, pChar++)
821 {
822 vidmem[offset + (dwCount * 2)] = *pChar;
823 }
824 }
825
826 Irp->IoStatus.Information = 0;
827 Status = STATUS_SUCCESS;
828 break;
829 }
830
831 case IOCTL_CONSOLE_DRAW:
832 {
833 PCONSOLE_DRAW ConsoleDraw;
834 PUCHAR Src, Dest;
835 UINT32 SrcDelta, DestDelta, i, Offset;
836
837 if (!InbvCheckDisplayOwnership())
838 {
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;
845
846 for (i = 0; i < ConsoleDraw->SizeY; i++)
847 {
848 RtlCopyMemory(Dest, Src, SrcDelta);
849 Src += SrcDelta;
850 Dest += DestDelta;
851 }
852
853 Offset = (ConsoleDraw->CursorY * DeviceExtension->Columns) +
854 ConsoleDraw->CursorX;
855
856 _disable();
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);
861 _enable();
862 }
863
864 Irp->IoStatus.Information = 0;
865 Status = STATUS_SUCCESS;
866 break;
867 }
868
869 case IOCTL_CONSOLE_LOADFONT:
870 {
871 ULONG CodePage = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
872
873 if (!InbvCheckDisplayOwnership())
874 {
875 /* Upload a font for the codepage if needed */
876 ScrLoadFontTable(CodePage);
877 }
878
879 Irp->IoStatus.Information = 0;
880 Status = STATUS_SUCCESS;
881 break;
882 }
883
884 default:
885 Status = STATUS_NOT_IMPLEMENTED;
886 }
887
888 Irp->IoStatus.Status = Status;
889 IoCompleteRequest(Irp, IO_NO_INCREMENT);
890
891 return Status;
892 }
893
894 static DRIVER_DISPATCH ScrDispatch;
895 static NTSTATUS
896 NTAPI
897 ScrDispatch(
898 _In_ PDEVICE_OBJECT DeviceObject,
899 _In_ PIRP Irp)
900 {
901 NTSTATUS Status;
902 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
903
904 switch (stk->MajorFunction)
905 {
906 case IRP_MJ_CLOSE:
907 Status = STATUS_SUCCESS;
908 break;
909
910 default:
911 Status = STATUS_NOT_IMPLEMENTED;
912 break;
913 }
914
915 Irp->IoStatus.Status = Status;
916 IoCompleteRequest(Irp, IO_NO_INCREMENT);
917 return Status;
918 }
919
920 /*
921 * Module entry point
922 */
923 NTSTATUS
924 NTAPI
925 DriverEntry(
926 _In_ PDRIVER_OBJECT DriverObject,
927 _In_ PUNICODE_STRING RegistryPath)
928 {
929 NTSTATUS Status;
930 PDEVICE_OBJECT DeviceObject;
931 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen");
932 UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\??\\BlueScreen");
933
934 DPRINT("Screen Driver 0.0.6\n");
935
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;
941
942 Status = IoCreateDevice(DriverObject,
943 sizeof(DEVICE_EXTENSION),
944 &DeviceName,
945 FILE_DEVICE_SCREEN,
946 FILE_DEVICE_SECURE_OPEN,
947 TRUE,
948 &DeviceObject);
949 if (!NT_SUCCESS(Status))
950 {
951 return Status;
952 }
953
954 Status = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
955 if (NT_SUCCESS(Status))
956 DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
957 else
958 IoDeleteDevice(DeviceObject);
959 return Status;
960 }
961
962 /* EOF */