[USP10_WINETEST] Sync with Wine Staging 2.9. CORE-13362
[reactos.git] / rostests / kmtests / ntos_io / IoDeviceObject_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 <thomas.faber@reactos.org>
7 */
8
9 #include <kmt_test.h>
10
11 //#define NDEBUG
12 #include <debug.h>
13
14 #define BASE_POOL_TYPE_MASK 1
15
16 typedef enum
17 {
18 DriverStatusEntry,
19 DriverStatusIrp,
20 DriverStatusUnload
21 } DRIVER_STATUS;
22
23 static DRIVER_DISPATCH TestDispatch;
24 static VOID TestDriverObject(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath OPTIONAL, IN DRIVER_STATUS DriverStatus);
25 static BOOLEAN TestZwLoad(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING DriverRegistryPath, IN PWCHAR NewDriverRegPath);
26 static BOOLEAN TestZwUnload(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING DriverRegistryPath, IN PWCHAR NewDriverRegPath);
27 static VOID TestLowerDeviceKernelAPI(IN PDEVICE_OBJECT DeviceObject);
28 static VOID TestDeviceCreated(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN ExclusiveAccess);
29 static VOID TestDeviceDeletion(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN Lower, IN BOOLEAN Attached);
30 static VOID TestDeviceCreateDelete(IN PDRIVER_OBJECT DriverObject);
31 static VOID TestAttachDevice(IN PDEVICE_OBJECT DeviceObject, IN PWCHAR NewDriverRegPath);
32 static VOID TestDetachDevice(IN PDEVICE_OBJECT AttachedDevice);
33
34 static PDEVICE_OBJECT MainDeviceObject;
35 static PDEVICE_OBJECT AttachDeviceObject;
36 static PDRIVER_OBJECT ThisDriverObject;
37
38 NTSTATUS
39 TestEntry(
40 IN PDRIVER_OBJECT DriverObject,
41 IN PCUNICODE_STRING RegistryPath,
42 OUT PCWSTR *DeviceName,
43 IN OUT INT *Flags)
44 {
45 NTSTATUS Status = STATUS_SUCCESS;
46 BOOLEAN Ret;
47 INT i;
48
49 PAGED_CODE();
50
51 UNREFERENCED_PARAMETER(DeviceName);
52
53 *Flags = TESTENTRY_NO_CREATE_DEVICE | TESTENTRY_NO_REGISTER_DISPATCH;
54
55 ThisDriverObject = DriverObject;
56
57 TestDriverObject(DriverObject, RegistryPath, DriverStatusEntry);
58
59 /* Create and delete device, on return MainDeviceObject has been created */
60 TestDeviceCreateDelete(DriverObject);
61
62 /* Make sure a device object was created */
63 if (!skip(MainDeviceObject != NULL, "Device object creation failed\n"))
64 {
65 PWCHAR LowerDriverRegPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Kmtest-IoHelper";
66
67 /* Load driver test and load the lower driver */
68 Ret = TestZwLoad(DriverObject, RegistryPath, LowerDriverRegPath);
69 if (!skip(Ret, "Failed to load helper driver\n"))
70 {
71 TestAttachDevice(MainDeviceObject, L"\\Device\\Kmtest-IoHelper");
72 if (!skip(AttachDeviceObject != NULL, "No attached device object\n"))
73 TestLowerDeviceKernelAPI(MainDeviceObject);
74
75 /* Unload lower driver without detaching from its device */
76 TestZwUnload(DriverObject, RegistryPath, LowerDriverRegPath);
77 TestLowerDeviceKernelAPI(MainDeviceObject);
78 }
79 }
80
81 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
82 DriverObject->MajorFunction[i] = NULL;
83 DriverObject->MajorFunction[IRP_MJ_CREATE] = TestDispatch;
84 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TestDispatch;
85 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestDispatch;
86
87 return Status;
88 }
89
90 VOID
91 TestUnload(
92 IN PDRIVER_OBJECT DriverObject)
93 {
94 PAGED_CODE();
95
96 if (!skip(AttachDeviceObject != NULL, "no attached device object\n"))
97 {
98 TestDeviceDeletion(MainDeviceObject, FALSE, TRUE);
99 TestDeviceDeletion(AttachDeviceObject, TRUE, FALSE);
100 TestDetachDevice(AttachDeviceObject);
101 }
102
103 TestDeviceDeletion(MainDeviceObject, FALSE, FALSE);
104 TestDriverObject(DriverObject, NULL, DriverStatusUnload);
105
106 if (MainDeviceObject)
107 IoDeleteDevice(MainDeviceObject);
108 }
109
110 static
111 NTSTATUS
112 NTAPI
113 TestDispatch(
114 IN PDEVICE_OBJECT DeviceObject,
115 IN PIRP Irp)
116 {
117 NTSTATUS Status = STATUS_SUCCESS;
118 PIO_STACK_LOCATION IoStackLocation;
119
120 PAGED_CODE();
121
122 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
123
124 DPRINT("TestIrpHandler. Function=%s, DeviceObject=%p, AttachDeviceObject=%p\n",
125 KmtMajorFunctionNames[IoStackLocation->MajorFunction],
126 DeviceObject,
127 AttachDeviceObject);
128
129 if (AttachDeviceObject)
130 {
131 IoSkipCurrentIrpStackLocation(Irp);
132 Status = IoCallDriver(AttachDeviceObject, Irp);
133 return Status;
134 }
135
136 TestDriverObject(DeviceObject->DriverObject, NULL, DriverStatusIrp);
137
138 Irp->IoStatus.Status = Status;
139 Irp->IoStatus.Information = 0;
140
141 IoCompleteRequest(Irp, IO_NO_INCREMENT);
142
143 return Status;
144 }
145
146 extern DRIVER_INITIALIZE DriverEntry;
147
148 static
149 VOID
150 TestDriverObject(
151 IN PDRIVER_OBJECT DriverObject,
152 IN PCUNICODE_STRING RegistryPath OPTIONAL,
153 IN DRIVER_STATUS DriverStatus)
154 {
155 BOOLEAN CheckThisDispatchRoutine;
156 PVOID FirstMajorFunc;
157 int i;
158 UNICODE_STRING HardwareDatabase = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
159 UNICODE_STRING RegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Kmtest-IoDeviceObject");
160 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"\\Driver\\Kmtest-IoDeviceObject");
161 UNICODE_STRING ServiceKeyName = RTL_CONSTANT_STRING(L"Kmtest-IoDeviceObject");
162 BOOLEAN Equal;
163
164 ok(DriverObject->Size == sizeof(DRIVER_OBJECT), "Size does not match, got %x\n",DriverObject->Size);
165 ok(DriverObject->Type == 4, "Type does not match 4. got %d\n", DriverObject->Type);
166
167 if (DriverStatus == DriverStatusEntry)
168 {
169 ok(DriverObject->DeviceObject == NULL, "Expected DeviceObject pointer to be 0, got %p\n",
170 DriverObject->DeviceObject);
171 ok (DriverObject->Flags == DRVO_LEGACY_DRIVER,
172 "Expected Flags to be DRVO_LEGACY_DRIVER, got %lu\n",
173 DriverObject->Flags);
174
175 ok(DriverObject->DriverStart < (PVOID)TestEntry,
176 "DriverStart is %p, expected < %p\n",
177 DriverObject->DriverStart, (PVOID)TestEntry);
178 ok(DriverObject->DriverSize > 0x2000,
179 "DriverSize 0x%lx\n", DriverObject->DriverSize);
180 ok_eq_pointer(DriverObject->DriverExtension, (PDRIVER_EXTENSION)(DriverObject + 1));
181 ok_eq_pointer(DriverObject->DriverExtension->DriverObject, DriverObject);
182 ok_eq_pointer(DriverObject->DriverExtension->AddDevice, NULL);
183 ok_eq_ulong(DriverObject->DriverExtension->Count, 0UL);
184 Equal = RtlEqualUnicodeString(RegistryPath,
185 &RegPath,
186 FALSE);
187 ok(Equal, "RegistryPath is '%wZ'\n", RegistryPath);
188 ok((ULONG_PTR)RegistryPath % PAGE_SIZE == 0, "RegistryPath %p not page-aligned\n", RegistryPath);
189 ok_eq_pointer(RegistryPath->Buffer, (PWCHAR)(RegistryPath + 1));
190 ok_eq_uint(RegistryPath->MaximumLength, RegistryPath->Length);
191 Equal = RtlEqualUnicodeString(&DriverObject->DriverExtension->ServiceKeyName,
192 &ServiceKeyName,
193 FALSE);
194 ok(Equal, "ServiceKeyName is '%wZ'\n", &DriverObject->DriverExtension->ServiceKeyName);
195 ok_eq_tag(KmtGetPoolTag(DriverObject->DriverExtension->ServiceKeyName.Buffer), ' oI');
196 ok_eq_uint((KmtGetPoolType(DriverObject->DriverExtension->ServiceKeyName.Buffer) - 1) & BASE_POOL_TYPE_MASK, NonPagedPool);
197 ok_eq_uint(DriverObject->DriverExtension->ServiceKeyName.MaximumLength, DriverObject->DriverExtension->ServiceKeyName.Length + sizeof(UNICODE_NULL));
198 ok_eq_uint(DriverObject->DriverExtension->ServiceKeyName.Buffer[DriverObject->DriverExtension->ServiceKeyName.Length / sizeof(WCHAR)], UNICODE_NULL);
199 Equal = RtlEqualUnicodeString(&DriverObject->DriverName,
200 &DriverName,
201 FALSE);
202 ok(Equal, "DriverName is '%wZ'\n", &DriverObject->DriverName);
203 ok_eq_tag(KmtGetPoolTag(DriverObject->DriverName.Buffer), ' oI');
204 ok_eq_uint((KmtGetPoolType(DriverObject->DriverName.Buffer) - 1) & BASE_POOL_TYPE_MASK, PagedPool);
205 ok_eq_uint(DriverObject->DriverName.MaximumLength, DriverObject->DriverName.Length);
206 // TODO: show that both string and buffer are constants inside ntos
207 Equal = RtlEqualUnicodeString(DriverObject->HardwareDatabase,
208 &HardwareDatabase,
209 FALSE);
210 ok(Equal, "HardwareDatabase is '%wZ'\n", DriverObject->HardwareDatabase);
211 ok_eq_uint(DriverObject->HardwareDatabase->MaximumLength, DriverObject->HardwareDatabase->Length + sizeof(UNICODE_NULL));
212 ok_eq_uint(DriverObject->HardwareDatabase->Buffer[DriverObject->HardwareDatabase->Length / sizeof(WCHAR)], UNICODE_NULL);
213 ok(DriverObject->DriverInit == DriverEntry,
214 "DriverInit is %p, expected %p\n",
215 (PVOID)DriverObject->DriverInit, (PVOID)DriverEntry);
216 }
217 else if (DriverStatus == DriverStatusIrp)
218 {
219 ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null\n");
220 ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED),
221 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED, got %lu\n",
222 DriverObject->Flags);
223 }
224 else if (DriverStatus == DriverStatusUnload)
225 {
226 ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null\n");
227 ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED),
228 "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED, got %lu\n",
229 DriverObject->Flags);
230 }
231 else
232 ASSERT(FALSE);
233
234 /* Select a routine that was not changed */
235 FirstMajorFunc = DriverObject->MajorFunction[1];
236 ok(FirstMajorFunc != 0, "Expected MajorFunction[1] to be non NULL\n");
237
238 if (!skip(FirstMajorFunc != NULL, "First major function not set!\n"))
239 {
240 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
241 {
242 if (DriverStatus > 0) CheckThisDispatchRoutine = (i > 3) && (i != 14);
243 else CheckThisDispatchRoutine = TRUE;
244
245 if (CheckThisDispatchRoutine)
246 {
247 ok(DriverObject->MajorFunction[i] == FirstMajorFunc, "Expected MajorFunction[%d] to match %p\n",
248 i, FirstMajorFunc);
249 }
250 }
251 }
252 }
253
254 static
255 BOOLEAN
256 TestZwLoad(
257 IN PDRIVER_OBJECT DriverObject,
258 IN PCUNICODE_STRING DriverRegistryPath,
259 IN PWCHAR NewDriverRegPath)
260 {
261 UNICODE_STRING RegPath;
262 NTSTATUS Status;
263
264 /* Try to load ourself */
265 Status = ZwLoadDriver((PUNICODE_STRING)DriverRegistryPath);
266 ok (Status == STATUS_IMAGE_ALREADY_LOADED, "Expected NTSTATUS STATUS_IMAGE_ALREADY_LOADED, got 0x%lX\n", Status);
267
268 if (Status != STATUS_IMAGE_ALREADY_LOADED)
269 {
270 DbgPrint("WARNING: Loading this a second time will cause BUGCHECK!\n");
271 }
272
273 /* Try to load with a Registry Path that doesnt exist */
274 RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
275 Status = ZwLoadDriver(&RegPath);
276 ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX\n", Status);
277
278 /* Load the driver */
279 RtlInitUnicodeString(&RegPath, NewDriverRegPath);
280 Status = ZwLoadDriver(&RegPath);
281 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status);
282
283 return NT_SUCCESS(Status);
284 }
285
286 static
287 BOOLEAN
288 TestZwUnload(
289 IN PDRIVER_OBJECT DriverObject,
290 IN PCUNICODE_STRING DriverRegistryPath,
291 IN PWCHAR NewDriverRegPath)
292 {
293 UNICODE_STRING RegPath;
294 NTSTATUS Status;
295
296 /* Try to unload ourself, which should fail as our Unload routine hasnt been set yet. */
297 Status = ZwUnloadDriver((PUNICODE_STRING)DriverRegistryPath);
298 ok (Status == STATUS_INVALID_DEVICE_REQUEST, "Expected NTSTATUS STATUS_INVALID_DEVICE_REQUEST, got 0x%lX\n", Status);
299
300 /* Try to unload with a Registry Path that doesnt exist */
301 RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef");
302 Status = ZwUnloadDriver(&RegPath);
303 ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX\n", Status);
304
305 /* Unload the driver */
306 RtlInitUnicodeString(&RegPath, NewDriverRegPath);
307 Status = ZwUnloadDriver(&RegPath);
308 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status);
309
310 return NT_SUCCESS(Status);
311 }
312
313 static
314 VOID
315 TestLowerDeviceKernelAPI(
316 IN PDEVICE_OBJECT DeviceObject)
317 {
318 PDEVICE_OBJECT RetObject;
319
320 RetObject = IoGetLowerDeviceObject(DeviceObject);
321
322 ok(RetObject == AttachDeviceObject,
323 "Expected an Attached DeviceObject %p, got %p\n", AttachDeviceObject, RetObject);
324
325 if (RetObject)
326 {
327 ObDereferenceObject(RetObject);
328 }
329
330 RetObject = IoGetDeviceAttachmentBaseRef(DeviceObject);
331 ok(RetObject == AttachDeviceObject,
332 "Expected an Attached DeviceObject %p, got %p\n", AttachDeviceObject, RetObject);
333
334 if (RetObject)
335 {
336 ObDereferenceObject(RetObject);
337 }
338
339 }
340
341 static
342 VOID
343 TestDeviceCreated(
344 IN PDEVICE_OBJECT DeviceObject,
345 IN BOOLEAN ExclusiveAccess)
346 {
347 PEXTENDED_DEVOBJ_EXTENSION extdev;
348
349 /* Check the device object members */
350 ok(DeviceObject->Type == 3, "Expected Type = 3, got %x\n", DeviceObject->Type);
351 ok(DeviceObject->Size == 0xb8, "Expected Size = 0xb8, got %x\n", DeviceObject->Size);
352 ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu\n",
353 DeviceObject->ReferenceCount);
354 ok(DeviceObject->DriverObject == ThisDriverObject,
355 "Expected DriverObject member to match this DriverObject %p, got %p\n",
356 ThisDriverObject, DeviceObject->DriverObject);
357 ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p\n", DeviceObject->NextDevice);
358 ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p\n", DeviceObject->AttachedDevice);
359 ok(DeviceObject->Characteristics == 0, "Expected Characteristics to be 0\n");
360 if (ExclusiveAccess)
361 {
362 ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE)),
363 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING | DO_EXCLUSIVE, got %lu\n", DeviceObject->Flags);
364 }
365 else
366 {
367 ok((DeviceObject->Flags == (DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING)),
368 "Expected Flags DO_DEVICE_HAS_NAME | DO_DEVICE_INITIALIZING, got %lu\n", DeviceObject->Flags);
369 }
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);
374
375 /* Check the extended extension */
376 extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
377 ok(extdev->ExtensionFlags == 0, "Expected Extended ExtensionFlags to be 0, got %lu\n", extdev->ExtensionFlags);
378 ok (extdev->Type == 13, "Expected Type of 13, got %d\n", extdev->Type);
379 ok (extdev->Size == 0, "Expected Size of 0, got %d\n", extdev->Size);
380 ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p\n",
381 DeviceObject, extdev->DeviceObject);
382 ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p\n", extdev->AttachedTo);
383 ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu\n", extdev->StartIoCount);
384 ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu\n", extdev->StartIoKey);
385 ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu\n", extdev->StartIoFlags);
386 }
387
388 static
389 VOID
390 TestDeviceDeletion(
391 IN PDEVICE_OBJECT DeviceObject,
392 IN BOOLEAN Lower,
393 IN BOOLEAN Attached)
394 {
395 PEXTENDED_DEVOBJ_EXTENSION extdev;
396
397 /* Check the device object members */
398 ok(DeviceObject->Type == 3, "Expected Type = 3, got %d\n", DeviceObject->Type);
399 ok(DeviceObject->Size == 0xb8, "Expected Size = 0xb8, got %d\n", DeviceObject->Size);
400 ok(DeviceObject->ReferenceCount == 0, "Expected ReferenceCount = 0, got %lu\n",
401 DeviceObject->ReferenceCount);
402 if (!Lower)
403 {
404 ok(DeviceObject->DriverObject == ThisDriverObject,
405 "Expected DriverObject member to match this DriverObject %p, got %p\n",
406 ThisDriverObject, DeviceObject->DriverObject);
407 }
408 ok(DeviceObject->NextDevice == NULL, "Expected NextDevice to be NULL, got %p\n", DeviceObject->NextDevice);
409
410 if (Lower)
411 {
412 ok(DeviceObject->AttachedDevice == MainDeviceObject,
413 "Expected AttachDevice to be %p, got %p\n", MainDeviceObject, DeviceObject->AttachedDevice);
414 }
415 else
416 {
417 ok(DeviceObject->AttachedDevice == NULL, "Expected AttachDevice to be NULL, got %p\n", DeviceObject->AttachedDevice);
418 }
419
420 ok(DeviceObject->Flags == (DO_DEVICE_HAS_NAME | (Lower ? DO_EXCLUSIVE : 0)),
421 "Expected Flags DO_DEVICE_HAS_NAME, got %lu\n", DeviceObject->Flags);
422 ok(DeviceObject->DeviceType == FILE_DEVICE_UNKNOWN,
423 "Expected DeviceType to match creation parameter FILE_DEVICE_UNKNWOWN, got %lu\n",
424 DeviceObject->DeviceType);
425 ok(DeviceObject->ActiveThreadCount == 0, "Expected ActiveThreadCount = 0, got %lu\n", DeviceObject->ActiveThreadCount);
426
427 /*Check the extended extension */
428 extdev = (PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension;
429 ok(extdev->ExtensionFlags == DOE_UNLOAD_PENDING,
430 "Expected Extended ExtensionFlags to be DOE_UNLOAD_PENDING, got %lu\n", extdev->ExtensionFlags);
431 ok (extdev->Type == 13, "Expected Type of 13, got %d\n", extdev->Type);
432 ok (extdev->Size == 0, "Expected Size of 0, got %d\n", extdev->Size);
433 ok (extdev->DeviceObject == DeviceObject, "Expected DeviceOject to match newly created device %p, got %p\n",
434 DeviceObject, extdev->DeviceObject);
435 if (Lower || !Attached)
436 {
437 ok(extdev->AttachedTo == NULL, "Expected AttachTo to be NULL, got %p\n", extdev->AttachedTo);
438 }
439 else
440 {
441 ok(extdev->AttachedTo == AttachDeviceObject, "Expected AttachTo to %p, got %p\n", AttachDeviceObject, extdev->AttachedTo);
442 }
443 ok(extdev->StartIoCount == 0, "Expected StartIoCount = 0, got %lu\n", extdev->StartIoCount);
444 ok(extdev->StartIoKey == 0, "Expected StartIoKey = 0, got %lu\n", extdev->StartIoKey);
445 ok(extdev->StartIoFlags == 0, "Expected StartIoFlags = 0, got %lu\n", extdev->StartIoFlags);
446 }
447
448 static
449 VOID
450 TestDeviceCreateDelete(
451 IN PDRIVER_OBJECT DriverObject)
452 {
453 NTSTATUS Status;
454 UNICODE_STRING DeviceString;
455 PDEVICE_OBJECT DeviceObject;
456
457 /* Create using wrong directory */
458 RtlInitUnicodeString(&DeviceString, L"\\Device1\\Kmtest-IoDeviceObject");
459 Status = IoCreateDevice(DriverObject,
460 0,
461 &DeviceString,
462 FILE_DEVICE_UNKNOWN,
463 0,
464 FALSE,
465 &DeviceObject);
466 ok(Status == STATUS_OBJECT_PATH_NOT_FOUND, "Expected STATUS_OBJECT_PATH_NOT_FOUND, got 0x%lX\n", Status);
467
468 /* Create using correct params with exclusice access */
469 RtlInitUnicodeString(&DeviceString, L"\\Device\\Kmtest-IoDeviceObject");
470 Status = IoCreateDevice(DriverObject,
471 0,
472 &DeviceString,
473 FILE_DEVICE_UNKNOWN,
474 0,
475 TRUE,
476 &DeviceObject);
477 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status);
478
479 TestDeviceCreated(DeviceObject, TRUE);
480
481 /* Delete the device */
482 if (NT_SUCCESS(Status))
483 {
484 IoDeleteDevice(DeviceObject);
485 ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p\n",
486 DriverObject->DeviceObject);
487 }
488
489 /* Create using correct params without exclusice access */
490 Status = IoCreateDevice(DriverObject,
491 0,
492 &DeviceString,
493 FILE_DEVICE_UNKNOWN,
494 0,
495 FALSE,
496 &DeviceObject);
497 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status);
498
499 TestDeviceCreated(DeviceObject, FALSE);
500
501 /* Delete the device */
502 if (NT_SUCCESS(Status))
503 {
504 IoDeleteDevice(DeviceObject);
505 ok(DriverObject->DeviceObject == 0, "Expected DriverObject->DeviceObject to be NULL, got %p\n",
506 DriverObject->DeviceObject);
507 }
508
509 /* Recreate device */
510 Status = IoCreateDevice(DriverObject,
511 0,
512 &DeviceString,
513 FILE_DEVICE_UNKNOWN,
514 0,
515 FALSE,
516 &DeviceObject);
517 ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status);
518
519 if (NT_SUCCESS(Status))
520 MainDeviceObject = DeviceObject;
521 }
522
523 static
524 VOID
525 TestAttachDevice(
526 IN PDEVICE_OBJECT DeviceObject,
527 IN PWCHAR NewDriverRegPath)
528 {
529 NTSTATUS Status;
530 UNICODE_STRING LowerDeviceName;
531
532 RtlInitUnicodeString(&LowerDeviceName, NewDriverRegPath);
533 Status = IoAttachDevice(DeviceObject, &LowerDeviceName, &AttachDeviceObject);
534 ok_eq_hex(Status, STATUS_SUCCESS);
535
536 /* TODO: Add more tests */
537 }
538
539 static
540 VOID
541 TestDetachDevice(
542 IN PDEVICE_OBJECT AttachedDevice)
543 {
544 IoDetachDevice(AttachedDevice);
545
546 /* TODO: Add more tests */
547 }