Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/tests/driver_pnp.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index b8d97f9cfb5..ecaaf9afdbc 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -50,6 +50,8 @@ static NTSTATUS fdo_pnp(IRP *irp) break;
case IRP_MN_SURPRISE_REMOVAL: + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_STOP_DEVICE: irp->IoStatus.Status = STATUS_SUCCESS; break;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/hidclass.sys/pnp.c | 4 +- dlls/ntoskrnl.exe/tests/Makefile.in | 2 +- dlls/ntoskrnl.exe/tests/driver.h | 4 + dlls/ntoskrnl.exe/tests/driver_pnp.c | 295 +++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 106 +++++++++- include/cfgmgr32.h | 12 ++ include/ddk/wdm.h | 5 +- 7 files changed, 423 insertions(+), 5 deletions(-)
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index a499aec93bb..5a4ebf8b42b 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -261,8 +261,10 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) irp->IoStatus.Information = (ULONG_PTR)id; rc = STATUS_SUCCESS; break; + + case BusQueryContainerID: case BusQueryDeviceSerialNumber: - FIXME("BusQueryDeviceSerialNumber not implemented\n"); + FIXME("unimplemented id type %#x\n", irpsp->Parameters.QueryId.IdType); ExFreePool(id); break; } diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in index d911879ff99..937cc3121fa 100644 --- a/dlls/ntoskrnl.exe/tests/Makefile.in +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -9,7 +9,7 @@ driver3_IMPORTS = winecrt0 ntoskrnl driver3_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native driver_netio_IMPORTS = winecrt0 ntoskrnl netio driver_netio_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native -driver_pnp_IMPORTS = winecrt0 ntoskrnl +driver_pnp_IMPORTS = winecrt0 ntoskrnl hal driver_pnp_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
SOURCES = \ diff --git a/dlls/ntoskrnl.exe/tests/driver.h b/dlls/ntoskrnl.exe/tests/driver.h index 10e2f13ed7b..a79ee8c42de 100644 --- a/dlls/ntoskrnl.exe/tests/driver.h +++ b/dlls/ntoskrnl.exe/tests/driver.h @@ -40,6 +40,10 @@ #define IOCTL_WINETEST_BUS_REGISTER_IFACE CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_BUS_ENABLE_IFACE CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINETEST_BUS_DISABLE_IFACE CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_BUS_ADD_CHILD CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_BUS_REMOVE_CHILD CTL_CODE(FILE_DEVICE_BUS_EXTENDER, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define IOCTL_WINETEST_CHILD_GET_ID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
static const char teststr[] = "Wine is not an emulator";
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index ecaaf9afdbc..2b3968fe395 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -29,15 +29,33 @@ #include "winioctl.h" #include "ddk/wdm.h"
+#include "wine/list.h" + #include "driver.h" #include "utils.h"
static const GUID control_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc0}}; static const GUID bus_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}}; +static const GUID child_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}}; static UNICODE_STRING control_symlink, bus_symlink;
+static DRIVER_OBJECT *driver_obj; static DEVICE_OBJECT *bus_fdo, *bus_pdo;
+struct device +{ + struct list entry; + DEVICE_OBJECT *device_obj; + unsigned int id; + BOOL removed; + UNICODE_STRING child_symlink; + DEVICE_POWER_STATE power_state; +}; + +static struct list device_list = LIST_INIT(device_list); + +static FAST_MUTEX driver_lock; + static NTSTATUS fdo_pnp(IRP *irp) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); @@ -65,24 +83,213 @@ static NTSTATUS fdo_pnp(IRP *irp) RtlFreeUnicodeString(&control_symlink); RtlFreeUnicodeString(&bus_symlink); return ret; + + case IRP_MN_QUERY_DEVICE_RELATIONS: + { + DEVICE_RELATIONS *devices; + struct device *device; + unsigned int i = 0; + + if (stack->Parameters.QueryDeviceRelations.Type == RemovalRelations) + break; + + if (stack->Parameters.QueryDeviceRelations.Type != BusRelations) + { + ok(0, "Unexpected relations type %#x.\n", stack->Parameters.QueryDeviceRelations.Type); + break; + } + + ExAcquireFastMutex(&driver_lock); + + if (!(devices = ExAllocatePool(PagedPool, + offsetof(DEVICE_RELATIONS, Objects[list_count(&device_list)])))) + { + ExReleaseFastMutex(&driver_lock); + irp->IoStatus.Status = STATUS_NO_MEMORY; + break; + } + + LIST_FOR_EACH_ENTRY(device, &device_list, struct device, entry) + { + devices->Objects[i++] = device->device_obj; + ObfReferenceObject(device->device_obj); + } + + ExReleaseFastMutex(&driver_lock); + + devices->Count = i; + irp->IoStatus.Information = (ULONG_PTR)devices; + irp->IoStatus.Status = STATUS_SUCCESS; + break; + } }
IoSkipCurrentIrpStackLocation(irp); return IoCallDriver(bus_pdo, irp); }
+static NTSTATUS query_id(struct device *device, IRP *irp, BUS_QUERY_ID_TYPE type) +{ + static const WCHAR device_id[] = L"wine\test"; + WCHAR *id = NULL; + + irp->IoStatus.Information = 0; + + switch (type) + { + case BusQueryDeviceID: + if (!(id = ExAllocatePool(PagedPool, sizeof(device_id)))) + return STATUS_NO_MEMORY; + wcscpy(id, device_id); + break; + + case BusQueryInstanceID: + if (!(id = ExAllocatePool(PagedPool, 9 * sizeof(WCHAR)))) + return STATUS_NO_MEMORY; + swprintf(id, 9, L"%x", device->id); + break; + + case BusQueryHardwareIDs: + { + static const WCHAR hardware_id[] = L"winetest_hardware"; + const size_t size = ARRAY_SIZE(hardware_id) + 27 + 1; + size_t len; + + if (!(id = ExAllocatePool(PagedPool, size * sizeof(WCHAR)))) + return STATUS_NO_MEMORY; + wcscpy(id, hardware_id); + len = swprintf(id + ARRAY_SIZE(hardware_id), size - ARRAY_SIZE(hardware_id), + L"winetest_hardware_%x", device->id); + id[ARRAY_SIZE(hardware_id) + len + 1] = 0; + break; + } + + case BusQueryCompatibleIDs: + { + static const WCHAR compat_id[] = L"winetest_compat"; + const size_t size = ARRAY_SIZE(compat_id) + 25 + 1; + size_t len; + + if (!(id = ExAllocatePool(PagedPool, size * sizeof(WCHAR)))) + return STATUS_NO_MEMORY; + wcscpy(id, compat_id); + len = swprintf(id + ARRAY_SIZE(compat_id), size - ARRAY_SIZE(compat_id), + L"winetest_compat_%x", device->id); + id[ARRAY_SIZE(compat_id) + len + 1] = 0; + break; + } + + case BusQueryContainerID: + return STATUS_NOT_SUPPORTED; + + default: + ok(0, "Unexpected ID query type %#x.\n", type); + return irp->IoStatus.Status; + } + + irp->IoStatus.Information = (ULONG_PTR)id; + return STATUS_SUCCESS; +} + static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + struct device *device = device_obj->DeviceExtension; NTSTATUS ret = irp->IoStatus.Status;
switch (stack->MinorFunction) { + case IRP_MN_QUERY_ID: + ret = query_id(device, irp, stack->Parameters.QueryId.IdType); + break; + case IRP_MN_START_DEVICE: + { + POWER_STATE state = {.DeviceState = PowerDeviceD0}; + NTSTATUS status; + + ok(!stack->Parameters.StartDevice.AllocatedResources, "expected no resources\n"); + ok(!stack->Parameters.StartDevice.AllocatedResourcesTranslated, "expected no translated resources\n"); + + status = IoRegisterDeviceInterface(device_obj, &child_class, NULL, &device->child_symlink); + ok(!status, "Failed to register interface, status %#x.\n", status); + + IoSetDeviceInterfaceState(&device->child_symlink, TRUE); + + state = PoSetPowerState(device_obj, DevicePowerState, state); + ok(state.DeviceState == device->power_state, "got previous state %u\n", state.DeviceState); + device->power_state = PowerDeviceD0; + ret = STATUS_SUCCESS; + break; + } + + case IRP_MN_REMOVE_DEVICE: + if (device->removed) + { + IoSetDeviceInterfaceState(&device->child_symlink, FALSE); + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + IoDeleteDevice(device->device_obj); + return STATUS_SUCCESS; + } + ret = STATUS_SUCCESS; break;
case IRP_MN_QUERY_CAPABILITIES: + { + DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities; + unsigned int i; + + ok(caps->Size == sizeof(*caps), "wrong size %u\n", caps->Size); + ok(caps->Version == 1, "wrong version %u\n", caps->Version); + ok(!caps->DeviceD1, "got DeviceD1 %u\n", caps->DeviceD1); + ok(!caps->DeviceD2, "got DeviceD2 %u\n", caps->DeviceD2); + ok(!caps->LockSupported, "got LockSupported %u\n", caps->LockSupported); + ok(!caps->EjectSupported, "got EjectSupported %u\n", caps->EjectSupported); + ok(!caps->Removable, "got Removable %u\n", caps->Removable); + ok(!caps->DockDevice, "got DockDevice %u\n", caps->DockDevice); + ok(!caps->UniqueID, "got UniqueID %u\n", caps->UniqueID); + ok(!caps->SilentInstall, "got SilentInstall %u\n", caps->SilentInstall); + ok(!caps->RawDeviceOK, "got RawDeviceOK %u\n", caps->RawDeviceOK); + ok(!caps->SurpriseRemovalOK, "got SurpriseRemovalOK %u\n", caps->SurpriseRemovalOK); + ok(!caps->WakeFromD0, "got WakeFromD0 %u\n", caps->WakeFromD0); + ok(!caps->WakeFromD1, "got WakeFromD1 %u\n", caps->WakeFromD1); + ok(!caps->WakeFromD2, "got WakeFromD2 %u\n", caps->WakeFromD2); + ok(!caps->WakeFromD3, "got WakeFromD3 %u\n", caps->WakeFromD3); + ok(!caps->HardwareDisabled, "got HardwareDisabled %u\n", caps->HardwareDisabled); + ok(!caps->NonDynamic, "got NonDynamic %u\n", caps->NonDynamic); + ok(!caps->WarmEjectSupported, "got WarmEjectSupported %u\n", caps->WarmEjectSupported); + ok(!caps->NoDisplayInUI, "got NoDisplayInUI %u\n", caps->NoDisplayInUI); + ok(caps->Address == 0xffffffff, "got Address %#x\n", caps->Address); + ok(caps->UINumber == 0xffffffff, "got UINumber %#x\n", caps->UINumber); + for (i = 0; i < PowerSystemMaximum; ++i) + ok(caps->DeviceState[i] == PowerDeviceUnspecified, "got DeviceState[%u] %u\n", i, caps->DeviceState[i]); + ok(caps->SystemWake == PowerSystemUnspecified, "got SystemWake %u\n", caps->SystemWake); + ok(caps->DeviceWake == PowerDeviceUnspecified, "got DeviceWake %u\n", caps->DeviceWake); + ok(!caps->D1Latency, "got D1Latency %u\n", caps->D1Latency); + ok(!caps->D2Latency, "got D2Latency %u\n", caps->D2Latency); + ok(!caps->D3Latency, "got D3Latency %u\n", caps->D3Latency); + + /* If caps->RawDeviceOK is not set, we won't receive + * IRP_MN_START_DEVICE unless there's a function driver. */ + caps->RawDeviceOK = 1; + caps->SurpriseRemovalOK = 1; + caps->EjectSupported = 1; + caps->UniqueID = 1; + + caps->DeviceState[PowerSystemWorking] = PowerDeviceD0; + caps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3; + caps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3; + caps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3; + caps->DeviceState[PowerSystemHibernate] = PowerDeviceD3; + caps->DeviceState[PowerSystemShutdown] = PowerDeviceD3; + + ret = STATUS_SUCCESS; + break; + } + + case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_SURPRISE_REMOVAL: ret = STATUS_SUCCESS; break; @@ -274,6 +481,88 @@ static NTSTATUS fdo_ioctl(IRP *irp, IO_STACK_LOCATION *stack, ULONG code) IoSetDeviceInterfaceState(&bus_symlink, FALSE); return STATUS_SUCCESS;
+ case IOCTL_WINETEST_BUS_ADD_CHILD: + { + DEVICE_OBJECT *device_obj; + UNICODE_STRING string; + struct device *device; + NTSTATUS status; + WCHAR name[30]; + int id; + + if (stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(int)) + return STATUS_BUFFER_TOO_SMALL; + id = *(int *)irp->AssociatedIrp.SystemBuffer; + + swprintf(name, ARRAY_SIZE(name), L"\Device\winetest_pnp_%x", id); + RtlInitUnicodeString(&string, name); + status = IoCreateDevice(driver_obj, sizeof(*device), &string, FILE_DEVICE_UNKNOWN, 0, FALSE, &device_obj); + ok(!status, "Failed to create device, status %#x.\n", status); + + device = device_obj->DeviceExtension; + memset(device, 0, sizeof(*device)); + device->device_obj = device_obj; + device->id = id; + device->removed = FALSE; + + ExAcquireFastMutex(&driver_lock); + list_add_tail(&device_list, &device->entry); + ExReleaseFastMutex(&driver_lock); + + device_obj->Flags &= ~DO_DEVICE_INITIALIZING; + + IoInvalidateDeviceRelations(bus_pdo, BusRelations); + + return STATUS_SUCCESS; + } + + case IOCTL_WINETEST_BUS_REMOVE_CHILD: + { + struct device *device; + int id; + + if (stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(int)) + return STATUS_BUFFER_TOO_SMALL; + id = *(int *)irp->AssociatedIrp.SystemBuffer; + + ExAcquireFastMutex(&driver_lock); + LIST_FOR_EACH_ENTRY(device, &device_list, struct device, entry) + { + if (device->id == id) + { + RtlFreeUnicodeString(&device->child_symlink); + list_remove(&device->entry); + device->removed = TRUE; + break; + } + } + ExReleaseFastMutex(&driver_lock); + + IoInvalidateDeviceRelations(bus_pdo, BusRelations); + + /* The actual removal might be asynchronous; we can't test that the + * device is gone here. */ + + return STATUS_SUCCESS; + } + + default: + ok(0, "Unexpected ioctl %#x.\n", code); + return STATUS_NOT_IMPLEMENTED; + } +} + +static NTSTATUS pdo_ioctl(struct device *device, IRP *irp, IO_STACK_LOCATION *stack, ULONG code) +{ + switch (code) + { + case IOCTL_WINETEST_CHILD_GET_ID: + if (stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(int)) + return STATUS_BUFFER_TOO_SMALL; + *(int *)irp->AssociatedIrp.SystemBuffer = device->id; + irp->IoStatus.Information = sizeof(device->id); + return STATUS_SUCCESS; + default: ok(0, "Unexpected ioctl %#x.\n", code); return STATUS_NOT_IMPLEMENTED; @@ -288,6 +577,8 @@ static NTSTATUS WINAPI driver_ioctl(DEVICE_OBJECT *device, IRP *irp)
if (device == bus_fdo) status = fdo_ioctl(irp, stack, code); + else + status = pdo_ioctl(device->DeviceExtension, irp, stack, code);
irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); @@ -346,5 +637,9 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) driver->MajorFunction[IRP_MJ_CREATE] = driver_create; driver->MajorFunction[IRP_MJ_CLOSE] = driver_close;
+ driver_obj = driver; + + ExInitializeFastMutex(&driver_lock); + return STATUS_SUCCESS; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 571d983ae8d..e0a6e0a30d4 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -34,6 +34,7 @@ #include "mscat.h" #include "mssip.h" #include "setupapi.h" +#include "cfgmgr32.h" #include "newdev.h" #include "initguid.h" #include "devguid.h" @@ -988,15 +989,22 @@ static void test_pnp_devices(void) { static const GUID control_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc0}}; static const GUID bus_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc1}}; + static const GUID child_class = {0xdeadbeef, 0x29ef, 0x4538, {0xa5, 0xfd, 0xb6, 0x95, 0x73, 0xa3, 0x62, 0xc2}}; + static const char expect_hardware_id[] = "winetest_hardware\0winetest_hardware_1\0"; + static const char expect_compat_id[] = "winetest_compat\0winetest_compat_1\0";
char buffer[200]; SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; SP_DEVINFO_DATA device = {sizeof(device)}; + DWORD size, type, dword; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING string; + IO_STATUS_BLOCK io; + HANDLE bus, child; HDEVINFO set; - HANDLE bus; - DWORD size; BOOL ret; + int id;
set = SetupDiGetClassDevsA(&control_class, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError()); @@ -1088,6 +1096,90 @@ static void test_pnp_devices(void) ok(GetLastError() == ERROR_NO_MORE_ITEMS, "got error %#x\n", GetLastError()); SetupDiDestroyDeviceInfoList(set);
+ /* Test exposing a child device. */ + + id = 1; + ret = DeviceIoControl(bus, IOCTL_WINETEST_BUS_ADD_CHILD, &id, sizeof(id), NULL, 0, &size, NULL); + ok(ret, "got error %u\n", GetLastError()); + + set = SetupDiGetClassDevsA(&child_class, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError()); + + ret = SetupDiEnumDeviceInfo(set, 0, &device); + todo_wine ok(ret, "failed to get device, error %#x\n", GetLastError()); + if (ret) + { + ok(IsEqualGUID(&device.ClassGuid, &GUID_NULL), "wrong class %s\n", debugstr_guid(&device.ClassGuid)); + + ret = SetupDiGetDeviceInstanceIdA(set, &device, buffer, sizeof(buffer), NULL); + ok(ret, "failed to get device ID, error %#x\n", GetLastError()); + ok(!strcasecmp(buffer, "wine\test\1"), "got ID %s\n", debugstr_a(buffer)); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CAPABILITIES, + &type, (BYTE *)&dword, sizeof(dword), NULL); + ok(ret, "got error %#x\n", GetLastError()); + ok(dword == (CM_DEVCAP_EJECTSUPPORTED | CM_DEVCAP_UNIQUEID + | CM_DEVCAP_RAWDEVICEOK | CM_DEVCAP_SURPRISEREMOVALOK), "got flags %#x\n", dword); + ok(type == REG_DWORD, "got type %u\n", type); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CLASSGUID, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DEVTYPE, + &type, (BYTE *)&dword, sizeof(dword), NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, + &type, (BYTE *)buffer, sizeof(buffer), &size); + ok(ret, "got error %#x\n", GetLastError()); + ok(type == REG_MULTI_SZ, "got type %u\n", type); + ok(size == sizeof(expect_hardware_id), "got size %u\n", size); + ok(!memcmp(buffer, expect_hardware_id, size), "got hardware IDs %s\n", debugstr_an(buffer, size)); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_COMPATIBLEIDS, + &type, (BYTE *)buffer, sizeof(buffer), &size); + ok(ret, "got error %#x\n", GetLastError()); + ok(type == REG_MULTI_SZ, "got type %u\n", type); + ok(size == sizeof(expect_compat_id), "got size %u\n", size); + ok(!memcmp(buffer, expect_compat_id, size), "got compatible IDs %s\n", debugstr_an(buffer, size)); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + ok(ret, "got error %#x\n", GetLastError()); + ok(type == REG_SZ, "got type %u\n", type); + ok(!strcmp(buffer, "\Device\winetest_pnp_1"), "got PDO name %s\n", debugstr_a(buffer)); + } + + SetupDiDestroyDeviceInfoList(set); + + RtlInitUnicodeString(&string, L"\Device\winetest_pnp_1"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL); + ret = NtOpenFile(&child, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); + ok(!ret, "failed to open child: %#x\n", ret); + + id = 0xdeadbeef; + ret = DeviceIoControl(child, IOCTL_WINETEST_CHILD_GET_ID, NULL, 0, &id, sizeof(id), &size, NULL); + ok(ret, "got error %u\n", GetLastError()); + ok(id == 1, "got id %d\n", id); + ok(size == sizeof(id), "got size %u\n", size); + + CloseHandle(child); + + id = 1; + ret = DeviceIoControl(bus, IOCTL_WINETEST_BUS_REMOVE_CHILD, &id, sizeof(id), NULL, 0, &size, NULL); + ok(ret, "got error %u\n", GetLastError()); + + /* The actual removal might be asynchronous; we can't test that the device + * is gone here. */ + CloseHandle(bus); }
@@ -1101,6 +1193,7 @@ static void test_pnp_driver(struct testsign_context *ctx) SC_HANDLE manager, service; BOOL ret, need_reboot; HANDLE catalog, file; + unsigned int i; HDEVINFO set; FILE *f;
@@ -1231,6 +1324,15 @@ static void test_pnp_driver(struct testsign_context *ctx) ret = SetupDiDestroyDeviceInfoList(set); ok(ret, "failed to destroy set, error %#x\n", GetLastError());
+ set = SetupDiGetClassDevsA(NULL, "wine", NULL, DIGCF_ALLCLASSES); + ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError()); + + for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i) + { + ret = SetupDiCallClassInstaller(DIF_REMOVE, set, &device); + ok(ret, "failed to remove device, error %#x\n", GetLastError()); + } + /* Windows stops the service but does not delete it. */ manager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT); ok(!!manager, "failed to open service manager, error %u\n", GetLastError()); diff --git a/include/cfgmgr32.h b/include/cfgmgr32.h index 15340a60c64..7c4f4714126 100644 --- a/include/cfgmgr32.h +++ b/include/cfgmgr32.h @@ -110,6 +110,18 @@ typedef DWORD CONFIGRET; #define MAX_GUID_STRING_LEN 39 #define MAX_PROFILE_LEN 80
+#define CM_DEVCAP_LOCKSUPPORTED 0x00000001 +#define CM_DEVCAP_EJECTSUPPORTED 0x00000002 +#define CM_DEVCAP_REMOVABLE 0x00000004 +#define CM_DEVCAP_DOCKDEVICE 0x00000008 +#define CM_DEVCAP_UNIQUEID 0x00000010 +#define CM_DEVCAP_SILENTINSTALL 0x00000020 +#define CM_DEVCAP_RAWDEVICEOK 0x00000040 +#define CM_DEVCAP_SURPRISEREMOVALOK 0x00000080 +#define CM_DEVCAP_HARDWAREDISABLED 0x00000100 +#define CM_DEVCAP_NONDYNAMIC 0x00000200 +#define CM_DEVCAP_SECUREDEVICE 0x00000400 + #define CM_DRP_DEVICEDESC 0x01 #define CM_DRP_HARDWAREID 0x02 #define CM_DRP_COMPATIBLEIDS 0x03 diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index d5a9c25a5e8..b389226d3df 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -833,7 +833,8 @@ typedef enum _BUS_QUERY_ID_TYPE { BusQueryHardwareIDs, BusQueryCompatibleIDs, BusQueryInstanceID, - BusQueryDeviceSerialNumber + BusQueryDeviceSerialNumber, + BusQueryContainerID, } BUS_QUERY_ID_TYPE, *PBUS_QUERY_ID_TYPE;
typedef enum _CREATE_FILE_TYPE { @@ -1656,6 +1657,7 @@ NTSTATUS WINAPI EtwRegister(const GUID *, PETWENABLECALLBACK, void *, REGHANDLE NTSTATUS WINAPI EtwUnregister(REGHANDLE); NTSTATUS WINAPI EtwWriteString(REGHANDLE, UCHAR, ULONGLONG, const GUID *, const WCHAR *);
+void FASTCALL ExAcquireFastMutex(FAST_MUTEX*); void FASTCALL ExAcquireFastMutexUnsafe(PFAST_MUTEX); BOOLEAN WINAPI ExAcquireResourceExclusiveLite(ERESOURCE*,BOOLEAN); BOOLEAN WINAPI ExAcquireResourceSharedLite(ERESOURCE*,BOOLEAN); @@ -1682,6 +1684,7 @@ LIST_ENTRY * WINAPI ExInterlockedRemoveHeadList(LIST_ENTRY*,KSPIN_LOCK*); BOOLEAN WINAPI ExIsResourceAcquiredExclusiveLite(ERESOURCE*); ULONG WINAPI ExIsResourceAcquiredSharedLite(ERESOURCE*); void * WINAPI ExRegisterCallback(PCALLBACK_OBJECT,PCALLBACK_FUNCTION,void*); +void FASTCALL ExReleaseFastMutex(FAST_MUTEX*); void FASTCALL ExReleaseFastMutexUnsafe(PFAST_MUTEX); void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD); ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88491
Your paranoid android.
=== build (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wineusb.sys/wineusb.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/wineusb.sys/wineusb.c b/dlls/wineusb.sys/wineusb.c index f46f17d66f4..b8cefdaff5e 100644 --- a/dlls/wineusb.sys/wineusb.c +++ b/dlls/wineusb.sys/wineusb.c @@ -377,8 +377,17 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) ret = query_id(device, irp, stack->Parameters.QueryId.IdType); break;
- case IRP_MN_START_DEVICE: case IRP_MN_QUERY_CAPABILITIES: + { + DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities; + + caps->RawDeviceOK = 1; + + ret = STATUS_SUCCESS; + break; + } + + case IRP_MN_START_DEVICE: case IRP_MN_SURPRISE_REMOVAL: ret = STATUS_SUCCESS; break;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88492
Your paranoid android.
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/pnp.c | 43 +++++++++++++++- dlls/ntoskrnl.exe/tests/driver_pnp.c | 2 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 76 +++++++++++++++------------- 3 files changed, 83 insertions(+), 38 deletions(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index 7994a8b85b9..f8dc8c31935 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -165,6 +165,36 @@ static void send_power_irp( DEVICE_OBJECT *device, DEVICE_POWER_STATE power ) KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); }
+static NTSTATUS get_device_caps( DEVICE_OBJECT *device, DEVICE_CAPABILITIES *caps ) +{ + IO_STACK_LOCATION *irpsp; + IO_STATUS_BLOCK irp_status; + KEVENT event; + IRP *irp; + + memset( caps, 0, sizeof(*caps) ); + caps->Size = sizeof(*caps); + caps->Version = 1; + caps->Address = 0xffffffff; + caps->UINumber = 0xffffffff; + + device = IoGetAttachedDevice( device ); + + KeInitializeEvent( &event, NotificationEvent, FALSE ); + if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, device, NULL, 0, NULL, NULL, &irp_status ))) + return STATUS_NO_MEMORY; + + irpsp = IoGetNextIrpStackLocation( irp ); + irpsp->MinorFunction = IRP_MN_QUERY_CAPABILITIES; + irpsp->Parameters.DeviceCapabilities.Capabilities = caps; + + irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED; + if (IoCallDriver( device, irp ) == STATUS_PENDING) + KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); + + return irp_status.u.Status; +} + static void load_function_driver( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *sp_device ) { static const WCHAR driverW[] = {'\','D','r','i','v','e','r','\',0}; @@ -299,7 +329,9 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set )
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; + DEVICE_CAPABILITIES caps; BOOL need_driver = TRUE; + NTSTATUS status; HKEY key;
if (get_device_instance_id( device, device_instance_id )) @@ -324,8 +356,17 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) RegCloseKey( key ); }
- if (need_driver && !install_device_driver( device, set, &sp_device )) + if ((status = get_device_caps( device, &caps ))) + { + ERR("Failed to get caps for device %s, status %#x.\n", debugstr_w(device_instance_id), status); return; + } + + if (need_driver && !install_device_driver( device, set, &sp_device ) && !caps.RawDeviceOK) + { + ERR("Unable to install a function driver for device %s.\n", debugstr_w(device_instance_id)); + return; + }
start_device( device, set, &sp_device ); } diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index 2b3968fe395..b121e790aa7 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -217,7 +217,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) IoSetDeviceInterfaceState(&device->child_symlink, TRUE);
state = PoSetPowerState(device_obj, DevicePowerState, state); - ok(state.DeviceState == device->power_state, "got previous state %u\n", state.DeviceState); + todo_wine ok(state.DeviceState == device->power_state, "got previous state %u\n", state.DeviceState); device->power_state = PowerDeviceD0; ret = STATUS_SUCCESS; break; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index e0a6e0a30d4..fe0b271b9df 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1106,54 +1106,58 @@ static void test_pnp_devices(void) ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError());
ret = SetupDiEnumDeviceInfo(set, 0, &device); - todo_wine ok(ret, "failed to get device, error %#x\n", GetLastError()); + ok(ret, "failed to get device, error %#x\n", GetLastError()); + ok(IsEqualGUID(&device.ClassGuid, &GUID_NULL), "wrong class %s\n", debugstr_guid(&device.ClassGuid)); + + ret = SetupDiGetDeviceInstanceIdA(set, &device, buffer, sizeof(buffer), NULL); + ok(ret, "failed to get device ID, error %#x\n", GetLastError()); + ok(!strcasecmp(buffer, "wine\test\1"), "got ID %s\n", debugstr_a(buffer)); + + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CAPABILITIES, + &type, (BYTE *)&dword, sizeof(dword), NULL); + todo_wine ok(ret, "got error %#x\n", GetLastError()); if (ret) { - ok(IsEqualGUID(&device.ClassGuid, &GUID_NULL), "wrong class %s\n", debugstr_guid(&device.ClassGuid)); - - ret = SetupDiGetDeviceInstanceIdA(set, &device, buffer, sizeof(buffer), NULL); - ok(ret, "failed to get device ID, error %#x\n", GetLastError()); - ok(!strcasecmp(buffer, "wine\test\1"), "got ID %s\n", debugstr_a(buffer)); - - ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CAPABILITIES, - &type, (BYTE *)&dword, sizeof(dword), NULL); - ok(ret, "got error %#x\n", GetLastError()); ok(dword == (CM_DEVCAP_EJECTSUPPORTED | CM_DEVCAP_UNIQUEID | CM_DEVCAP_RAWDEVICEOK | CM_DEVCAP_SURPRISEREMOVALOK), "got flags %#x\n", dword); ok(type == REG_DWORD, "got type %u\n", type); + }
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CLASSGUID, - &type, (BYTE *)buffer, sizeof(buffer), NULL); - ok(!ret, "expected failure\n"); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CLASSGUID, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + todo_wine ok(!ret, "expected failure\n"); + if (ret) ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DEVTYPE, - &type, (BYTE *)&dword, sizeof(dword), NULL); - ok(!ret, "expected failure\n"); - ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DEVTYPE, + &type, (BYTE *)&dword, sizeof(dword), NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, - &type, (BYTE *)buffer, sizeof(buffer), NULL); - ok(!ret, "expected failure\n"); - ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, - &type, (BYTE *)buffer, sizeof(buffer), &size); - ok(ret, "got error %#x\n", GetLastError()); - ok(type == REG_MULTI_SZ, "got type %u\n", type); - ok(size == sizeof(expect_hardware_id), "got size %u\n", size); - ok(!memcmp(buffer, expect_hardware_id, size), "got hardware IDs %s\n", debugstr_an(buffer, size)); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, + &type, (BYTE *)buffer, sizeof(buffer), &size); + ok(ret, "got error %#x\n", GetLastError()); + ok(type == REG_MULTI_SZ, "got type %u\n", type); + ok(size == sizeof(expect_hardware_id), "got size %u\n", size); + ok(!memcmp(buffer, expect_hardware_id, size), "got hardware IDs %s\n", debugstr_an(buffer, size));
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_COMPATIBLEIDS, - &type, (BYTE *)buffer, sizeof(buffer), &size); - ok(ret, "got error %#x\n", GetLastError()); - ok(type == REG_MULTI_SZ, "got type %u\n", type); - ok(size == sizeof(expect_compat_id), "got size %u\n", size); - ok(!memcmp(buffer, expect_compat_id, size), "got compatible IDs %s\n", debugstr_an(buffer, size)); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_COMPATIBLEIDS, + &type, (BYTE *)buffer, sizeof(buffer), &size); + ok(ret, "got error %#x\n", GetLastError()); + ok(type == REG_MULTI_SZ, "got type %u\n", type); + ok(size == sizeof(expect_compat_id), "got size %u\n", size); + ok(!memcmp(buffer, expect_compat_id, size), "got compatible IDs %s\n", debugstr_an(buffer, size));
- ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, - &type, (BYTE *)buffer, sizeof(buffer), NULL); - ok(ret, "got error %#x\n", GetLastError()); + ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, + &type, (BYTE *)buffer, sizeof(buffer), NULL); + todo_wine ok(ret, "got error %#x\n", GetLastError()); + if (ret) + { ok(type == REG_SZ, "got type %u\n", type); ok(!strcmp(buffer, "\Device\winetest_pnp_1"), "got PDO name %s\n", debugstr_a(buffer)); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88493
Your paranoid android.
=== build (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/pnp.c | 28 ---------------------------- 1 file changed, 28 deletions(-)
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index f8dc8c31935..0d9d816e3c0 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -141,30 +141,6 @@ static NTSTATUS get_device_instance_id( DEVICE_OBJECT *device, WCHAR *buffer ) return STATUS_SUCCESS; }
-static void send_power_irp( DEVICE_OBJECT *device, DEVICE_POWER_STATE power ) -{ - IO_STATUS_BLOCK irp_status; - IO_STACK_LOCATION *irpsp; - KEVENT event; - IRP *irp; - - device = IoGetAttachedDevice( device ); - - KeInitializeEvent( &event, NotificationEvent, FALSE ); - if (!(irp = IoBuildSynchronousFsdRequest( IRP_MJ_POWER, device, NULL, 0, NULL, &event, &irp_status ))) - return; - - irpsp = IoGetNextIrpStackLocation( irp ); - irpsp->MinorFunction = IRP_MN_SET_POWER; - - irpsp->Parameters.Power.Type = DevicePowerState; - irpsp->Parameters.Power.State.DeviceState = power; - - irp->IoStatus.u.Status = STATUS_NOT_SUPPORTED; - if (IoCallDriver( device, irp ) == STATUS_PENDING) - KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); -} - static NTSTATUS get_device_caps( DEVICE_OBJECT *device, DEVICE_CAPABILITIES *caps ) { IO_STACK_LOCATION *irpsp; @@ -317,10 +293,7 @@ static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA * { load_function_driver( device, set, sp_device ); if (device->DriverObject) - { send_pnp_irp( device, IRP_MN_START_DEVICE ); - send_power_irp( device, PowerDeviceD0 ); - } }
static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) @@ -384,7 +357,6 @@ static void remove_device( DEVICE_OBJECT *device ) remove_device( wine_device->children->Objects[i] ); }
- send_power_irp( device, PowerDeviceD3 ); send_pnp_irp( device, IRP_MN_SURPRISE_REMOVAL ); send_pnp_irp( device, IRP_MN_REMOVE_DEVICE ); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88494
Your paranoid android.
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This is mostly a bit of cautiousness, not that anyone running the ntoskrnl tests shouldn't be prepared for a kernel panic.
dlls/ntoskrnl.exe/tests/driver_pnp.c | 29 ++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/driver_pnp.c b/dlls/ntoskrnl.exe/tests/driver_pnp.c index b121e790aa7..707b6f7c696 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -307,6 +307,34 @@ static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) return pdo_pnp(device, irp); }
+static NTSTATUS WINAPI driver_power(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + NTSTATUS ret = STATUS_NOT_SUPPORTED; + + /* We do not expect power IRPs as part of normal operation. */ + ok(0, "unexpected call\n"); + + if (device == bus_fdo) + { + PoStartNextPowerIrp(irp); + IoSkipCurrentIrpStackLocation(irp); + return PoCallDriver(bus_pdo, irp); + } + + if (stack->MinorFunction == IRP_MN_SET_POWER) + { + if (stack->Parameters.Power.Type == DevicePowerState) + PoSetPowerState(device, DevicePowerState, stack->Parameters.Power.State); + ret = STATUS_SUCCESS; + } + + PoStartNextPowerIrp(irp); + irp->IoStatus.Status = ret; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return ret; +} + static void test_bus_query_caps(DEVICE_OBJECT *top_device) { DEVICE_CAPABILITIES caps; @@ -633,6 +661,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; + driver->MajorFunction[IRP_MJ_POWER] = driver_power; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_ioctl; driver->MajorFunction[IRP_MJ_CREATE] = driver_create; driver->MajorFunction[IRP_MJ_CLOSE] = driver_close;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=88495
Your paranoid android.
=== build (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/ddk/wdm.h:1656 Task: Patch failed to apply