Fix handling of input and output buffers Modified: trunk/reactos/drivers/dd/serial/devctrl.c _____
Modified: trunk/reactos/drivers/dd/serial/devctrl.c --- trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-27 11:13:25 UTC (rev 14344) +++ trunk/reactos/drivers/dd/serial/devctrl.c 2005-03-27 11:14:30 UTC (rev 14345) @@ -12,6 +12,38 @@
#define NDEBUG #include "serial.h"
+#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003) + +static VOID +SerialGetUserBuffers( + IN PIRP Irp, + IN ULONG IoControlCode, + OUT PVOID* BufferIn, + OUT PVOID* BufferOut) +{ + ASSERT(Irp); + ASSERT(BufferIn); + ASSERT(BufferOut); + + switch (IO_METHOD_FROM_CTL_CODE(IoControlCode)) + { + case METHOD_BUFFERED: + *BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer; + return; + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: + *BufferIn = Irp->AssociatedIrp.SystemBuffer; + *BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress); + return; + case METHOD_NEITHER: + *BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3Input Buffer; + *BufferOut = Irp->UserBuffer; + return; + } + + /* Should never happen */ +} + NTSTATUS STDCALL SerialSetBaudRate( IN PSERIAL_DEVICE_EXTENSION DeviceExtension, @@ -244,10 +276,11 @@ IN PIRP Irp) { PIO_STACK_LOCATION Stack; + ULONG IoControlCode; PSERIAL_DEVICE_EXTENSION DeviceExtension; ULONG LengthIn, LengthOut; ULONG Information = 0; - PUCHAR Buffer; + PVOID BufferIn, BufferOut; PUCHAR ComPortBase; NTSTATUS Status; @@ -258,13 +291,14 @@ Stack = IoGetCurrentIrpStackLocation(Irp); LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength; LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength; - Buffer = Irp->AssociatedIrp.SystemBuffer; DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension; ComPortBase = (PUCHAR)DeviceExtension->BaseAddress; + IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode; + SerialGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut); /* FIXME: need to probe buffers */ /* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */ - switch (Stack->Parameters.DeviceIoControl.IoControlCode) + switch (IoControlCode) { case IOCTL_SERIAL_CLEAR_STATS: { @@ -301,11 +335,11 @@ /* Obsolete on Microsoft Windows 2000+ */ PULONG pConfigSize; DPRINT("Serial: IOCTL_SERIAL_CONFIG_SIZE\n"); - if (LengthOut != sizeof(ULONG) || Buffer == NULL) + if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - pConfigSize = (PULONG)Buffer; + pConfigSize = (PULONG)BufferOut; *pConfigSize = 0; Status = STATUS_SUCCESS; } @@ -314,18 +348,17 @@ case IOCTL_SERIAL_GET_BAUD_RATE: { DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n"); - /* FIXME: HACK!!! following line MUST NOT be here! */ - Buffer = Irp->UserBuffer; if (LengthOut < sizeof(SERIAL_BAUD_RATE)) Status = STATUS_BUFFER_TOO_SMALL; - else if (Buffer == NULL) + else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - ((PSERIAL_BAUD_RATE)Buffer)->BaudRate = DeviceExtension->BaudRate; + ((PSERIAL_BAUD_RATE)BufferOut)->BaudRate = DeviceExtension->BaudRate; Information = sizeof(SERIAL_BAUD_RATE); Status = STATUS_SUCCESS; } + break; } case IOCTL_SERIAL_GET_CHARS: { @@ -342,14 +375,14 @@ DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; } - else if (Buffer == NULL) + else if (BufferOut == NULL) { DPRINT("Serial: return STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else { - Status = SerialGetCommStatus((PSERIAL_STATUS)Buffer, DeviceExtension); + Status = SerialGetCommStatus((PSERIAL_STATUS)BufferOut, DeviceExtension); Information = sizeof(SERIAL_STATUS); } break; @@ -358,11 +391,11 @@ { PULONG pDtrRts; DPRINT("Serial: IOCTL_SERIAL_GET_DTRRTS\n"); - if (LengthOut != sizeof(ULONG) || Buffer == NULL) + if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - pDtrRts = (PULONG)Buffer; + pDtrRts = (PULONG)BufferOut; *pDtrRts = 0; if (DeviceExtension->MCR & SR_MCR_DTR) *pDtrRts |= SERIAL_DTR_STATE; @@ -384,11 +417,11 @@ DPRINT("Serial: IOCTL_SERIAL_GET_LINE_CONTROL\n"); if (LengthOut < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; - else if (Buffer == NULL) + else if (BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - *((PSERIAL_LINE_CONTROL)Buffer) = DeviceExtension->SerialLineControl; + *((PSERIAL_LINE_CONTROL)BufferOut) = DeviceExtension->SerialLineControl; Information = sizeof(SERIAL_LINE_CONTROL); Status = STATUS_SUCCESS; } @@ -398,11 +431,11 @@ { PULONG pMCR; DPRINT("Serial: IOCTL_SERIAL_GET_MODEM_CONTROL\n"); - if (LengthOut != sizeof(ULONG) || Buffer == NULL) + if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - pMCR = (PULONG)Buffer; + pMCR = (PULONG)BufferOut; *pMCR = DeviceExtension->MCR; Status = STATUS_SUCCESS; } @@ -412,11 +445,11 @@ { PULONG pMSR; DPRINT("Serial: IOCTL_SERIAL_GET_MODEMSTATUS\n"); - if (LengthOut != sizeof(ULONG) || Buffer == NULL) + if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - pMSR = (PULONG)Buffer; + pMSR = (PULONG)BufferOut; *pMSR = DeviceExtension->MSR; Status = STATUS_SUCCESS; } @@ -430,14 +463,14 @@ DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; } - else if (Buffer == NULL) + else if (BufferOut == NULL) { DPRINT("Serial: return STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else { - Status = SerialGetCommProp((PSERIAL_COMMPROP)Buffer, DeviceExtension); + Status = SerialGetCommProp((PSERIAL_COMMPROP)BufferOut, DeviceExtension); Information = sizeof(SERIAL_COMMPROP); } break; @@ -450,7 +483,7 @@ DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n"); Status = STATUS_BUFFER_TOO_SMALL; } - else if (Buffer == NULL) + else if (BufferOut == NULL) { DPRINT("Serial: return STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; @@ -467,11 +500,11 @@ case IOCTL_SERIAL_GET_TIMEOUTS: { DPRINT("Serial: IOCTL_SERIAL_GET_TIMEOUTS\n"); - if (LengthOut != sizeof(SERIAL_TIMEOUTS) || Buffer == NULL) + if (LengthOut != sizeof(SERIAL_TIMEOUTS) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - *(PSERIAL_TIMEOUTS)Buffer = DeviceExtension->SerialTimeOuts; + *(PSERIAL_TIMEOUTS)BufferOut = DeviceExtension->SerialTimeOuts; Status = STATUS_SUCCESS; } break; @@ -480,11 +513,11 @@ { PULONG pWaitMask; DPRINT("Serial: IOCTL_SERIAL_GET_WAIT_MASK\n"); - if (LengthOut != sizeof(ULONG) || Buffer == NULL) + if (LengthOut != sizeof(ULONG) || BufferOut == NULL) Status = STATUS_INVALID_PARAMETER; else { - pWaitMask = (PULONG)Buffer; + pWaitMask = (PULONG)BufferOut; *pWaitMask = DeviceExtension->WaitMask; Status = STATUS_SUCCESS; } @@ -534,11 +567,11 @@ { PULONG pNewBaudRate; DPRINT("Serial: IOCTL_SERIAL_SET_BAUD_RATE\n"); - if (LengthIn != sizeof(ULONG) || Buffer == NULL) + if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { - pNewBaudRate = (PULONG)Buffer; + pNewBaudRate = (PULONG)BufferIn; Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate); } break; @@ -580,11 +613,11 @@ case IOCTL_SERIAL_SET_FIFO_CONTROL: { DPRINT("Serial: IOCTL_SERIAL_SET_FIFO_CONTROL\n"); - if (LengthIn != sizeof(ULONG) || Buffer == NULL) + if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { - WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)Buffer) & 0xff)); + WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff)); Status = STATUS_SUCCESS; } break; @@ -601,21 +634,21 @@ DPRINT("Serial: IOCTL_SERIAL_SET_LINE_CONTROL\n"); if (LengthIn < sizeof(SERIAL_LINE_CONTROL)) Status = STATUS_BUFFER_TOO_SMALL; - else if (Buffer == NULL) + else if (BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else - Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)Buffer); + Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)BufferIn); break; } case IOCTL_SERIAL_SET_MODEM_CONTROL: { PULONG pMCR; DPRINT("Serial: IOCTL_SERIAL_SET_MODEM_CONTROL\n"); - if (LengthIn != sizeof(ULONG) || Buffer == NULL) + if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { - pMCR = (PULONG)Buffer; + pMCR = (PULONG)BufferIn; DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff); WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR); Status = STATUS_SUCCESS; @@ -626,22 +659,23 @@ { if (LengthIn < sizeof(SERIAL_QUEUE_SIZE )) return STATUS_BUFFER_TOO_SMALL; - else if (Buffer == NULL) + else if (BufferIn == NULL) return STATUS_INVALID_PARAMETER; else { KIRQL Irql; + PSERIAL_QUEUE_SIZE NewQueueSize = (PSERIAL_QUEUE_SIZE)BufferIn; Status = STATUS_SUCCESS; - if (((PSERIAL_QUEUE_SIZE)Buffer)->InSize
DeviceExtension->InputBuffer.Length)
+ if (NewQueueSize->InSize > DeviceExtension->InputBuffer.Length) {
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql); - Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->InSize); + Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, NewQueueSize->InSize);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql); } - if (NT_SUCCESS(Status) && ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize > DeviceExtension->OutputBuffer.Length) + if (NT_SUCCESS(Status) && NewQueueSize->OutSize > DeviceExtension->OutputBuffer.Length) {
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql); - Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, ((PSERIAL_QUEUE_SIZE)Buffer)->OutSize); + Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, NewQueueSize->OutSize);
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql); } } @@ -663,11 +697,11 @@ case IOCTL_SERIAL_SET_TIMEOUTS: { DPRINT("Serial: IOCTL_SERIAL_SET_TIMEOUTS\n"); - if (LengthIn != sizeof(SERIAL_TIMEOUTS) || Buffer == NULL) + if (LengthIn != sizeof(SERIAL_TIMEOUTS) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { - DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)Buffer; + DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)BufferIn; Status = STATUS_SUCCESS; } break; @@ -676,11 +710,11 @@ { PULONG pWaitMask; DPRINT("Serial: IOCTL_SERIAL_SET_WAIT_MASK\n"); - if (LengthIn != sizeof(ULONG) || Buffer == NULL) + if (LengthIn != sizeof(ULONG) || BufferIn == NULL) Status = STATUS_INVALID_PARAMETER; else { - pWaitMask = (PULONG)Buffer; + pWaitMask = (PULONG)BufferIn; DeviceExtension->WaitMask = *pWaitMask; Status = STATUS_SUCCESS; }