ntoskrnl.exe: Correctly handle instance IDs.

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@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Zebediah Figura 2019-06-05 09:22:16 -05:00 committed by Alexandre Julliard
parent 510261a4b4
commit 6c6aeea8a8
4 changed files with 85 additions and 73 deletions

View File

@ -75,6 +75,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;
@ -87,6 +89,10 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
RtlInitUnicodeString( &nameW, ext->device_name);
lstrcpyW(device_instance_id, ext->device_id);
lstrcatW(device_instance_id, backslashW);
lstrcatW(device_instance_id, ext->instance_id);
devinfo = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_HIDCLASS, NULL);
if (devinfo == INVALID_HANDLE_VALUE)
{
@ -94,7 +100,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))
{

View File

@ -32,8 +32,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)
@ -43,7 +41,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;
@ -65,7 +63,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;
lstrcpyW(id, (WCHAR *)irp->IoStatus.Information);
ExFreePool( (WCHAR *)irp->IoStatus.Information );
status = irp->IoStatus.u.Status;
IoCompleteRequest(irp, IO_NO_INCREMENT );
CloseHandle(event);
@ -75,6 +74,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;
@ -84,17 +84,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));
@ -105,7 +108,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;
}
@ -120,7 +122,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;
}
@ -132,7 +133,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;
}
@ -147,7 +147,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++)
@ -158,7 +157,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;
}
@ -170,7 +168,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;
}
@ -181,7 +178,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;
}
@ -189,16 +185,11 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
ext->information.DescriptorSize = ext->preparseData->dwSize;
lstrcpyW(ext->instance_id, device_enumeratorW);
lstrcatW(ext->instance_id, separator_W);
/* Skip the original enumerator */
id_ptr = wcschr(PDO_id, '\\');
id_ptr++;
lstrcatW(ext->instance_id, id_ptr);
HeapFree(GetProcessHeap(), 0, PDO_id);
lstrcpyW(ext->instance_id, instance_id);
swprintf(ext->device_id, ARRAY_SIZE(ext->device_id), device_deviceid_fmtW,
device_enumeratorW, ext->information.VendorID, ext->information.ProductID);
lstrcpyW(ext->device_id, device_enumeratorW);
lstrcatW(ext->device_id, separator_W);
lstrcatW(ext->device_id, wcschr(device_id, '\\') + 1);
HID_LinkDevice(device);
@ -261,7 +252,11 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
{
WCHAR *ptr;
ptr = id;
/* Instance ID */
/* Device instance ID */
lstrcpyW(ptr, ext->device_id);
ptr += lstrlenW(ext->device_id);
lstrcpyW(ptr, separator_W);
ptr += 1;
lstrcpyW(ptr, ext->instance_id);
ptr += lstrlenW(ext->instance_id) + 1;
/* Device ID */

View File

@ -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;

View File

@ -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;
}