📄 ioctl.c
字号:
pIrp->IoStatus.Information = sizeof(ULONG);
break;
}
case IOCTL_SERIAL_GET_COMMSTATUS: {
PSERIAL_STATUS pSysBuf;
PIRP pIrpWrite;
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_STATUS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pSysBuf = (PSERIAL_STATUS)pIrp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(pSysBuf, sizeof(*pSysBuf));
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
pSysBuf->AmountInInQueue = (ULONG)C0C_BUFFER_BUSY(&pIoPortLocal->readBuf);
pIrpWrite = pIoPortLocal->irpQueues[C0C_QUEUE_WRITE].pCurrent;
if (pIrpWrite) {
PIO_STACK_LOCATION pIrpStackWrite = IoGetCurrentIrpStackLocation(pIrpWrite);
if (pIrpStackWrite->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
pIrpStackWrite->Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR)
{
pSysBuf->WaitForImmediate = TRUE;
}
}
pSysBuf->AmountInOutQueue = pIoPortLocal->amountInWriteQueue;
pSysBuf->HoldReasons = pIoPortLocal->writeHolding;
if ((pIoPortLocal->handFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) &&
(pIoPortLocal->modemStatus & C0C_MSB_DSR) == 0)
{
pSysBuf->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR;
}
if (pIoPortLocal->writeHoldingRemote & SERIAL_TX_WAITING_FOR_XON)
pSysBuf->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
pSysBuf->Errors = pIoPortLocal->errors;
pIoPortLocal->errors = 0;
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIAL_STATUS);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
}
case IOCTL_SERIAL_SET_HANDFLOW: {
LIST_ENTRY queueToComplete;
PSERIAL_HANDFLOW pSysBuf;
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_HANDFLOW)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pSysBuf = (PSERIAL_HANDFLOW)pIrp->AssociatedIrp.SystemBuffer;
if (pSysBuf->ControlHandShake & SERIAL_CONTROL_INVALID ||
pSysBuf->FlowReplace & SERIAL_FLOW_INVALID ||
(pSysBuf->ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_MASK ||
pSysBuf->XonLimit < 0 ||
pSysBuf->XoffLimit < 0)
{
status = STATUS_INVALID_PARAMETER;
break;
}
InitializeListHead(&queueToComplete);
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
status = SetHandFlow(pIoPortLocal, pSysBuf, &queueToComplete);
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
FdoPortCompleteQueue(&queueToComplete);
break;
}
case IOCTL_SERIAL_GET_HANDFLOW:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_HANDFLOW)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
*(PSERIAL_HANDFLOW)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->handFlow;
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_SET_TIMEOUTS:
status = FdoPortSetTimeouts(pDevExt, pIrp, pIrpStack);
break;
case IOCTL_SERIAL_GET_TIMEOUTS:
status = FdoPortGetTimeouts(pDevExt, pIrp, pIrpStack);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_SET_CHARS: {
PSERIAL_CHARS pSysBuf;
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_CHARS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pSysBuf = (PSERIAL_CHARS)pIrp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
if (pIoPortLocal->escapeChar &&
((pIoPortLocal->escapeChar == pSysBuf->XoffChar) ||
(pIoPortLocal->escapeChar == pSysBuf->XonChar)))
{
status = STATUS_INVALID_PARAMETER;
}
if (status == STATUS_SUCCESS)
pIoPortLocal->specialChars = *pSysBuf;
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
break;
}
case IOCTL_SERIAL_GET_CHARS:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_CHARS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
*(PSERIAL_CHARS)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->specialChars;
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIAL_CHARS);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_LSRMST_INSERT: {
UCHAR escapeChar;
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(UCHAR)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
escapeChar = *(PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
if (escapeChar && ((escapeChar == pIoPortLocal->specialChars.XoffChar) ||
(escapeChar == pIoPortLocal->specialChars.XonChar) ||
(pIoPortLocal->handFlow.FlowReplace & SERIAL_ERROR_CHAR)))
{
status = STATUS_INVALID_PARAMETER;
}
if (status == STATUS_SUCCESS) {
pIoPortLocal->escapeChar = escapeChar;
pIrp->IoStatus.Information = sizeof(UCHAR);
}
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
break;
}
case IOCTL_SERIAL_SET_LINE_CONTROL:
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
pDevExt->lineControl = *(PSERIAL_LINE_CONTROL)pIrp->AssociatedIrp.SystemBuffer;
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
SetWriteDelay(pIoPortLocal);
break;
case IOCTL_SERIAL_GET_LINE_CONTROL:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
*(PSERIAL_LINE_CONTROL)pIrp->AssociatedIrp.SystemBuffer = pDevExt->lineControl;
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_SET_BAUD_RATE:
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_BAUD_RATE)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
pDevExt->baudRate = *(PSERIAL_BAUD_RATE)pIrp->AssociatedIrp.SystemBuffer;
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
SetWriteDelay(pIoPortLocal);
break;
case IOCTL_SERIAL_GET_BAUD_RATE:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_BAUD_RATE)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
*(PSERIAL_BAUD_RATE)pIrp->AssociatedIrp.SystemBuffer = pDevExt->baudRate;
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_GET_PROPERTIES: {
ULONG size;
status = GetCommProp(pDevExt,
pIrp->AssociatedIrp.SystemBuffer,
pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
&size);
if (status == STATUS_SUCCESS)
pIrp->IoStatus.Information = size;
break;
}
case IOCTL_SERIAL_CONFIG_SIZE:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pIrp->IoStatus.Information = sizeof(ULONG);
*(PULONG)pIrp->AssociatedIrp.SystemBuffer = 0;
break;
case IOCTL_SERIAL_SET_QUEUE_SIZE: {
PSERIAL_QUEUE_SIZE pSysBuf = (PSERIAL_QUEUE_SIZE)pIrp->AssociatedIrp.SystemBuffer;
LIST_ENTRY queueToComplete;
PC0C_BUFFER pReadBuf;
PUCHAR pBase;
if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_QUEUE_SIZE)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
pReadBuf = &pIoPortLocal->readBuf;
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
if (pSysBuf->InSize <= C0C_BUFFER_SIZE(pReadBuf)) {
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
break;
}
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
try {
pBase = ExAllocatePoolWithQuota(NonPagedPool, pSysBuf->InSize);
} except (EXCEPTION_EXECUTE_HANDLER) {
pBase = NULL;
status = GetExceptionCode();
}
if (!pBase)
break;
InitializeListHead(&queueToComplete);
KeAcquireSpinLock(pIoPortLocal->pIoLock, &oldIrql);
if (SetNewBufferBase(pReadBuf, pBase, pSysBuf->InSize)) {
pIoPortLocal->handFlow.XoffLimit = pSysBuf->InSize >> 3;
pIoPortLocal->handFlow.XonLimit = pSysBuf->InSize >> 1;
SetLimit(pIoPortLocal);
UpdateHandFlow(pIoPortLocal, TRUE, &queueToComplete);
if (pIoPortLocal->tryWrite || pIoPortLocal->pIoPortRemote->tryWrite) {
ReadWrite(
pIoPortLocal, FALSE,
pIoPortLocal->pIoPortRemote, FALSE,
&queueToComplete);
}
}
KeReleaseSpinLock(pIoPortLocal->pIoLock, oldIrql);
FdoPortCompleteQueue(&queueToComplete);
break;
}
case IOCTL_SERIAL_GET_STATS:
if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIALPERF_STATS)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
*(PSERIALPERF_STATS)pIrp->AssociatedIrp.SystemBuffer = pIoPortLocal->perfStats;
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
pIrp->IoStatus.Information = sizeof(SERIALPERF_STATS);
TraceIrp("FdoPortIoCtl", pIrp, &status, TRACE_FLAG_RESULTS);
break;
case IOCTL_SERIAL_CLEAR_STATS:
KeAcquireSpinLock(&pDevExt->controlLock, &oldIrql);
RtlZeroMemory(&pIoPortLocal->perfStats, sizeof(pIoPortLocal->perfStats));
KeReleaseSpinLock(&pDevExt->controlLock, oldIrql);
break;
default:
status = STATUS_INVALID_PARAMETER;
}
}
if (status != STATUS_PENDING) {
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
return status;
}
NTSTATUS c0cIoControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp)
{
NTSTATUS status;
PC0C_COMMON_EXTENSION pDevExt = pDevObj->DeviceExtension;
#if DBG
ULONG code = IoGetCurrentIrpStackLocation(pIrp)->Parameters.DeviceIoControl.IoControlCode;
#endif /* DBG */
TraceIrp("c0cIoControl", pIrp, NULL, TRACE_FLAG_PARAMS);
switch (pDevExt->doType) {
case C0C_DOTYPE_FP:
status = FdoPortIoCtl((PC0C_FDOPORT_EXTENSION)pDevExt, pIrp);
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = status;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
#if DBG
if (status != STATUS_SUCCESS)
TraceCode(pDevExt, "IOCTL_", codeNameTableIoctl, code, &status);
#endif /* DBG */
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -