📄 ioctl.c
字号:
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
*((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = deviceExtension->Timeouts;
Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_CHARS: {
SERIAL_IOCTL_SYNC S;
PSERIAL_CHARS NewChars =
((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_CHARS)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// The only thing that can be wrong with the chars
// is that the xon and xoff characters are the
// same.
//
#if 0
if (NewChars->XonChar == NewChars->XoffChar) {
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
#endif
//
// We acquire the control lock so that only
// one request can GET or SET the characters
// at a time. The sets could be synchronized
// by the interrupt spinlock, but that wouldn't
// prevent multiple gets at the same time.
//
S.Extension = deviceExtension;
S.Data = NewChars;
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
//
// Under the protection of the lock, make sure that
// the xon and xoff characters aren't the same as
// the escape character.
//
if (deviceExtension->EscapeChar) {
if ((deviceExtension->EscapeChar == NewChars->XonChar) ||
(deviceExtension->EscapeChar == NewChars->XoffChar)) {
ntStatus = STATUS_INVALID_PARAMETER;
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
}
deviceExtension->WmiCommData.XonCharacter = NewChars->XonChar;
deviceExtension->WmiCommData.XoffCharacter = NewChars->XoffChar;
/*
KeSynchronizeExecution(
Extension->Interrupt,
SerialSetChars,
&S
);
*/
SerialSetChars(&S);
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_GET_CHARS: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_CHARS)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
*((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) = deviceExtension->SpecialChars;
Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
break;
}
case IOCTL_SERIAL_SET_DTR:
case IOCTL_SERIAL_CLR_DTR: {
//
// Make sure we are at power D0
//
/*
if (Extension->PowerState != PowerDeviceD0) {
ntStatus = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(ntStatus)) {
break;
}
}
*/
//
// We acquire the lock so that we can check whether
// automatic dtr flow control is enabled. If it is
// then we return an error since the app is not allowed
// to touch this if it is automatic.
//
/*
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
*/
if ((deviceExtension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
== SERIAL_DTR_HANDSHAKE) {
ntStatus = STATUS_INVALID_PARAMETER;
} else {
/*
KeSynchronizeExecution(
Extension->Interrupt,
((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_DTR)?
(SerialSetDTR):(SerialClrDTR)),
Extension
);
*/
if (irpStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_DTR)
SerialSetDTR(deviceExtension);
else
SerialClrDTR(deviceExtension);
}
/*
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
*/
break;
}
case IOCTL_SERIAL_RESET_DEVICE: {
break;
}
case IOCTL_SERIAL_SET_RTS:
case IOCTL_SERIAL_CLR_RTS: {
//
// Make sure we are at power D0
//
/*
if (Extension->PowerState != PowerDeviceD0) {
ntStatus = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(ntStatus)) {
break;
}
}
*/
//
// We acquire the lock so that we can check whether
// automatic rts flow control or transmit toggleing
// is enabled. If it is then we return an error since
// the app is not allowed to touch this if it is automatic
// or toggling.
//
/* This is remarked away because later calling IoBuildDeviceIoControlRequest must be
called at passive level.
KeAcquireSpinLock(
&deviceExtension->ControlLock,
&OldIrql
);
*/
if (((deviceExtension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
== SERIAL_RTS_HANDSHAKE) ||
((deviceExtension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
== SERIAL_TRANSMIT_TOGGLE)) {
ntStatus = STATUS_INVALID_PARAMETER;
} else {
/*
KeSynchronizeExecution(
Extension->Interrupt,
((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_RTS)?
(SerialSetRTS):(SerialClrRTS)),
Extension
);
*/
if (irpStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_RTS)
SerialSetRTS(deviceExtension);
else
SerialClrRTS(deviceExtension);
}
/*
KeReleaseSpinLock(
&deviceExtension->ControlLock,
OldIrql
);
*/
break;
}
case IOCTL_SERIAL_SET_XOFF: {
/*
KeSynchronizeExecution(
Extension->Interrupt,
SerialPretendXoff,
Extension
);
*/
SerialPretendXoff(deviceExtension);
break;
}
case IOCTL_SERIAL_SET_XON: {
/*
KeSynchronizeExecution(
Extension->Interrupt,
SerialPretendXon,
Extension
);
*/
SerialPretendXon(deviceExtension);
break;
}
case IOCTL_SERIAL_SET_BREAK_ON: {
//
// Make sure we are at power D0
//
/*
if (Extension->PowerState != PowerDeviceD0) {
ntStatus = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(ntStatus)) {
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialTurnOnBreak,
Extension
);
*/
SerialTurnOnBreak(deviceExtension);
break;
}
case IOCTL_SERIAL_SET_BREAK_OFF: {
//
// Make sure we are at power D0
//
/*
if (Extension->PowerState != PowerDeviceD0) {
ntStatus = SerialGotoPowerState(Extension->Pdo, Extension,
PowerDeviceD0);
if (!NT_SUCCESS(ntStatus)) {
break;
}
}
KeSynchronizeExecution(
Extension->Interrupt,
SerialTurnOffBreak,
Extension
);
*/
SerialTurnOffBreak(deviceExtension);
break;
}
case IOCTL_SERIAL_SET_QUEUE_SIZE: {
//
// Type ahead buffer is fixed, so we just validate
// the the users request is not bigger that our
// own internal buffer size.
//
PSERIAL_QUEUE_SIZE Rs =
((PSERIAL_QUEUE_SIZE)(Irp->AssociatedIrp.SystemBuffer));
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_QUEUE_SIZE)) {
ntStatus = 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 <= deviceExtension->BufferSize) {
ntStatus = STATUS_SUCCESS;
break;
}
try {
irpStack->Parameters.DeviceIoControl.Type3InputBuffer =
ExAllocatePoolWithQuota(
NonPagedPool,
Rs->InSize
);
} except (EXCEPTION_EXECUTE_HANDLER) {
irpStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
ntStatus = GetExceptionCode();
}
if (!irpStack->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(
deviceExtension,
Irp,
&deviceExtension->ReadQueue,
&deviceExtension->CurrentReadIrp,
SerialStartRead
);
break;
}
case IOCTL_SERIAL_GET_WAIT_MASK: {
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Simple scalar read. No reason to acquire a lock.
//
Irp->IoStatus.Information = sizeof(ULONG);
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) = deviceExtension->IsrWaitMask;
break;
}
case IOCTL_SERIAL_SET_WAIT_MASK: {
ULONG NewMask;
DbgPrint("SERIAL: In Ioctl processing for set mask\n");
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG)) {
DbgPrint("SERIAL: Invalid size fo the buffer %d\n",
irpStack->Parameters.DeviceIoControl.InputBufferLength);
ntStatus = 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)) {
DbgPrint("SERIAL: Unknown mask %x\n",NewMask);
ntStatus = STATUS_INVALID_PARAMETER;
break;
}
//
// Either start this irp or put it on the
// queue.
//
DbgPrint("SERIAL: Starting or queuing set mask irp %x\n",Irp);
return SerialStartOrQueue(
deviceExtension,
Irp,
&deviceExtension->MaskQueue,
&deviceExtension->CurrentMaskIrp,
SerialStartMask
);
}
case IOCTL_SERIAL_WAIT_ON_MASK: {
SerialDump(
SERDIAG3 | SERIRPPATH,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -