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 <thomas.faber@reactos.org>
21 static DRIVER_DISPATCH TestDispatch
;
22 static VOID
TestDriverObject(IN PDRIVER_OBJECT DriverObject
, IN DRIVER_STATUS DriverStatus
);
23 static BOOLEAN
TestZwLoad(IN PDRIVER_OBJECT DriverObject
, IN PCUNICODE_STRING DriverRegistryPath
, IN PWCHAR NewDriverRegPath
);
24 static BOOLEAN
TestZwUnload(IN PDRIVER_OBJECT DriverObject
, IN PCUNICODE_STRING DriverRegistryPath
, IN PWCHAR NewDriverRegPath
);
25 static VOID
TestLowerDeviceKernelAPI(IN PDEVICE_OBJECT DeviceObject
);
26 static VOID
TestDeviceCreated(IN PDEVICE_OBJECT DeviceObject
, IN BOOLEAN ExclusiveAccess
);
27 static VOID
TestDeviceDeletion(IN PDEVICE_OBJECT DeviceObject
, IN BOOLEAN Lower
, IN BOOLEAN Attached
);
28 static VOID
TestDeviceCreateDelete(IN PDRIVER_OBJECT DriverObject
);
29 static VOID
TestAttachDevice(IN PDEVICE_OBJECT DeviceObject
, IN PWCHAR NewDriverRegPath
);
30 static VOID
TestDetachDevice(IN PDEVICE_OBJECT AttachedDevice
);
32 static PDEVICE_OBJECT MainDeviceObject
;
33 static PDEVICE_OBJECT AttachDeviceObject
;
34 static PDRIVER_OBJECT ThisDriverObject
;
38 IN PDRIVER_OBJECT DriverObject
,
39 IN PCUNICODE_STRING RegistryPath
,
40 OUT PCWSTR
*DeviceName
,
43 NTSTATUS Status
= STATUS_SUCCESS
;
49 UNREFERENCED_PARAMETER(DeviceName
);
51 *Flags
= TESTENTRY_NO_CREATE_DEVICE
| TESTENTRY_NO_REGISTER_DISPATCH
;
53 ThisDriverObject
= DriverObject
;
55 TestDriverObject(DriverObject
, DriverEntry
);
57 /* Create and delete device, on return MainDeviceObject has been created */
58 TestDeviceCreateDelete(DriverObject
);
60 /* Make sure a device object was created */
61 if (!skip(MainDeviceObject
!= NULL
, "Device object creation failed\n"))
63 PWCHAR LowerDriverRegPath
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Kmtest-IoHelper";
65 /* Load driver test and load the lower driver */
66 Ret
= TestZwLoad(DriverObject
, RegistryPath
, LowerDriverRegPath
);
67 if (!skip(Ret
, "Failed to load helper driver\n"))
69 TestAttachDevice(MainDeviceObject
, L
"\\Device\\Kmtest-IoHelper");
70 if (!skip(AttachDeviceObject
!= NULL
, "No attached device object\n"))
71 TestLowerDeviceKernelAPI(MainDeviceObject
);
73 /* Unload lower driver without detaching from its device */
74 TestZwUnload(DriverObject
, RegistryPath
, LowerDriverRegPath
);
75 TestLowerDeviceKernelAPI(MainDeviceObject
);
79 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; ++i
)
80 DriverObject
->MajorFunction
[i
] = NULL
;
81 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = TestDispatch
;
82 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = TestDispatch
;
83 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = TestDispatch
;
90 IN PDRIVER_OBJECT DriverObject
)
94 if (!skip(AttachDeviceObject
!= NULL
, "no attached device object\n"))
96 TestDeviceDeletion(MainDeviceObject
, FALSE
, TRUE
);
97 TestDeviceDeletion(AttachDeviceObject
, TRUE
, FALSE
);
98 TestDetachDevice(AttachDeviceObject
);
101 TestDeviceDeletion(MainDeviceObject
, FALSE
, FALSE
);
102 TestDriverObject(DriverObject
, DriverUnload
);
104 if (MainDeviceObject
)
105 IoDeleteDevice(MainDeviceObject
);
112 IN PDEVICE_OBJECT DeviceObject
,
115 NTSTATUS Status
= STATUS_SUCCESS
;
116 PIO_STACK_LOCATION IoStackLocation
;
120 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
122 DPRINT("TestIrpHandler. Function=%s, DeviceObject=%p, AttachDeviceObject=%p\n",
123 KmtMajorFunctionNames
[IoStackLocation
->MajorFunction
],
127 if (AttachDeviceObject
)
129 IoSkipCurrentIrpStackLocation(Irp
);
130 Status
= IoCallDriver(AttachDeviceObject
, Irp
);
134 TestDriverObject(DeviceObject
->DriverObject
, DriverIrp
);
136 Irp
->IoStatus
.Status
= Status
;
137 Irp
->IoStatus
.Information
= 0;
139 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
147 IN PDRIVER_OBJECT DriverObject
,
148 IN DRIVER_STATUS DriverStatus
)
150 BOOLEAN CheckThisDispatchRoutine
;
151 PVOID FirstMajorFunc
;
154 ok(DriverObject
->Size
== sizeof(DRIVER_OBJECT
), "Size does not match, got %x\n",DriverObject
->Size
);
155 ok(DriverObject
->Type
== 4, "Type does not match 4. got %d\n", DriverObject
->Type
);
157 if (DriverStatus
== DriverEntry
)
159 ok(DriverObject
->DeviceObject
== NULL
, "Expected DeviceObject pointer to be 0, got %p\n",
160 DriverObject
->DeviceObject
);
161 ok (DriverObject
->Flags
== DRVO_LEGACY_DRIVER
,
162 "Expected Flags to be DRVO_LEGACY_DRIVER, got %lu\n",
163 DriverObject
->Flags
);
165 else if (DriverStatus
== DriverIrp
)
167 ok(DriverObject
->DeviceObject
!= NULL
, "Expected DeviceObject pointer to non null\n");
168 ok (DriverObject
->Flags
== (DRVO_LEGACY_DRIVER
| DRVO_INITIALIZED
),
169 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED, got %lu\n",
170 DriverObject
->Flags
);
172 else if (DriverStatus
== DriverUnload
)
174 ok(DriverObject
->DeviceObject
!= NULL
, "Expected DeviceObject pointer to non null\n");
175 ok (DriverObject
->Flags
== (DRVO_LEGACY_DRIVER
| DRVO_INITIALIZED
| DRVO_UNLOAD_INVOKED
),
176 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED, got %lu\n",
177 DriverObject
->Flags
);
182 /* Select a routine that was not changed */
183 FirstMajorFunc
= DriverObject
->MajorFunction
[1];
184 ok(FirstMajorFunc
!= 0, "Expected MajorFunction[1] to be non NULL\n");
186 if (!skip(FirstMajorFunc
!= NULL
, "First major function not set!\n"))
188 for (i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++)
190 if (DriverStatus
> 0) CheckThisDispatchRoutine
= (i
> 3) && (i
!= 14);
191 else CheckThisDispatchRoutine
= TRUE
;
193 if (CheckThisDispatchRoutine
)
195 ok(DriverObject
->MajorFunction
[i
] == FirstMajorFunc
, "Expected MajorFunction[%d] to match %p\n",
205 IN PDRIVER_OBJECT DriverObject
,
206 IN PCUNICODE_STRING DriverRegistryPath
,
207 IN PWCHAR NewDriverRegPath
)
209 UNICODE_STRING RegPath
;
212 /* Try to load ourself */
213 Status
= ZwLoadDriver((PUNICODE_STRING
)DriverRegistryPath
);
214 ok (Status
== STATUS_IMAGE_ALREADY_LOADED
, "Expected NTSTATUS STATUS_IMAGE_ALREADY_LOADED, got 0x%lX\n", Status
);
216 if (Status
!= STATUS_IMAGE_ALREADY_LOADED
)
218 DbgPrint("WARNING: Loading this a second time will cause BUGCHECK!\n");
221 /* Try to load with a Registry Path that doesnt exist */
222 RtlInitUnicodeString(&RegPath
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
223 Status
= ZwLoadDriver(&RegPath
);
224 ok (Status
== STATUS_OBJECT_NAME_NOT_FOUND
, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX\n", Status
);
226 /* Load the driver */
227 RtlInitUnicodeString(&RegPath
, NewDriverRegPath
);
228 Status
= ZwLoadDriver(&RegPath
);
229 ok(Status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got 0x%lX\n", Status
);
231 return NT_SUCCESS(Status
);
237 IN PDRIVER_OBJECT DriverObject
,
238 IN PCUNICODE_STRING DriverRegistryPath
,
239 IN PWCHAR NewDriverRegPath
)
241 UNICODE_STRING RegPath
;
244 /* Try to unload ourself, which should fail as our Unload routine hasnt been set yet. */
245 Status
= ZwUnloadDriver((PUNICODE_STRING
)DriverRegistryPath
);
246 ok (Status
== STATUS_INVALID_DEVICE_REQUEST
, "Expected NTSTATUS STATUS_INVALID_DEVICE_REQUEST, got 0x%lX\n", Status
);
248 /* Try to unload with a Registry Path that doesnt exist */
249 RtlInitUnicodeString(&RegPath
, L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
250 Status
= ZwUnloadDriver(&RegPath
);
251 ok (Status
== STATUS_OBJECT_NAME_NOT_FOUND
, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX\n", Status
);
253 /* Unload the driver */
254 RtlInitUnicodeString(&RegPath
, NewDriverRegPath
);
255 Status
= ZwUnloadDriver(&RegPath
);
256 ok(Status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got 0x%lX\n", Status
);
258 return NT_SUCCESS(Status
);
263 TestLowerDeviceKernelAPI(
264 IN PDEVICE_OBJECT DeviceObject
)
266 PDEVICE_OBJECT RetObject
;
268 RetObject
= IoGetLowerDeviceObject(DeviceObject
);
270 ok(RetObject
== AttachDeviceObject
,
271 "Expected an Attached DeviceObject %p, got %p\n", AttachDeviceObject
, RetObject
);
275 ObDereferenceObject(RetObject
);
278 RetObject
= IoGetDeviceAttachmentBaseRef(DeviceObject
);
279 ok(RetObject
== AttachDeviceObject
,
280 "Expected an Attached DeviceObject %p, got %p\n", AttachDeviceObject
, RetObject
);
284 ObDereferenceObject(RetObject
);
292 IN PDEVICE_OBJECT DeviceObject
,
293 IN BOOLEAN ExclusiveAccess
)
295 PEXTENDED_DEVOBJ_EXTENSION extdev
;
297 /* Check the device object members */
298 ok(DeviceObject
->Type
== 3, "Expected Type = 3, got %x\n", DeviceObject
->Type
);
299 ok(DeviceObject
->Size
== 0xb8, "Expected Size = 0xb8, got %x\n", DeviceObject
->Size
);
300 ok(DeviceObject
->ReferenceCount
== 0, "Expected ReferenceCount = 0, got %lu\n",
301 DeviceObject
->ReferenceCount
);
302 ok(DeviceObject
->DriverObject
== ThisDriverObject
,
303 "Expected DriverObject member to match this DriverObject %p, got %p\n",
304 ThisDriverObject
, DeviceObject
->DriverObject
);
305 ok(DeviceObject
->NextDevice
== NULL
, "Expected NextDevice to be NULL, got %p\n", DeviceObject
->NextDevice
);
306 ok(DeviceObject
->AttachedDevice
== NULL
, "Expected AttachDevice to be NULL, got %p\n", DeviceObject
->AttachedDevice
);
307 ok(DeviceObject
->Characteristics
== 0, "Expected Characteristics to be 0\n");
310 ok((DeviceObject
->Flags
== (DO_DEVICE_HAS_NAME
| DO_DEVICE_INITIALIZING
| DO_EXCLUSIVE
)),
311 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE, got %lu\n", DeviceObject
->Flags
);
315 ok((DeviceObject
->Flags
== (DO_DEVICE_HAS_NAME
| DO_DEVICE_INITIALIZING
)),
316 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING, got %lu\n", DeviceObject
->Flags
);
318 ok(DeviceObject
->DeviceType
== FILE_DEVICE_UNKNOWN
,
319 "Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu\n",
320 DeviceObject
->DeviceType
);
321 ok(DeviceObject
->ActiveThreadCount
== 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject
->ActiveThreadCount
);
323 /* Check the extended extension */
324 extdev
= (PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
;
325 ok(extdev
->ExtensionFlags
== 0, "Expected Extended ExtensionFlags to be 0, got %lu\n", extdev
->ExtensionFlags
);
326 ok (extdev
->Type
== 13, "Expected Type of 13, got %d\n", extdev
->Type
);
327 ok (extdev
->Size
== 0, "Expected Size of 0, got %d\n", extdev
->Size
);
328 ok (extdev
->DeviceObject
== DeviceObject
, "Expected DeviceOject to match newly created device %p, got %p\n",
329 DeviceObject
, extdev
->DeviceObject
);
330 ok(extdev
->AttachedTo
== NULL
, "Expected AttachTo to be NULL, got %p\n", extdev
->AttachedTo
);
331 ok(extdev
->StartIoCount
== 0, "Expected StartIoCount = 0, got %lu\n", extdev
->StartIoCount
);
332 ok(extdev
->StartIoKey
== 0, "Expected StartIoKey = 0, got %lu\n", extdev
->StartIoKey
);
333 ok(extdev
->StartIoFlags
== 0, "Expected StartIoFlags = 0, got %lu\n", extdev
->StartIoFlags
);
339 IN PDEVICE_OBJECT DeviceObject
,
343 PEXTENDED_DEVOBJ_EXTENSION extdev
;
345 /* Check the device object members */
346 ok(DeviceObject
->Type
== 3, "Expected Type = 3, got %d\n", DeviceObject
->Type
);
347 ok(DeviceObject
->Size
== 0xb8, "Expected Size = 0xb8, got %d\n", DeviceObject
->Size
);
348 ok(DeviceObject
->ReferenceCount
== 0, "Expected ReferenceCount = 0, got %lu\n",
349 DeviceObject
->ReferenceCount
);
352 ok(DeviceObject
->DriverObject
== ThisDriverObject
,
353 "Expected DriverObject member to match this DriverObject %p, got %p\n",
354 ThisDriverObject
, DeviceObject
->DriverObject
);
356 ok(DeviceObject
->NextDevice
== NULL
, "Expected NextDevice to be NULL, got %p\n", DeviceObject
->NextDevice
);
360 ok(DeviceObject
->AttachedDevice
== MainDeviceObject
,
361 "Expected AttachDevice to be %p, got %p\n", MainDeviceObject
, DeviceObject
->AttachedDevice
);
365 ok(DeviceObject
->AttachedDevice
== NULL
, "Expected AttachDevice to be NULL, got %p\n", DeviceObject
->AttachedDevice
);
368 ok(DeviceObject
->Flags
== (DO_DEVICE_HAS_NAME
| (Lower
? DO_EXCLUSIVE
: 0)),
369 "Expected Flags DO_DEVICE_HAS_NAME, got %lu\n", DeviceObject
->Flags
);
370 ok(DeviceObject
->DeviceType
== FILE_DEVICE_UNKNOWN
,
371 "Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu\n",
372 DeviceObject
->DeviceType
);
373 ok(DeviceObject
->ActiveThreadCount
== 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject
->ActiveThreadCount
);
375 /*Check the extended extension */
376 extdev
= (PEXTENDED_DEVOBJ_EXTENSION
)DeviceObject
->DeviceObjectExtension
;
377 ok(extdev
->ExtensionFlags
== DOE_UNLOAD_PENDING
,
378 "Expected Extended ExtensionFlags to be DOE_UNLOAD_PENDING, got %lu\n", extdev
->ExtensionFlags
);
379 ok (extdev
->Type
== 13, "Expected Type of 13, got %d\n", extdev
->Type
);
380 ok (extdev
->Size
== 0, "Expected Size of 0, got %d\n", extdev
->Size
);
381 ok (extdev
->DeviceObject
== DeviceObject
, "Expected DeviceOject to match newly created device %p, got %p\n",
382 DeviceObject
, extdev
->DeviceObject
);
383 if (Lower
|| !Attached
)
385 ok(extdev
->AttachedTo
== NULL
, "Expected AttachTo to be NULL, got %p\n", extdev
->AttachedTo
);
389 ok(extdev
->AttachedTo
== AttachDeviceObject
, "Expected AttachTo to %p, got %p\n", AttachDeviceObject
, extdev
->AttachedTo
);
391 ok(extdev
->StartIoCount
== 0, "Expected StartIoCount = 0, got %lu\n", extdev
->StartIoCount
);
392 ok(extdev
->StartIoKey
== 0, "Expected StartIoKey = 0, got %lu\n", extdev
->StartIoKey
);
393 ok(extdev
->StartIoFlags
== 0, "Expected StartIoFlags = 0, got %lu\n", extdev
->StartIoFlags
);
398 TestDeviceCreateDelete(
399 IN PDRIVER_OBJECT DriverObject
)
402 UNICODE_STRING DeviceString
;
403 PDEVICE_OBJECT DeviceObject
;
405 /* Create using wrong directory */
406 RtlInitUnicodeString(&DeviceString
, L
"\\Device1\\Kmtest-IoDeviceObject");
407 Status
= IoCreateDevice(DriverObject
,
414 ok(Status
== STATUS_OBJECT_PATH_NOT_FOUND
, "Expected STATUS_OBJECT_PATH_NOT_FOUND, got 0x%lX\n", Status
);
416 /* Create using correct params with exclusice access */
417 RtlInitUnicodeString(&DeviceString
, L
"\\Device\\Kmtest-IoDeviceObject");
418 Status
= IoCreateDevice(DriverObject
,
425 ok(Status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got 0x%lX\n", Status
);
427 TestDeviceCreated(DeviceObject
, TRUE
);
429 /* Delete the device */
430 if (NT_SUCCESS(Status
))
432 IoDeleteDevice(DeviceObject
);
433 ok(DriverObject
->DeviceObject
== 0, "Expected DriverObject->DeviceObject to be NULL, got %p\n",
434 DriverObject
->DeviceObject
);
437 /* Create using correct params without exclusice access */
438 Status
= IoCreateDevice(DriverObject
,
445 ok(Status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got 0x%lX\n", Status
);
447 TestDeviceCreated(DeviceObject
, FALSE
);
449 /* Delete the device */
450 if (NT_SUCCESS(Status
))
452 IoDeleteDevice(DeviceObject
);
453 ok(DriverObject
->DeviceObject
== 0, "Expected DriverObject->DeviceObject to be NULL, got %p\n",
454 DriverObject
->DeviceObject
);
457 /* Recreate device */
458 Status
= IoCreateDevice(DriverObject
,
465 ok(Status
== STATUS_SUCCESS
, "Expected STATUS_SUCCESS, got 0x%lX\n", Status
);
467 if (NT_SUCCESS(Status
))
468 MainDeviceObject
= DeviceObject
;
474 IN PDEVICE_OBJECT DeviceObject
,
475 IN PWCHAR NewDriverRegPath
)
478 UNICODE_STRING LowerDeviceName
;
480 RtlInitUnicodeString(&LowerDeviceName
, NewDriverRegPath
);
481 Status
= IoAttachDevice(DeviceObject
, &LowerDeviceName
, &AttachDeviceObject
);
482 ok_eq_hex(Status
, STATUS_SUCCESS
);
484 /* TODO: Add more tests */
490 IN PDEVICE_OBJECT AttachedDevice
)
492 IoDetachDevice(AttachedDevice
);
494 /* TODO: Add more tests */