hidclass.sys: Don't leak report queues on device removal.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-09-24 10:07:11 +02:00 committed by Alexandre Julliard
parent 8f1f061349
commit 9421dd2b3c
3 changed files with 33 additions and 2 deletions

View file

@ -116,9 +116,10 @@ static struct hid_report_queue *hid_report_queue_create( void )
return queue;
}
static void hid_report_queue_destroy( struct hid_report_queue *queue )
void hid_report_queue_destroy( struct hid_report_queue *queue )
{
while (queue->length--) hid_report_decref( queue->reports[queue->length] );
list_remove( &queue->entry );
free( queue );
}
@ -654,10 +655,22 @@ NTSTATUS WINAPI pdo_create(DEVICE_OBJECT *device, IRP *irp)
{
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_report_queue *queue;
BOOL removed;
KIRQL irql;
TRACE("Open handle on device %p\n", device);
KeAcquireSpinLock( &ext->u.pdo.lock, &irql );
removed = ext->u.pdo.removed;
KeReleaseSpinLock( &ext->u.pdo.lock, irql );
if (removed)
{
irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest( irp, IO_NO_INCREMENT );
return STATUS_DELETE_PENDING;
}
if (!(queue = hid_report_queue_create())) irp->IoStatus.Status = STATUS_NO_MEMORY;
else
{
@ -677,10 +690,22 @@ NTSTATUS WINAPI pdo_close(DEVICE_OBJECT *device, IRP *irp)
{
struct hid_report_queue *queue = irp->Tail.Overlay.OriginalFileObject->FsContext;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
BOOL removed;
KIRQL irql;
TRACE("Close handle on device %p\n", device);
KeAcquireSpinLock( &ext->u.pdo.lock, &irql );
removed = ext->u.pdo.removed;
KeReleaseSpinLock( &ext->u.pdo.lock, irql );
if (removed)
{
irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest( irp, IO_NO_INCREMENT );
return STATUS_DELETE_PENDING;
}
if (queue)
{
KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql );

View file

@ -123,7 +123,7 @@ void call_minidriver( ULONG code, DEVICE_OBJECT *device, void *in_buff, ULONG in
/* Internal device functions */
void HID_StartDeviceThread(DEVICE_OBJECT *device) DECLSPEC_HIDDEN;
void hid_report_queue_destroy( struct hid_report_queue *queue );
IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext) DECLSPEC_HIDDEN;
NTSTATUS WINAPI pdo_ioctl(DEVICE_OBJECT *device, IRP *irp) DECLSPEC_HIDDEN;

View file

@ -387,6 +387,7 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp)
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
HIDP_COLLECTION_DESC *desc = ext->u.pdo.device_desc.CollectionDesc;
NTSTATUS status = irp->IoStatus.Status;
struct hid_report_queue *queue, *next;
KIRQL irql;
TRACE("irp %p, minor function %#x.\n", irp, irpsp->MinorFunction);
@ -498,6 +499,11 @@ static NTSTATUS pdo_pnp(DEVICE_OBJECT *device, IRP *irp)
}
CloseHandle(ext->u.pdo.halt_event);
KeAcquireSpinLock( &ext->u.pdo.report_queues_lock, &irql );
LIST_FOR_EACH_ENTRY_SAFE( queue, next, &ext->u.pdo.report_queues, struct hid_report_queue, entry )
hid_report_queue_destroy( queue );
KeReleaseSpinLock( &ext->u.pdo.report_queues_lock, irql );
HidP_FreeCollectionDescription(&ext->u.pdo.device_desc);
RtlFreeUnicodeString(&ext->u.pdo.link_name);