- Fixed the buffer handling for ioctl requests and direct access
[reactos.git] / reactos / drivers / dd / blue / blue.c
1 /* $Id: blue.c,v 1.37 2003/03/21 21:09:40 hbirr Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/dd/blue/blue.c
6 * PURPOSE: Console (blue screen) device driver
7 * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
8 * UPDATE HISTORY:
9 * ??? Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ddk/ntddblue.h>
16 #include <string.h>
17 #include <defines.h>
18
19 #define NDEBUG
20 #include <debug.h>
21
22
23 /* DEFINITIONS ***************************************************************/
24
25 #define VIDMEM_BASE 0xb8000
26 #define VIDMEM_SIZE 0x2000
27
28 #define CRTC_COMMAND ((PUCHAR)0x3d4)
29 #define CRTC_DATA ((PUCHAR)0x3d5)
30
31 #define CRTC_COLUMNS 0x01
32 #define CRTC_OVERFLOW 0x07
33 #define CRTC_ROWS 0x12
34 #define CRTC_SCANLINES 0x09
35 #define CRTC_CURSORSTART 0x0a
36 #define CRTC_CURSOREND 0x0b
37 #define CRTC_CURSORPOSHI 0x0e
38 #define CRTC_CURSORPOSLO 0x0f
39
40 #define ATTRC_WRITEREG ((PUCHAR)0x3c0)
41 #define ATTRC_READREG ((PUCHAR)0x3c1)
42 #define ATTRC_INPST1 ((PUCHAR)0x3da)
43
44 #define TAB_WIDTH 8
45
46
47 /* NOTES ******************************************************************/
48 /*
49 * [[character][attribute]][[character][attribute]]....
50 */
51
52
53 /* TYPEDEFS ***************************************************************/
54
55 typedef struct _DEVICE_EXTENSION
56 {
57 PBYTE VideoMemory; /* Pointer to video memory */
58 DWORD CursorSize;
59 BOOL CursorVisible;
60 WORD CharAttribute;
61 DWORD Mode;
62 BYTE ScanLines; /* Height of a text line */
63 WORD Rows; /* Number of rows */
64 WORD Columns; /* Number of columns */
65 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
66
67
68 /* FUNCTIONS **************************************************************/
69
70 NTSTATUS STDCALL
71 ScrCreate(PDEVICE_OBJECT DeviceObject,
72 PIRP Irp)
73 {
74 PDEVICE_EXTENSION DeviceExtension;
75 PHYSICAL_ADDRESS BaseAddress;
76 NTSTATUS Status;
77 unsigned int offset;
78 BYTE data, value;
79
80 DeviceExtension = DeviceObject->DeviceExtension;
81
82 /* get pointer to video memory */
83 BaseAddress.QuadPart = VIDMEM_BASE;
84 DeviceExtension->VideoMemory =
85 (PBYTE)MmMapIoSpace (BaseAddress, VIDMEM_SIZE, FALSE);
86
87 /* disable interrupts */
88 __asm__("cli\n\t");
89
90 /* get current output position */
91 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
92 offset = READ_PORT_UCHAR (CRTC_DATA);
93 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
94 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
95
96 /* switch blinking characters off */
97 READ_PORT_UCHAR (ATTRC_INPST1);
98 value = READ_PORT_UCHAR (ATTRC_WRITEREG);
99 WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10);
100 data = READ_PORT_UCHAR (ATTRC_READREG);
101 data = data & ~0x08;
102 WRITE_PORT_UCHAR (ATTRC_WRITEREG, data);
103 WRITE_PORT_UCHAR (ATTRC_WRITEREG, value);
104 READ_PORT_UCHAR (ATTRC_INPST1);
105
106 /* read screen information from crt controller */
107 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS);
108 DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1;
109 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS);
110 DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA);
111 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW);
112 data = READ_PORT_UCHAR (CRTC_DATA);
113 DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3));
114 DeviceExtension->Rows++;
115 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES);
116 DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1;
117
118 /* enable interrupts */
119 __asm__("sti\n\t");
120
121 /* calculate number of text rows */
122 DeviceExtension->Rows =
123 DeviceExtension->Rows / DeviceExtension->ScanLines;
124 #ifdef BOCHS_30ROWS
125 DeviceExtension->Rows = 30;
126 #endif
127
128 DPRINT ("%d Columns %d Rows %d Scanlines\n",
129 DeviceExtension->Columns,
130 DeviceExtension->Rows,
131 DeviceExtension->ScanLines);
132
133 DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
134 DeviceExtension->CursorVisible = TRUE;
135
136 /* more initialization */
137 DeviceExtension->CharAttribute = 0x17; /* light grey on blue */
138 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
139 ENABLE_WRAP_AT_EOL_OUTPUT;
140
141 /* show blinking cursor */
142 __asm__("cli\n\t");
143 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
144 WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F);
145 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
146 data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
147 WRITE_PORT_UCHAR (CRTC_DATA,
148 data | ((DeviceExtension->ScanLines - 1) & 0x1F));
149 __asm__("sti\n\t");
150
151 Status = STATUS_SUCCESS;
152
153 Irp->IoStatus.Status = Status;
154 IoCompleteRequest (Irp, IO_NO_INCREMENT);
155
156 return (Status);
157 }
158
159
160 NTSTATUS STDCALL
161 ScrWrite(PDEVICE_OBJECT DeviceObject,
162 PIRP Irp)
163 {
164 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
165 PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
166 NTSTATUS Status;
167 char *pch = Irp->UserBuffer;
168 char *vidmem;
169 int i, j, offset;
170 int cursorx, cursory;
171 int rows, columns;
172 int processed = DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT;
173
174 vidmem = DeviceExtension->VideoMemory;
175 rows = DeviceExtension->Rows;
176 columns = DeviceExtension->Columns;
177
178 __asm__ ("cli\n\t");
179 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
180 offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
181 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
182 offset += READ_PORT_UCHAR (CRTC_DATA);
183 __asm__ ("sti\n\t");
184
185 cursory = offset / columns;
186 cursorx = offset % columns;
187 if( processed == 0 )
188 {
189 /* raw output mode */
190 memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
191 offset += (stk->Parameters.Write.Length / 2);
192 }
193 else {
194 for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
195 {
196 switch (*pch)
197 {
198 case '\b':
199 if (cursorx > 0)
200 {
201 cursorx--;
202 }
203 else if (cursory > 0)
204 {
205 cursorx = columns - 1;
206 cursory--;
207 }
208 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
209 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
210 break;
211
212 case '\n':
213 cursory++;
214 cursorx = 0;
215 break;
216
217 case '\r':
218 cursorx = 0;
219 break;
220
221 case '\t':
222 offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
223 for (j = 0; j < offset; j++)
224 {
225 vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
226 cursorx++;
227
228 if (cursorx >= columns)
229 {
230 cursory++;
231 cursorx = 0;
232 }
233 }
234 break;
235
236 default:
237 vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
238 vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
239 cursorx++;
240 if (cursorx >= columns)
241 {
242 cursory++;
243 cursorx = 0;
244 }
245 break;
246 }
247 if (cursory >= rows)
248 {
249 unsigned short *LinePtr;
250
251 memcpy (vidmem,
252 &vidmem[columns * 2],
253 columns * (rows - 1) * 2);
254
255 LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
256
257 for (j = 0; j < columns; j++)
258 {
259 LinePtr[j] = DeviceExtension->CharAttribute << 8;
260 }
261 cursory = rows - 1;
262 for (j = 0; j < columns; j++)
263 {
264 vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
265 vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
266 }
267 }
268 }
269
270 /* Set the cursor position */
271 offset = (cursory * columns) + cursorx;
272 }
273 __asm__ ("cli\n\t");
274 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
275 WRITE_PORT_UCHAR (CRTC_DATA, offset);
276 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
277 offset >>= 8;
278 WRITE_PORT_UCHAR (CRTC_DATA, offset);
279 __asm__ ("sti\n\t");
280
281 Status = STATUS_SUCCESS;
282
283 Irp->IoStatus.Status = Status;
284 IoCompleteRequest (Irp, IO_NO_INCREMENT);
285
286 return (Status);
287 }
288
289
290 NTSTATUS STDCALL
291 ScrIoControl(PDEVICE_OBJECT DeviceObject,
292 PIRP Irp)
293 {
294 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
295 PDEVICE_EXTENSION DeviceExtension;
296 NTSTATUS Status;
297 DeviceExtension = DeviceObject->DeviceExtension;
298 switch (stk->Parameters.DeviceIoControl.IoControlCode)
299 {
300 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
301 {
302 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
303 int rows = DeviceExtension->Rows;
304 int columns = DeviceExtension->Columns;
305 unsigned int offset;
306
307 /* read cursor position from crtc */
308 __asm__("cli\n\t");
309 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
310 offset = READ_PORT_UCHAR (CRTC_DATA);
311 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
312 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
313 __asm__("sti\n\t");
314
315 pcsbi->dwSize.X = columns;
316 pcsbi->dwSize.Y = rows;
317
318 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
319 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
320
321 pcsbi->wAttributes = DeviceExtension->CharAttribute;
322
323 pcsbi->srWindow.Left = 0;
324 pcsbi->srWindow.Right = columns - 1;
325 pcsbi->srWindow.Top = 0;
326 pcsbi->srWindow.Bottom = rows - 1;
327
328 pcsbi->dwMaximumWindowSize.X = columns;
329 pcsbi->dwMaximumWindowSize.Y = rows;
330
331 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
332 Status = STATUS_SUCCESS;
333 }
334 break;
335
336 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
337 {
338 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
339 unsigned int offset;
340
341 DeviceExtension->CharAttribute = pcsbi->wAttributes;
342 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
343 pcsbi->dwCursorPosition.X;
344
345 __asm__("cli\n\t");
346 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
347 WRITE_PORT_UCHAR (CRTC_DATA, offset);
348 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
349 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
350 __asm__("sti\n\t");
351
352 Irp->IoStatus.Information = 0;
353 Status = STATUS_SUCCESS;
354 }
355 break;
356
357 case IOCTL_CONSOLE_GET_CURSOR_INFO:
358 {
359 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
360
361 pcci->dwSize = DeviceExtension->CursorSize;
362 pcci->bVisible = DeviceExtension->CursorVisible;
363
364 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
365 Status = STATUS_SUCCESS;
366 }
367 break;
368
369 case IOCTL_CONSOLE_SET_CURSOR_INFO:
370 {
371 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
372 BYTE data, value;
373 DWORD size, height;
374
375 DeviceExtension->CursorSize = pcci->dwSize;
376 DeviceExtension->CursorVisible = pcci->bVisible;
377 height = DeviceExtension->ScanLines;
378 data = (pcci->bVisible) ? 0x40 : 0x20;
379
380 size = (pcci->dwSize * height) / 100;
381 if (size < 1)
382 size = 1;
383
384 data |= (BYTE)(height - size);
385
386 __asm__("cli\n\t");
387 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
388 WRITE_PORT_UCHAR (CRTC_DATA, data);
389 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
390 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
391 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
392
393 __asm__("sti\n\t");
394
395 Irp->IoStatus.Information = 0;
396 Status = STATUS_SUCCESS;
397 }
398 break;
399
400 case IOCTL_CONSOLE_GET_MODE:
401 {
402 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
403
404 pcm->dwMode = DeviceExtension->Mode;
405
406 Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
407 Status = STATUS_SUCCESS;
408 }
409 break;
410
411 case IOCTL_CONSOLE_SET_MODE:
412 {
413 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
414
415 DeviceExtension->Mode = pcm->dwMode;
416
417 Irp->IoStatus.Information = 0;
418 Status = STATUS_SUCCESS;
419 }
420 break;
421
422 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
423 {
424 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
425 char *vidmem;
426 int offset;
427 DWORD dwCount;
428
429 vidmem = DeviceExtension->VideoMemory;
430 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
431 (Buf->dwCoord.X * 2) + 1;
432
433 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
434 {
435 vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
436 }
437
438 Buf->dwTransfered = Buf->nLength;
439
440 Irp->IoStatus.Information = 0;
441 Status = STATUS_SUCCESS;
442 }
443 break;
444
445 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
446 {
447 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
448 PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
449 char *vidmem;
450 int offset;
451 DWORD dwCount;
452
453 vidmem = DeviceExtension->VideoMemory;
454 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
455 (Buf->dwCoord.X * 2) + 1;
456
457 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pAttr++)
458 {
459 (char) *pAttr = vidmem[offset + (dwCount * 2)];
460 }
461
462 Buf->dwTransfered = dwCount;
463
464 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
465 Status = STATUS_SUCCESS;
466 }
467 break;
468
469 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
470 {
471 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
472 CHAR *pAttr = (CHAR *)(pCoord + 1);
473 char *vidmem;
474 int offset;
475 DWORD dwCount;
476
477 vidmem = DeviceExtension->VideoMemory;
478 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
479 (pCoord->X * 2) + 1;
480
481 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pAttr++)
482 {
483 vidmem[offset + (dwCount * 2)] = *pAttr;
484 }
485 Irp->IoStatus.Information = 0;
486 Status = STATUS_SUCCESS;
487 }
488 break;
489
490 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
491 DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer;
492 Irp->IoStatus.Information = 0;
493 Status = STATUS_SUCCESS;
494 break;
495
496
497 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
498 {
499 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
500 char *vidmem;
501 int offset;
502 DWORD dwCount;
503
504 vidmem = DeviceExtension->VideoMemory;
505 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
506 (Buf->dwCoord.X * 2);
507
508 CHECKPOINT
509
510 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
511 {
512 vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
513 }
514
515 Buf->dwTransfered = Buf->nLength;
516
517 Irp->IoStatus.Information = 0;
518 Status = STATUS_SUCCESS;
519 }
520 break;
521
522 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
523 {
524 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
525 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
526 char *vidmem;
527 int offset;
528 DWORD dwCount;
529
530 vidmem = DeviceExtension->VideoMemory;
531 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
532 (Buf->dwCoord.X * 2);
533
534 for (dwCount = 0; dwCount < stk->Parameters.DeviceIoControl.OutputBufferLength; dwCount++, pChar++)
535 {
536 *pChar = vidmem[offset + (dwCount * 2)];
537 }
538
539 Buf->dwTransfered = dwCount;
540
541 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
542 Status = STATUS_SUCCESS;
543 }
544 break;
545
546 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
547 {
548 COORD *pCoord;
549 LPSTR pChar;
550 char *vidmem;
551 int offset;
552 DWORD dwCount;
553 pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
554 pChar = (CHAR *)(pCoord + 1);
555 vidmem = DeviceExtension->VideoMemory;
556 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
557 (pCoord->X * 2);
558
559 for (dwCount = 0; dwCount < (stk->Parameters.DeviceIoControl.InputBufferLength - sizeof( COORD )); dwCount++, pChar++)
560 {
561 vidmem[offset + (dwCount * 2)] = *pChar;
562 }
563
564 Irp->IoStatus.Information = 0;
565 Status = STATUS_SUCCESS;
566 }
567 break;
568
569
570 default:
571 Status = STATUS_NOT_IMPLEMENTED;
572 }
573
574 Irp->IoStatus.Status = Status;
575 IoCompleteRequest (Irp, IO_NO_INCREMENT);
576
577 return (Status);
578 }
579
580
581 NTSTATUS STDCALL
582 ScrDispatch(PDEVICE_OBJECT DeviceObject,
583 PIRP Irp)
584 {
585 PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
586 NTSTATUS Status;
587
588 switch (stk->MajorFunction)
589 {
590 case IRP_MJ_CLOSE:
591 Status = STATUS_SUCCESS;
592 break;
593
594 default:
595 Status = STATUS_NOT_IMPLEMENTED;
596 break;
597 }
598
599
600 Irp->IoStatus.Status = Status;
601 IoCompleteRequest (Irp, IO_NO_INCREMENT);
602
603 return (Status);
604 }
605
606
607 /*
608 * Module entry point
609 */
610 NTSTATUS STDCALL
611 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
612 {
613 PDEVICE_OBJECT DeviceObject;
614 UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\BlueScreen");
615 UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\BlueScreen");
616
617 DPRINT ("Screen Driver 0.0.6\n");
618
619 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
620 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
621 DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
622 DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
623 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
624
625 IoCreateDevice (DriverObject,
626 sizeof(DEVICE_EXTENSION),
627 &DeviceName,
628 FILE_DEVICE_SCREEN,
629 0,
630 TRUE,
631 &DeviceObject);
632
633 IoCreateSymbolicLink (&SymlinkName, &DeviceName);
634
635 return (STATUS_SUCCESS);
636 }
637
638 /* EOF */