[PATCH v2 5/5] ntoskrnl.exe: Correctly handle instance IDs.

Zebediah Figura zfigura at codeweavers.com
Wed Jun 5 09:22:16 CDT 2019


From: Zebediah Figura <z.figura12 at gmail.com>

The instance ID is only the third part of the "A\B\C" form, and must be
combined with the device ID to form the whole name for setupapi (the "device
instance ID").

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/hidclass.sys/device.c |  8 +++++-
 dlls/hidclass.sys/pnp.c    | 48 +++++++++++++++++-------------------
 dlls/ntoskrnl.exe/pnp.c    | 61 ++++++++++++++++++++++++++++------------------
 dlls/winebus.sys/main.c    | 40 +++++++++++++++---------------
 4 files changed, 85 insertions(+), 72 deletions(-)

diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
index 4495300..de963fa 100644
--- a/dlls/hidclass.sys/device.c
+++ b/dlls/hidclass.sys/device.c
@@ -78,6 +78,8 @@ NTSTATUS HID_CreateDevice(DEVICE_OBJECT *native_device, HID_MINIDRIVER_REGISTRAT
 
 NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
 {
+    static const WCHAR backslashW[] = {'\\',0};
+    WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
     SP_DEVINFO_DATA Data;
     UNICODE_STRING nameW;
     NTSTATUS status;
@@ -90,6 +92,10 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
 
     RtlInitUnicodeString( &nameW, ext->device_name);
 
+    strcpyW(device_instance_id, ext->device_id);
+    strcatW(device_instance_id, backslashW);
+    strcatW(device_instance_id, ext->instance_id);
+
     devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_HIDCLASS, NULL);
     if (devinfo == INVALID_HANDLE_VALUE)
     {
@@ -97,7 +103,7 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
         return STATUS_UNSUCCESSFUL;
     }
     Data.cbSize = sizeof(Data);
-    if (SetupDiCreateDeviceInfoW(devinfo, ext->instance_id, &GUID_DEVCLASS_HIDCLASS, NULL, NULL, DICD_INHERIT_CLASSDRVS, &Data))
+    if (SetupDiCreateDeviceInfoW(devinfo, device_instance_id, &GUID_DEVCLASS_HIDCLASS, NULL, NULL, DICD_INHERIT_CLASSDRVS, &Data))
     {
         if (!SetupDiRegisterDeviceInfo(devinfo, &Data, 0, NULL, NULL, NULL))
         {
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c
index c47e7d2..5042b80 100644
--- a/dlls/hidclass.sys/pnp.c
+++ b/dlls/hidclass.sys/pnp.c
@@ -33,8 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(hid);
 
 static const WCHAR device_enumeratorW[] = {'H','I','D',0};
 static const WCHAR separator_W[] = {'\\',0};
-static const WCHAR device_deviceid_fmtW[] = {'%','s','\\',
-    'v','i','d','_','%','0','4','x','&','p','i','d','_','%', '0','4','x',0};
 
 static NTSTATUS WINAPI internalComplete(DEVICE_OBJECT *deviceObject, IRP *irp,
     void *context)
@@ -44,7 +42,7 @@ static NTSTATUS WINAPI internalComplete(DEVICE_OBJECT *deviceObject, IRP *irp,
     return STATUS_MORE_PROCESSING_REQUIRED;
 }
 
-static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCHAR **id)
+static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCHAR *id)
 {
     NTSTATUS status;
     IO_STACK_LOCATION *irpsp;
@@ -66,7 +64,8 @@ static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCH
     if (status == STATUS_PENDING)
         WaitForSingleObject(event, INFINITE);
 
-    *id = (WCHAR*)irp->IoStatus.Information;
+    strcpyW(id, (WCHAR *)irp->IoStatus.Information);
+    ExFreePool( (WCHAR *)irp->IoStatus.Information );
     status = irp->IoStatus.u.Status;
     IoCompleteRequest(irp, IO_NO_INCREMENT );
     CloseHandle(event);
@@ -76,6 +75,7 @@ static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCH
 
 NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
 {
+    WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN];
     hid_device *hiddev;
     DEVICE_OBJECT *device = NULL;
     NTSTATUS status;
@@ -85,17 +85,20 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     HID_DESCRIPTOR descriptor;
     BYTE *reportDescriptor;
     INT i;
-    WCHAR *PDO_id;
-    WCHAR *id_ptr;
 
-    status = get_device_id(PDO, BusQueryInstanceID, &PDO_id);
-    if (status != STATUS_SUCCESS)
+    if ((status = get_device_id(PDO, BusQueryDeviceID, device_id)))
     {
-        ERR("Failed to get PDO id(%x)\n",status);
+        ERR("Failed to get PDO device id, status %#x.\n", status);
         return status;
     }
 
-    TRACE("PDO add device(%p:%s)\n", PDO, debugstr_w(PDO_id));
+    if ((status = get_device_id(PDO, BusQueryInstanceID, instance_id)))
+    {
+        ERR("Failed to get PDO instance id, status %#x.\n", status);
+        return status;
+    }
+
+    TRACE("Adding device to PDO %p, id %s\\%s.\n", PDO, debugstr_w(device_id), debugstr_w(instance_id));
     minidriver = find_minidriver(driver);
 
     hiddev = HeapAlloc(GetProcessHeap(), 0, sizeof(*hiddev));
@@ -106,7 +109,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     if (status != STATUS_SUCCESS)
     {
         ERR("Failed to create HID object (%x)\n",status);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         HeapFree(GetProcessHeap(), 0, hiddev);
         return status;
     }
@@ -121,7 +123,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     if (status != STATUS_SUCCESS)
     {
         ERR("Minidriver AddDevice failed (%x)\n",status);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         HID_DeleteDevice(&minidriver->minidriver, device);
         return status;
     }
@@ -133,7 +134,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     {
         ERR("Minidriver failed to get Attributes(%x)\n",status);
         HID_DeleteDevice(&minidriver->minidriver, device);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         return status;
     }
 
@@ -148,7 +148,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     {
         ERR("Cannot get Device Descriptor(%x)\n",status);
         HID_DeleteDevice(&minidriver->minidriver, device);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         return status;
     }
     for (i = 0; i < descriptor.bNumDescriptors; i++)
@@ -159,7 +158,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     {
         ERR("No Report Descriptor found in reply\n");
         HID_DeleteDevice(&minidriver->minidriver, device);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         return status;
     }
 
@@ -171,7 +169,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
         ERR("Cannot get Report Descriptor(%x)\n",status);
         HID_DeleteDevice(&minidriver->minidriver, device);
         HeapFree(GetProcessHeap(), 0, reportDescriptor);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         return status;
     }
 
@@ -182,7 +179,6 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
     {
         ERR("Cannot parse Report Descriptor\n");
         HID_DeleteDevice(&minidriver->minidriver, device);
-        HeapFree(GetProcessHeap(), 0, PDO_id);
         return STATUS_NOT_SUPPORTED;
     }
 
@@ -190,15 +186,11 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
 
     ext->information.DescriptorSize = ext->preparseData->dwSize;
 
-    lstrcpyW(ext->instance_id, device_enumeratorW);
-    strcatW(ext->instance_id, separator_W);
-    /* Skip the original enumerator */
-    id_ptr = strchrW(PDO_id, '\\');
-    id_ptr++;
-    strcatW(ext->instance_id, id_ptr);
-    HeapFree(GetProcessHeap(), 0, PDO_id);
+    strcpyW(ext->instance_id, instance_id);
 
-    sprintfW(ext->device_id, device_deviceid_fmtW, device_enumeratorW, ext->information.VendorID, ext->information.ProductID);
+    strcpyW(ext->device_id, device_enumeratorW);
+    strcatW(ext->device_id, separator_W);
+    strcatW(ext->device_id, strchrW(device_id, '\\') + 1);
 
     HID_LinkDevice(device);
 
@@ -261,7 +253,11 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
                 {
                     WCHAR *ptr;
                     ptr = id;
-                    /* Instance ID */
+                    /* Device instance ID */
+                    strcpyW(ptr, ext->device_id);
+                    ptr += lstrlenW(ext->device_id);
+                    strcpyW(ptr, separator_W);
+                    ptr += 1;
                     strcpyW(ptr, ext->instance_id);
                     ptr += lstrlenW(ext->instance_id) + 1;
                     /* Device ID */
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
index b88b9f1..20e1538 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -204,6 +204,36 @@ static NTSTATUS send_pnp_irp( DEVICE_OBJECT *device, UCHAR minor )
     return send_device_irp( device, irp, NULL );
 }
 
+static NTSTATUS get_device_instance_id( DEVICE_OBJECT *device, WCHAR *buffer )
+{
+    static const WCHAR backslashW[] = {'\\',0};
+    NTSTATUS status;
+    WCHAR *id;
+
+    if ((status = get_device_id( device, BusQueryDeviceID, &id )))
+    {
+        ERR("Failed to get device ID, status %#x.\n", status);
+        return status;
+    }
+
+    strcpyW( buffer, id );
+    ExFreePool( id );
+
+    if ((status = get_device_id( device, BusQueryInstanceID, &id )))
+    {
+        ERR("Failed to get instance ID, status %#x.\n", status);
+        return status;
+    }
+
+    strcatW( buffer, backslashW );
+    strcatW( buffer, id );
+    ExFreePool( id );
+
+    TRACE("Returning ID %s.\n", debugstr_w(buffer));
+
+    return STATUS_SUCCESS;
+}
+
 static BOOL get_driver_for_id( const WCHAR *id, WCHAR *driver )
 {
     static const WCHAR serviceW[] = {'S','e','r','v','i','c','e',0};
@@ -593,22 +623,6 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
     return ret;
 }
 
-static NTSTATUS get_instance_id(DEVICE_OBJECT *device, WCHAR **instance_id)
-{
-    WCHAR *id, *ptr;
-    NTSTATUS status;
-
-    status = get_device_id( device, BusQueryInstanceID, &id );
-    if (status != STATUS_SUCCESS) return status;
-
-    struprW( id );
-    for (ptr = id; *ptr; ptr++)
-        if (*ptr == '\\') *ptr = '#';
-
-    *instance_id = id;
-    return STATUS_SUCCESS;
-}
-
 /***********************************************************************
  *           IoRegisterDeviceInterface (NTOSKRNL.EXE.@)
  */
@@ -617,29 +631,28 @@ NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device, const GUID *cla
 {
     SP_DEVICE_INTERFACE_DATA sp_iface = {sizeof(sp_iface)};
     SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
+    WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
     SP_DEVICE_INTERFACE_DETAIL_DATA_W *data;
     NTSTATUS status = STATUS_SUCCESS;
     struct device_interface *iface;
-    WCHAR *instance_id;
     DWORD required;
     HDEVINFO set;
 
     TRACE("device %p, class_guid %s, refstr %s, symbolic_link %p.\n",
             device, debugstr_guid(class_guid), debugstr_us(refstr), symbolic_link);
 
+    if ((status = get_device_instance_id( device, device_instance_id )))
+        return status;
+
     set = SetupDiGetClassDevsW( class_guid, NULL, NULL, DIGCF_DEVICEINTERFACE );
     if (set == INVALID_HANDLE_VALUE) return STATUS_UNSUCCESSFUL;
 
-    status = get_instance_id( device, &instance_id );
-    if (status != STATUS_SUCCESS) return status;
-
-    if (!SetupDiCreateDeviceInfoW( set, instance_id, class_guid, NULL, NULL, 0, &sp_device )
-            && !SetupDiOpenDeviceInfoW( set, instance_id, NULL, 0, &sp_device ))
+    if (!SetupDiCreateDeviceInfoW( set, device_instance_id, class_guid, NULL, NULL, 0, &sp_device )
+            && !SetupDiOpenDeviceInfoW( set, device_instance_id, NULL, 0, &sp_device ))
     {
-        ERR("Failed to create device %s, error %#x.\n", debugstr_w(instance_id), GetLastError());
+        ERR("Failed to create device %s, error %#x.\n", debugstr_w(device_instance_id), GetLastError());
         return GetLastError();
     }
-    ExFreePool( instance_id );
 
     if (!SetupDiCreateDeviceInterfaceW( set, &sp_device, class_guid, refstr ? refstr->Buffer : NULL, 0, &sp_iface ))
         return STATUS_UNSUCCESSFUL;
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c
index b649bfb..3616ebe 100644
--- a/dlls/winebus.sys/main.c
+++ b/dlls/winebus.sys/main.c
@@ -31,6 +31,7 @@
 #include "winternl.h"
 #include "winreg.h"
 #include "setupapi.h"
+#include "cfgmgr32.h"
 #include "winioctl.h"
 #include "ddk/wdm.h"
 #include "ddk/hidport.h"
@@ -43,6 +44,8 @@
 WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
 WINE_DECLARE_DEBUG_CHANNEL(hid_report);
 
+static const WCHAR backslashW[] = {'\\',0};
+
 #define VID_MICROSOFT 0x045e
 
 static const WORD PID_XBOX_CONTROLLERS[] =  {
@@ -140,28 +143,14 @@ static DWORD get_device_index(WORD vid, WORD pid, WORD input)
 
 static WCHAR *get_instance_id(DEVICE_OBJECT *device)
 {
-    static const WCHAR formatW[] =  {'%','s','\\','v','i','d','_','%','0','4','x','&','p','i','d','_','%','0','4','x',
-                                     '\\','%','i','&','%','s','&','%','x','&','%','i',0};
-    static const WCHAR format_inputW[] = {'%','s','\\','v','i','d','_','%','0','4','x','&','p','i','d','_','%','0','4','x','&',
-                                     '%','s','_','%','i','\\','%','i','&','%','s','&','%','x','&','%','i',0};
+    static const WCHAR formatW[] =  {'%','i','&','%','s','&','%','x','&','%','i',0};
     struct device_extension *ext = (struct device_extension *)device->DeviceExtension;
     const WCHAR *serial = ext->serial ? ext->serial : zero_serialW;
-    DWORD len = strlenW(ext->busid) + strlenW(serial) + 64;
+    DWORD len = strlenW(serial) + 33;
     WCHAR *dst;
 
     if ((dst = ExAllocatePool(PagedPool, len * sizeof(WCHAR))))
-    {
-        if (ext->input == (WORD)-1)
-        {
-            sprintfW(dst, formatW, ext->busid, ext->vid, ext->pid,
-                    ext->version, serial, ext->uid, ext->index);
-        }
-        else
-        {
-            sprintfW(dst, format_inputW, ext->busid, ext->vid, ext->pid, ext->is_gamepad ? igW : miW,
-                    ext->input, ext->version, serial, ext->uid, ext->index);
-        }
-    }
+        sprintfW(dst, formatW, ext->version, serial, ext->uid, ext->index);
 
     return dst;
 }
@@ -211,6 +200,7 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid,
                                      const GUID *class, const platform_vtbl *vtbl, DWORD platform_data_size)
 {
     static const WCHAR device_name_fmtW[] = {'\\','D','e','v','i','c','e','\\','%','s','#','%','p',0};
+    WCHAR *id, instance[MAX_DEVICE_ID_LEN];
     struct device_extension *ext;
     struct pnp_device *pnp_dev;
     DEVICE_OBJECT *device;
@@ -218,7 +208,6 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid,
     WCHAR dev_name[256];
     HDEVINFO devinfo;
     SP_DEVINFO_DATA data = {sizeof(data)};
-    WCHAR *instance = NULL;
     NTSTATUS status;
     DWORD length;
 
@@ -279,12 +268,22 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid,
         goto error;
     }
 
-    instance = get_instance_id(device);
-    if (!instance)
+    if (!(id = get_device_id(device)))
     {
         ERR("failed to generate instance id\n");
         goto error;
     }
+    strcpyW(instance, id);
+    ExFreePool(id);
+
+    if (!(id = get_instance_id(device)))
+    {
+        ERR("failed to generate instance id\n");
+        goto error;
+    }
+    strcatW(instance, backslashW);
+    strcatW(instance, id);
+    ExFreePool(id);
 
     if (SetupDiCreateDeviceInfoW(devinfo, instance, class, NULL, NULL, DICD_INHERIT_CLASSDRVS, &data))
     {
@@ -295,7 +294,6 @@ DEVICE_OBJECT *bus_create_hid_device(const WCHAR *busidW, WORD vid, WORD pid,
         ERR("failed to create device info, error %#x\n", GetLastError());
 
 error:
-    HeapFree(GetProcessHeap(), 0, instance);
     SetupDiDestroyDeviceInfoList(devinfo);
     return device;
 }
-- 
2.7.4




More information about the wine-devel mailing list