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 | 82 +++++++++++++++------------- 3 files changed, 86 insertions(+), 41 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 9f358ae73d8..34b21e4de48 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 ab559817e58..aa5fcdaf3f3 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1221,61 +1221,65 @@ static void test_pnp_devices(void) ok(ret, "got error %u\n", GetLastError());
pump_messages(); - todo_wine ok(got_child_arrival == 1, "got %u child arrival messages\n", got_child_arrival); + ok(got_child_arrival == 1, "got %u child arrival messages\n", got_child_arrival); ok(!got_child_removal, "got %u child removal messages\n", got_child_removal);
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()); + 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)); } @@ -1300,8 +1304,8 @@ static void test_pnp_devices(void) ok(ret, "got error %u\n", GetLastError());
pump_messages(); - todo_wine ok(got_child_arrival == 1, "got %u child arrival messages\n", got_child_arrival); - todo_wine ok(got_child_removal == 1, "got %u child removal messages\n", got_child_removal); + ok(got_child_arrival == 1, "got %u child arrival messages\n", got_child_arrival); + ok(got_child_removal == 1, "got %u child removal messages\n", got_child_removal);
ret = NtOpenFile(&child, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); ok(ret == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", ret);