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

📄 io.c

📁 这个是一个开源项目, 有能力的人可以一起来写
💻 C
📖 第 1 页 / 共 3 页
字号:
    PNTSTATUS pStatusRead,
    PC0C_IO_PORT pReadIoPort,
    PLIST_ENTRY pQueueToComplete,
    PSIZE_T pWriteLimit,
    PSIZE_T pReadDone,
    PSIZE_T pWriteDone)
{
  SIZE_T readDone, writeDone;
  SIZE_T writeLength, readLength;
  C0C_FLOW_FILTER flowFilter;
  PVOID pWriteBuf, pReadBuf;
  BOOLEAN isBreak;

  isBreak = FALSE;

  pReadBuf = GET_REST_BUFFER(pIrpRead, pIrpRead->IoStatus.Information);
  readLength = IoGetCurrentIrpStackLocation(pIrpRead)->Parameters.Read.Length
                                                - pIrpRead->IoStatus.Information;

  if (pDataWrite->type == RW_DATA_TYPE_IRP) {
    PIRP pIrpWrite = pDataWrite->data.irp.pIrp;

    pWriteBuf = GET_REST_BUFFER(pIrpWrite, pIrpWrite->IoStatus.Information);
    writeLength = GetWriteLength(pIrpWrite) - pIrpWrite->IoStatus.Information;
  } else {
    HALT_UNLESS1(pDataWrite->type == RW_DATA_TYPE_CHR, pDataWrite->type);

    pWriteBuf = &pDataWrite->data.chr.chr;
    writeLength = pDataWrite->data.chr.isChr ? 1 : 0;
    if (pDataWrite->data.chr.type == RW_DATA_TYPE_CHR_BREAK)
      isBreak = TRUE;
  }

  FlowFilterInit(pReadIoPort, &flowFilter);

  CopyCharsWithEscape(
      &pReadIoPort->readBuf, &flowFilter,
      pReadBuf, readLength,
      pWriteBuf, (pWriteLimit && writeLength > *pWriteLimit) ? *pWriteLimit : writeLength,
      &readDone, &writeDone);

  if (pWriteLimit)
    *pWriteLimit -= writeDone;

  pIrpRead->IoStatus.Information += readDone;

  if (pDataWrite->type == RW_DATA_TYPE_IRP) {
    pDataWrite->data.irp.pIrp->IoStatus.Information += writeDone;
    pReadIoPort->pIoPortRemote->amountInWriteQueue -= (ULONG)writeDone;
  }

  if (readDone == readLength)
    *pStatusRead = STATUS_SUCCESS;

  if (writeDone == writeLength) {
    if (pDataWrite->type == RW_DATA_TYPE_IRP) {
      pDataWrite->data.irp.status = STATUS_SUCCESS;
    } else {
      HALT_UNLESS1(pDataWrite->type == RW_DATA_TYPE_CHR, pDataWrite->type);

      pDataWrite->data.chr.isChr = FALSE;
    }
  }

  if (writeDone) {
    OnRxChars(pReadIoPort, writeDone, &flowFilter, pQueueToComplete);
    if (isBreak)
      OnRxBreak(pReadIoPort, pQueueToComplete);
    else
      pReadIoPort->pIoPortRemote->perfStats.TransmittedCount += (ULONG)writeDone;
  }

  *pReadDone += readDone;
  *pWriteDone += writeDone;
}

VOID InsertDirect(
    PC0C_RAW_DATA pRawData,
    PIRP pIrpRead,
    PNTSTATUS pStatusWrite,
    PNTSTATUS pStatusRead,
    PSIZE_T pReadDone)
{
  SIZE_T readDone;
  SIZE_T readLength;
  PVOID pReadBuf;

  pReadBuf = GET_REST_BUFFER(pIrpRead, pIrpRead->IoStatus.Information);
  readLength = IoGetCurrentIrpStackLocation(pIrpRead)->Parameters.Read.Length
                                                - pIrpRead->IoStatus.Information;

  readDone = WriteRawData(pRawData, pStatusWrite, pReadBuf, readLength);

  pIrpRead->IoStatus.Information += readDone;

  if (readDone == readLength)
    *pStatusRead = STATUS_SUCCESS;

  *pReadDone += readDone;
}

PIRP StartCurrentIrp(PC0C_IRP_QUEUE pQueue, PDRIVER_CANCEL *ppCancelRoutine, PBOOLEAN pFirst)
{
  while (pQueue->pCurrent) {
    PIRP pIrp;

    pIrp = pQueue->pCurrent;

    #pragma warning(push, 3)
    *ppCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
    #pragma warning(pop)

    if (*ppCancelRoutine) {
#if DBG
      HALT_UNLESS(!pQueue->started);
      pQueue->started = TRUE;
#endif /* DBG */
      return pIrp;
    }

    ShiftQueue(pQueue);
    *pFirst = FALSE;
  }
  return NULL;
}

NTSTATUS StopCurrentIrp(
    NTSTATUS status,
    PDRIVER_CANCEL pCancelRoutine,
    BOOLEAN first,
    SIZE_T done,
    PC0C_IO_PORT pIoPort,
    PC0C_IRP_QUEUE pQueue,
    PLIST_ENTRY pQueueToComplete)
{
  PIRP pIrp;

#if DBG
  HALT_UNLESS(pQueue->started);
  pQueue->started = FALSE;
#endif /* DBG */

  pIrp = pQueue->pCurrent;

  if (status == STATUS_PENDING && done) {
    PC0C_IRP_STATE pState;

    pState = GetIrpState(pIrp);
    HALT_UNLESS(pState);

    if ((pState->flags & C0C_IRP_FLAG_WAIT_ONE) != 0) {
      status = STATUS_SUCCESS;
    }
    else
    if (first && (pState->flags & C0C_IRP_FLAG_INTERVAL_TIMEOUT) != 0) {
      SetIntervalTimeout(pIoPort);
    }
  }

  if (!first && status == STATUS_PENDING)
    status = SetIrpTimeout(pIoPort, pIrp);

  HALT_UNLESS(pCancelRoutine);

  if (status == STATUS_PENDING) {
    #pragma warning(push, 3)
    IoSetCancelRoutine(pIrp, pCancelRoutine);
    #pragma warning(pop)
    if (pIrp->Cancel) {
      #pragma warning(push, 3)
      pCancelRoutine = IoSetCancelRoutine(pIrp, NULL);
      #pragma warning(pop)

      if (pCancelRoutine) {
        ShiftQueue(pQueue);
        pIrp->IoStatus.Status = STATUS_CANCELLED;
        InsertTailList(pQueueToComplete, &pIrp->Tail.Overlay.ListEntry);
        return STATUS_CANCELLED;
      }
    }
  } else {
    ShiftQueue(pQueue);
    pIrp->IoStatus.Status = status;
    InsertTailList(pQueueToComplete, &pIrp->Tail.Overlay.ListEntry);
  }

  return status;
}

NTSTATUS FdoPortIo(
    short ioType,
    PVOID pParam,
    PC0C_IO_PORT pIoPort,
    PC0C_IRP_QUEUE pQueue,
    PLIST_ENTRY pQueueToComplete)
{
  NTSTATUS status;
  BOOLEAN first;
  BOOLEAN firstCurrent;
  PIRP pIrpCurrent;
  PDRIVER_CANCEL pCancelRoutineCurrent;
  SIZE_T done;

  first = TRUE;
  done = 0;

  status = STATUS_PENDING;

  for (firstCurrent = TRUE ; (pIrpCurrent = StartCurrentIrp(pQueue, &pCancelRoutineCurrent, &firstCurrent)) != NULL ; firstCurrent = FALSE) {
    NTSTATUS statusCurrent;
    SIZE_T doneCurrent;

    statusCurrent = STATUS_PENDING;
    doneCurrent = 0;

    switch (ioType) {
    case C0C_IO_TYPE_WAIT_COMPLETE:
      HALT_UNLESS(pParam);
      *((PULONG)pIrpCurrent->AssociatedIrp.SystemBuffer) = *((PULONG)pParam);
      *((PULONG)pParam) = 0;
      pIrpCurrent->IoStatus.Information = sizeof(ULONG);
      statusCurrent = STATUS_SUCCESS;
      break;
    case C0C_IO_TYPE_INSERT:
      HALT_UNLESS(pParam);
      InsertDirect((PC0C_RAW_DATA)pParam, pIrpCurrent, &status, &statusCurrent, &doneCurrent);
      break;
    }

    statusCurrent = StopCurrentIrp(statusCurrent,
                                   pCancelRoutineCurrent,
                                   firstCurrent,
                                   doneCurrent,
                                   pIoPort,
                                   pQueue,
                                   pQueueToComplete);

    if (statusCurrent == STATUS_PENDING)
      break;
  }

  if (status == STATUS_PENDING) {
    switch (ioType) {
    case C0C_IO_TYPE_INSERT:
      HALT_UNLESS(pParam);
      status = WriteRawDataToBuffer((PC0C_RAW_DATA)pParam, &pIoPort->readBuf);
      if (status == STATUS_PENDING && !pIoPort->emuOverrun)
        status = MoveRawData(&pIoPort->readBuf.insertData, (PC0C_RAW_DATA)pParam);
      UpdateHandFlow(pIoPort, FALSE, pQueueToComplete);
      break;
    }
  }
  return status;
}

VOID InsertLsrMst(
    PC0C_IO_PORT pIoPortRead,
    BOOLEAN isMST,
    UCHAR value,
    PLIST_ENTRY pQueueToComplete)
{
  C0C_RAW_DATA insertData;

  insertData.size = 3;
  insertData.data[0] = pIoPortRead->escapeChar;
  insertData.data[1] = (UCHAR)(isMST ? SERIAL_LSRMST_MST : SERIAL_LSRMST_LSR_NODATA);
  insertData.data[2] = value;

  if (FdoPortIo(
      C0C_IO_TYPE_INSERT,
      &insertData,
      pIoPortRead,
      &pIoPortRead->irpQueues[C0C_QUEUE_READ],
      pQueueToComplete) == STATUS_PENDING)
  {
    AlertOverrun(pIoPortRead, pQueueToComplete);
    Trace00((PC0C_COMMON_EXTENSION)pIoPortRead->pDevExt,
        L"WARNING: Lost SERIAL_LSRMST_", isMST ? L"MST" : L"LSR_NODATA");
  }
}

VOID InsertChar(
    PC0C_IO_PORT pIoPortRead,
    UCHAR value,
    PLIST_ENTRY pQueueToComplete)
{
  C0C_RAW_DATA insertData;

  insertData.size = 1;
  insertData.data[0] = value;

  if (FdoPortIo(
      C0C_IO_TYPE_INSERT,
      &insertData,
      pIoPortRead,
      &pIoPortRead->irpQueues[C0C_QUEUE_READ],
      pQueueToComplete) == STATUS_PENDING)
  {
    AlertOverrun(pIoPortRead, pQueueToComplete);
    Trace0((PC0C_COMMON_EXTENSION)pIoPortRead->pDevExt, L"WARNING: Lost char");
  }
}

NTSTATUS TryReadWrite(
    PC0C_IO_PORT pIoPortRead,
    BOOLEAN startRead,
    PC0C_IO_PORT pIoPortWrite,
    BOOLEAN startWrite,
    PLIST_ENTRY pQueueToComplete)
{
  NTSTATUS status;
  SIZE_T readBufBusyBeg, readBufBusyEnd;

  RW_DATA dataIrpRead;
  PC0C_IRP_QUEUE pQueueRead;
  BOOLEAN firstRead;
  PDRIVER_CANCEL pCancelRoutineRead;
  SIZE_T doneRead;

  RW_DATA dataChar;

  RW_DATA dataIrpWrite;
  PC0C_IRP_QUEUE pQueueWrite;
  BOOLEAN firstWrite;
  PDRIVER_CANCEL pCancelRoutineWrite;
  SIZE_T doneWrite;
  BOOLEAN wasWrite;

  PC0C_ADAPTIVE_DELAY pWriteDelay;
  SIZE_T writeLimit;
  PSIZE_T pWriteLimit;

  dataIrpRead.type = RW_DATA_TYPE_IRP;
  dataChar.type = RW_DATA_TYPE_CHR;
  dataIrpWrite.type = RW_DATA_TYPE_IRP;

  pQueueRead = &pIoPortRead->irpQueues[C0C_QUEUE_READ];
  pQueueWrite = &pIoPortWrite->irpQueues[C0C_QUEUE_WRITE];
  pWriteDelay = pIoPortWrite->pWriteDelay;

  if (pWriteDelay) {
    if (pQueueWrite->pCurrent || pIoPortWrite->sendBreak || pIoPortWrite->sendXonXoff) {
      StartWriteDelayTimer(pWriteDelay);
      writeLimit = GetWriteLimit(pWriteDelay);
      status = STATUS_PENDING;
    } else {
      writeLimit = 0;
      status = STATUS_SUCCESS;
    }

    pWriteLimit = &writeLimit;
  } else {
    status = STATUS_SUCCESS;
    pWriteLimit = NULL;
  }

  readBufBusyBeg = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);

  /* get first pIrpRead */

  dataIrpRead.data.irp.status = STATUS_PENDING;
  doneRead = 0;
  firstRead = TRUE;

  if (startRead) {
    dataIrpRead.data.irp.pIrp = pQueueRead->pCurrent;
    pCancelRoutineRead = NULL;
  } else {
    dataIrpRead.data.irp.pIrp = StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);
  }

  /* read from buffer */

  while (dataIrpRead.data.irp.pIrp) {
    dataIrpRead.data.irp.status = ReadBuffer(dataIrpRead.data.irp.pIrp, &pIoPortRead->readBuf, &doneRead);

    if (dataIrpRead.data.irp.status == STATUS_PENDING)
      break;

    if (startRead && firstRead) {
      status = dataIrpRead.data.irp.status;
      ShiftQueue(pQueueRead);
    } else {
      StopCurrentIrp(dataIrpRead.data.irp.status, pCancelRoutineRead, firstRead,
                     doneRead, pIoPortRead, pQueueRead, pQueueToComplete);
    }

    /* get next pIrpRead */

    doneRead = 0;
    firstRead = FALSE;

    dataIrpRead.data.irp.pIrp =
        StartCurrentIrp(pQueueRead, &pCancelRoutineRead, &firstRead);
  }

  readBufBusyEnd = C0C_BUFFER_BUSY(&pIoPortRead->readBuf);

  if (readBufBusyBeg > readBufBusyEnd) {
    UpdateHandFlow(pIoPortRead, TRUE, pQueueToComplete);
    readBufBusyBeg = readBufBusyEnd;
  }

  /* get char */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -