Amd64/misc 64bit fixes (#236)
[reactos.git] / drivers / serial / serial / devctrl.c
index f7d1566..74b8139 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "serial.h"
 
+#include <debug.h>
+
 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
 
 static VOID
@@ -156,36 +158,37 @@ SerialSetLineControl(
        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
@@ -307,7 +310,7 @@ SerialDeviceControl(
                        TRACE_(SERIAL, "IOCTL_SERIAL_CLEAR_STATS\n");
                        KeSynchronizeExecution(
                                DeviceExtension->Interrupt,
-                               (PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats,
+                               SerialClearPerfStats,
                                DeviceExtension);
                        Status = STATUS_SUCCESS;
                        break;
@@ -517,7 +520,7 @@ SerialDeviceControl(
                        else
                        {
                                KeSynchronizeExecution(DeviceExtension->Interrupt,
-                                       (PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
+                                       SerialGetPerfStats, Irp);
                                Information = sizeof(SERIALPERF_STATS);
                                Status = STATUS_SUCCESS;
                        }
@@ -827,12 +830,10 @@ SerialDeviceControl(
                                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);
 
@@ -841,13 +842,11 @@ SerialDeviceControl(
                                {
                                        /* 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;
                }