⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ioctl.c

📁 这个是一个开源项目, 有能力的人可以一起来写
💻 C
📖 第 1 页 / 共 2 页
字号:
      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 + -