xref: /reactos/drivers/base/null/null.c (revision cc439606)
1 /*
2  * PROJECT:     ReactOS Kernel
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Null Device Driver
5  * COPYRIGHT:   Copyright 1998-2018 David Welch (welch@mcmail.com)
6  *              Copyright 2007-2018 Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <wdm.h>
12 
13 /* GLOBALS *******************************************************************/
14 
15 FAST_IO_DISPATCH FastIoDispatch;
16 
17 /* FUNCTIONS *****************************************************************/
18 
19 NTSTATUS
20 NTAPI
21 NullQueryFileInformation(OUT PVOID Buffer,
22                          IN PULONG Length,
23                          IN FILE_INFORMATION_CLASS InformationClass)
24 {
25     PFILE_STANDARD_INFORMATION StandardInfo = Buffer;
26 
27     PAGED_CODE();
28 
29     /* We only support one class */
30     if (InformationClass != FileStandardInformation)
31     {
32         /* Fail */
33         return STATUS_INVALID_INFO_CLASS;
34     }
35 
36     /* Fill out the information */
37     RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
38     StandardInfo->NumberOfLinks = 1;
39 
40     /* Return the length and success */
41     *Length = sizeof(FILE_STANDARD_INFORMATION);
42     return STATUS_SUCCESS;
43 }
44 
45 BOOLEAN
46 NTAPI
47 NullRead(IN PFILE_OBJECT FileObject,
48          IN PLARGE_INTEGER FileOffset,
49          IN ULONG Length,
50          IN BOOLEAN Wait,
51          IN ULONG LockKey,
52          OUT PVOID Buffer,
53          OUT PIO_STATUS_BLOCK IoStatus,
54          IN PDEVICE_OBJECT DeviceObject)
55 {
56     PAGED_CODE();
57 
58     /* Complete successfully */
59     IoStatus->Status = STATUS_END_OF_FILE;
60     IoStatus->Information = 0;
61     return TRUE;
62 }
63 
64 BOOLEAN
65 NTAPI
66 NullWrite(IN PFILE_OBJECT FileObject,
67           IN PLARGE_INTEGER FileOffset,
68           IN ULONG Length,
69           IN BOOLEAN Wait,
70           IN ULONG LockKey,
71           IN PVOID Buffer,
72           OUT PIO_STATUS_BLOCK IoStatus,
73           IN PDEVICE_OBJECT DeviceObject)
74 {
75     PAGED_CODE();
76 
77     /* Complete successfully */
78     IoStatus->Status = STATUS_SUCCESS;
79     IoStatus->Information = Length;
80     return TRUE;
81 }
82 
83 NTSTATUS
84 NTAPI
85 NullDispatch(IN PDEVICE_OBJECT DeviceObject,
86              IN PIRP Irp)
87 {
88     NTSTATUS Status;
89     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
90     PFILE_OBJECT FileObject;
91     ULONG Length;
92 
93     PAGED_CODE();
94 
95     /* Get the file object and check what kind of request this is */
96     FileObject = IoStack->FileObject;
97     switch (IoStack->MajorFunction)
98     {
99         case IRP_MJ_CREATE:
100         case IRP_MJ_CLOSE:
101 
102             /* Check if this is synch I/O */
103             if (FileObject->Flags & FO_SYNCHRONOUS_IO)
104             {
105                 /* Set distinguished value for Cc */
106                 FileObject->PrivateCacheMap = (PVOID)1;
107             }
108 
109             /* Complete successfully */
110             Irp->IoStatus.Status = STATUS_SUCCESS;
111             Irp->IoStatus.Information = 0;
112             break;
113 
114          case IRP_MJ_READ:
115 
116             /* Return as if we read the entire file */
117             Irp->IoStatus.Status = STATUS_END_OF_FILE;
118             Irp->IoStatus.Information = 0;
119             break;
120 
121         case IRP_MJ_WRITE:
122 
123             /* Return as if we wrote the entire request */
124             Irp->IoStatus.Status = STATUS_SUCCESS;
125             Irp->IoStatus.Information = IoStack->Parameters.Write.Length;
126             break;
127 
128         case IRP_MJ_LOCK_CONTROL:
129 
130             /* Dummy */
131             Irp->IoStatus.Status = STATUS_SUCCESS;
132             Irp->IoStatus.Information = 0;
133             break;
134 
135         case IRP_MJ_QUERY_INFORMATION:
136 
137             /* Get the length inputted and do the request */
138             Length = IoStack->Parameters.QueryFile.Length;
139             Irp->IoStatus.Status = NullQueryFileInformation(Irp->AssociatedIrp.
140                                                             SystemBuffer,
141                                                             &Length,
142                                                             IoStack->
143                                                             Parameters.
144                                                             QueryFile.
145                                                             FileInformationClass);
146 
147             /* Return the actual length */
148             Irp->IoStatus.Information = Length;
149             break;
150     }
151 
152     /* Complete the request */
153     Status = Irp->IoStatus.Status;
154     IoCompleteRequest(Irp, IO_NO_INCREMENT);
155     return Status;
156 }
157 
158 VOID
159 NTAPI
160 NullUnload(IN PDRIVER_OBJECT DriverObject)
161 {
162     PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
163 
164     /* Delete the Null device */
165     IoDeleteDevice(DeviceObject);
166 }
167 
168 NTSTATUS
169 NTAPI
170 DriverEntry(IN PDRIVER_OBJECT DriverObject,
171             IN PUNICODE_STRING RegistryPath)
172 {
173     NTSTATUS Status;
174     PDEVICE_OBJECT DeviceObject;
175     UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Null");
176 
177     PAGED_CODE();
178 
179     UNREFERENCED_PARAMETER(RegistryPath);
180 
181     /* Page the driver */
182     MmPageEntireDriver(DriverEntry);
183 
184     /* Create the Null device */
185     Status = IoCreateDevice(DriverObject,
186                             0,
187                             &DeviceName,
188                             FILE_DEVICE_NULL,
189                             0,
190                             FALSE,
191                             &DeviceObject);
192     if (!NT_SUCCESS(Status))
193         return Status;
194 
195     /* Register driver routines */
196     DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch;
197     DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch;
198     DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch;
199     DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch;
200     DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = NullDispatch;
201     DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = NullDispatch;
202     DriverObject->DriverUnload = NullUnload;
203 
204     /* Initialize the fast I/O dispatch table */
205     RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch));
206     FastIoDispatch.SizeOfFastIoDispatch = sizeof(FastIoDispatch);
207 
208     /* Setup our pointers */
209     FastIoDispatch.FastIoRead = NullRead;
210     FastIoDispatch.FastIoWrite = NullWrite;
211     DriverObject->FastIoDispatch = &FastIoDispatch;
212 
213     /* Return success */
214     return STATUS_SUCCESS;
215 }
216 
217 /* EOF */
218