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