* Sync up to trunk head (r64716).
[reactos.git] / drivers / serial / serial / devctrl.c
index 2f8f563..b7f056d 100644 (file)
@@ -9,6 +9,8 @@
 
 #include "serial.h"
 
+#include <debug.h>
+
 #define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
 
 static VOID
@@ -374,8 +376,24 @@ SerialDeviceControl(
                case IOCTL_SERIAL_GET_CHARS:
                {
                        /* FIXME */
+                       PSERIAL_CHARS pSerialChars;
                        ERR_(SERIAL, "IOCTL_SERIAL_GET_CHARS not implemented.\n");
-                       Status = STATUS_NOT_IMPLEMENTED;
+                       if (LengthOut < sizeof(SERIAL_CHARS))
+                               Status = STATUS_BUFFER_TOO_SMALL;
+                       else if (BufferOut == NULL)
+                               Status = STATUS_INVALID_PARAMETER;
+                       else
+                       {
+                               pSerialChars = (PSERIAL_CHARS)BufferOut;
+                               pSerialChars->EofChar = 0;
+                               pSerialChars->ErrorChar = 0;
+                               pSerialChars->BreakChar = 0;
+                               pSerialChars->EventChar = 0;
+                               pSerialChars->XonChar = 0;
+                               pSerialChars->XoffChar = 0;
+                               Information = sizeof(SERIAL_CHARS);
+                               Status = STATUS_SUCCESS;
+                       }
                        break;
                }
                case IOCTL_SERIAL_GET_COMMSTATUS:
@@ -414,8 +432,22 @@ SerialDeviceControl(
                case IOCTL_SERIAL_GET_HANDFLOW:
                {
                        /* FIXME */
+                       PSERIAL_HANDFLOW pSerialHandflow;
                        ERR_(SERIAL, "IOCTL_SERIAL_GET_HANDFLOW not implemented.\n");
-                       Status = STATUS_NOT_IMPLEMENTED;
+                       if (LengthOut < sizeof(SERIAL_HANDFLOW))
+                               Status = STATUS_BUFFER_TOO_SMALL;
+                       else if (BufferOut == NULL)
+                               Status = STATUS_INVALID_PARAMETER;
+                       else
+                       {
+                               pSerialHandflow = (PSERIAL_HANDFLOW)BufferOut;
+                               pSerialHandflow->ControlHandShake = 0;
+                               pSerialHandflow->FlowReplace = 0;
+                               pSerialHandflow->XonLimit = 0;
+                               pSerialHandflow->XoffLimit = 0;
+                               Information = sizeof(SERIAL_HANDFLOW);
+                               Status = STATUS_SUCCESS;
+                       }
                        break;
                }
                case IOCTL_SERIAL_GET_LINE_CONTROL:
@@ -623,7 +655,7 @@ SerialDeviceControl(
                {
                        /* FIXME */
                        ERR_(SERIAL, "IOCTL_SERIAL_SET_CHARS not implemented.\n");
-                       Status = STATUS_NOT_IMPLEMENTED;
+                       Status = STATUS_SUCCESS;
                        break;
                }
                case IOCTL_SERIAL_SET_DTR:
@@ -665,7 +697,7 @@ SerialDeviceControl(
                {
                        /* FIXME */
                        ERR_(SERIAL, "IOCTL_SERIAL_SET_HANDFLOW not implemented.\n");
-                       Status = STATUS_NOT_IMPLEMENTED;
+                       Status = STATUS_SUCCESS;
                        break;
                }
                case IOCTL_SERIAL_SET_LINE_CONTROL:
@@ -797,12 +829,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,
+                                       &DeviceExtension->WaitOnMaskIrp,
                                        Irp,
                                        NULL);
 
@@ -811,13 +841,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;
                }