hidclass.sys: Make read IRP queue thread safe.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Aric Stewart <aric@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-05-08 23:09:03 +02:00 committed by Alexandre Julliard
parent 08a899d433
commit 85082e8bd3
4 changed files with 27 additions and 11 deletions

View File

@ -1,6 +1,6 @@
MODULE = hidclass.sys MODULE = hidclass.sys
IMPORTLIB = hidclass IMPORTLIB = hidclass
IMPORTS = ntoskrnl IMPORTS = hal ntoskrnl
DELAYIMPORTS = setupapi hid DELAYIMPORTS = setupapi hid
C_SRCS = \ C_SRCS = \

View File

@ -126,10 +126,25 @@ error:
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
static IRP *pop_irp_from_queue(BASE_DEVICE_EXTENSION *ext)
{
LIST_ENTRY *entry;
KIRQL old_irql;
IRP *irp = NULL;
KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql);
entry = RemoveHeadList(&ext->irp_queue);
if (entry != &ext->irp_queue)
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry);
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
return irp;
}
void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device) void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device)
{ {
BASE_DEVICE_EXTENSION *ext; BASE_DEVICE_EXTENSION *ext;
LIST_ENTRY *entry;
IRP *irp; IRP *irp;
ext = device->DeviceExtension; ext = device->DeviceExtension;
@ -145,13 +160,10 @@ void HID_DeleteDevice(HID_MINIDRIVER_REGISTRATION *driver, DEVICE_OBJECT *device
if (ext->ring_buffer) if (ext->ring_buffer)
RingBuffer_Destroy(ext->ring_buffer); RingBuffer_Destroy(ext->ring_buffer);
entry = RemoveHeadList(&ext->irp_queue); while((irp = pop_irp_from_queue(ext)))
while(entry != &ext->irp_queue)
{ {
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry);
irp->IoStatus.u.Status = STATUS_DEVICE_REMOVED; irp->IoStatus.u.Status = STATUS_DEVICE_REMOVED;
IoCompleteRequest(irp, IO_NO_INCREMENT); IoCompleteRequest(irp, IO_NO_INCREMENT);
entry = RemoveHeadList(&ext->irp_queue);
} }
TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name)); TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name));
@ -189,7 +201,6 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U
static void HID_Device_processQueue(DEVICE_OBJECT *device) static void HID_Device_processQueue(DEVICE_OBJECT *device)
{ {
LIST_ENTRY *entry;
IRP *irp; IRP *irp;
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
UINT buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer); UINT buffer_size = RingBuffer_GetBufferSize(ext->ring_buffer);
@ -197,11 +208,9 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
packet = HeapAlloc(GetProcessHeap(), 0, buffer_size); packet = HeapAlloc(GetProcessHeap(), 0, buffer_size);
entry = RemoveHeadList(&ext->irp_queue); while((irp = pop_irp_from_queue(ext)))
while(entry != &ext->irp_queue)
{ {
int ptr; int ptr;
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.s.ListEntry);
ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext ); ptr = PtrToUlong( irp->Tail.Overlay.OriginalFileObject->FsContext );
RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size); RingBuffer_Read(ext->ring_buffer, ptr, packet, &buffer_size);
@ -222,7 +231,6 @@ static void HID_Device_processQueue(DEVICE_OBJECT *device)
irp->IoStatus.u.Status = STATUS_UNSUCCESSFUL; irp->IoStatus.u.Status = STATUS_UNSUCCESSFUL;
} }
IoCompleteRequest( irp, IO_NO_INCREMENT ); IoCompleteRequest( irp, IO_NO_INCREMENT );
entry = RemoveHeadList(&ext->irp_queue);
} }
HeapFree(GetProcessHeap(), 0, packet); HeapFree(GetProcessHeap(), 0, packet);
} }
@ -656,9 +664,15 @@ NTSTATUS WINAPI HID_Device_read(DEVICE_OBJECT *device, IRP *irp)
BASE_DEVICE_EXTENSION *extension = device->DeviceExtension; BASE_DEVICE_EXTENSION *extension = device->DeviceExtension;
if (extension->poll_interval) if (extension->poll_interval)
{ {
KIRQL old_irql;
TRACE_(hid_report)("Queue irp\n"); TRACE_(hid_report)("Queue irp\n");
KeAcquireSpinLock(&ext->irp_queue_lock, &old_irql);
InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry); InsertTailList(&ext->irp_queue, &irp->Tail.Overlay.s.ListEntry);
rc = STATUS_PENDING; rc = STATUS_PENDING;
KeReleaseSpinLock(&ext->irp_queue_lock, old_irql);
} }
else else
{ {

View File

@ -54,6 +54,7 @@ typedef struct _BASE_DEVICE_EXTENSION {
HANDLE halt_event; HANDLE halt_event;
HANDLE thread; HANDLE thread;
KSPIN_LOCK irp_queue_lock;
LIST_ENTRY irp_queue; LIST_ENTRY irp_queue;
/* Minidriver Specific stuff will end up here */ /* Minidriver Specific stuff will end up here */

View File

@ -114,6 +114,7 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
ext = device->DeviceExtension; ext = device->DeviceExtension;
InitializeListHead(&ext->irp_queue); InitializeListHead(&ext->irp_queue);
KeInitializeSpinLock(&ext->irp_queue_lock);
TRACE("Created device %p\n",device); TRACE("Created device %p\n",device);
status = minidriver->AddDevice(minidriver->minidriver.DriverObject, device); status = minidriver->AddDevice(minidriver->minidriver.DriverObject, device);