dinput/tests: Add some windows.gaming.input device tests.
[wine.git] / dlls / ntoskrnl.exe / tests / driver_pnp.c
blobaa078ab0b2ff28b258959d7e0740377acc1e7ecd
1 /*
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
21 #include <stdarg.h>
22 #include <stdio.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winternl.h"
29 #include "winioctl.h"
30 #include "ddk/wdm.h"
32 #include "wine/list.h"
34 #include "driver.h"
35 #include "utils.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;
49 struct irp_queue
51 KSPIN_LOCK lock;
52 LIST_ENTRY list;
55 static IRP *irp_queue_pop(struct irp_queue *queue)
57 KIRQL irql;
58 IRP *irp;
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);
65 return irp;
68 static void irp_queue_push(struct irp_queue *queue, IRP *irp)
70 KIRQL irql;
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)
79 IRP *irp;
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);
94 struct device
96 struct list entry;
97 DEVICE_OBJECT *device_obj;
98 unsigned int id;
99 BOOL removed;
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);
112 NTSTATUS ret;
114 switch (stack->MinorFunction)
116 case IRP_MN_START_DEVICE:
117 irp->IoStatus.Status = IoSetDeviceInterfaceState(&control_symlink, TRUE);
118 break;
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;
124 break;
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);
135 return ret;
137 case IRP_MN_QUERY_DEVICE_RELATIONS:
139 DEVICE_RELATIONS *devices;
140 struct device *device;
141 unsigned int i = 0;
143 if (stack->Parameters.QueryDeviceRelations.Type == RemovalRelations)
144 break;
146 if (stack->Parameters.QueryDeviceRelations.Type != BusRelations)
148 ok(0, "Unexpected relations type %#x.\n", stack->Parameters.QueryDeviceRelations.Type);
149 break;
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;
159 break;
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);
170 devices->Count = i;
171 irp->IoStatus.Information = (ULONG_PTR)devices;
172 irp->IoStatus.Status = STATUS_SUCCESS;
173 break;
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";
184 WCHAR *id = NULL;
186 irp->IoStatus.Information = 0;
188 switch (type)
190 case BusQueryDeviceID:
191 if (!(id = ExAllocatePool(PagedPool, sizeof(device_id))))
192 return STATUS_NO_MEMORY;
193 wcscpy(id, device_id);
194 break;
196 case BusQueryInstanceID:
197 if (!(id = ExAllocatePool(PagedPool, 9 * sizeof(WCHAR))))
198 return STATUS_NO_MEMORY;
199 swprintf(id, 9, L"%x", device->id);
200 break;
202 case BusQueryHardwareIDs:
204 static const WCHAR hardware_id[] = L"winetest_hardware";
205 const size_t size = ARRAY_SIZE(hardware_id) + 27 + 1;
206 size_t len;
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;
214 break;
217 case BusQueryCompatibleIDs:
219 static const WCHAR compat_id[] = L"winetest_compat";
220 const size_t size = ARRAY_SIZE(compat_id) + 25 + 1;
221 size_t len;
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;
229 break;
232 case BusQueryContainerID:
233 return STATUS_NOT_SUPPORTED;
235 default:
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);
254 break;
256 case IRP_MN_START_DEVICE:
258 POWER_STATE state = {.DeviceState = PowerDeviceD0};
259 NTSTATUS status;
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;
275 break;
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);
287 if (device->removed)
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;
298 break;
300 case IRP_MN_QUERY_CAPABILITIES:
302 DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities;
303 unsigned int i;
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;
340 caps->UniqueID = 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;
350 break;
353 case IRP_MN_SURPRISE_REMOVAL:
354 surprise_removal_count++;
355 irp_queue_clear(&device->irp_queue);
356 ret = STATUS_SUCCESS;
357 break;
359 case IRP_MN_QUERY_REMOVE_DEVICE:
360 query_remove_device_count++;
361 irp_queue_clear(&device->irp_queue);
362 ret = STATUS_SUCCESS;
363 break;
365 case IRP_MN_CANCEL_REMOVE_DEVICE:
366 cancel_remove_device_count++;
367 ret = STATUS_SUCCESS;
368 break;
371 irp->IoStatus.Status = ret;
372 IoCompleteRequest(irp, IO_NO_INCREMENT);
373 return ret;
376 static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp)
378 if (device == bus_fdo)
379 return fdo_pnp(irp);
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);
408 return ret;
411 static void test_bus_query_caps(DEVICE_OBJECT *top_device)
413 DEVICE_CAPABILITIES caps;
414 IO_STACK_LOCATION *stack;
415 IO_STATUS_BLOCK io;
416 unsigned int i;
417 NTSTATUS ret;
418 KEVENT event;
419 IRP *irp;
421 memset(&caps, 0, sizeof(caps));
422 caps.Size = sizeof(caps);
423 caps.Version = 1;
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);
472 caps.Version = 1;
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;
523 IO_STATUS_BLOCK io;
524 NTSTATUS ret;
525 KEVENT event;
526 IRP *irp;
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)
568 switch (code)
570 case IOCTL_WINETEST_BUS_MAIN:
571 test_bus_query();
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;
590 NTSTATUS status;
591 WCHAR name[30];
592 int id;
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;
606 device->id = id;
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;
623 int id;
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;
636 break;
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;
649 default:
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;
659 switch (code)
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;
684 default:
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);
698 else
699 status = pdo_ioctl(device, irp, stack, code);
701 irp->IoStatus.Status = status;
702 if (status != STATUS_PENDING) IoCompleteRequest(irp, IO_NO_INCREMENT);
703 return status;
706 static NTSTATUS WINAPI driver_add_device(DRIVER_OBJECT *driver, DEVICE_OBJECT *pdo)
708 NTSTATUS ret;
710 if ((ret = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &bus_fdo)))
711 return ret;
713 if ((ret = IoRegisterDeviceInterface(pdo, &control_class, NULL, &control_symlink)))
715 IoDeleteDevice(bus_fdo);
716 return ret;
719 IoAttachDeviceToDeviceStack(bus_fdo, pdo);
720 bus_pdo = 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)
741 winetest_cleanup();
744 NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry)
746 NTSTATUS ret;
748 if ((ret = winetest_init()))
749 return ret;
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;
759 driver_obj = driver;
761 ExInitializeFastMutex(&driver_lock);
763 return STATUS_SUCCESS;