Commit 48b2e67d authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntoskrnl: Start the device even without a function driver if it reports RawDeviceOK.

parent 66a0cc96
...@@ -165,6 +165,36 @@ static void send_power_irp( DEVICE_OBJECT *device, DEVICE_POWER_STATE power ) ...@@ -165,6 +165,36 @@ static void send_power_irp( DEVICE_OBJECT *device, DEVICE_POWER_STATE power )
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); 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 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}; 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 ) ...@@ -299,7 +329,9 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set )
SP_DEVINFO_DATA sp_device = {sizeof(sp_device)}; SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
DEVICE_CAPABILITIES caps;
BOOL need_driver = TRUE; BOOL need_driver = TRUE;
NTSTATUS status;
HKEY key; HKEY key;
if (get_device_instance_id( device, device_instance_id )) if (get_device_instance_id( device, device_instance_id ))
...@@ -324,8 +356,17 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set ) ...@@ -324,8 +356,17 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set )
RegCloseKey( key ); 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; 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 ); start_device( device, set, &sp_device );
} }
......
...@@ -217,7 +217,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) ...@@ -217,7 +217,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp)
IoSetDeviceInterfaceState(&device->child_symlink, TRUE); IoSetDeviceInterfaceState(&device->child_symlink, TRUE);
state = PoSetPowerState(device_obj, DevicePowerState, state); 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; device->power_state = PowerDeviceD0;
ret = STATUS_SUCCESS; ret = STATUS_SUCCESS;
break; break;
......
...@@ -1221,61 +1221,65 @@ static void test_pnp_devices(void) ...@@ -1221,61 +1221,65 @@ static void test_pnp_devices(void)
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());
pump_messages(); 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); ok(!got_child_removal, "got %u child removal messages\n", got_child_removal);
set = SetupDiGetClassDevsA(&child_class, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); set = SetupDiGetClassDevsA(&child_class, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError()); ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError());
ret = SetupDiEnumDeviceInfo(set, 0, &device); 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());
if (ret) ok(IsEqualGUID(&device.ClassGuid, &GUID_NULL), "wrong class %s\n", debugstr_guid(&device.ClassGuid));
{
ok(IsEqualGUID(&device.ClassGuid, &GUID_NULL), "wrong class %s\n", debugstr_guid(&device.ClassGuid));
ret = SetupDiGetDeviceInstanceIdA(set, &device, buffer, sizeof(buffer), NULL); ret = SetupDiGetDeviceInstanceIdA(set, &device, buffer, sizeof(buffer), NULL);
ok(ret, "failed to get device ID, error %#x\n", GetLastError()); ok(ret, "failed to get device ID, error %#x\n", GetLastError());
ok(!strcasecmp(buffer, "wine\\test\\1"), "got ID %s\n", debugstr_a(buffer)); ok(!strcasecmp(buffer, "wine\\test\\1"), "got ID %s\n", debugstr_a(buffer));
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CAPABILITIES, ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CAPABILITIES,
&type, (BYTE *)&dword, sizeof(dword), NULL); &type, (BYTE *)&dword, sizeof(dword), NULL);
ok(ret, "got error %#x\n", GetLastError()); todo_wine ok(ret, "got error %#x\n", GetLastError());
if (ret)
{
ok(dword == (CM_DEVCAP_EJECTSUPPORTED | CM_DEVCAP_UNIQUEID ok(dword == (CM_DEVCAP_EJECTSUPPORTED | CM_DEVCAP_UNIQUEID
| CM_DEVCAP_RAWDEVICEOK | CM_DEVCAP_SURPRISEREMOVALOK), "got flags %#x\n", dword); | CM_DEVCAP_RAWDEVICEOK | CM_DEVCAP_SURPRISEREMOVALOK), "got flags %#x\n", dword);
ok(type == REG_DWORD, "got type %u\n", type); ok(type == REG_DWORD, "got type %u\n", type);
}
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CLASSGUID, ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_CLASSGUID,
&type, (BYTE *)buffer, sizeof(buffer), NULL); &type, (BYTE *)buffer, sizeof(buffer), NULL);
ok(!ret, "expected failure\n"); todo_wine ok(!ret, "expected failure\n");
ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); if (ret)
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()); ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER, ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DEVTYPE,
&type, (BYTE *)buffer, sizeof(buffer), NULL); &type, (BYTE *)&dword, sizeof(dword), NULL);
ok(!ret, "expected failure\n"); ok(!ret, "expected failure\n");
ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError()); ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_HARDWAREID, ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_DRIVER,
&type, (BYTE *)buffer, sizeof(buffer), &size); &type, (BYTE *)buffer, sizeof(buffer), NULL);
ok(ret, "got error %#x\n", GetLastError()); ok(!ret, "expected failure\n");
ok(type == REG_MULTI_SZ, "got type %u\n", type); ok(GetLastError() == ERROR_INVALID_DATA, "got error %#x\n", GetLastError());
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);
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_COMPATIBLEIDS, ok(ret, "got error %#x\n", GetLastError());
&type, (BYTE *)buffer, sizeof(buffer), &size); ok(type == REG_MULTI_SZ, "got type %u\n", type);
ok(ret, "got error %#x\n", GetLastError()); ok(size == sizeof(expect_hardware_id), "got size %u\n", size);
ok(type == REG_MULTI_SZ, "got type %u\n", type); ok(!memcmp(buffer, expect_hardware_id, size), "got hardware IDs %s\n", debugstr_an(buffer, size));
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);
ret = SetupDiGetDeviceRegistryPropertyA(set, &device, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, ok(ret, "got error %#x\n", GetLastError());
&type, (BYTE *)buffer, sizeof(buffer), NULL); ok(type == REG_MULTI_SZ, "got type %u\n", type);
ok(ret, "got error %#x\n", GetLastError()); 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);
todo_wine ok(ret, "got error %#x\n", GetLastError());
if (ret)
{
ok(type == REG_SZ, "got type %u\n", type); ok(type == REG_SZ, "got type %u\n", type);
ok(!strcmp(buffer, "\\Device\\winetest_pnp_1"), "got PDO name %s\n", debugstr_a(buffer)); 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) ...@@ -1300,8 +1304,8 @@ static void test_pnp_devices(void)
ok(ret, "got error %u\n", GetLastError()); ok(ret, "got error %u\n", GetLastError());
pump_messages(); 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);
todo_wine ok(got_child_removal == 1, "got %u child removal messages\n", got_child_removal); 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); ret = NtOpenFile(&child, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT);
ok(ret == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", ret); ok(ret == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", ret);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment