hidclass.sys: Unload all devices before unloading a minidriver.
Signed-off-by: Aric Stewart <aric@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
87acb93586
commit
f97bbef0e5
|
@ -70,6 +70,12 @@ void RingBuffer_Destroy(struct ReportRingBuffer *buffer) DECLSPEC_HIDDEN;
|
||||||
struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN;
|
struct ReportRingBuffer* RingBuffer_Create(UINT buffer_size) DECLSPEC_HIDDEN;
|
||||||
NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *buffer, UINT size) DECLSPEC_HIDDEN;
|
NTSTATUS RingBuffer_SetSize(struct ReportRingBuffer *buffer, UINT size) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
typedef struct _hiddevice
|
||||||
|
{
|
||||||
|
struct list entry;
|
||||||
|
DEVICE_OBJECT *device;
|
||||||
|
} hid_device;
|
||||||
|
|
||||||
typedef struct _minidriver
|
typedef struct _minidriver
|
||||||
{
|
{
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
@ -80,6 +86,7 @@ typedef struct _minidriver
|
||||||
|
|
||||||
pAddDevice AddDevice;
|
pAddDevice AddDevice;
|
||||||
PDRIVER_DISPATCH PNPDispatch;
|
PDRIVER_DISPATCH PNPDispatch;
|
||||||
|
struct list device_list;
|
||||||
} minidriver;
|
} minidriver;
|
||||||
|
|
||||||
NTSTATUS call_minidriver(ULONG code, DEVICE_OBJECT *device, void *in_buff, ULONG in_size, void *out_buff, ULONG out_size) DECLSPEC_HIDDEN;
|
NTSTATUS call_minidriver(ULONG code, DEVICE_OBJECT *device, void *in_buff, ULONG in_size, void *out_buff, ULONG out_size) DECLSPEC_HIDDEN;
|
||||||
|
@ -100,6 +107,7 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDE
|
||||||
|
|
||||||
/* Pseudo-Plug and Play support*/
|
/* Pseudo-Plug and Play support*/
|
||||||
NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT* PDO) DECLSPEC_HIDDEN;
|
NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT* PDO) DECLSPEC_HIDDEN;
|
||||||
|
NTSTATUS PNP_RemoveDevice(minidriver *minidriver, DEVICE_OBJECT* device, IRP* irp) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* Parsing HID Report Descriptors into preparsed data */
|
/* Parsing HID Report Descriptors into preparsed data */
|
||||||
WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) DECLSPEC_HIDDEN;
|
WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -49,6 +49,12 @@ static VOID WINAPI UnloadDriver(DRIVER_OBJECT *driver)
|
||||||
md = find_minidriver(driver);
|
md = find_minidriver(driver);
|
||||||
if (md)
|
if (md)
|
||||||
{
|
{
|
||||||
|
hid_device *device, *next;
|
||||||
|
TRACE("%i devices to unload\n", list_count(&md->device_list));
|
||||||
|
LIST_FOR_EACH_ENTRY_SAFE(device, next, &md->device_list, hid_device, entry)
|
||||||
|
{
|
||||||
|
PNP_RemoveDevice(md, device->device, NULL);
|
||||||
|
}
|
||||||
if (md->DriverUnload)
|
if (md->DriverUnload)
|
||||||
md->DriverUnload(md->minidriver.DriverObject);
|
md->DriverUnload(md->minidriver.DriverObject);
|
||||||
list_remove(&md->entry);
|
list_remove(&md->entry);
|
||||||
|
@ -82,6 +88,8 @@ NTSTATUS WINAPI HidRegisterMinidriver(HID_MINIDRIVER_REGISTRATION *registration)
|
||||||
driver->minidriver = *registration;
|
driver->minidriver = *registration;
|
||||||
list_add_tail(&minidriver_list, &driver->entry);
|
list_add_tail(&minidriver_list, &driver->entry);
|
||||||
|
|
||||||
|
list_init(&driver->device_list);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,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)
|
NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
|
||||||
{
|
{
|
||||||
|
hid_device *hiddev;
|
||||||
DEVICE_OBJECT *device = NULL;
|
DEVICE_OBJECT *device = NULL;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
minidriver *minidriver;
|
minidriver *minidriver;
|
||||||
|
@ -96,13 +97,19 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
|
||||||
TRACE("PDO add device(%p:%s)\n", PDO, debugstr_w(PDO_id));
|
TRACE("PDO add device(%p:%s)\n", PDO, debugstr_w(PDO_id));
|
||||||
minidriver = find_minidriver(driver);
|
minidriver = find_minidriver(driver);
|
||||||
|
|
||||||
status = HID_CreateDevice(PDO, &minidriver->minidriver, &device);
|
hiddev = HeapAlloc(GetProcessHeap(), 0, sizeof(*hiddev));
|
||||||
|
if (!hiddev)
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
|
||||||
|
status = HID_CreateDevice(PDO, &minidriver->minidriver, &hiddev->device);
|
||||||
if (status != STATUS_SUCCESS)
|
if (status != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("Failed to create HID object (%x)\n",status);
|
ERR("Failed to create HID object (%x)\n",status);
|
||||||
HeapFree(GetProcessHeap(), 0, PDO_id);
|
HeapFree(GetProcessHeap(), 0, PDO_id);
|
||||||
|
HeapFree(GetProcessHeap(), 0, hiddev);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
device = hiddev->device;
|
||||||
|
|
||||||
ext = device->DeviceExtension;
|
ext = device->DeviceExtension;
|
||||||
InitializeListHead(&ext->irp_queue);
|
InitializeListHead(&ext->irp_queue);
|
||||||
|
@ -177,6 +184,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
|
||||||
return STATUS_NOT_SUPPORTED;
|
return STATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_add_tail(&(minidriver->device_list), &hiddev->entry);
|
||||||
|
|
||||||
ext->information.DescriptorSize = ext->preparseData->dwSize;
|
ext->information.DescriptorSize = ext->preparseData->dwSize;
|
||||||
|
|
||||||
lstrcpyW(ext->instance_id, device_enumeratorW);
|
lstrcpyW(ext->instance_id, device_enumeratorW);
|
||||||
|
@ -200,6 +209,26 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS PNP_RemoveDevice(minidriver *minidriver, DEVICE_OBJECT *device, IRP *irp)
|
||||||
|
{
|
||||||
|
hid_device *hiddev;
|
||||||
|
NTSTATUS rc = STATUS_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
if (irp)
|
||||||
|
rc = minidriver->PNPDispatch(device, irp);
|
||||||
|
HID_DeleteDevice(&minidriver->minidriver, device);
|
||||||
|
LIST_FOR_EACH_ENTRY(hiddev, &minidriver->device_list, hid_device, entry)
|
||||||
|
{
|
||||||
|
if (hiddev->device == device)
|
||||||
|
{
|
||||||
|
list_remove(&hiddev->entry);
|
||||||
|
HeapFree(GetProcessHeap(), 0, hiddev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
|
NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
{
|
{
|
||||||
NTSTATUS rc = STATUS_NOT_SUPPORTED;
|
NTSTATUS rc = STATUS_NOT_SUPPORTED;
|
||||||
|
@ -255,9 +284,7 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
|
||||||
}
|
}
|
||||||
case IRP_MN_REMOVE_DEVICE:
|
case IRP_MN_REMOVE_DEVICE:
|
||||||
{
|
{
|
||||||
rc = minidriver->PNPDispatch(device, irp);
|
return PNP_RemoveDevice(minidriver, device, irp);
|
||||||
HID_DeleteDevice(&minidriver->minidriver, device);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue