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

📄 enum.c

📁 enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play
💻 C
📖 第 1 页 / 共 4 页
字号:
                              sizeof(PDO_DEVICE_DATA), &pdoUniName,
                              FILE_DEVICE_UNKNOWN,
                              FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &pdo);

      if (!NT_SUCCESS(status)) {
         Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Create device failed\n"));
         Irp->AssociatedIrp.SystemBuffer = stack->Parameters.Others.Argument1;
         return status;
      }

      Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE,
                      ("Created PDO on top of filter: %x\n",pdo));

      pdoData = pdo->DeviceExtension;

      //
      // Initialize the rest of the device object
      //
      // Set this to potential, not found, since this is used for dynamic
      // detection using the DSR bit.  There could be a broken pnp device
      // attached that isn't able to set DSR.
      //

      FdoData->PDOLegacyEnumerated = legacyPotential;

      //
      // Copy our temp buffers over to the DevExt
      //

      pdoData->HardwareIDs = HardwareIDs;
      pdoData->CompIDs = CompIDs;
      pdoData->DeviceIDs = DeviceIDs;
      pdoData->DevDesc = DevDesc;

      Serenum_InitPDO(pdo, FdoData);
   }

   // TODO: Poll

ExitReenumerate:;

   stack = IoGetCurrentIrpStackLocation(Irp);
   Irp->AssociatedIrp.SystemBuffer = stack->Parameters.Others.Argument1;

   return STATUS_SUCCESS;
}

void
Serenum_PDO_EnumMarkMissing(PFDO_DEVICE_DATA FdoData, PPDO_DEVICE_DATA PdoData)
/*++

Routine Description:
    Removes the attached pdo from the fdo's list of children.

    NOTE: THIS FUNCTION CAN ONLY BE CALLED DURING AN ENUMERATION. If called
          outside of enumeration, Serenum might delete it's PDO before PnP has
          been told the PDO is gone.

Arguments:
    FdoData - Pointer to the fdo's device extension
    PdoData - Pointer to the pdo's device extension

Return value:
    none

--*/
{
    Serenum_KdPrint (FdoData, SER_DBG_SS_TRACE, ("Removing Pdo %x\n",
                                                 PdoData->Self));

    ASSERT(PdoData->Attached);
    PdoData->Attached = FALSE;
    FdoData->AttachedPDO = NULL;
    FdoData->PdoData = NULL;
    FdoData->NumPDOs = 0;
    FdoData->PDOForcedRemove = FALSE;
}

NTSTATUS
Serenum_IoSyncReqWithIrp(PIRP PIrp, UCHAR MajorFunction, PKEVENT PEvent,
                         PDEVICE_OBJECT PDevObj )
/*++

Routine Description:
    Performs a synchronous IO request by waiting on the event object
    passed to it.  The IRP isn't deallocated after this call.

Arguments:
    PIrp - The IRP to be used for this request

    MajorFunction - The major function

    PEvent - An event used to wait for the IRP

    PDevObj - The object that we're performing the IO request upon

Return value:
    NTSTATUS

--*/
{
    PIO_STACK_LOCATION stack;
    NTSTATUS status;

    stack = IoGetNextIrpStackLocation(PIrp);

    stack->MajorFunction = MajorFunction;

    KeClearEvent(PEvent);

    IoSetCompletionRoutine(PIrp, Serenum_EnumComplete, PEvent, TRUE,
                           TRUE, TRUE);

    status = Serenum_IoSyncReq(PDevObj, PIrp, PEvent);

    if (status == STATUS_SUCCESS) {
       status = PIrp->IoStatus.Status;
    }

    return status;
}

NTSTATUS
Serenum_IoSyncIoctlEx(ULONG Ioctl, BOOLEAN Internal, PDEVICE_OBJECT PDevObj,
                      PKEVENT PEvent, PIO_STATUS_BLOCK PIoStatusBlock,
                      PVOID PInBuffer, ULONG InBufferLen, PVOID POutBuffer,                    // output buffer - optional
                      ULONG OutBufferLen)
/*++

Routine Description:
    Performs a synchronous IO control request by waiting on the event object
    passed to it.  The IRP is deallocated by the IO system when finished.

Return value:
    NTSTATUS

--*/
{
    PIRP pIrp;
    NTSTATUS status;

    KeClearEvent(PEvent);

    // Allocate an IRP - No need to release
    // When the next-lower driver completes this IRP, the IO Mgr releases it.

    pIrp = IoBuildDeviceIoControlRequest(Ioctl, PDevObj, PInBuffer, InBufferLen,
                                         POutBuffer, OutBufferLen, Internal,
                                         PEvent, PIoStatusBlock);

    if (pIrp == NULL) {
        Serenum_KdPrint_Def (SER_DBG_SS_ERROR, ("Failed to allocate IRP\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = Serenum_IoSyncReq(PDevObj, pIrp, PEvent);


    if (status == STATUS_SUCCESS) {
       status = PIoStatusBlock->Status;
    }

    return status;
}


NTSTATUS
Serenum_IoSyncReq(PDEVICE_OBJECT PDevObj, IN PIRP PIrp, PKEVENT PEvent)
/*++

Routine Description:
    Performs a synchronous IO request by waiting on the event object
    passed to it.  The IRP is deallocated by the IO system when finished.

Return value:
    NTSTATUS

--*/
{
   NTSTATUS status;

   status = IoCallDriver(PDevObj, PIrp);

   if (status == STATUS_PENDING) {
      // wait for it...
      status = KeWaitForSingleObject(PEvent, Executive, KernelMode, FALSE,
                                     NULL);
   }

    return status;
}

NTSTATUS
Serenum_Wait(IN PKTIMER Timer, IN LARGE_INTEGER DueTime)
/*++

Routine Description:
    Performs a wait for the specified time.
    NB: Negative time is relative to the current time.  Positive time
    represents an absolute time to wait until.

Return value:
    NTSTATUS

--*/
{
   if (KeSetTimer(Timer, DueTime, NULL)) {
      Serenum_KdPrint_Def(SER_DBG_SS_INFO, ("Timer already set: %x\n", Timer));
   }

   return KeWaitForSingleObject(Timer, Executive, KernelMode, FALSE, NULL);
}

NTSTATUS
Serenum_EnumComplete (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++
Routine Description:
    A completion routine for use when calling the lower device objects to
    which our bus (FDO) is attached.  It sets the event for the synchronous
    calls done.

--*/
{
    UNREFERENCED_PARAMETER (DeviceObject);

    if (Irp->PendingReturned) {
        IoMarkIrpPending( Irp );
    }

    KeSetEvent ((PKEVENT) Context, 1, FALSE);
    // No special priority
    // No Wait

    return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
}


NTSTATUS
Serenum_ReadSerialPort(OUT PCHAR PReadBuffer, IN USHORT Buflen,
                       IN ULONG Timeout, OUT PUSHORT nActual,
                       OUT PIO_STATUS_BLOCK PIoStatusBlock,
                       IN const PFDO_DEVICE_DATA FdoData)
{
    NTSTATUS status;
    PIRP pIrp;
    LARGE_INTEGER startingOffset = RtlConvertLongToLargeInteger(0);
    KEVENT event;
    SERIAL_TIMEOUTS timeouts;
    IO_STATUS_BLOCK statusBlock;
    ULONG i;

    //
    // Set the proper timeouts for the read
    //

    timeouts.ReadIntervalTimeout = MAXULONG;
    timeouts.ReadTotalTimeoutMultiplier = MAXULONG;
    timeouts.ReadTotalTimeoutConstant = Timeout;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    status = Serenum_IoSyncIoctlEx(IOCTL_SERIAL_SET_TIMEOUTS, FALSE,
                                   FdoData->TopOfStack, &event, &statusBlock,
                                   &timeouts, sizeof(timeouts), NULL, 0);

    if (!NT_SUCCESS(status)) {
       return status;
    }

    Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Read pending...\n"));

    *nActual = 0;

    while (*nActual < Buflen) {
        KeClearEvent(&event);

        pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, FdoData->TopOfStack,
                                            PReadBuffer, 1, &startingOffset,
                                            &event, PIoStatusBlock);

        if (pIrp == NULL) {
            Serenum_KdPrint(FdoData, SER_DBG_SS_ERROR, ("Failed to allocate IRP"
                                                        "\n"));
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        status = IoCallDriver(FdoData->TopOfStack, pIrp);

        if (status == STATUS_PENDING) {

            //
            // Wait for the IRP
            //

            status = KeWaitForSingleObject(&event, Executive, KernelMode,
                                           FALSE, NULL);

            if (status == STATUS_SUCCESS) {
               status = PIoStatusBlock->Status;
            }
        }

        if (!NT_SUCCESS(status) || status == STATUS_TIMEOUT) {
           Serenum_KdPrint (FdoData, SER_DBG_SS_ERROR,
                            ("IO Call failed with status %x\n", status));
           return status;
        }

        *nActual += (USHORT)PIoStatusBlock->Information;
        PReadBuffer += (USHORT)PIoStatusBlock->Information;
    }

    return status;
}

void
Serenum_PollingTimerRoutine (IN PKDPC Dpc, IN PFDO_DEVICE_DATA FdoData,
                             IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
    UNREFERENCED_PARAMETER (Dpc);
    UNREFERENCED_PARAMETER (SystemArgument1);
    UNREFERENCED_PARAMETER (SystemArgument2);

    //
    // Make sure we are allowed to poll
    //

    if (KeResetEvent(&FdoData->PollingEvent) == 0) {
       return;
    }

    IoQueueWorkItem(FdoData->PollingWorker,
                    (PIO_WORKITEM_ROUTINE)Serenum_PollingRoutine,
                    DelayedWorkQueue, FdoData);
}

void
Serenum_PollingRoutine(PDEVICE_OBJECT PDevObj, PFDO_DEVICE_DATA FdoData)
{
   ULONG bitMask;
   KEVENT event;
   KTIMER timer;
   IO_STATUS_BLOCK IoStatusBlock;
   NTSTATUS status;
   PIRP Irp;
   CHAR ReadBuffer = '\0';
   USHORT nActual = 0;
   SERIAL_BASIC_SETTINGS basicSettings;
   BOOLEAN restoreSettings = FALSE;
   SERIAL_TIMEOUTS timeouts, newTimeouts;

   UNREFERENCED_PARAMETER(PDevObj);


   Serenum_KdPrint(FdoData, SER_DBG_SS_TRACE, ("Serenum_PollingRoutine for "
                                               "0x%x\n", FdoData));

   KeInitializeEvent(&event, NotificationEvent, FALSE);

   //
   // Open the serial port before doing anything
   //

   if (NULL == (Irp = IoAllocateIrp(FdoData->Self->StackSize, FALSE))) {
      Serenum_KdPrint (FdoData, SER_DBG_SS_ERROR, ("Failed to allocate IRP\n"));
      KeSetEvent(&FdoData->PollingEvent, 1, FALSE);
      return;
   }

   Irp->UserIosb = &IoStatusBlock;
   status = Serenum_IoSyncReqWithIrp(Irp, IRP_MJ_CREATE, &event,
                                     FdoData->TopOfStack);

   if (!NT_SUCCESS(status)) {
      Serenum_KdPrint (FdoData, SER_DBG_SS_INFO,
                       ("Failed to open the serial port while polling DSR\n"));
      IoFreeIrp(Irp);
      KeSetEvent(&FdoData->PollingEvent, 1, FALSE);

⌨️ 快捷键说明

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