:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / dd / blue / blue.c
1 /* $Id$
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     WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
179     offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
180     WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
181     offset += READ_PORT_UCHAR (CRTC_DATA);
182
183     cursory = offset / columns;
184     cursorx = offset % columns;
185     if( processed == 0 )
186        {
187           /* raw output mode */
188           memcpy( &vidmem[(cursorx * 2) + (cursory * columns * 2)], pch, stk->Parameters.Write.Length );
189           offset += (stk->Parameters.Write.Length / 2);
190        }
191     else {
192        for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
193           {
194              switch (*pch)
195                 {
196                 case '\b':
197                    if (cursorx > 0)
198                       {
199                          cursorx--;
200                       }
201                    else if (cursory > 0)
202                       {
203                          cursorx = columns - 1;
204                          cursory--;
205                       }
206                    vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
207                    vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
208                    break;
209                    
210                 case '\n':
211                    cursory++;
212                    cursorx = 0;
213                    break;
214                    
215                 case '\r':
216                    cursorx = 0;
217                    break;
218                    
219                 case '\t':
220                    offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
221                    for (j = 0; j < offset; j++)
222                       {
223                          vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
224                          cursorx++;
225                          
226                          if (cursorx >= columns)
227                             {
228                                cursory++;
229                                cursorx = 0;
230                             }
231                       }
232                    break;
233                    
234                 default:
235                    vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
236                    vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
237                    cursorx++;
238                    if (cursorx >= columns)
239                       {
240                          cursory++;
241                          cursorx = 0;
242                       }
243                    break;
244                 }
245              if (cursory >= rows)
246                 {
247                    unsigned short *LinePtr;
248
249                    memcpy (vidmem,
250                            &vidmem[columns * 2],
251                            columns * (rows - 1) * 2);
252
253                    LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
254
255                    for (j = 0; j < columns; j++)
256                       {
257                          LinePtr[j] = DeviceExtension->CharAttribute << 8;
258                       }
259                    cursory = rows - 1;
260                    for (j = 0; j < columns; j++)
261                       {
262                          vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
263                          vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
264                       }
265                 }
266           }
267        
268        /* Set the cursor position */
269        offset = (cursory * columns) + cursorx;
270     }
271     WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
272     WRITE_PORT_UCHAR (CRTC_DATA, offset);
273     WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
274     offset >>= 8;
275     WRITE_PORT_UCHAR (CRTC_DATA, offset);
276
277     Status = STATUS_SUCCESS;
278
279     Irp->IoStatus.Status = Status;
280     IoCompleteRequest (Irp, IO_NO_INCREMENT);
281
282     return (Status);
283 }
284
285
286 NTSTATUS STDCALL
287 ScrIoControl(PDEVICE_OBJECT DeviceObject,
288              PIRP Irp)
289 {
290     PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
291     PDEVICE_EXTENSION DeviceExtension;
292     NTSTATUS Status;
293     DeviceExtension = DeviceObject->DeviceExtension;
294     switch (stk->Parameters.DeviceIoControl.IoControlCode)
295     {
296         case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
297             {
298                 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
299                 int rows = DeviceExtension->Rows;
300                 int columns = DeviceExtension->Columns;
301                 unsigned int offset;
302
303                 /* read cursor position from crtc */
304                 __asm__("cli\n\t");
305                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
306                 offset = READ_PORT_UCHAR (CRTC_DATA);
307                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
308                 offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
309                 __asm__("sti\n\t");
310
311                 pcsbi->dwSize.X = columns;
312                 pcsbi->dwSize.Y = rows;
313
314                 pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
315                 pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
316
317                 pcsbi->wAttributes = DeviceExtension->CharAttribute;
318
319                 pcsbi->srWindow.Left   = 0;
320                 pcsbi->srWindow.Right  = columns - 1;
321                 pcsbi->srWindow.Top    = 0;
322                 pcsbi->srWindow.Bottom = rows - 1;
323
324                 pcsbi->dwMaximumWindowSize.X = columns;
325                 pcsbi->dwMaximumWindowSize.Y = rows;
326
327                 Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
328                 Status = STATUS_SUCCESS;
329             }
330             break;
331
332         case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
333             {
334                 PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
335                 unsigned int offset;
336
337                 DeviceExtension->CharAttribute = pcsbi->wAttributes;
338                 offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
339                           pcsbi->dwCursorPosition.X;
340
341                 __asm__("cli\n\t");
342                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
343                 WRITE_PORT_UCHAR (CRTC_DATA, offset);
344                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
345                 WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
346                 __asm__("sti\n\t");
347
348                 Irp->IoStatus.Information = 0;
349                 Status = STATUS_SUCCESS;
350             }
351             break;
352
353         case IOCTL_CONSOLE_GET_CURSOR_INFO:
354             {
355                 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
356
357                 pcci->dwSize = DeviceExtension->CursorSize;
358                 pcci->bVisible = DeviceExtension->CursorVisible;
359
360                 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
361                 Status = STATUS_SUCCESS;
362             }
363             break;
364
365         case IOCTL_CONSOLE_SET_CURSOR_INFO:
366             {
367                 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
368                 BYTE data, value;
369                 DWORD size, height;
370
371                 DeviceExtension->CursorSize = pcci->dwSize;
372                 DeviceExtension->CursorVisible = pcci->bVisible;
373                 height = DeviceExtension->ScanLines;
374                 data = (pcci->bVisible) ? 0x40 : 0x20;
375
376                 size = (pcci->dwSize * height) / 100;
377                 if (size < 1)
378                     size = 1;
379
380                 data |= (BYTE)(height - size);
381
382                 __asm__("cli\n\t");
383                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
384                 WRITE_PORT_UCHAR (CRTC_DATA, data);
385                 WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
386                 value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
387                 WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
388
389                 __asm__("sti\n\t");
390
391                 Irp->IoStatus.Information = 0;
392                 Status = STATUS_SUCCESS;
393             }
394             break;
395
396         case IOCTL_CONSOLE_GET_MODE:
397             {
398                 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
399
400                 pcm->dwMode = DeviceExtension->Mode;
401
402                 Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
403                 Status = STATUS_SUCCESS;
404             }
405             break;
406
407         case IOCTL_CONSOLE_SET_MODE:
408             {
409                 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
410
411                 DeviceExtension->Mode = pcm->dwMode;
412
413                 Irp->IoStatus.Information = 0;
414                 Status = STATUS_SUCCESS;
415             }
416             break;
417
418         case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
419             {
420                 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
421                 char *vidmem;
422                 int offset;
423                 DWORD dwCount;
424
425                 vidmem = DeviceExtension->VideoMemory;
426                 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
427                          (Buf->dwCoord.X * 2) + 1;
428
429                 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
430                 {
431                     vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
432                 }
433
434                 Buf->dwTransfered = Buf->nLength;
435                 
436                 Irp->IoStatus.Information = 0;
437                 Status = STATUS_SUCCESS;
438             }
439             break;
440
441         case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
442             {
443                 POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
444                 PWORD pAttr = (PWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
445                 char *vidmem;
446                 int offset;
447                 DWORD dwCount;
448
449                 vidmem = DeviceExtension->VideoMemory;
450                 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
451                          (Buf->dwCoord.X * 2) + 1;
452
453                 for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++)
454                 {
455                     (char) *pAttr = vidmem[offset + (dwCount * 2)];
456                 }
457
458                 Buf->dwTransfered = dwCount;
459
460                 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
461                 Status = STATUS_SUCCESS;
462             }
463             break;
464
465         case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
466             {
467                 COORD *pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
468                 CHAR *pAttr = (CHAR *)(pCoord + 1);
469                 char *vidmem;
470                 int offset;
471                 DWORD dwCount;
472
473                 vidmem = DeviceExtension->VideoMemory;
474                 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
475                          (pCoord->X * 2) + 1;
476
477                 for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pAttr++)
478                 {
479                     vidmem[offset + (dwCount * 2)] = *pAttr;
480                 }
481                 Irp->IoStatus.Information = 0;
482                 Status = STATUS_SUCCESS;
483             }
484             break;
485
486         case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
487             DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer;
488             Irp->IoStatus.Information = 0;
489             Status = STATUS_SUCCESS;
490             break;
491
492
493         case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
494             {
495                 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
496                 char *vidmem;
497                 int offset;
498                 DWORD dwCount;
499
500                 vidmem = DeviceExtension->VideoMemory;
501                 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
502                          (Buf->dwCoord.X * 2);
503
504                 CHECKPOINT
505
506                 for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
507                 {
508                     vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
509                 }
510
511                 Buf->dwTransfered = Buf->nLength;
512
513                 Irp->IoStatus.Information = 0;
514                 Status = STATUS_SUCCESS;
515             }
516             break;
517
518         case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
519             {
520                 POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
521                 LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
522                 char *vidmem;
523                 int offset;
524                 DWORD dwCount;
525
526                 vidmem = DeviceExtension->VideoMemory;
527                 offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
528                          (Buf->dwCoord.X * 2);
529
530                 for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++)
531                 {
532                     *pChar = vidmem[offset + (dwCount * 2)];
533                 }
534
535                 Buf->dwTransfered = dwCount;
536
537                 Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
538                 Status = STATUS_SUCCESS;
539             }
540             break;
541
542         case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
543             {
544                 COORD *pCoord;
545                 LPSTR pChar;
546                 char *vidmem;
547                 int offset;
548                 DWORD dwCount;
549                 pCoord = (COORD *)MmGetSystemAddressForMdl(Irp->MdlAddress);
550                 pChar = (CHAR *)(pCoord + 1);
551                 vidmem = DeviceExtension->VideoMemory;
552                 offset = (pCoord->Y * DeviceExtension->Columns * 2) +
553                          (pCoord->X * 2);
554
555                 for (dwCount = 0; dwCount < (stk->Parameters.Write.Length - sizeof( COORD )); dwCount++, pChar++)
556                 {
557                     vidmem[offset + (dwCount * 2)] = *pChar;
558                 }
559
560                 Irp->IoStatus.Information = 0;
561                 Status = STATUS_SUCCESS;
562             }
563             break;
564
565
566         default:
567             Status = STATUS_NOT_IMPLEMENTED;
568     }
569
570     Irp->IoStatus.Status = Status;
571     IoCompleteRequest (Irp, IO_NO_INCREMENT);
572
573     return (Status);
574 }
575
576
577 NTSTATUS STDCALL
578 ScrDispatch(PDEVICE_OBJECT DeviceObject,
579             PIRP Irp)
580 {
581     PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
582     NTSTATUS Status;
583
584     switch (stk->MajorFunction)
585     {
586         case IRP_MJ_CLOSE:
587             Status = STATUS_SUCCESS;
588             break;
589
590         default:
591             Status = STATUS_NOT_IMPLEMENTED;
592             break;
593     }
594
595
596     Irp->IoStatus.Status = Status;
597     IoCompleteRequest (Irp, IO_NO_INCREMENT);
598
599     return (Status);
600 }
601
602
603 /*
604  * Module entry point
605  */
606 NTSTATUS STDCALL
607 DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
608 {
609     PDEVICE_OBJECT DeviceObject;
610     UNICODE_STRING DeviceName = UNICODE_STRING_INITIALIZER(L"\\Device\\BlueScreen");
611     UNICODE_STRING SymlinkName = UNICODE_STRING_INITIALIZER(L"\\??\\BlueScreen");
612
613     DPRINT ("Screen Driver 0.0.6\n");
614
615     DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
616     DriverObject->MajorFunction[IRP_MJ_CLOSE]  = ScrDispatch;
617     DriverObject->MajorFunction[IRP_MJ_READ]   = ScrDispatch;
618     DriverObject->MajorFunction[IRP_MJ_WRITE]  = ScrWrite;
619     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
620
621     IoCreateDevice (DriverObject,
622                     sizeof(DEVICE_EXTENSION),
623                     &DeviceName,
624                     FILE_DEVICE_SCREEN,
625                     0,
626                     TRUE,
627                     &DeviceObject);
628
629     IoCreateSymbolicLink (&SymlinkName, &DeviceName);
630
631     return (STATUS_SUCCESS);
632 }
633
634 /* EOF */