From: Aric Stewart Subject: [PATCH 2/3] hidclass.sys: Implement IRP_MN_QUERY_ID for HID devices Message-Id: <56ABA0E9.2080005@codeweavers.com> Date: Fri, 29 Jan 2016 11:27:05 -0600 Signed-off-by: Aric Stewart --- dlls/hidclass.sys/hid.h | 5 ++++ dlls/hidclass.sys/main.c | 3 ++ dlls/hidclass.sys/pnp.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 0dcc3a6..8d384c6 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -27,6 +27,7 @@ #include "ddk/hidport.h" #include "ddk/hidclass.h" #include "ddk/hidpi.h" +#include "cfgmgr32.h" #include "wine/list.h" #include "parse.h" @@ -47,6 +48,8 @@ typedef struct _BASE_DEVICE_EXTENSTION { ULONG poll_interval; WCHAR *device_name; WCHAR *link_name; + WCHAR device_id[MAX_DEVICE_ID_LEN]; + WCHAR instance_id[MAX_DEVICE_ID_LEN]; struct ReportRingBuffer *ring_buffer; HANDLE halt_event; HANDLE thread; @@ -75,6 +78,7 @@ typedef struct _minidriver PDRIVER_UNLOAD DriverUnload; pAddDevice AddDevice; + PDRIVER_DISPATCH PNPDispatch; } minidriver; NTSTATUS call_minidriver(ULONG code, DEVICE_OBJECT *device, void *in_buff, ULONG in_size, void *out_buff, ULONG out_size) DECLSPEC_HIDDEN; @@ -91,6 +95,7 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN NTSTATUS WINAPI HID_Device_write(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; NTSTATUS WINAPI HID_Device_create(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; NTSTATUS WINAPI HID_Device_close(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; +NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN; /* Pseudo-Plug and Play support*/ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT* PDO) DECLSPEC_HIDDEN; diff --git a/dlls/hidclass.sys/main.c b/dlls/hidclass.sys/main.c index b124218..7fdcd59 100644 --- a/dlls/hidclass.sys/main.c +++ b/dlls/hidclass.sys/main.c @@ -74,6 +74,9 @@ NTSTATUS WINAPI HidRegisterMinidriver(HID_MINIDRIVER_REGISTRATION *registration) registration->DriverObject->MajorFunction[IRP_MJ_CREATE] = HID_Device_create; registration->DriverObject->MajorFunction[IRP_MJ_CLOSE] = HID_Device_close; + driver->PNPDispatch = registration->DriverObject->MajorFunction[IRP_MJ_PNP]; + registration->DriverObject->MajorFunction[IRP_MJ_PNP] = HID_PNP_Dispatch; + driver->AddDevice = registration->DriverObject->DriverExtension->AddDevice; registration->DriverObject->DriverExtension->AddDevice = PNP_AddDevice; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 24dd140..d8b4a80 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -23,12 +23,20 @@ #include #include "hid.h" #include "ddk/hidtypes.h" +#include "regstr.h" #include "wine/debug.h" #include "wine/unicode.h" #include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(hid); +static const WCHAR device_enumeratorW[] = {'H','I','D',0}; +static const WCHAR device_deviceid_fmtW[] = {'%','s','\\', + 'v','i','d','_','%','0','4','x','&','p','i','d','_','%', '0','4','x'}; +static const WCHAR device_instanceid_fmtW[] = {'%','s','\\', + 'v','i','d','_','%','0','4','x','&','p','i','d','_','%', + '0','4','x','&','%','s','\\','%','i','&','%','s',0}; + typedef struct _NATIVE_DEVICE { struct list entry; @@ -231,6 +239,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO) sprintfW(interface, ig_fmtW, interface_index); else sprintfW(interface, im_fmtW, interface_index); + sprintfW(ext->instance_id, device_instanceid_fmtW, device_enumeratorW, ext->information.VendorID, ext->information.ProductID, interface, ext->information.VersionNumber, serial); + sprintfW(ext->device_id, device_deviceid_fmtW, device_enumeratorW, ext->information.VendorID, ext->information.ProductID); HID_LinkDevice(device, serial, interface); @@ -261,3 +271,65 @@ void PNP_CleanupPNP(DRIVER_OBJECT *driver) } } } + +NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) +{ + NTSTATUS rc = STATUS_NOT_SUPPORTED; + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation(irp); + + TRACE("%p, %p\n", device, irp); + + switch(irpsp->MinorFunction) + { + case IRP_MN_QUERY_ID: + { + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + ULONG type = irpsp->Parameters.QueryId.IdType; + WCHAR *id = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*REGSTR_VAL_MAX_HCID_LEN); + TRACE("IRP_MN_QUERY_ID[%i]\n", type); + switch (type) + { + case BusQueryHardwareIDs: + case BusQueryCompatibleIDs: + { + WCHAR *ptr; + ptr = id; + /* Instance ID */ + strcpyW(ptr, ext->instance_id); + ptr += lstrlenW(ext->instance_id) + 1; + /* Device ID */ + strcpyW(ptr, ext->device_id); + ptr += lstrlenW(ext->device_id) + 1; + /* Bus ID */ + strcpyW(ptr, device_enumeratorW); + ptr += lstrlenW(device_enumeratorW) + 1; + *ptr = 0; + irp->IoStatus.Information = (ULONG_PTR)id; + rc = STATUS_SUCCESS; + break; + } + case BusQueryDeviceID: + strcpyW(id, ext->device_id); + irp->IoStatus.Information = (ULONG_PTR)id; + rc = STATUS_SUCCESS; + break; + case BusQueryInstanceID: + strcpyW(id, ext->instance_id); + irp->IoStatus.Information = (ULONG_PTR)id; + rc = STATUS_SUCCESS; + break; + } + break; + } + default: + { + /* Forward IRP to the minidriver */ + minidriver *minidriver = find_minidriver(device->DriverObject); + return minidriver->PNPDispatch(device, irp); + } + } + + irp->IoStatus.u.Status = rc; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return rc; +}