[KMTESTS]
[reactos.git] / kmtests / ntos_io / IoDriverObject_drv.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Driver Object Test Driver
5 * PROGRAMMER: Michael Martin <martinmnet@hotmail.com>
6 * Thomas Faber <thfabba@gmx.de>
7 */
8
9 #include <kmt_test.h>
10
11 //#define NDEBUG
12 #include <debug.h>
13
14 typedef enum
15 {
16 DriverEntry,
17 DriverIrp,
18 DriverUnload
19 } DRIVER_STATUS;
20
21 static KMT_IRP_HANDLER TestIrpHandler;
22 static VOID TestDriverObject(IN PDRIVER_OBJECT DriverObject, IN DRIVER_STATUS DriverStatus);
23
24 static PDEVICE_OBJECT MainDeviceObject;
25 static PDEVICE_OBJECT AttachDeviceObject;
26 static PDRIVER_OBJECT ThisDriverObject;
27
28 NTSTATUS
29 TestEntry(
30 IN PDRIVER_OBJECT DriverObject,
31 IN PCUNICODE_STRING RegistryPath,
32 OUT PCWSTR *DeviceName,
33 IN OUT INT *Flags)
34 {
35 NTSTATUS Status = STATUS_SUCCESS;
36
37 PAGED_CODE();
38
39 UNREFERENCED_PARAMETER(RegistryPath);
40 UNREFERENCED_PARAMETER(Flags);
41
42 *DeviceName = L"IoDriverObject";
43
44 KmtRegisterIrpHandler(IRP_MJ_CREATE, NULL, TestIrpHandler);
45 KmtRegisterIrpHandler(IRP_MJ_CLOSE, NULL, TestIrpHandler);
46
47 TestDriverObject(DriverObject, DriverEntry);
48
49 return Status;
50 }
51
52 VOID
53 TestUnload(
54 IN PDRIVER_OBJECT DriverObject)
55 {
56 PAGED_CODE();
57
58 TestDriverObject(DriverObject, DriverUnload);
59 }
60
61 static
62 NTSTATUS
63 TestIrpHandler(
64 IN PDEVICE_OBJECT DeviceObject,
65 IN PIRP Irp,
66 IN PIO_STACK_LOCATION IoStackLocation)
67 {
68 NTSTATUS Status = STATUS_SUCCESS;
69
70 UNREFERENCED_PARAMETER(IoStackLocation);
71
72 TestDriverObject(DeviceObject->DriverObject, DriverIrp);
73
74 Irp->IoStatus.Status = Status;
75 Irp->IoStatus.Information = 0;
76
77 IoCompleteRequest(Irp, IO_NO_INCREMENT);
78
79 return Status;
80 }
81
82 static
83 VOID
84 TestDriverObject(
85 IN PDRIVER_OBJECT DriverObject,
86 IN DRIVER_STATUS DriverStatus)
87 {
88 BOOLEAN CheckThisDispatchRoutine;
89 PVOID FirstMajorFunc;
90 int i;
91
92 ok(DriverObject->Size == sizeof(DRIVER_OBJECT), "Size does not match, got %x",DriverObject->Size);
93 ok(DriverObject->Type == 4, "Type does not match 4. got %d",DriverObject->Type);
94
95 if (DriverStatus == DriverEntry)
96 {
97 ok(DriverObject->DeviceObject == NULL, "Expected DeviceObject pointer to be 0, got %p",
98 DriverObject->DeviceObject);
99 ok (DriverObject->Flags == DRVO_LEGACY_DRIVER,
100 "Expected Flags to be DRVO_LEGACY_DRIVER, got %lu",
101 DriverObject->Flags);
102 }
103 else if (DriverStatus == DriverIrp)
104 {
105 ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null");
106 ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED),
107 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED, got %lu",
108 DriverObject->Flags);
109 }
110 else if (DriverStatus == DriverUnload)
111 {
112 ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null");
113 ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED),
114 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED, got %lu",
115 DriverObject->Flags);
116 }
117 else
118 ASSERT(FALSE);
119
120 /* Select a routine that was not changed */
121 FirstMajorFunc = DriverObject->MajorFunction[1];
122 ok(FirstMajorFunc != 0, "Expected MajorFunction[1] to be non NULL");
123
124 if (!skip(FirstMajorFunc != NULL, "First major function not set!\n"))
125 {
126 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
127 {
128 if (DriverStatus > 0) CheckThisDispatchRoutine = (i > 3) && (i != 14);
129 else CheckThisDispatchRoutine = TRUE;
130
131 if (CheckThisDispatchRoutine)
132 {
133 ok(DriverObject->MajorFunction[i] == FirstMajorFunc, "Expected MajorFunction[%d] to match %p",
134 i, FirstMajorFunc);
135 }
136 }
137 }
138 }
139
140 BOOLEAN ZwLoadTest(PDRIVER_OBJECT DriverObject, PUNICODE_STRING DriverRegistryPath, PWCHAR NewDriverRegPath)
141 {
142 UNICODE_STRING RegPath;
143 NTSTATUS Status;
144
145 /* Try to load ourself */
146 Status = ZwLoadDriver(DriverRegistryPath);
147 ok (Status == STATUS_IMAGE_ALREADY_LOADED, "Expected NTSTATUS STATUS_IMAGE_ALREADY_LOADED, got 0x%lX", Status);
148
149 if (Status != STATUS_IMAGE_ALREADY_LOADED)
150 {
151 DbgPrint("WARNING: Loading this a second time will cause BUGCHECK!\n");
152 }
153
154 /* Try to load with a Registry Path that doesnt exist */
155 RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
156 Status = ZwLoadDriver(&RegPath);
157 ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX", Status);
158
159 /* Load the driver */
160 RtlInitUnicodeString(&RegPath, NewDriverRegPath);
161 Status = ZwLoadDriver(&RegPath);
162 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
163
164 if (!NT_SUCCESS(Status))
165 {
166 return FALSE;
167 }
168
169 return TRUE;
170 }
171
172 BOOLEAN ZwUnloadTest(PDRIVER_OBJECT DriverObject, PUNICODE_STRING DriverRegistryPath, PWCHAR NewDriverRegPath)
173 {
174 UNICODE_STRING RegPath;
175 NTSTATUS Status;
176
177 /* Try to unload ourself, which should fail as our Unload routine hasnt been set yet. */
178 Status = ZwUnloadDriver(DriverRegistryPath);
179 ok (Status == STATUS_INVALID_DEVICE_REQUEST, "Expected NTSTATUS STATUS_INVALID_DEVICE_REQUEST, got 0x%lX", Status);
180
181 /* Try to unload with a Registry Path that doesnt exist */
182 RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
183 Status = ZwUnloadDriver(&RegPath);
184 ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX", Status);
185
186 /* Unload the driver */
187 RtlInitUnicodeString(&RegPath, NewDriverRegPath);
188 Status = ZwUnloadDriver(&RegPath);
189 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
190
191 if (!NT_SUCCESS(Status))
192 {
193 return FALSE;
194 }
195
196 return TRUE;
197 }
198
199 VOID LowerDeviceKernelAPITest(PDEVICE_OBJECT DeviceObject, BOOLEAN UnLoading)
200 {
201 PDEVICE_OBJECT RetObject;
202
203 RetObject = IoGetLowerDeviceObject(DeviceObject);
204
205 if (UnLoading)
206 {
207 ok(RetObject == 0,
208 "Expected no Lower DeviceObject, got %p", RetObject);
209 }
210 else
211 {
212 ok(RetObject == AttachDeviceObject,
213 "Expected an Attached DeviceObject %p, got %p", AttachDeviceObject, RetObject);
214 }
215
216 if (RetObject)
217 {
218 ObDereferenceObject(RetObject);
219 }
220
221 RetObject = IoGetDeviceAttachmentBaseRef(DeviceObject);
222 ok(RetObject == DeviceObject,
223 "Expected an Attached DeviceObject %p, got %p", DeviceObject, RetObject);
224
225 if (RetObject)
226 {
227 ObDereferenceObject(RetObject);
228 }
229
230 }
231 VOID DeviceCreatedTest(PDEVICE_OBJECT DeviceObject, BOOLEAN ExclusiveAccess)
232 {
233 PEXTENDED_DEVOBJ_EXTENSION extdev;
234
235 /*Check the device object members */
236 ok(DeviceObject->Type==3, "Expected Type = 3, got %x", DeviceObject->Type);
237 ok(DeviceObject->Size = 0xb8, "Expected Size = 0xba, got %x", DeviceObject->Size);
238 ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu",
239 DeviceObject->ReferenceCount);
240 ok(DeviceObject->DriverObject == ThisDriverObject,
241 "Expected DriverObject member to match this DriverObject %p, got %p",
242 ThisDriverObject, DeviceObject->DriverObject);
243 ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p", DeviceObject->NextDevice);
244 ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p", DeviceObject->AttachedDevice);
245 ok(DeviceObject->Characteristics == 0, "Expected Characteristics to be 0");
246 if (ExclusiveAccess)
247 {
248 ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE)),
249 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE, got %lu", DeviceObject->Flags);
250 }
251 else
252 {
253 ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING)),
254 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING, got %lu", DeviceObject->Flags);
255 }
256 ok(DeviceObject->DeviceType == FILE_DEVICE_UNKNOWN,
257 "Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu",
258 DeviceObject->DeviceType);
259 ok(DeviceObject->ActiveThreadCount == 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject->ActiveThreadCount);
260
261 /*Check the extended extension */
262 extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
263 ok(extdev->ExtensionFlags == 0, "Expected Extended ExtensionFlags to be 0, got %lu", extdev->ExtensionFlags);
264 ok (extdev->Type == 13, "Expected Type of 13, got %d", extdev->Type);
265 ok (extdev->Size == 0, "Expected Size of 0, got %d", extdev->Size);
266 ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p",
267 DeviceObject, extdev->DeviceObject);
268 ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p", extdev->AttachedTo);
269 ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu", extdev->StartIoCount);
270 ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu", extdev->StartIoKey);
271 ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu", extdev->StartIoFlags);
272 }
273
274 VOID DeviceDeletionTest(PDEVICE_OBJECT DeviceObject, BOOLEAN Lower)
275 {
276 PEXTENDED_DEVOBJ_EXTENSION extdev;
277
278 /*Check the device object members */
279 ok(DeviceObject->Type==3, "Expected Type = 3, got %d", DeviceObject->Type);
280 ok(DeviceObject->Size = 0xb8, "Expected Size = 0xba, got %d", DeviceObject->Size);
281 ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu",
282 DeviceObject->ReferenceCount);
283 if (!Lower)
284 {
285 ok(DeviceObject->DriverObject == ThisDriverObject,
286 "Expected DriverObject member to match this DriverObject %p, got %p",
287 ThisDriverObject, DeviceObject->DriverObject);
288 }
289 ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p", DeviceObject->NextDevice);
290
291 if (Lower)
292 {
293 ok(DeviceObject->AttachedDevice == MainDeviceObject,
294 "Expected AttachDevice to be %p, got %p", MainDeviceObject, DeviceObject->AttachedDevice);
295 }
296 else
297 {
298 ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p", DeviceObject->AttachedDevice);
299 }
300
301 ok(DeviceObject->Flags ==FILE_VIRTUAL_VOLUME,
302 "Expected Flags FILE_VIRTUAL_VOLUME, got %lu", DeviceObject->Flags);
303 ok(DeviceObject->DeviceType == FILE_DEVICE_UNKNOWN,
304 "Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu",
305 DeviceObject->DeviceType);
306 ok(DeviceObject->ActiveThreadCount == 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject->ActiveThreadCount);
307
308 /*Check the extended extension */
309 extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
310 ok(extdev->ExtensionFlags == DOE_UNLOAD_PENDING,
311 "Expected Extended ExtensionFlags to be DOE_UNLOAD_PENDING, got %lu", extdev->ExtensionFlags);
312 ok (extdev->Type == 13, "Expected Type of 13, got %d", extdev->Type);
313 ok (extdev->Size == 0, "Expected Size of 0, got %d", extdev->Size);
314 ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p",
315 DeviceObject, extdev->DeviceObject);
316 if (Lower)
317 {
318 /* Skip this for now */
319 //ok(extdev->AttachedTo == MainDeviceObject, "Expected AttachTo to %p, got %p", MainDeviceObject, extdev->AttachedTo);
320 }
321 else
322 {
323 ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p", extdev->AttachedTo);
324 }
325 ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu", extdev->StartIoCount);
326 ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu", extdev->StartIoKey);
327 ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu", extdev->StartIoFlags);
328 }
329
330 VOID DeviceCreateDeleteTest(PDRIVER_OBJECT DriverObject)
331 {
332 NTSTATUS Status;
333 UNICODE_STRING DeviceString;
334 UNICODE_STRING DosDeviceString;
335 PDEVICE_OBJECT DeviceObject;
336
337 /* Create using wrong directory */
338 RtlInitUnicodeString(&DeviceString, L"\\Device1\\Kmtest");
339 Status = IoCreateDevice(DriverObject,
340 0,
341 &DeviceString,
342 FILE_DEVICE_UNKNOWN,
343 0,
344 FALSE,
345 &DeviceObject);
346 ok(Status == STATUS_OBJECT_PATH_NOT_FOUND, "Expected STATUS_OBJECT_PATH_NOT_FOUND, got 0x%lX", Status);
347
348 /* Create using correct params with exlusice access */
349 RtlInitUnicodeString(&DeviceString, L"\\Device\\Kmtest");
350 Status = IoCreateDevice(DriverObject,
351 0,
352 &DeviceString,
353 FILE_DEVICE_UNKNOWN,
354 0,
355 TRUE,
356 &DeviceObject);
357 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
358
359 DeviceCreatedTest(DeviceObject, TRUE);
360
361 /* Delete the device */
362 if (NT_SUCCESS(Status))
363 {
364 IoDeleteDevice(DeviceObject);
365 ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p",
366 DriverObject->DeviceObject);
367 }
368
369 /* Create using correct params with exlusice access */
370 Status = IoCreateDevice(DriverObject,
371 0,
372 &DeviceString,
373 FILE_DEVICE_UNKNOWN,
374 0,
375 FALSE,
376 &DeviceObject);
377 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
378
379 DeviceCreatedTest(DeviceObject, FALSE);
380
381 /* Delete the device */
382 if (NT_SUCCESS(Status))
383 {
384 IoDeleteDevice(DeviceObject);
385 ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p",
386 DriverObject->DeviceObject);
387 }
388
389 /* Recreate device */
390 Status = IoCreateDevice(DriverObject,
391 0,
392 &DeviceString,
393 FILE_DEVICE_UNKNOWN,
394 0,
395 FALSE,
396 &DeviceObject);
397 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX", Status);
398
399 RtlInitUnicodeString(&DosDeviceString, L"\\DosDevices\\kmtest");
400 Status = IoCreateSymbolicLink(&DosDeviceString, &DeviceString);
401
402 if (!NT_SUCCESS(Status))
403 {
404 /* Delete device object if not successful */
405 IoDeleteDevice(DeviceObject);
406 return;
407 }
408
409 MainDeviceObject = DeviceObject;
410
411 return;
412 }
413
414 BOOLEAN AttachDeviceTest(PDEVICE_OBJECT DeviceObject, PWCHAR NewDriverRegPath)
415 {
416 NTSTATUS Status;
417 UNICODE_STRING LowerDeviceName;
418
419 RtlInitUnicodeString(&LowerDeviceName, NewDriverRegPath);
420 Status = IoAttachDevice(DeviceObject, &LowerDeviceName, &AttachDeviceObject);
421
422 /* TODO: Add more tests */
423
424 return TRUE;
425 }
426
427 BOOLEAN DetachDeviceTest(PDEVICE_OBJECT AttachedDevice)
428 {
429
430 IoDetachDevice(AttachedDevice);
431
432 /* TODO: Add more tests */
433
434 return TRUE;
435 }