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)
12 /* INCLUDES ******************************************************************/
16 /* FIXME: W32API NEEDS TO BE FIXED */
19 * Wincon.h can't be included due to missing user-mode types,
20 * so we'll define them here
22 typedef ULONG DWORD
, *LPDWORD
;
23 typedef USHORT UINT
, *LPWORD
;
30 #define APIENTRY WINAPI
32 typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES
, *PSECURITY_ATTRIBUTES
;
36 #include <blue/ntddblue.h>
37 #include <ndk/halfuncs.h>
42 /* DEFINITIONS ***************************************************************/
44 #define VIDMEM_BASE 0xb8000
46 #define CRTC_COMMAND ((PUCHAR)0x3d4)
47 #define CRTC_DATA ((PUCHAR)0x3d5)
49 #define CRTC_COLUMNS 0x01
50 #define CRTC_OVERFLOW 0x07
51 #define CRTC_ROWS 0x12
52 #define CRTC_SCANLINES 0x09
53 #define CRTC_CURSORSTART 0x0a
54 #define CRTC_CURSOREND 0x0b
55 #define CRTC_CURSORPOSHI 0x0e
56 #define CRTC_CURSORPOSLO 0x0f
58 #define ATTRC_WRITEREG ((PUCHAR)0x3c0)
59 #define ATTRC_READREG ((PUCHAR)0x3c1)
60 #define ATTRC_INPST1 ((PUCHAR)0x3da)
65 /* NOTES ******************************************************************/
67 * [[character][attribute]][[character][attribute]]....
71 /* TYPEDEFS ***************************************************************/
73 typedef struct _DEVICE_EXTENSION
75 PUCHAR VideoMemory
; /* Pointer to video memory */
80 UCHAR ScanLines
; /* Height of a text line */
81 USHORT Rows
; /* Number of rows */
82 USHORT Columns
; /* Number of columns */
83 } DEVICE_EXTENSION
, *PDEVICE_EXTENSION
;
86 /* FUNCTIONS **************************************************************/
89 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
);
91 static NTSTATUS STDCALL
92 ScrCreate(PDEVICE_OBJECT DeviceObject
,
95 PDEVICE_EXTENSION DeviceExtension
;
96 PHYSICAL_ADDRESS BaseAddress
;
101 DeviceExtension
= DeviceObject
->DeviceExtension
;
103 /* disable interrupts */
106 /* get current output position */
107 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
108 offset
= READ_PORT_UCHAR (CRTC_DATA
);
109 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
110 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
112 /* switch blinking characters off */
113 READ_PORT_UCHAR (ATTRC_INPST1
);
114 value
= READ_PORT_UCHAR (ATTRC_WRITEREG
);
115 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, 0x10);
116 data
= READ_PORT_UCHAR (ATTRC_READREG
);
118 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, data
);
119 WRITE_PORT_UCHAR (ATTRC_WRITEREG
, value
);
120 READ_PORT_UCHAR (ATTRC_INPST1
);
122 /* read screen information from crt controller */
123 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_COLUMNS
);
124 DeviceExtension
->Columns
= READ_PORT_UCHAR (CRTC_DATA
) + 1;
125 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_ROWS
);
126 DeviceExtension
->Rows
= READ_PORT_UCHAR (CRTC_DATA
);
127 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_OVERFLOW
);
128 data
= READ_PORT_UCHAR (CRTC_DATA
);
129 DeviceExtension
->Rows
|= (((data
& 0x02) << 7) | ((data
& 0x40) << 3));
130 DeviceExtension
->Rows
++;
131 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_SCANLINES
);
132 DeviceExtension
->ScanLines
= (READ_PORT_UCHAR (CRTC_DATA
) & 0x1F) + 1;
134 /* enable interrupts */
137 /* calculate number of text rows */
138 DeviceExtension
->Rows
=
139 DeviceExtension
->Rows
/ DeviceExtension
->ScanLines
;
141 DeviceExtension
->Rows
= 30;
144 DPRINT ("%d Columns %d Rows %d Scanlines\n",
145 DeviceExtension
->Columns
,
146 DeviceExtension
->Rows
,
147 DeviceExtension
->ScanLines
);
149 /* get pointer to video memory */
150 BaseAddress
.QuadPart
= VIDMEM_BASE
;
151 DeviceExtension
->VideoMemory
=
152 (PUCHAR
)MmMapIoSpace (BaseAddress
, DeviceExtension
->Rows
* DeviceExtension
->Columns
* 2, MmNonCached
);
154 DeviceExtension
->CursorSize
= 5; /* FIXME: value correct?? */
155 DeviceExtension
->CursorVisible
= TRUE
;
157 /* more initialization */
158 DeviceExtension
->CharAttribute
= 0x17; /* light grey on blue */
159 DeviceExtension
->Mode
= ENABLE_PROCESSED_OUTPUT
|
160 ENABLE_WRAP_AT_EOL_OUTPUT
;
162 /* show blinking cursor */
164 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
165 WRITE_PORT_UCHAR (CRTC_DATA
, (DeviceExtension
->ScanLines
- 1) & 0x1F);
166 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
167 data
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
168 WRITE_PORT_UCHAR (CRTC_DATA
,
169 data
| ((DeviceExtension
->ScanLines
- 1) & 0x1F));
172 Status
= STATUS_SUCCESS
;
174 Irp
->IoStatus
.Status
= Status
;
175 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
181 static NTSTATUS STDCALL
182 ScrWrite(PDEVICE_OBJECT DeviceObject
,
185 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
186 PDEVICE_EXTENSION DeviceExtension
= DeviceObject
->DeviceExtension
;
188 char *pch
= Irp
->UserBuffer
;
192 int cursorx
, cursory
;
194 int processed
= DeviceExtension
->Mode
& ENABLE_PROCESSED_OUTPUT
;
196 if (HalQueryDisplayOwnership())
198 /* Display is in graphics mode, we're not allowed to touch it */
199 Status
= STATUS_SUCCESS
;
201 Irp
->IoStatus
.Status
= Status
;
202 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
207 vidmem
= DeviceExtension
->VideoMemory
;
208 rows
= DeviceExtension
->Rows
;
209 columns
= DeviceExtension
->Columns
;
212 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
213 offset
= READ_PORT_UCHAR (CRTC_DATA
)<<8;
214 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
215 offset
+= READ_PORT_UCHAR (CRTC_DATA
);
218 cursory
= offset
/ columns
;
219 cursorx
= offset
% columns
;
222 /* raw output mode */
223 memcpy( &vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)], pch
, stk
->Parameters
.Write
.Length
);
224 offset
+= (stk
->Parameters
.Write
.Length
/ 2);
227 for (i
= 0; i
< stk
->Parameters
.Write
.Length
; i
++, pch
++)
236 else if (cursory
> 0)
238 cursorx
= columns
- 1;
241 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
242 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
255 offset
= TAB_WIDTH
- (cursorx
% TAB_WIDTH
);
256 for (j
= 0; j
< offset
; j
++)
258 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = ' ';
261 if (cursorx
>= columns
)
270 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2)] = *pch
;
271 vidmem
[(cursorx
* 2) + (cursory
* columns
* 2) + 1] = (char) DeviceExtension
->CharAttribute
;
273 if (cursorx
>= columns
)
282 unsigned short *LinePtr
;
285 &vidmem
[columns
* 2],
286 columns
* (rows
- 1) * 2);
288 LinePtr
= (unsigned short *) &vidmem
[columns
* (rows
- 1) * 2];
290 for (j
= 0; j
< columns
; j
++)
292 LinePtr
[j
] = DeviceExtension
->CharAttribute
<< 8;
295 for (j
= 0; j
< columns
; j
++)
297 vidmem
[(j
* 2) + (cursory
* columns
* 2)] = ' ';
298 vidmem
[(j
* 2) + (cursory
* columns
* 2) + 1] = (char)DeviceExtension
->CharAttribute
;
303 /* Set the cursor position */
304 offset
= (cursory
* columns
) + cursorx
;
307 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
308 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
309 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
311 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
314 Status
= STATUS_SUCCESS
;
316 Irp
->IoStatus
.Status
= Status
;
317 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
323 static NTSTATUS STDCALL
324 ScrIoControl(PDEVICE_OBJECT DeviceObject
,
327 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation (Irp
);
328 PDEVICE_EXTENSION DeviceExtension
;
331 DeviceExtension
= DeviceObject
->DeviceExtension
;
332 switch (stk
->Parameters
.DeviceIoControl
.IoControlCode
)
334 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO
:
336 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
337 int rows
= DeviceExtension
->Rows
;
338 int columns
= DeviceExtension
->Columns
;
341 /* read cursor position from crtc */
343 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
344 offset
= READ_PORT_UCHAR (CRTC_DATA
);
345 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
346 offset
+= (READ_PORT_UCHAR (CRTC_DATA
) << 8);
349 pcsbi
->dwSize
.X
= columns
;
350 pcsbi
->dwSize
.Y
= rows
;
352 pcsbi
->dwCursorPosition
.X
= (SHORT
)(offset
% columns
);
353 pcsbi
->dwCursorPosition
.Y
= (SHORT
)(offset
/ columns
);
355 pcsbi
->wAttributes
= DeviceExtension
->CharAttribute
;
357 pcsbi
->srWindow
.Left
= 0;
358 pcsbi
->srWindow
.Right
= columns
- 1;
359 pcsbi
->srWindow
.Top
= 0;
360 pcsbi
->srWindow
.Bottom
= rows
- 1;
362 pcsbi
->dwMaximumWindowSize
.X
= columns
;
363 pcsbi
->dwMaximumWindowSize
.Y
= rows
;
365 Irp
->IoStatus
.Information
= sizeof (CONSOLE_SCREEN_BUFFER_INFO
);
366 Status
= STATUS_SUCCESS
;
370 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO
:
372 PCONSOLE_SCREEN_BUFFER_INFO pcsbi
= (PCONSOLE_SCREEN_BUFFER_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
375 DeviceExtension
->CharAttribute
= pcsbi
->wAttributes
;
376 offset
= (pcsbi
->dwCursorPosition
.Y
* DeviceExtension
->Columns
) +
377 pcsbi
->dwCursorPosition
.X
;
380 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
381 WRITE_PORT_UCHAR (CRTC_DATA
, offset
);
382 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
383 WRITE_PORT_UCHAR (CRTC_DATA
, offset
>>8);
386 Irp
->IoStatus
.Information
= 0;
387 Status
= STATUS_SUCCESS
;
391 case IOCTL_CONSOLE_GET_CURSOR_INFO
:
393 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
395 pcci
->dwSize
= DeviceExtension
->CursorSize
;
396 pcci
->bVisible
= DeviceExtension
->CursorVisible
;
398 Irp
->IoStatus
.Information
= sizeof (CONSOLE_CURSOR_INFO
);
399 Status
= STATUS_SUCCESS
;
403 case IOCTL_CONSOLE_SET_CURSOR_INFO
:
405 PCONSOLE_CURSOR_INFO pcci
= (PCONSOLE_CURSOR_INFO
)Irp
->AssociatedIrp
.SystemBuffer
;
409 DeviceExtension
->CursorSize
= pcci
->dwSize
;
410 DeviceExtension
->CursorVisible
= pcci
->bVisible
;
411 height
= DeviceExtension
->ScanLines
;
412 data
= (pcci
->bVisible
) ? 0x00 : 0x20;
414 size
= (pcci
->dwSize
* height
) / 100;
420 data
|= (UCHAR
)(height
- size
);
423 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORSTART
);
424 WRITE_PORT_UCHAR (CRTC_DATA
, data
);
425 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSOREND
);
426 value
= READ_PORT_UCHAR (CRTC_DATA
) & 0xE0;
427 WRITE_PORT_UCHAR (CRTC_DATA
, value
| (height
- 1));
431 Irp
->IoStatus
.Information
= 0;
432 Status
= STATUS_SUCCESS
;
436 case IOCTL_CONSOLE_GET_MODE
:
438 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
440 pcm
->dwMode
= DeviceExtension
->Mode
;
442 Irp
->IoStatus
.Information
= sizeof(CONSOLE_MODE
);
443 Status
= STATUS_SUCCESS
;
447 case IOCTL_CONSOLE_SET_MODE
:
449 PCONSOLE_MODE pcm
= (PCONSOLE_MODE
)Irp
->AssociatedIrp
.SystemBuffer
;
451 DeviceExtension
->Mode
= pcm
->dwMode
;
453 Irp
->IoStatus
.Information
= 0;
454 Status
= STATUS_SUCCESS
;
458 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE
:
460 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
465 vidmem
= DeviceExtension
->VideoMemory
;
466 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
467 (Buf
->dwCoord
.X
* 2) + 1;
469 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
471 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->wAttribute
;
474 Buf
->dwTransfered
= Buf
->nLength
;
476 Irp
->IoStatus
.Information
= 0;
477 Status
= STATUS_SUCCESS
;
481 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE
:
483 POUTPUT_ATTRIBUTE Buf
= (POUTPUT_ATTRIBUTE
)Irp
->AssociatedIrp
.SystemBuffer
;
484 PUSHORT pAttr
= (PUSHORT
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
489 vidmem
= DeviceExtension
->VideoMemory
;
490 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
491 (Buf
->dwCoord
.X
* 2) + 1;
493 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pAttr
++)
495 *((char *) pAttr
) = vidmem
[offset
+ (dwCount
* 2)];
498 Buf
->dwTransfered
= dwCount
;
500 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
501 Status
= STATUS_SUCCESS
;
505 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE
:
507 COORD
*pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
508 CHAR
*pAttr
= (CHAR
*)(pCoord
+ 1);
513 vidmem
= DeviceExtension
->VideoMemory
;
514 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
517 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof( COORD
)); dwCount
++, pAttr
++)
519 vidmem
[offset
+ (dwCount
* 2)] = *pAttr
;
521 Irp
->IoStatus
.Information
= 0;
522 Status
= STATUS_SUCCESS
;
526 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE
:
527 DeviceExtension
->CharAttribute
= (USHORT
)*(PUSHORT
)Irp
->AssociatedIrp
.SystemBuffer
;
528 Irp
->IoStatus
.Information
= 0;
529 Status
= STATUS_SUCCESS
;
532 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER
:
534 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
539 vidmem
= DeviceExtension
->VideoMemory
;
540 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
541 (Buf
->dwCoord
.X
* 2);
545 for (dwCount
= 0; dwCount
< Buf
->nLength
; dwCount
++)
547 vidmem
[offset
+ (dwCount
* 2)] = (char) Buf
->cCharacter
;
550 Buf
->dwTransfered
= Buf
->nLength
;
552 Irp
->IoStatus
.Information
= 0;
553 Status
= STATUS_SUCCESS
;
557 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER
:
559 POUTPUT_CHARACTER Buf
= (POUTPUT_CHARACTER
)Irp
->AssociatedIrp
.SystemBuffer
;
560 LPSTR pChar
= (LPSTR
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
565 vidmem
= DeviceExtension
->VideoMemory
;
566 offset
= (Buf
->dwCoord
.Y
* DeviceExtension
->Columns
* 2) +
567 (Buf
->dwCoord
.X
* 2);
569 for (dwCount
= 0; dwCount
< stk
->Parameters
.DeviceIoControl
.OutputBufferLength
; dwCount
++, pChar
++)
571 *pChar
= vidmem
[offset
+ (dwCount
* 2)];
574 Buf
->dwTransfered
= dwCount
;
576 Irp
->IoStatus
.Information
= sizeof(OUTPUT_ATTRIBUTE
);
577 Status
= STATUS_SUCCESS
;
581 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER
:
589 pCoord
= (COORD
*)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
590 pChar
= (CHAR
*)(pCoord
+ 1);
591 vidmem
= DeviceExtension
->VideoMemory
;
592 offset
= (pCoord
->Y
* DeviceExtension
->Columns
* 2) +
595 for (dwCount
= 0; dwCount
< (stk
->Parameters
.DeviceIoControl
.OutputBufferLength
- sizeof( COORD
)); dwCount
++, pChar
++)
597 vidmem
[offset
+ (dwCount
* 2)] = *pChar
;
600 Irp
->IoStatus
.Information
= 0;
601 Status
= STATUS_SUCCESS
;
605 case IOCTL_CONSOLE_DRAW
:
607 PCONSOLE_DRAW ConsoleDraw
;
609 UINT SrcDelta
, DestDelta
, i
, Offset
;
611 ConsoleDraw
= (PCONSOLE_DRAW
) MmGetSystemAddressForMdl(Irp
->MdlAddress
);
612 Src
= (PUCHAR
) (ConsoleDraw
+ 1);
613 SrcDelta
= ConsoleDraw
->SizeX
* 2;
614 Dest
= DeviceExtension
->VideoMemory
+
615 (ConsoleDraw
->Y
* DeviceExtension
->Columns
+ ConsoleDraw
->X
) * 2;
616 DestDelta
= DeviceExtension
->Columns
* 2;
618 for (i
= 0; i
< ConsoleDraw
->SizeY
; i
++)
620 RtlCopyMemory(Dest
, Src
, SrcDelta
);
625 Offset
= (ConsoleDraw
->CursorY
* DeviceExtension
->Columns
) +
626 ConsoleDraw
->CursorX
;
629 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSLO
);
630 WRITE_PORT_UCHAR (CRTC_DATA
, Offset
);
631 WRITE_PORT_UCHAR (CRTC_COMMAND
, CRTC_CURSORPOSHI
);
632 WRITE_PORT_UCHAR (CRTC_DATA
, Offset
>> 8);
635 Irp
->IoStatus
.Information
= 0;
636 Status
= STATUS_SUCCESS
;
641 Status
= STATUS_NOT_IMPLEMENTED
;
644 Irp
->IoStatus
.Status
= Status
;
645 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
651 static NTSTATUS STDCALL
652 ScrDispatch(PDEVICE_OBJECT DeviceObject
,
655 PIO_STACK_LOCATION stk
= IoGetCurrentIrpStackLocation(Irp
);
658 switch (stk
->MajorFunction
)
661 Status
= STATUS_SUCCESS
;
665 Status
= STATUS_NOT_IMPLEMENTED
;
670 Irp
->IoStatus
.Status
= Status
;
671 IoCompleteRequest (Irp
, IO_NO_INCREMENT
);
681 DriverEntry (PDRIVER_OBJECT DriverObject
, PUNICODE_STRING RegistryPath
)
683 PDEVICE_OBJECT DeviceObject
;
684 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\BlueScreen");
685 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\??\\BlueScreen");
687 DPRINT ("Screen Driver 0.0.6\n");
689 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ScrCreate
;
690 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ScrDispatch
;
691 DriverObject
->MajorFunction
[IRP_MJ_READ
] = ScrDispatch
;
692 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = ScrWrite
;
693 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ScrIoControl
;
695 IoCreateDevice (DriverObject
,
696 sizeof(DEVICE_EXTENSION
),
703 IoCreateSymbolicLink (&SymlinkName
, &DeviceName
);
705 return (STATUS_SUCCESS
);