e8a9012097c4c33e880ceb329e012491987e4155
[reactos.git] / reactos / drivers / dd / null / null.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: services/null/null.c
6 * PURPOSE: NULL device driver
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * 13/08/1998: Created
10 * 29/04/2002: Fixed bugs, added zero-stream device
11 * 28/06/2004: Compile against the DDK, use PSEH where necessary
12 */
13
14 /* INCLUDES */
15 #include <ntddk.h>
16
17 #include <rosrtl/string.h>
18 #include <pseh.h>
19
20 #include "null.h"
21
22 /* OBJECTS */
23 static const NULL_EXTENSION nxNull = NullBitBucket;
24 static const NULL_EXTENSION nxZero = NullZeroStream;
25
26 /* FUNCTIONS */
27 NTSTATUS STDCALL
28 NullDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
29 {
30 PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
31 NTSTATUS nErrCode;
32
33 nErrCode = STATUS_SUCCESS;
34 Irp->IoStatus.Information = 0;
35
36 switch(piosStack->MajorFunction)
37 {
38 /* opening and closing handles to the device */
39 case IRP_MJ_CREATE:
40 case IRP_MJ_CLOSE:
41 switch(NULL_DEVICE_TYPE(DeviceObject))
42 {
43 case NullBitBucket:
44 case NullZeroStream:
45 break;
46
47 default:
48 ASSERT(FALSE);
49 }
50
51 break;
52
53 /* write data */
54 case IRP_MJ_WRITE:
55 {
56 switch(NULL_DEVICE_TYPE(DeviceObject))
57 {
58 case NullBitBucket:
59 Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
60 break;
61
62 case NullZeroStream:
63 nErrCode = STATUS_INVALID_DEVICE_REQUEST;
64 break;
65
66 default:
67 ASSERT(FALSE);
68 }
69
70 break;
71 }
72
73 /* read data */
74 case IRP_MJ_READ:
75 {
76 switch(NULL_DEVICE_TYPE(DeviceObject))
77 {
78 case NullBitBucket:
79 nErrCode = STATUS_END_OF_FILE;
80 break;
81
82 case NullZeroStream:
83 _SEH_TRY
84 {
85 RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, piosStack->Parameters.Read.Length);
86 Irp->IoStatus.Information = piosStack->Parameters.Read.Length;
87 }
88 _SEH_HANDLE
89 {
90 nErrCode = _SEH_GetExceptionCode();
91 }
92 _SEH_END;
93
94 break;
95
96 default:
97 Irp->IoStatus.Information = 0;
98 nErrCode = STATUS_NOT_IMPLEMENTED;
99 }
100
101 break;
102 }
103
104 default:
105 ASSERT(FALSE);
106 }
107
108 Irp->IoStatus.Status = nErrCode;
109 IoCompleteRequest(Irp, IO_NO_INCREMENT);
110
111 return (nErrCode);
112 }
113
114 VOID STDCALL
115 NullUnload(PDRIVER_OBJECT DriverObject)
116 {
117 }
118
119 /* TODO: \Device\Zero should be memory-mappable */
120 NTSTATUS STDCALL
121 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
122 {
123 PDEVICE_OBJECT pdoNullDevice;
124 PDEVICE_OBJECT pdoZeroDevice;
125 UNICODE_STRING wstrDeviceName;
126 NTSTATUS nErrCode;
127
128 /* register driver routines */
129 DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch;
130 DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch;
131 DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch;
132 DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch;
133 DriverObject->DriverUnload = NullUnload;
134
135 /* create null device */
136 RtlRosInitUnicodeStringFromLiteral(&wstrDeviceName, L"\\Device\\Null");
137
138 nErrCode = IoCreateDevice
139 (
140 DriverObject,
141 sizeof(NULL_EXTENSION),
142 &wstrDeviceName,
143 FILE_DEVICE_NULL,
144 0,
145 FALSE,
146 &pdoNullDevice
147 );
148
149 /* failure */
150 if(!NT_SUCCESS(nErrCode))
151 {
152 return (nErrCode);
153 }
154
155 pdoNullDevice->DeviceExtension = (PVOID)&nxNull;
156
157 /* create zero device */
158 RtlRosInitUnicodeStringFromLiteral(&wstrDeviceName, L"\\Device\\Zero");
159
160 nErrCode = IoCreateDevice
161 (
162 DriverObject,
163 sizeof(NULL_EXTENSION),
164 &wstrDeviceName,
165 FILE_DEVICE_NULL,
166 FILE_READ_ONLY_DEVICE, /* zero device is read-only */
167 FALSE,
168 &pdoZeroDevice
169 );
170
171 /* failure */
172 if(!NT_SUCCESS(nErrCode))
173 {
174 IoDeleteDevice(pdoNullDevice);
175 return (nErrCode);
176 }
177
178 pdoZeroDevice->DeviceExtension = (PVOID)&nxZero;
179 pdoZeroDevice->Flags |= DO_BUFFERED_IO;
180
181 return (nErrCode);
182 }
183
184 /* EOF */