📄 ioctl.c
字号:
((PSERIAL_QUEUE_SIZE)(Irp->AssociatedIrp.SystemBuffer));
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_QUEUE_SIZE)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// We have to allocate the memory for the new
// buffer while we're still in the context of the
// caller. We don't even try to protect this
// with a lock because the value could be stale
// as soon as we release the lock - The only time
// we will know for sure is when we actually try
// to do the resize.
//
if (Rs->InSize <= Extension->BufferSize) {
Status = STATUS_SUCCESS;
break;
}
try {
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer =
ExAllocatePoolWithQuota(
NonPagedPool,
Rs->InSize
);
} except (EXCEPTION_EXECUTE_HANDLER) {
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
Status = GetExceptionCode();
}
if (!IrpSp->Parameters.DeviceIoControl.Type3InputBuffer) {
break;
}
//
// Well the data passed was big enough. Do the request.
//
// There are two reason we place it in the read queue:
//
// 1) We want to serialize these resize requests so that
// they don't contend with each other.
//
// 2) We want to serialize these requests with reads since
// we don't want reads and resizes contending over the
// read buffer.
//
return SerialStartOrQueue(
Extension,
Irp,
&Extension->ReadQueue,
&Extension->CurrentReadIrp,
SerialStartRead
);
break;
}
case IOCTL_SERIAL_GET_WAIT_MASK: {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Simple scalar read. No reason to acquire a lock.
//
Irp->IoStatus.Information = sizeof(ULONG);
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) = Extension->IsrWaitMask;
break;
}
case IOCTL_SERIAL_SET_WAIT_MASK: {
ULONG NewMask;
SerialDbgPrintEx(SERIRPPATH, "In Ioctl processing for set mask\n");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG)) {
SerialDbgPrintEx(SERDIAG3, "Invalid size fo the buffer %d\n",
IrpSp->Parameters
.DeviceIoControl.InputBufferLength);
Status = STATUS_BUFFER_TOO_SMALL;
break;
} else {
NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
}
//
// Make sure that the mask only contains valid
// waitable events.
//
if (NewMask & ~(SERIAL_EV_RXCHAR |
SERIAL_EV_RXFLAG |
SERIAL_EV_TXEMPTY |
SERIAL_EV_CTS |
SERIAL_EV_DSR |
SERIAL_EV_RLSD |
SERIAL_EV_BREAK |
SERIAL_EV_ERR |
SERIAL_EV_RING |
SERIAL_EV_PERR |
SERIAL_EV_RX80FULL |
SERIAL_EV_EVENT1 |
SERIAL_EV_EVENT2)) {
SerialDbgPrintEx(SERDIAG3, "Unknown mask %x\n", NewMask);
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Either start this irp or put it on the
// queue.
//
SerialDbgPrintEx(SERIRPPATH, "Starting or queuing set mask irp %x"
"\n", Irp);
return SerialStartOrQueue(Extension, Irp, &Extension->MaskQueue,
&Extension->CurrentMaskIrp,
SerialStartMask);
}
case IOCTL_SERIAL_WAIT_ON_MASK: {
SerialDbgPrintEx(SERIRPPATH, "In Ioctl processing for wait mask\n");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
SerialDbgPrintEx(SERDIAG3, "Invalid size for the buffer %d\n",
IrpSp->Parameters
.DeviceIoControl.OutputBufferLength);
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Either start this irp or put it on the
// queue.
//
SerialDbgPrintEx(SERIRPPATH, "Starting or queuing wait mask irp"
"%x\n", Irp);
return SerialStartOrQueue(
Extension,
Irp,
&Extension->MaskQueue,
&Extension->CurrentMaskIrp,
SerialStartMask
);
}
case IOCTL_SERIAL_IMMEDIATE_CHAR: {
KIRQL OldIrql;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(UCHAR)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
IoAcquireCancelSpinLock(&OldIrql);
if (Extension->CurrentImmediateIrp) {
Status = STATUS_INVALID_PARAMETER;
IoReleaseCancelSpinLock(OldIrql);
} else {
//
// We can queue the char. We need to set
// a cancel routine because flow control could
// keep the char from transmitting. Make sure
// that the irp hasn't already been canceled.
//
if (Irp->Cancel) {
IoReleaseCancelSpinLock(OldIrql);
Status = STATUS_CANCELLED;
} else {
Extension->CurrentImmediateIrp = Irp;
Extension->TotalCharsQueued++;
IoReleaseCancelSpinLock(OldIrql);
SerialStartImmediate(Extension);
return STATUS_PENDING;
}
}
break;
}
case IOCTL_SERIAL_PURGE: {
ULONG Mask;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Check to make sure that the mask only has
// 0 or the other appropriate values.
//
Mask = *((ULONG *)(Irp->AssociatedIrp.SystemBuffer));
if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
SERIAL_PURGE_RXABORT |
SERIAL_PURGE_TXCLEAR |
SERIAL_PURGE_RXCLEAR
)
)
)) {
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Either start this irp or put it on the
// queue.
//
return SerialStartOrQueue(
Extension,
Irp,
&Extension->PurgeQueue,
&Extension->CurrentPurgeIrp,
SerialStartPurge
);
}
case IOCTL_SERIAL_GET_HANDFLOW: {
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
*((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
Extension->HandFlow;
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_HANDFLOW: {
SERIAL_IOCTL_SYNC S;
PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
//
// Make sure that the hand shake and control is the
// right size.
//
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Make sure that there are no invalid bits set in
// the control and handshake.
//
if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) {
Status = STATUS_INVALID_PARAMETER;
break;
}
if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) {
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Make sure that the app hasn't set an invlid DTR mode.
//
if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_MASK) {
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Make sure that haven't set totally invalid xon/xoff
// limits.
//
if ((HandFlow->XonLimit < 0) ||
((ULONG)HandFlow->XonLimit > Extension->BufferSize)) {
Status = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->XoffLimit < 0) ||
((ULONG)HandFlow->XoffLimit > Extension->BufferSize)) {
Status = STATUS_INVALID_PARAMETER;
break;
}
S.Extension = Extension;
S.Data = HandFlow;
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
//
// Under the protection of the lock, make sure that
// we aren't turning on error replacement when we
// are doing line status/modem status insertion.
//
if (Extension->EscapeChar) {
if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) {
Status = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetHandFlow,
&S
);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS: {
SERIAL_IOCTL_SYNC S;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
S.Extension = Extension;
S.Data = Irp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
KeSynchronizeExecution(
Extension->Interrupt,
SerialGetModemUpdate,
&S
);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_DTRRTS: {
ULONG ModemControl;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Reading this hardware has no effect on the device.
//
ModemControl = READ_MODEM_CONTROL(Extension->Controller);
ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE;
*(PULONG)Irp->AssociatedIrp.SystemBuffer = ModemControl;
break;
}
case IOCTL_SERIAL_GET_COMMSTATUS: {
SERIAL_IOCTL_SYNC S;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_STATUS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -