📄 ioctl.c
字号:
("SERIAL: In Ioctl processing for wait mask\n")
);
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
SerialDump(
SERDIAG3,
("SERIAL: Invalid size for the buffer %d\n",
irpStack->Parameters.DeviceIoControl.OutputBufferLength)
);
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Either start this irp or put it on the
// queue.
//
SerialDump(
SERDIAG3 | SERIRPPATH,
("SERIAL: Starting or queuing wait mask irp %x\n",Irp)
);
return SerialStartOrQueue(
deviceExtension,
Irp,
&deviceExtension->MaskQueue,
&deviceExtension->CurrentMaskIrp,
SerialStartMask
);
}
case IOCTL_SERIAL_IMMEDIATE_CHAR: {
KIRQL OldIrql;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(UCHAR)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
IoAcquireCancelSpinLock(&OldIrql);
if (deviceExtension->CurrentImmediateIrp) {
ntStatus = 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);
ntStatus = STATUS_CANCELLED;
} else {
deviceExtension->CurrentImmediateIrp = Irp;
deviceExtension->TotalCharsQueued++;
IoReleaseCancelSpinLock(OldIrql);
// SerialStartImmediate(deviceExtension);
return STATUS_PENDING;
}
}
break;
}
case IOCTL_SERIAL_PURGE: {
ULONG Mask;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG)) {
ntStatus = 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
)
)
)) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
//
// Either start this irp or put it on the
// queue.
//
return SerialStartOrQueue(
deviceExtension,
Irp,
&deviceExtension->PurgeQueue,
&deviceExtension->CurrentPurgeIrp,
SerialStartPurge
);
}
case IOCTL_SERIAL_GET_HANDFLOW: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
*((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
deviceExtension->HandFlow;
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_HANDFLOW: {
SERIAL_IOCTL_SYNC S;
PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
USHORT Value = 0;
//
// Make sure that the hand shake and control is the
// right size.
//
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
ntStatus = 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) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) {
ntStatus = 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) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
//
// Make sure that haven't set totally invalid xon/xoff
// limits.
//
if ((HandFlow->XonLimit < 0) ||
((ULONG)HandFlow->XonLimit > deviceExtension->BufferSize)) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->XoffLimit < 0) ||
((ULONG)HandFlow->XoffLimit > deviceExtension->BufferSize)) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
S.Extension = deviceExtension;
S.Data = HandFlow;
DbgPrint("ControlHandShake = 0x%x\n", HandFlow->ControlHandShake);
DbgPrint("FlowReplace = 0x%x\n", HandFlow->FlowReplace);
DbgPrint("XonLimit = %ld\n", HandFlow->XonLimit);
DbgPrint("XoffLimit = %ld\n", HandFlow->XoffLimit);
if (HandFlow->ControlHandShake & SERIAL_DTR_HANDSHAKE)
Value = 0x0A;
if (HandFlow->FlowReplace & SERIAL_RTS_HANDSHAKE)
Value |= 0x11;
if (HandFlow->FlowReplace & (SERIAL_AUTO_TRANSMIT | SERIAL_AUTO_RECEIVE))
Value |= 0x180;
UsbCom_SendVendor(DeviceObject, VendorFlowCtrl, Value);
/*
KeAcquireSpinLock(
&deviceExtension->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 (deviceExtension->EscapeChar) {
if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) {
ntStatus = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetHandFlow,
&S
);
// SerialSetHandFlow(&S);
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
*/
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS: {
SERIAL_IOCTL_SYNC S;
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
S.Extension = deviceExtension;
S.Data = Irp->AssociatedIrp.SystemBuffer;
/*
KeAcquireSpinLock(
&Extension->ControlLock,
&OldIrql
);
KeSynchronizeExecution(
Extension->Interrupt,
SerialGetModemUpdate,
&S
);
KeReleaseSpinLock(
&Extension->ControlLock,
OldIrql
);
*/
SerialGetModemUpdate(&S);
break;
}
case IOCTL_SERIAL_GET_PROPERTIES: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_COMMPROP)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// No synchronization is required since this information
// is "static".
//
SerialGetProperties(
deviceExtension,
Irp->AssociatedIrp.SystemBuffer
);
Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_XOFF_COUNTER: {
PSERIAL_XOFF_COUNTER Xc = Irp->AssociatedIrp.SystemBuffer;
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_XOFF_COUNTER)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
if (Xc->Counter <= 0) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
//
// There is no output, so make that clear now
//
Irp->IoStatus.Information = 0;
//
// So far so good. Put the irp onto the write queue.
//
return SerialStartOrQueue(
deviceExtension,
Irp,
&deviceExtension->WriteQueue,
&deviceExtension->CurrentWriteIrp,
SerialStartWrite
);
}
case IOCTL_SERIAL_LSRMST_INSERT: {
PUCHAR escapeChar = Irp->AssociatedIrp.SystemBuffer;
SERIAL_IOCTL_SYNC S;
//
// Make sure we get a byte.
//
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(UCHAR)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
if (*escapeChar) {
//
// We've got some escape work to do. We will make sure that
// the character is not the same as the Xon or Xoff character,
// or that we are already doing error replacement.
//
if ((*escapeChar == deviceExtension->SpecialChars.XoffChar) ||
(*escapeChar == deviceExtension->SpecialChars.XonChar) ||
(deviceExtension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR)) {
ntStatus = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
}
S.Extension = deviceExtension;
S.Data = Irp->AssociatedIrp.SystemBuffer;
/*
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetEscapeChar,
Irp
);
*/
SerialSetEscapeChar(Irp);
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_CONFIG_SIZE: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
Irp->IoStatus.Status = STATUS_SUCCESS;
*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
break;
}
case IOCTL_SERIAL_GET_STATS: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIALPERF_STATS)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIALPERF_STATS);
Irp->IoStatus.Status = STATUS_SUCCESS;
/*
KeSynchronizeExecution(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -