2 * ntoskrnl.exe testing framework
4 * Copyright 2020 Zebediah Figura
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
32 #include "wine/list.h"
37 static const GUID bus_class
= {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}};
38 static const GUID child_class
= {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}};
39 static UNICODE_STRING control_symlink
, bus_symlink
;
41 static DRIVER_OBJECT
*driver_obj
;
42 static DEVICE_OBJECT
*bus_fdo
, *bus_pdo
;
44 static DWORD remove_device_count
;
45 static DWORD surprise_removal_count
;
46 static DWORD query_remove_device_count
;
47 static DWORD cancel_remove_device_count
;
55 static IRP
*irp_queue_pop(struct irp_queue
*queue
)
60 KeAcquireSpinLock(&queue
->lock
, &irql
);
61 if (IsListEmpty(&queue
->list
)) irp
= NULL
;
62 else irp
= CONTAINING_RECORD(RemoveHeadList(&queue
->list
), IRP
, Tail
.Overlay
.ListEntry
);
63 KeReleaseSpinLock(&queue
->lock
, irql
);
68 static void irp_queue_push(struct irp_queue
*queue
, IRP
*irp
)
72 KeAcquireSpinLock(&queue
->lock
, &irql
);
73 InsertTailList(&queue
->list
, &irp
->Tail
.Overlay
.ListEntry
);
74 KeReleaseSpinLock(&queue
->lock
, irql
);
77 static void irp_queue_clear(struct irp_queue
*queue
)
81 while ((irp
= irp_queue_pop(queue
)))
83 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
84 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
88 static void irp_queue_init(struct irp_queue
*queue
)
90 KeInitializeSpinLock(&queue
->lock
);
91 InitializeListHead(&queue
->list
);
97 DEVICE_OBJECT
*device_obj
;
100 UNICODE_STRING child_symlink
;
101 DEVICE_POWER_STATE power_state
;
102 struct irp_queue irp_queue
;
105 static struct list device_list
= LIST_INIT(device_list
);
107 static FAST_MUTEX driver_lock
;
109 static NTSTATUS
fdo_pnp(IRP
*irp
)
111 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
114 switch (stack
->MinorFunction
)
116 case IRP_MN_START_DEVICE
:
117 irp
->IoStatus
.Status
= IoSetDeviceInterfaceState(&control_symlink
, TRUE
);
120 case IRP_MN_SURPRISE_REMOVAL
:
121 case IRP_MN_QUERY_REMOVE_DEVICE
:
122 case IRP_MN_STOP_DEVICE
:
123 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
126 case IRP_MN_REMOVE_DEVICE
:
127 IoSetDeviceInterfaceState(&control_symlink
, FALSE
);
128 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
129 IoSkipCurrentIrpStackLocation(irp
);
130 ret
= IoCallDriver(bus_pdo
, irp
);
131 IoDetachDevice(bus_pdo
);
132 IoDeleteDevice(bus_fdo
);
133 RtlFreeUnicodeString(&control_symlink
);
134 RtlFreeUnicodeString(&bus_symlink
);
137 case IRP_MN_QUERY_DEVICE_RELATIONS
:
139 DEVICE_RELATIONS
*devices
;
140 struct device
*device
;
143 if (stack
->Parameters
.QueryDeviceRelations
.Type
== RemovalRelations
)
146 if (stack
->Parameters
.QueryDeviceRelations
.Type
!= BusRelations
)
148 ok(0, "Unexpected relations type %#x.\n", stack
->Parameters
.QueryDeviceRelations
.Type
);
152 ExAcquireFastMutex(&driver_lock
);
154 if (!(devices
= ExAllocatePool(PagedPool
,
155 offsetof(DEVICE_RELATIONS
, Objects
[list_count(&device_list
)]))))
157 ExReleaseFastMutex(&driver_lock
);
158 irp
->IoStatus
.Status
= STATUS_NO_MEMORY
;
162 LIST_FOR_EACH_ENTRY(device
, &device_list
, struct device
, entry
)
164 devices
->Objects
[i
++] = device
->device_obj
;
165 ObfReferenceObject(device
->device_obj
);
168 ExReleaseFastMutex(&driver_lock
);
171 irp
->IoStatus
.Information
= (ULONG_PTR
)devices
;
172 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
177 IoSkipCurrentIrpStackLocation(irp
);
178 return IoCallDriver(bus_pdo
, irp
);
181 static NTSTATUS
query_id(struct device
*device
, IRP
*irp
, BUS_QUERY_ID_TYPE type
)
183 static const WCHAR device_id
[] = L
"wine\\test";
186 irp
->IoStatus
.Information
= 0;
190 case BusQueryDeviceID
:
191 if (!(id
= ExAllocatePool(PagedPool
, sizeof(device_id
))))
192 return STATUS_NO_MEMORY
;
193 wcscpy(id
, device_id
);
196 case BusQueryInstanceID
:
197 if (!(id
= ExAllocatePool(PagedPool
, 9 * sizeof(WCHAR
))))
198 return STATUS_NO_MEMORY
;
199 swprintf(id
, 9, L
"%x", device
->id
);
202 case BusQueryHardwareIDs
:
204 static const WCHAR hardware_id
[] = L
"winetest_hardware";
205 const size_t size
= ARRAY_SIZE(hardware_id
) + 27 + 1;
208 if (!(id
= ExAllocatePool(PagedPool
, size
* sizeof(WCHAR
))))
209 return STATUS_NO_MEMORY
;
210 wcscpy(id
, hardware_id
);
211 len
= swprintf(id
+ ARRAY_SIZE(hardware_id
), size
- ARRAY_SIZE(hardware_id
),
212 L
"winetest_hardware_%x", device
->id
);
213 id
[ARRAY_SIZE(hardware_id
) + len
+ 1] = 0;
217 case BusQueryCompatibleIDs
:
219 static const WCHAR compat_id
[] = L
"winetest_compat";
220 const size_t size
= ARRAY_SIZE(compat_id
) + 25 + 1;
223 if (!(id
= ExAllocatePool(PagedPool
, size
* sizeof(WCHAR
))))
224 return STATUS_NO_MEMORY
;
225 wcscpy(id
, compat_id
);
226 len
= swprintf(id
+ ARRAY_SIZE(compat_id
), size
- ARRAY_SIZE(compat_id
),
227 L
"winetest_compat_%x", device
->id
);
228 id
[ARRAY_SIZE(compat_id
) + len
+ 1] = 0;
232 case BusQueryContainerID
:
233 return STATUS_NOT_SUPPORTED
;
236 ok(0, "Unexpected ID query type %#x.\n", type
);
237 return irp
->IoStatus
.Status
;
240 irp
->IoStatus
.Information
= (ULONG_PTR
)id
;
241 return STATUS_SUCCESS
;
244 static NTSTATUS
pdo_pnp(DEVICE_OBJECT
*device_obj
, IRP
*irp
)
246 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
247 struct device
*device
= device_obj
->DeviceExtension
;
248 NTSTATUS ret
= irp
->IoStatus
.Status
;
250 switch (stack
->MinorFunction
)
252 case IRP_MN_QUERY_ID
:
253 ret
= query_id(device
, irp
, stack
->Parameters
.QueryId
.IdType
);
256 case IRP_MN_START_DEVICE
:
258 POWER_STATE state
= {.DeviceState
= PowerDeviceD0
};
261 irp_queue_init(&device
->irp_queue
);
263 ok(!stack
->Parameters
.StartDevice
.AllocatedResources
, "expected no resources\n");
264 ok(!stack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
, "expected no translated resources\n");
266 status
= IoRegisterDeviceInterface(device_obj
, &child_class
, NULL
, &device
->child_symlink
);
267 ok(!status
, "Failed to register interface, status %#x.\n", status
);
269 IoSetDeviceInterfaceState(&device
->child_symlink
, TRUE
);
271 state
= PoSetPowerState(device_obj
, DevicePowerState
, state
);
272 todo_wine
ok(state
.DeviceState
== device
->power_state
, "got previous state %u\n", state
.DeviceState
);
273 device
->power_state
= PowerDeviceD0
;
274 ret
= STATUS_SUCCESS
;
278 case IRP_MN_REMOVE_DEVICE
:
279 /* should've been checked and reset by IOCTL_WINETEST_CHILD_CHECK_REMOVED */
280 ok(remove_device_count
== 0, "expected no IRP_MN_REMOVE_DEVICE\n");
281 todo_wine
ok(surprise_removal_count
== 0, "expected no IRP_MN_SURPRISE_REMOVAL\n");
282 ok(query_remove_device_count
== 0, "expected no IRP_MN_QUERY_REMOVE_DEVICE\n");
283 ok(cancel_remove_device_count
== 0, "expected no IRP_MN_CANCEL_REMOVE_DEVICE\n");
285 remove_device_count
++;
286 irp_queue_clear(&device
->irp_queue
);
289 IoSetDeviceInterfaceState(&device
->child_symlink
, FALSE
);
290 RtlFreeUnicodeString(&device
->child_symlink
);
291 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
292 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
293 IoDeleteDevice(device
->device_obj
);
294 return STATUS_SUCCESS
;
297 ret
= STATUS_SUCCESS
;
300 case IRP_MN_QUERY_CAPABILITIES
:
302 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
305 ok(caps
->Size
== sizeof(*caps
), "wrong size %u\n", caps
->Size
);
306 ok(caps
->Version
== 1, "wrong version %u\n", caps
->Version
);
307 ok(!caps
->DeviceD1
, "got DeviceD1 %u\n", caps
->DeviceD1
);
308 ok(!caps
->DeviceD2
, "got DeviceD2 %u\n", caps
->DeviceD2
);
309 ok(!caps
->LockSupported
, "got LockSupported %u\n", caps
->LockSupported
);
310 ok(!caps
->EjectSupported
, "got EjectSupported %u\n", caps
->EjectSupported
);
311 ok(!caps
->Removable
, "got Removable %u\n", caps
->Removable
);
312 ok(!caps
->DockDevice
, "got DockDevice %u\n", caps
->DockDevice
);
313 ok(!caps
->UniqueID
, "got UniqueID %u\n", caps
->UniqueID
);
314 ok(!caps
->SilentInstall
, "got SilentInstall %u\n", caps
->SilentInstall
);
315 ok(!caps
->RawDeviceOK
, "got RawDeviceOK %u\n", caps
->RawDeviceOK
);
316 ok(!caps
->SurpriseRemovalOK
, "got SurpriseRemovalOK %u\n", caps
->SurpriseRemovalOK
);
317 ok(!caps
->WakeFromD0
, "got WakeFromD0 %u\n", caps
->WakeFromD0
);
318 ok(!caps
->WakeFromD1
, "got WakeFromD1 %u\n", caps
->WakeFromD1
);
319 ok(!caps
->WakeFromD2
, "got WakeFromD2 %u\n", caps
->WakeFromD2
);
320 ok(!caps
->WakeFromD3
, "got WakeFromD3 %u\n", caps
->WakeFromD3
);
321 ok(!caps
->HardwareDisabled
, "got HardwareDisabled %u\n", caps
->HardwareDisabled
);
322 ok(!caps
->NonDynamic
, "got NonDynamic %u\n", caps
->NonDynamic
);
323 ok(!caps
->WarmEjectSupported
, "got WarmEjectSupported %u\n", caps
->WarmEjectSupported
);
324 ok(!caps
->NoDisplayInUI
, "got NoDisplayInUI %u\n", caps
->NoDisplayInUI
);
325 ok(caps
->Address
== 0xffffffff, "got Address %#x\n", caps
->Address
);
326 ok(caps
->UINumber
== 0xffffffff, "got UINumber %#x\n", caps
->UINumber
);
327 for (i
= 0; i
< PowerSystemMaximum
; ++i
)
328 ok(caps
->DeviceState
[i
] == PowerDeviceUnspecified
, "got DeviceState[%u] %u\n", i
, caps
->DeviceState
[i
]);
329 ok(caps
->SystemWake
== PowerSystemUnspecified
, "got SystemWake %u\n", caps
->SystemWake
);
330 ok(caps
->DeviceWake
== PowerDeviceUnspecified
, "got DeviceWake %u\n", caps
->DeviceWake
);
331 ok(!caps
->D1Latency
, "got D1Latency %u\n", caps
->D1Latency
);
332 ok(!caps
->D2Latency
, "got D2Latency %u\n", caps
->D2Latency
);
333 ok(!caps
->D3Latency
, "got D3Latency %u\n", caps
->D3Latency
);
335 /* If caps->RawDeviceOK is not set, we won't receive
336 * IRP_MN_START_DEVICE unless there's a function driver. */
337 caps
->RawDeviceOK
= 1;
338 caps
->SurpriseRemovalOK
= 1;
339 caps
->EjectSupported
= 1;
342 caps
->DeviceState
[PowerSystemWorking
] = PowerDeviceD0
;
343 caps
->DeviceState
[PowerSystemSleeping1
] = PowerDeviceD3
;
344 caps
->DeviceState
[PowerSystemSleeping2
] = PowerDeviceD3
;
345 caps
->DeviceState
[PowerSystemSleeping3
] = PowerDeviceD3
;
346 caps
->DeviceState
[PowerSystemHibernate
] = PowerDeviceD3
;
347 caps
->DeviceState
[PowerSystemShutdown
] = PowerDeviceD3
;
349 ret
= STATUS_SUCCESS
;
353 case IRP_MN_SURPRISE_REMOVAL
:
354 surprise_removal_count
++;
355 irp_queue_clear(&device
->irp_queue
);
356 ret
= STATUS_SUCCESS
;
359 case IRP_MN_QUERY_REMOVE_DEVICE
:
360 query_remove_device_count
++;
361 irp_queue_clear(&device
->irp_queue
);
362 ret
= STATUS_SUCCESS
;
365 case IRP_MN_CANCEL_REMOVE_DEVICE
:
366 cancel_remove_device_count
++;
367 ret
= STATUS_SUCCESS
;
371 irp
->IoStatus
.Status
= ret
;
372 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
376 static NTSTATUS WINAPI
driver_pnp(DEVICE_OBJECT
*device
, IRP
*irp
)
378 if (device
== bus_fdo
)
380 return pdo_pnp(device
, irp
);
383 static NTSTATUS WINAPI
driver_power(DEVICE_OBJECT
*device
, IRP
*irp
)
385 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
386 NTSTATUS ret
= STATUS_NOT_SUPPORTED
;
388 /* We do not expect power IRPs as part of normal operation. */
389 ok(0, "unexpected call\n");
391 if (device
== bus_fdo
)
393 PoStartNextPowerIrp(irp
);
394 IoSkipCurrentIrpStackLocation(irp
);
395 return PoCallDriver(bus_pdo
, irp
);
398 if (stack
->MinorFunction
== IRP_MN_SET_POWER
)
400 if (stack
->Parameters
.Power
.Type
== DevicePowerState
)
401 PoSetPowerState(device
, DevicePowerState
, stack
->Parameters
.Power
.State
);
402 ret
= STATUS_SUCCESS
;
405 PoStartNextPowerIrp(irp
);
406 irp
->IoStatus
.Status
= ret
;
407 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
411 static void test_bus_query_caps(DEVICE_OBJECT
*top_device
)
413 DEVICE_CAPABILITIES caps
;
414 IO_STACK_LOCATION
*stack
;
421 memset(&caps
, 0, sizeof(caps
));
422 caps
.Size
= sizeof(caps
);
425 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
427 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
, top_device
, NULL
, 0, NULL
, &event
, &io
);
428 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
429 stack
= IoGetNextIrpStackLocation(irp
);
430 stack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
431 stack
->Parameters
.DeviceCapabilities
.Capabilities
= &caps
;
432 ret
= IoCallDriver(top_device
, irp
);
433 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
434 ok(io
.Status
== STATUS_SUCCESS
, "got %#x\n", ret
);
436 ok(caps
.Size
== sizeof(caps
), "wrong size %u\n", caps
.Size
);
437 ok(caps
.Version
== 1, "wrong version %u\n", caps
.Version
);
438 ok(!caps
.DeviceD1
, "got DeviceD1 %u\n", caps
.DeviceD1
);
439 ok(!caps
.DeviceD2
, "got DeviceD2 %u\n", caps
.DeviceD2
);
440 ok(!caps
.LockSupported
, "got LockSupported %u\n", caps
.LockSupported
);
441 ok(!caps
.EjectSupported
, "got EjectSupported %u\n", caps
.EjectSupported
);
442 ok(!caps
.Removable
, "got Removable %u\n", caps
.Removable
);
443 ok(!caps
.DockDevice
, "got DockDevice %u\n", caps
.DockDevice
);
444 ok(!caps
.UniqueID
, "got UniqueID %u\n", caps
.UniqueID
);
445 ok(!caps
.SilentInstall
, "got SilentInstall %u\n", caps
.SilentInstall
);
446 ok(!caps
.RawDeviceOK
, "got RawDeviceOK %u\n", caps
.RawDeviceOK
);
447 ok(!caps
.SurpriseRemovalOK
, "got SurpriseRemovalOK %u\n", caps
.SurpriseRemovalOK
);
448 ok(!caps
.WakeFromD0
, "got WakeFromD0 %u\n", caps
.WakeFromD0
);
449 ok(!caps
.WakeFromD1
, "got WakeFromD1 %u\n", caps
.WakeFromD1
);
450 ok(!caps
.WakeFromD2
, "got WakeFromD2 %u\n", caps
.WakeFromD2
);
451 ok(!caps
.WakeFromD3
, "got WakeFromD3 %u\n", caps
.WakeFromD3
);
452 ok(!caps
.HardwareDisabled
, "got HardwareDisabled %u\n", caps
.HardwareDisabled
);
453 ok(!caps
.NonDynamic
, "got NonDynamic %u\n", caps
.NonDynamic
);
454 ok(!caps
.WarmEjectSupported
, "got WarmEjectSupported %u\n", caps
.WarmEjectSupported
);
455 ok(!caps
.NoDisplayInUI
, "got NoDisplayInUI %u\n", caps
.NoDisplayInUI
);
456 ok(!caps
.Address
, "got Address %#x\n", caps
.Address
);
457 ok(!caps
.UINumber
, "got UINumber %#x\n", caps
.UINumber
);
458 ok(caps
.DeviceState
[PowerSystemUnspecified
] == PowerDeviceUnspecified
,
459 "got DeviceState[PowerSystemUnspecified] %u\n", caps
.DeviceState
[PowerSystemUnspecified
]);
460 todo_wine
ok(caps
.DeviceState
[PowerSystemWorking
] == PowerDeviceD0
,
461 "got DeviceState[PowerSystemWorking] %u\n", caps
.DeviceState
[PowerSystemWorking
]);
462 for (i
= PowerSystemSleeping1
; i
< PowerSystemMaximum
; ++i
)
463 todo_wine
ok(caps
.DeviceState
[i
] == PowerDeviceD3
, "got DeviceState[%u] %u\n", i
, caps
.DeviceState
[i
]);
464 ok(caps
.SystemWake
== PowerSystemUnspecified
, "got SystemWake %u\n", caps
.SystemWake
);
465 ok(caps
.DeviceWake
== PowerDeviceUnspecified
, "got DeviceWake %u\n", caps
.DeviceWake
);
466 ok(!caps
.D1Latency
, "got D1Latency %u\n", caps
.D1Latency
);
467 ok(!caps
.D2Latency
, "got D2Latency %u\n", caps
.D2Latency
);
468 ok(!caps
.D3Latency
, "got D3Latency %u\n", caps
.D3Latency
);
470 memset(&caps
, 0xff, sizeof(caps
));
471 caps
.Size
= sizeof(caps
);
474 KeClearEvent(&event
);
476 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
, top_device
, NULL
, 0, NULL
, &event
, &io
);
477 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
478 stack
= IoGetNextIrpStackLocation(irp
);
479 stack
->MinorFunction
= IRP_MN_QUERY_CAPABILITIES
;
480 stack
->Parameters
.DeviceCapabilities
.Capabilities
= &caps
;
481 ret
= IoCallDriver(top_device
, irp
);
482 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
483 ok(io
.Status
== STATUS_SUCCESS
, "got %#x\n", ret
);
485 ok(caps
.Size
== sizeof(caps
), "wrong size %u\n", caps
.Size
);
486 ok(caps
.Version
== 1, "wrong version %u\n", caps
.Version
);
487 ok(caps
.DeviceD1
, "got DeviceD1 %u\n", caps
.DeviceD1
);
488 ok(caps
.DeviceD2
, "got DeviceD2 %u\n", caps
.DeviceD2
);
489 ok(caps
.LockSupported
, "got LockSupported %u\n", caps
.LockSupported
);
490 ok(caps
.EjectSupported
, "got EjectSupported %u\n", caps
.EjectSupported
);
491 ok(caps
.Removable
, "got Removable %u\n", caps
.Removable
);
492 ok(caps
.DockDevice
, "got DockDevice %u\n", caps
.DockDevice
);
493 ok(caps
.UniqueID
, "got UniqueID %u\n", caps
.UniqueID
);
494 ok(caps
.SilentInstall
, "got SilentInstall %u\n", caps
.SilentInstall
);
495 ok(caps
.RawDeviceOK
, "got RawDeviceOK %u\n", caps
.RawDeviceOK
);
496 ok(caps
.SurpriseRemovalOK
, "got SurpriseRemovalOK %u\n", caps
.SurpriseRemovalOK
);
497 ok(caps
.WakeFromD0
, "got WakeFromD0 %u\n", caps
.WakeFromD0
);
498 ok(caps
.WakeFromD1
, "got WakeFromD1 %u\n", caps
.WakeFromD1
);
499 ok(caps
.WakeFromD2
, "got WakeFromD2 %u\n", caps
.WakeFromD2
);
500 ok(caps
.WakeFromD3
, "got WakeFromD3 %u\n", caps
.WakeFromD3
);
501 ok(caps
.HardwareDisabled
, "got HardwareDisabled %u\n", caps
.HardwareDisabled
);
502 ok(caps
.NonDynamic
, "got NonDynamic %u\n", caps
.NonDynamic
);
503 ok(caps
.WarmEjectSupported
, "got WarmEjectSupported %u\n", caps
.WarmEjectSupported
);
504 ok(caps
.NoDisplayInUI
, "got NoDisplayInUI %u\n", caps
.NoDisplayInUI
);
505 ok(caps
.Address
== 0xffffffff, "got Address %#x\n", caps
.Address
);
506 ok(caps
.UINumber
== 0xffffffff, "got UINumber %#x\n", caps
.UINumber
);
507 todo_wine
ok(caps
.DeviceState
[PowerSystemUnspecified
] == PowerDeviceUnspecified
,
508 "got DeviceState[PowerSystemUnspecified] %u\n", caps
.DeviceState
[PowerSystemUnspecified
]);
509 todo_wine
ok(caps
.DeviceState
[PowerSystemWorking
] == PowerDeviceD0
,
510 "got DeviceState[PowerSystemWorking] %u\n", caps
.DeviceState
[PowerSystemWorking
]);
511 for (i
= PowerSystemSleeping1
; i
< PowerSystemMaximum
; ++i
)
512 todo_wine
ok(caps
.DeviceState
[i
] == PowerDeviceD3
, "got DeviceState[%u] %u\n", i
, caps
.DeviceState
[i
]);
513 ok(caps
.SystemWake
== 0xffffffff, "got SystemWake %u\n", caps
.SystemWake
);
514 ok(caps
.DeviceWake
== 0xffffffff, "got DeviceWake %u\n", caps
.DeviceWake
);
515 ok(caps
.D1Latency
== 0xffffffff, "got D1Latency %u\n", caps
.D1Latency
);
516 ok(caps
.D2Latency
== 0xffffffff, "got D2Latency %u\n", caps
.D2Latency
);
517 ok(caps
.D3Latency
== 0xffffffff, "got D3Latency %u\n", caps
.D3Latency
);
520 static void test_bus_query_id(DEVICE_OBJECT
*top_device
)
522 IO_STACK_LOCATION
*stack
;
528 KeInitializeEvent(&event
, NotificationEvent
, FALSE
);
530 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
, top_device
, NULL
, 0, NULL
, &event
, &io
);
531 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
532 stack
= IoGetNextIrpStackLocation(irp
);
533 stack
->MinorFunction
= IRP_MN_QUERY_ID
;
534 stack
->Parameters
.QueryId
.IdType
= BusQueryDeviceID
;
535 ret
= IoCallDriver(top_device
, irp
);
536 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
537 ok(io
.Status
== STATUS_SUCCESS
, "got %#x\n", ret
);
538 ok(!wcscmp((WCHAR
*)io
.Information
, L
"ROOT\\WINETEST"), "got id '%ls'\n", (WCHAR
*)io
.Information
);
539 ExFreePool((WCHAR
*)io
.Information
);
541 irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
, top_device
, NULL
, 0, NULL
, &event
, &io
);
542 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
543 stack
= IoGetNextIrpStackLocation(irp
);
544 stack
->MinorFunction
= IRP_MN_QUERY_ID
;
545 stack
->Parameters
.QueryId
.IdType
= BusQueryInstanceID
;
546 ret
= IoCallDriver(top_device
, irp
);
547 ok(ret
== STATUS_SUCCESS
, "got %#x\n", ret
);
548 ok(io
.Status
== STATUS_SUCCESS
, "got %#x\n", ret
);
549 ok(!wcscmp((WCHAR
*)io
.Information
, L
"0"), "got id '%ls'\n", (WCHAR
*)io
.Information
);
550 ExFreePool((WCHAR
*)io
.Information
);
553 static void test_bus_query(void)
555 DEVICE_OBJECT
*top_device
;
557 top_device
= IoGetAttachedDeviceReference(bus_pdo
);
558 ok(top_device
== bus_fdo
, "wrong top device\n");
560 test_bus_query_caps(top_device
);
561 test_bus_query_id(top_device
);
563 ObDereferenceObject(top_device
);
566 static NTSTATUS
fdo_ioctl(IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG code
)
570 case IOCTL_WINETEST_BUS_MAIN
:
572 return STATUS_SUCCESS
;
574 case IOCTL_WINETEST_BUS_REGISTER_IFACE
:
575 return IoRegisterDeviceInterface(bus_pdo
, &bus_class
, NULL
, &bus_symlink
);
577 case IOCTL_WINETEST_BUS_ENABLE_IFACE
:
578 IoSetDeviceInterfaceState(&bus_symlink
, TRUE
);
579 return STATUS_SUCCESS
;
581 case IOCTL_WINETEST_BUS_DISABLE_IFACE
:
582 IoSetDeviceInterfaceState(&bus_symlink
, FALSE
);
583 return STATUS_SUCCESS
;
585 case IOCTL_WINETEST_BUS_ADD_CHILD
:
587 DEVICE_OBJECT
*device_obj
;
588 UNICODE_STRING string
;
589 struct device
*device
;
594 if (stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(int))
595 return STATUS_BUFFER_TOO_SMALL
;
596 id
= *(int *)irp
->AssociatedIrp
.SystemBuffer
;
598 swprintf(name
, ARRAY_SIZE(name
), L
"\\Device\\winetest_pnp_%x", id
);
599 RtlInitUnicodeString(&string
, name
);
600 status
= IoCreateDevice(driver_obj
, sizeof(*device
), &string
, FILE_DEVICE_UNKNOWN
, 0, FALSE
, &device_obj
);
601 ok(!status
, "Failed to create device, status %#x.\n", status
);
603 device
= device_obj
->DeviceExtension
;
604 memset(device
, 0, sizeof(*device
));
605 device
->device_obj
= device_obj
;
607 device
->removed
= FALSE
;
609 ExAcquireFastMutex(&driver_lock
);
610 list_add_tail(&device_list
, &device
->entry
);
611 ExReleaseFastMutex(&driver_lock
);
613 device_obj
->Flags
&= ~DO_DEVICE_INITIALIZING
;
615 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
617 return STATUS_SUCCESS
;
620 case IOCTL_WINETEST_BUS_REMOVE_CHILD
:
622 struct device
*device
;
625 if (stack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(int))
626 return STATUS_BUFFER_TOO_SMALL
;
627 id
= *(int *)irp
->AssociatedIrp
.SystemBuffer
;
629 ExAcquireFastMutex(&driver_lock
);
630 LIST_FOR_EACH_ENTRY(device
, &device_list
, struct device
, entry
)
632 if (device
->id
== id
)
634 list_remove(&device
->entry
);
635 device
->removed
= TRUE
;
639 ExReleaseFastMutex(&driver_lock
);
641 IoInvalidateDeviceRelations(bus_pdo
, BusRelations
);
643 /* The actual removal might be asynchronous; we can't test that the
644 * device is gone here. */
646 return STATUS_SUCCESS
;
650 ok(0, "Unexpected ioctl %#x.\n", code
);
651 return STATUS_NOT_IMPLEMENTED
;
655 static NTSTATUS
pdo_ioctl(DEVICE_OBJECT
*device_obj
, IRP
*irp
, IO_STACK_LOCATION
*stack
, ULONG code
)
657 struct device
*device
= device_obj
->DeviceExtension
;
661 case IOCTL_WINETEST_CHILD_GET_ID
:
662 if (stack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(int))
663 return STATUS_BUFFER_TOO_SMALL
;
664 *(int *)irp
->AssociatedIrp
.SystemBuffer
= device
->id
;
665 irp
->IoStatus
.Information
= sizeof(device
->id
);
666 return STATUS_SUCCESS
;
668 case IOCTL_WINETEST_CHILD_MARK_PENDING
:
669 IoMarkIrpPending(irp
);
670 irp_queue_push(&device
->irp_queue
, irp
);
671 return STATUS_PENDING
;
673 case IOCTL_WINETEST_CHILD_CHECK_REMOVED
:
674 ok(remove_device_count
== 0, "expected IRP_MN_REMOVE_DEVICE\n");
675 ok(surprise_removal_count
== 1, "expected IRP_MN_SURPRISE_REMOVAL\n");
676 ok(query_remove_device_count
== 0, "expected no IRP_MN_QUERY_REMOVE_DEVICE\n");
677 ok(cancel_remove_device_count
== 0, "expected no IRP_MN_CANCEL_REMOVE_DEVICE\n");
678 remove_device_count
= 0;
679 surprise_removal_count
= 0;
680 query_remove_device_count
= 0;
681 cancel_remove_device_count
= 0;
682 return STATUS_SUCCESS
;
685 ok(0, "Unexpected ioctl %#x.\n", code
);
686 return STATUS_NOT_IMPLEMENTED
;
690 static NTSTATUS WINAPI
driver_ioctl(DEVICE_OBJECT
*device
, IRP
*irp
)
692 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation(irp
);
693 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
694 NTSTATUS status
= STATUS_NOT_IMPLEMENTED
;
696 if (device
== bus_fdo
)
697 status
= fdo_ioctl(irp
, stack
, code
);
699 status
= pdo_ioctl(device
, irp
, stack
, code
);
701 irp
->IoStatus
.Status
= status
;
702 if (status
!= STATUS_PENDING
) IoCompleteRequest(irp
, IO_NO_INCREMENT
);
706 static NTSTATUS WINAPI
driver_add_device(DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*pdo
)
710 if ((ret
= IoCreateDevice(driver
, 0, NULL
, FILE_DEVICE_BUS_EXTENDER
, 0, FALSE
, &bus_fdo
)))
713 if ((ret
= IoRegisterDeviceInterface(pdo
, &control_class
, NULL
, &control_symlink
)))
715 IoDeleteDevice(bus_fdo
);
719 IoAttachDeviceToDeviceStack(bus_fdo
, pdo
);
721 bus_fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
722 return STATUS_SUCCESS
;
725 static NTSTATUS WINAPI
driver_create(DEVICE_OBJECT
*device
, IRP
*irp
)
727 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
728 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
729 return STATUS_SUCCESS
;
732 static NTSTATUS WINAPI
driver_close(DEVICE_OBJECT
*device
, IRP
*irp
)
734 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
735 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
736 return STATUS_SUCCESS
;
739 static void WINAPI
driver_unload(DRIVER_OBJECT
*driver
)
744 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry
)
748 if ((ret
= winetest_init()))
751 driver
->DriverExtension
->AddDevice
= driver_add_device
;
752 driver
->DriverUnload
= driver_unload
;
753 driver
->MajorFunction
[IRP_MJ_PNP
] = driver_pnp
;
754 driver
->MajorFunction
[IRP_MJ_POWER
] = driver_power
;
755 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_ioctl
;
756 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_create
;
757 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_close
;
761 ExInitializeFastMutex(&driver_lock
);
763 return STATUS_SUCCESS
;