#include "serial.h"
+#include <debug.h>
+
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
static VOID
return Status;
}
-static BOOLEAN
-SerialClearPerfStats(
- IN PSERIAL_DEVICE_EXTENSION DeviceExtension)
+static
+BOOLEAN
+NTAPI
+SerialClearPerfStats(IN PVOID SynchronizeContext)
{
- ASSERT(DeviceExtension);
-
- RtlZeroMemory(&DeviceExtension->SerialPerfStats, sizeof(SERIALPERF_STATS));
- DeviceExtension->BreakInterruptErrorCount = 0;
- return TRUE;
+ PSERIAL_DEVICE_EXTENSION DeviceExtension = SynchronizeContext;
+ ASSERT(DeviceExtension);
+ RtlZeroMemory(&DeviceExtension->SerialPerfStats, sizeof(SERIALPERF_STATS));
+ DeviceExtension->BreakInterruptErrorCount = 0;
+ return TRUE;
}
-static BOOLEAN
-SerialGetPerfStats(IN PIRP pIrp)
+static
+BOOLEAN
+NTAPI
+SerialGetPerfStats(IN PVOID SynchronizeContext)
{
- PSERIAL_DEVICE_EXTENSION pDeviceExtension;
-
- ASSERT(pIrp);
- pDeviceExtension = (PSERIAL_DEVICE_EXTENSION)
- IoGetCurrentIrpStackLocation(pIrp)->DeviceObject->DeviceExtension;
-
- /*
- * we assume buffer is big enough to hold SerialPerfStats structure
- * caller must verify this
- */
- RtlCopyMemory(
- pIrp->AssociatedIrp.SystemBuffer,
- &pDeviceExtension->SerialPerfStats,
- sizeof(SERIALPERF_STATS)
- );
- return TRUE;
+ PIRP pIrp = SynchronizeContext;
+ PSERIAL_DEVICE_EXTENSION pDeviceExtension;
+
+ ASSERT(pIrp);
+ pDeviceExtension = IoGetCurrentIrpStackLocation(pIrp)->DeviceObject->DeviceExtension;
+
+ /*
+ * we assume buffer is big enough to hold SerialPerfStats structure
+ * caller must verify this
+ */
+ RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer,
+ &pDeviceExtension->SerialPerfStats,
+ sizeof(SERIALPERF_STATS));
+ return TRUE;
}
static NTSTATUS
TRACE_(SERIAL, "IOCTL_SERIAL_CLEAR_STATS\n");
KeSynchronizeExecution(
DeviceExtension->Interrupt,
- (PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats,
+ SerialClearPerfStats,
DeviceExtension);
Status = STATUS_SUCCESS;
break;
else
{
KeSynchronizeExecution(DeviceExtension->Interrupt,
- (PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
+ SerialGetPerfStats, Irp);
Information = sizeof(SERIALPERF_STATS);
Status = STATUS_SUCCESS;
}
Status = STATUS_INVALID_PARAMETER;
else
{
- /* FIXME: Race condition here:
- * If an interrupt comes before we can mark the Irp
- * as pending, it might be possible to complete the
- * Irp before pending it, leading to a crash! */
+ IoMarkIrpPending(Irp);
+
WaitingIrp = InterlockedCompareExchangePointer(
- (PVOID)&DeviceExtension->WaitOnMaskIrp,
+ (PVOID*)&DeviceExtension->WaitOnMaskIrp,
Irp,
NULL);
{
/* Unable to have a 2nd pending IRP for this IOCTL */
WARN_(SERIAL, "Unable to pend a second IRP for IOCTL_SERIAL_WAIT_ON_MASK\n");
- Status = STATUS_INVALID_PARAMETER;
- }
- else
- {
- Status = STATUS_PENDING;
- /* FIXME: immediately return if a wait event already occurred */
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+ return STATUS_PENDING;
}
break;
}