mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
Support IRP cancellation
svn path=/trunk/; revision=30066
This commit is contained in:
parent
42bab9d044
commit
426db02b5b
4 changed files with 207 additions and 139 deletions
|
@ -19,6 +19,12 @@ static DRIVER_DISPATCH ClassDeviceControl;
|
|||
static DRIVER_DISPATCH IrpStub;
|
||||
static DRIVER_ADD_DEVICE ClassAddDevice;
|
||||
static DRIVER_STARTIO ClassStartIo;
|
||||
static DRIVER_CANCEL ClassCancelRoutine;
|
||||
static NTSTATUS
|
||||
HandleReadIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
BOOLEAN IsInStartIo);
|
||||
|
||||
static VOID NTAPI
|
||||
DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||
|
@ -82,8 +88,14 @@ ClassRead(
|
|||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("IRP_MJ_READ\n");
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
|
||||
|
@ -96,9 +108,10 @@ ClassRead(
|
|||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
return STATUS_PENDING;
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
|
||||
Status = HandleReadIrp(DeviceObject, Irp, FALSE);
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
|
@ -370,7 +383,6 @@ cleanup:
|
|||
InitializeListHead(&DeviceExtension->ListHead);
|
||||
KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
|
||||
KeInitializeSpinLock(&DeviceExtension->SpinLock);
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
DeviceExtension->InputCount = 0;
|
||||
DeviceExtension->PortData = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA), CLASS_TAG);
|
||||
if (!DeviceExtension->PortData)
|
||||
|
@ -454,56 +466,16 @@ ClassCallback(
|
|||
IN OUT PULONG ConsumedCount)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
PIRP Irp = NULL;
|
||||
KIRQL OldIrql;
|
||||
SIZE_T InputCount = DataEnd - DataStart;
|
||||
SIZE_T ReadSize;
|
||||
|
||||
DPRINT("ClassCallback()\n");
|
||||
|
||||
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
||||
|
||||
DPRINT("ClassCallback()\n");
|
||||
/* A filter driver might have consumed all the data already; I'm
|
||||
* not sure if they are supposed to move the packets when they
|
||||
* consume them though.
|
||||
*/
|
||||
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
||||
{
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
||||
|
||||
Status = FillEntries(
|
||||
ClassDeviceObject,
|
||||
Irp,
|
||||
DataStart,
|
||||
NumberOfEntries);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
||||
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
/* Skip the packet we just sent away */
|
||||
DataStart += NumberOfEntries;
|
||||
(*ConsumedCount) += (ULONG)NumberOfEntries;
|
||||
InputCount -= NumberOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have data from the port driver and a higher service to send the data to */
|
||||
if (InputCount != 0)
|
||||
if (InputCount > 0)
|
||||
{
|
||||
if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize)
|
||||
{
|
||||
|
@ -529,20 +501,13 @@ ClassCallback(
|
|||
ClassDeviceExtension->InputCount += ReadSize;
|
||||
|
||||
(*ConsumedCount) += (ULONG)ReadSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("ClassCallback(): no more data to process\n");
|
||||
}
|
||||
|
||||
/* Complete pending IRP (if any) */
|
||||
if (ClassDeviceExtension->PendingIrp)
|
||||
HandleReadIrp(ClassDeviceObject, ClassDeviceExtension->PendingIrp, FALSE);
|
||||
}
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
||||
|
||||
if (Irp != NULL)
|
||||
{
|
||||
IoStartNextPacket(ClassDeviceObject, FALSE);
|
||||
IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
|
||||
}
|
||||
|
||||
DPRINT("Leaving ClassCallback()\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -693,6 +658,7 @@ ClassAddDevice(
|
|||
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
||||
goto cleanup;
|
||||
}
|
||||
IoSetStartIoAttributes(Fdo, TRUE, TRUE);
|
||||
|
||||
DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(PORT_DEVICE_EXTENSION));
|
||||
|
@ -753,26 +719,61 @@ cleanup:
|
|||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
ClassCancelRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN wasQueued = FALSE;
|
||||
|
||||
DPRINT("ClassCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
||||
IoAcquireCancelSpinLock(&OldIrql);
|
||||
if (ClassDeviceExtension->PendingIrp == Irp)
|
||||
{
|
||||
ClassDeviceExtension->PendingIrp = NULL;
|
||||
wasQueued = TRUE;
|
||||
}
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
||||
|
||||
if (wasQueued)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hm, this shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
HandleReadIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
BOOLEAN IsInStartIo)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("HandleReadIrp(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
if (DeviceExtension->InputCount > 0)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
DeviceExtension->InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(KEYBOARD_INPUT_DATA));
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
||||
|
||||
Status = FillEntries(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
|
@ -790,22 +791,55 @@ ClassStartIo(
|
|||
}
|
||||
|
||||
DeviceExtension->InputCount -= NumberOfEntries;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(KEYBOARD_INPUT_DATA);
|
||||
}
|
||||
|
||||
/* Go to next packet and complete this request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
|
||||
|
||||
if (IsInStartIo)
|
||||
IoStartNextPacket(DeviceObject, TRUE);
|
||||
|
||||
(VOID)IoSetCancelRoutine(Irp, NULL);
|
||||
IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
DeviceExtension->PendingIrp = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceExtension->ReadIsPending = TRUE;
|
||||
(VOID)IoSetCancelRoutine(Irp, ClassCancelRoutine);
|
||||
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
||||
{
|
||||
DeviceExtension->PendingIrp = NULL;
|
||||
Status = STATUS_CANCELLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
DeviceExtension->PendingIrp = Irp;
|
||||
Status = STATUS_PENDING;
|
||||
if (!IsInStartIo)
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("ClassStartIo(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
|
||||
HandleReadIrp(DeviceObject, Irp, TRUE);
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct _CLASS_DEVICE_EXTENSION
|
|||
LIST_ENTRY ListHead;
|
||||
KSPIN_LOCK ListSpinLock;
|
||||
KSPIN_LOCK SpinLock;
|
||||
BOOLEAN ReadIsPending;
|
||||
PIRP PendingIrp;
|
||||
SIZE_T InputCount;
|
||||
PKEYBOARD_INPUT_DATA PortData;
|
||||
LPCWSTR DeviceName;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Mouse class driver
|
||||
* FILE: drivers/mouclass/mouclass.c
|
||||
* PURPOSE: Mouse class driver
|
||||
*
|
||||
*
|
||||
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
|
||||
*/
|
||||
|
||||
|
@ -19,6 +19,12 @@ static DRIVER_DISPATCH ClassDeviceControl;
|
|||
static DRIVER_DISPATCH IrpStub;
|
||||
static DRIVER_ADD_DEVICE ClassAddDevice;
|
||||
static DRIVER_STARTIO ClassStartIo;
|
||||
static DRIVER_CANCEL ClassCancelRoutine;
|
||||
static NTSTATUS
|
||||
HandleReadIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
BOOLEAN IsInStartIo);
|
||||
|
||||
static VOID NTAPI
|
||||
DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||
|
@ -82,8 +88,14 @@ ClassRead(
|
|||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("IRP_MJ_READ\n");
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
|
||||
return ForwardIrpAndForget(DeviceObject, Irp);
|
||||
|
||||
|
@ -96,9 +108,10 @@ ClassRead(
|
|||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
return STATUS_PENDING;
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
|
||||
Status = HandleReadIrp(DeviceObject, Irp, FALSE);
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
|
||||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
|
@ -347,9 +360,8 @@ cleanup:
|
|||
InitializeListHead(&DeviceExtension->ListHead);
|
||||
KeInitializeSpinLock(&DeviceExtension->ListSpinLock);
|
||||
KeInitializeSpinLock(&DeviceExtension->SpinLock);
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
DeviceExtension->InputCount = 0;
|
||||
DeviceExtension->PortData = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(KEYBOARD_INPUT_DATA), CLASS_TAG);
|
||||
DeviceExtension->PortData = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->DriverExtension->DataQueueSize * sizeof(MOUSE_INPUT_DATA), CLASS_TAG);
|
||||
if (!DeviceExtension->PortData)
|
||||
{
|
||||
ExFreePoolWithTag(DeviceNameU.Buffer, CLASS_TAG);
|
||||
|
@ -430,56 +442,16 @@ ClassCallback(
|
|||
IN OUT PULONG ConsumedCount)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = ClassDeviceObject->DeviceExtension;
|
||||
PIRP Irp = NULL;
|
||||
KIRQL OldIrql;
|
||||
SIZE_T InputCount = DataEnd - DataStart;
|
||||
SIZE_T ReadSize;
|
||||
|
||||
DPRINT("ClassCallback()\n");
|
||||
|
||||
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
||||
|
||||
DPRINT("ClassCallback()\n");
|
||||
/* A filter driver might have consumed all the data already; I'm
|
||||
* not sure if they are supposed to move the packets when they
|
||||
* consume them though.
|
||||
*/
|
||||
if (ClassDeviceExtension->ReadIsPending == TRUE && InputCount)
|
||||
{
|
||||
/* A read request is waiting for input, so go straight to it */
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
Irp = ClassDeviceObject->CurrentIrp;
|
||||
ClassDeviceObject->CurrentIrp = NULL;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(MOUSE_INPUT_DATA));
|
||||
|
||||
Status = FillEntries(
|
||||
ClassDeviceObject,
|
||||
Irp,
|
||||
DataStart,
|
||||
NumberOfEntries);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Go to next packet and complete this request with STATUS_SUCCESS */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(MOUSE_INPUT_DATA);
|
||||
|
||||
ClassDeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
/* Skip the packet we just sent away */
|
||||
DataStart += NumberOfEntries;
|
||||
(*ConsumedCount) += (ULONG)NumberOfEntries;
|
||||
InputCount -= NumberOfEntries;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have data from the port driver and a higher service to send the data to */
|
||||
if (InputCount != 0)
|
||||
if (InputCount > 0)
|
||||
{
|
||||
if (ClassDeviceExtension->InputCount + InputCount > ClassDeviceExtension->DriverExtension->DataQueueSize)
|
||||
{
|
||||
|
@ -505,20 +477,13 @@ ClassCallback(
|
|||
ClassDeviceExtension->InputCount += ReadSize;
|
||||
|
||||
(*ConsumedCount) += (ULONG)ReadSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("ClassCallback(): no more data to process\n");
|
||||
}
|
||||
|
||||
/* Complete pending IRP (if any) */
|
||||
if (ClassDeviceExtension->PendingIrp)
|
||||
HandleReadIrp(ClassDeviceObject, ClassDeviceExtension->PendingIrp, FALSE);
|
||||
}
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
||||
|
||||
if (Irp != NULL)
|
||||
{
|
||||
IoStartNextPacket(ClassDeviceObject, FALSE);
|
||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||
}
|
||||
|
||||
DPRINT("Leaving ClassCallback()\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -669,6 +634,7 @@ ClassAddDevice(
|
|||
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
|
||||
goto cleanup;
|
||||
}
|
||||
IoSetStartIoAttributes(Fdo, TRUE, TRUE);
|
||||
|
||||
DeviceExtension = (PPORT_DEVICE_EXTENSION)Fdo->DeviceExtension;
|
||||
RtlZeroMemory(DeviceExtension, sizeof(PORT_DEVICE_EXTENSION));
|
||||
|
@ -729,26 +695,61 @@ cleanup:
|
|||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
ClassCancelRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION ClassDeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN wasQueued = FALSE;
|
||||
|
||||
DPRINT("ClassCancelRoutine(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(ClassDeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&ClassDeviceExtension->SpinLock, &OldIrql);
|
||||
IoAcquireCancelSpinLock(&OldIrql);
|
||||
if (ClassDeviceExtension->PendingIrp == Irp)
|
||||
{
|
||||
ClassDeviceExtension->PendingIrp = NULL;
|
||||
wasQueued = TRUE;
|
||||
}
|
||||
KeReleaseSpinLock(&ClassDeviceExtension->SpinLock, OldIrql);
|
||||
|
||||
if (wasQueued)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Hm, this shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
HandleReadIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
BOOLEAN IsInStartIo)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("HandleReadIrp(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
if (DeviceExtension->InputCount > 0)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
NTSTATUS Status;
|
||||
SIZE_T NumberOfEntries;
|
||||
|
||||
NumberOfEntries = MIN(
|
||||
DeviceExtension->InputCount,
|
||||
IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length / sizeof(MOUSE_INPUT_DATA));
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &oldIrql);
|
||||
|
||||
Status = FillEntries(
|
||||
DeviceObject,
|
||||
Irp,
|
||||
|
@ -766,22 +767,55 @@ ClassStartIo(
|
|||
}
|
||||
|
||||
DeviceExtension->InputCount -= NumberOfEntries;
|
||||
DeviceExtension->ReadIsPending = FALSE;
|
||||
|
||||
Irp->IoStatus.Information = NumberOfEntries * sizeof(MOUSE_INPUT_DATA);
|
||||
}
|
||||
|
||||
/* Go to next packet and complete this request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, oldIrql);
|
||||
|
||||
if (IsInStartIo)
|
||||
IoStartNextPacket(DeviceObject, TRUE);
|
||||
|
||||
(VOID)IoSetCancelRoutine(Irp, NULL);
|
||||
IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
DeviceExtension->PendingIrp = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceExtension->ReadIsPending = TRUE;
|
||||
(VOID)IoSetCancelRoutine(Irp, ClassCancelRoutine);
|
||||
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
||||
{
|
||||
DeviceExtension->PendingIrp = NULL;
|
||||
Status = STATUS_CANCELLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
IoMarkIrpPending(Irp);
|
||||
DeviceExtension->PendingIrp = Irp;
|
||||
Status = STATUS_PENDING;
|
||||
if (!IsInStartIo)
|
||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
ClassStartIo(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PCLASS_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("ClassStartIo(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
|
||||
|
||||
ASSERT(DeviceExtension->Common.IsClassDO);
|
||||
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &OldIrql);
|
||||
HandleReadIrp(DeviceObject, Irp, TRUE);
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, OldIrql);
|
||||
}
|
||||
|
||||
static VOID NTAPI
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct _CLASS_DEVICE_EXTENSION
|
|||
LIST_ENTRY ListHead;
|
||||
KSPIN_LOCK ListSpinLock;
|
||||
KSPIN_LOCK SpinLock;
|
||||
BOOLEAN ReadIsPending;
|
||||
PIRP PendingIrp;
|
||||
SIZE_T InputCount;
|
||||
PMOUSE_INPUT_DATA PortData;
|
||||
LPCWSTR DeviceName;
|
||||
|
|
Loading…
Reference in a new issue