From: Connor McAdams <cmcadams@codeweavers.com> Signed-off-by: Connor McAdams <cmcadams@codeweavers.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 5 +++ dlls/ntoskrnl.exe/ntoskrnl_private.h | 11 +++++ dlls/ntoskrnl.exe/pnp.c | 64 ++++++++++++++++++++++------ dlls/ntoskrnl.exe/tests/driver_pnp.c | 10 ++--- 4 files changed, 71 insertions(+), 19 deletions(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index b2078e51b8b..c4b05fbe0fe 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1760,6 +1760,11 @@ void WINAPI IoDeleteDevice( DEVICE_OBJECT *device ) ObDereferenceObject( children->Objects[i] ); ExFreePool( children ); } + if (wine_device->devnode_data) + { + free( wine_device->devnode_data ); + wine_device->devnode_data = NULL; + } ObDereferenceObject( device ); } } diff --git a/dlls/ntoskrnl.exe/ntoskrnl_private.h b/dlls/ntoskrnl.exe/ntoskrnl_private.h index 760ceb24751..7e6fcf64350 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl_private.h +++ b/dlls/ntoskrnl.exe/ntoskrnl_private.h @@ -29,8 +29,10 @@ #include "winbase.h" #include "winsvc.h" #include "winternl.h" +#include "winreg.h" #include "ddk/ntifs.h" #include "ddk/wdm.h" +#include "cfgmgr32.h" #include "wine/asm.h" #include "wine/debug.h" @@ -116,11 +118,20 @@ static const WCHAR servicesW[] = {'\\','R','e','g','i','s','t','r','y', '\\','S','e','r','v','i','c','e','s', '\\',0}; +struct wine_devnode_data +{ + /* Combo of device_id and instance_id. */ + WCHAR device_instance_id[MAX_DEVICE_ID_LEN]; +}; + struct wine_device { DEVICE_OBJECT device_obj; DEVOBJ_EXTENSION devobj_ext; DEVICE_RELATIONS *children; HKEY dyn_data_key; + + /* Only set on PDO devices. */ + struct wine_devnode_data *devnode_data; }; #endif diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c index e87e3a05103..1a99262d280 100644 --- a/dlls/ntoskrnl.exe/pnp.c +++ b/dlls/ntoskrnl.exe/pnp.c @@ -149,29 +149,49 @@ static NTSTATUS send_pnp_irp( DEVICE_OBJECT *device, UCHAR minor ) static NTSTATUS get_device_instance_id( DEVICE_OBJECT *device, WCHAR *buffer ) { - static const WCHAR backslashW[] = {'\\',0}; + struct wine_device *pdo_dev; NTSTATUS status; WCHAR *id; - if ((status = get_device_id( device, BusQueryDeviceID, &id ))) + while (device->DeviceObjectExtension->AttachedTo) + device = device->DeviceObjectExtension->AttachedTo; + + if (!(device->Flags & DO_BUS_ENUMERATED_DEVICE)) { - ERR("Failed to get device ID, status %#lx.\n", status); - return status; + ERR( "Lowest device in stack is not a PDO.\n" ); + return STATUS_INVALID_DEVICE_REQUEST; } - lstrcpyW( buffer, id ); - ExFreePool( id ); - - if ((status = get_device_id( device, BusQueryInstanceID, &id ))) + pdo_dev = CONTAINING_RECORD(device, struct wine_device, device_obj); + if (!pdo_dev->devnode_data) { - ERR("Failed to get instance ID, status %#lx.\n", status); - return status; + ERR( "PDO has no devnode data.\n" ); + return STATUS_UNSUCCESSFUL; } - lstrcatW( buffer, backslashW ); - lstrcatW( buffer, id ); - ExFreePool( id ); + if (!wcslen( pdo_dev->devnode_data->device_instance_id )) + { + if ((status = get_device_id( device, BusQueryDeviceID, &id ))) + { + ERR("Failed to get device ID, status %#lx.\n", status); + return status; + } + wcscpy( pdo_dev->devnode_data->device_instance_id, id ); + wcscat( pdo_dev->devnode_data->device_instance_id, L"\\" ); + ExFreePool( id ); + + if ((status = get_device_id( device, BusQueryInstanceID, &id ))) + { + ERR("Failed to get instance ID, status %#lx.\n", status); + pdo_dev->devnode_data->device_instance_id[0] = 0; + return status; + } + wcscat( pdo_dev->devnode_data->device_instance_id, id ); + ExFreePool( id ); + } + + wcscpy( buffer, pdo_dev->devnode_data->device_instance_id ); TRACE("Returning ID %s.\n", debugstr_w(buffer)); return STATUS_SUCCESS; @@ -372,7 +392,6 @@ static void create_dyn_data_key( DEVICE_OBJECT *device ) * send IRPs to start the device. */ static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA *sp_device ) { - device->Flags |= DO_BUS_ENUMERATED_DEVICE; load_function_driver( device, set, sp_device ); if (device->DriverObject) send_pnp_irp( device, IRP_MN_START_DEVICE ); @@ -380,6 +399,21 @@ static void start_device( DEVICE_OBJECT *device, HDEVINFO set, SP_DEVINFO_DATA * create_dyn_data_key( device ); } +static void create_wine_devnode_data( DEVICE_OBJECT *pdo ) +{ + struct wine_device *wine_device = CONTAINING_RECORD(pdo, struct wine_device, device_obj); + struct wine_devnode_data *node; + + pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; + if (!(node = calloc( 1, sizeof(*node) ))) + { + ERR( "Failed to allocate node memory!\n" ); + return; + } + + wine_device->devnode_data = node; +} + static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set, DEVICE_OBJECT *parent_device ) { static const WCHAR infpathW[] = {'I','n','f','P','a','t','h',0}; @@ -393,6 +427,7 @@ static void enumerate_new_device( DEVICE_OBJECT *device, HDEVINFO set, DEVICE_OB HKEY key; WCHAR *id; + create_wine_devnode_data( device ); if (get_device_instance_id( device, device_instance_id )) return; @@ -1648,6 +1683,7 @@ void CDECL wine_enumerate_root_devices( const WCHAR *driver_name ) wcscpy( pnp_device->id, id ); pnp_device->device = device; list_add_tail( &new_list, &pnp_device->entry ); + create_wine_devnode_data( device ); 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 70295bdc09b..cd7f30ef82d 100644 --- a/dlls/ntoskrnl.exe/tests/driver_pnp.c +++ b/dlls/ntoskrnl.exe/tests/driver_pnp.c @@ -324,7 +324,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device_obj, IRP *irp) query_id_count = 0; status = IoRegisterDeviceInterface(device_obj, &child_class, NULL, &device->child_symlink); - todo_wine ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); + ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); ok(!status, "Failed to register interface, status %#lx.\n", status); ok(device->child_symlink.Length == sizeof(expect_symlink) - sizeof(WCHAR), "Got length %u.\n", device->child_symlink.Length); @@ -768,12 +768,12 @@ static void test_child_device_properties(DEVICE_OBJECT *device) query_id_count = 0; status = IoSetDevicePropertyData(device, key, LOCALE_NEUTRAL, 0, type, size, &value); - todo_wine ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); + ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); ok(status == STATUS_SUCCESS, "failed to set device property, status %#lx\n", status); query_id_count = 0; status = IoGetDevicePropertyData(device, key, LOCALE_NEUTRAL, 0, size, &stored_value, &req_size, &stored_type); - todo_wine ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); + ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); ok(status == STATUS_SUCCESS, "failed to get device property, status %#lx\n", status); ok(req_size == size, "expected required size %lu, got %lu\n", req_size, size); ok(stored_type == type, "expected DEVPROPTYPE value %#lx, got %#lx\n", type, stored_type); @@ -781,7 +781,7 @@ static void test_child_device_properties(DEVICE_OBJECT *device) query_id_count = 0; status = IoSetDevicePropertyData(device, key, LOCALE_NEUTRAL, 0, type, 0, NULL); - todo_wine ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); + ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); ok(status == STATUS_SUCCESS, "failed to delete device property, status %#lx\n", status); } @@ -938,7 +938,7 @@ static void test_child_device_registry_key(DEVICE_OBJECT *device) query_id_count = 0; status = IoOpenDeviceRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &hkey); - todo_wine ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); + ok(query_id_count == 0, "expected no IRP_MN_QUERY_ID\n"); ok(status == STATUS_SUCCESS, "IoOpenDeviceRegistryKey failed: %#lx\n", status); if (status == STATUS_SUCCESS) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11263