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

📄 serenum.c

📁 enumerates Plug-n-Play RS-232 devices that are compliant with the current revision of Plug and Play
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++
Copyright (c) 1997-1998  Microsoft Corporation

Module Name:

    SERENUM.C

Abstract:

    This module contains contains the entry points for a standard bus
    PNP / WDM driver.


Environment:

    kernel mode only

Notes:



--*/

#include "pch.h"

//
// Declare some entry functions as pageable, and make DriverEntry
// discardable
//

NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, Serenum_DriverUnload)
//#pragma alloc_text (PAGE, Serenum_InitPDO)
#endif

NTSTATUS
DriverEntry (
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING UniRegistryPath
    )
/*++
Routine Description:

    Initialize the entry points of the driver.

--*/
{
    ULONG i;

    UNREFERENCED_PARAMETER (UniRegistryPath);

    Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("Driver Entry\n"));
    Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("RegPath: %x\n", UniRegistryPath));

    //
    // Set ever slot to initially pass the request through to the lower
    // device object
    //
    for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
       DriverObject->MajorFunction[i] = Serenum_DispatchPassThrough;
    }

    //
    // Fill in the Dispatch slots intercepted by the filter driver.
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Serenum_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Serenum_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Serenum_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Serenum_IoCtl;
    DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]
        = Serenum_InternIoCtl;
    DriverObject->DriverUnload = Serenum_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Serenum_AddDevice;

    return STATUS_SUCCESS;
}


NTSTATUS
SerenumSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
                      IN PKEVENT SerenumSyncEvent)
{
   UNREFERENCED_PARAMETER(DeviceObject);
   UNREFERENCED_PARAMETER(Irp);


   KeSetEvent(SerenumSyncEvent, IO_NO_INCREMENT, FALSE);
   return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
Serenum_CreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
/*++
Routine Description:
    Some outside source is trying to create a file against us.

    If this is for the FDO (the bus itself) then the caller is trying to
    open the propriatary conection to tell us which serial port to enumerate.

    If this is for the PDO (an object on the bus) then this is a client that
    wishes to use the serial port.
--*/
{
   PIO_STACK_LOCATION irpStack;
   NTSTATUS status;
   PFDO_DEVICE_DATA fdoData;
   KEVENT completionEvent;
   PDEVICE_OBJECT pNextDevice;


   UNREFERENCED_PARAMETER(DeviceObject);

   irpStack = IoGetCurrentIrpStackLocation(Irp);

   if (((PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension)->IsFDO) {
      fdoData = (PFDO_DEVICE_DATA)DeviceObject->DeviceExtension;
      pNextDevice = ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension)
                    ->TopOfStack;
   } else {
      fdoData = ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->
                ParentFdo->DeviceExtension;
      pNextDevice = ((PFDO_DEVICE_DATA)((PPDO_DEVICE_DATA)DeviceObject->
                                        DeviceExtension)->ParentFdo->
                     DeviceExtension)->TopOfStack;
   }

   switch (irpStack->MajorFunction) {
   case IRP_MJ_CREATE:
      Serenum_KdPrint_Def(SER_DBG_SS_TRACE, ("Create"));

      Serenum_StopPolling(fdoData, SERENUM_OPEN_LOCK);

      //
      // Pass on the create and the close
      //

      status = Serenum_DispatchPassThrough(DeviceObject, Irp);
      break;

   case IRP_MJ_CLOSE:
      Serenum_KdPrint_Def (SER_DBG_SS_TRACE, ("Close \n"));

      //
      // Send the close down; after it finishes we can open and take
      // over the port
      //

      IoCopyCurrentIrpStackLocationToNext(Irp);

      KeInitializeEvent(&completionEvent, SynchronizationEvent, FALSE);

      IoSetCompletionRoutine(Irp, SerenumSyncCompletion, &completionEvent,
                             TRUE, TRUE, TRUE);

      status = IoCallDriver(pNextDevice, Irp);


      if (status == STATUS_PENDING) {
         KeWaitForSingleObject(&completionEvent, Executive, KernelMode, FALSE,
                               NULL);
      }

      status = Irp->IoStatus.Status;

      IoCompleteRequest(Irp, IO_NO_INCREMENT);

      if (status == STATUS_SUCCESS) {
         Serenum_StartPolling(fdoData, SERENUM_OPEN_LOCK);
      }

      break;
   }

   return status;
}

NTSTATUS
Serenum_ListPorts (
    PSERENUM_PORT_DESC Desc,
    PFDO_DEVICE_DATA    FdoData
    )
/*++
Routine Description:
    This driver has just detected that a device has departed from the bus.
    (Actually the control panels has just told us that something has departed,
    but who is counting?

    We therefore need to flag the PDO as no longer attached, remove it from
    the linked list of PDOs for this bus, and then tell Plug and Play about it.
--*/
{
    Desc->PortHandle = FdoData->Self;
    Desc->PortAddress = FdoData->PhysicalAddress;

    return STATUS_SUCCESS;
}



NTSTATUS
Serenum_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen;
    ULONG                   outlen;
    PCOMMON_DEVICE_DATA     commonData;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;
    HANDLE                  keyHandle;
    ULONG                   actualLength;

    status = STATUS_SUCCESS;
    irpStack = IoGetCurrentIrpStackLocation (Irp);
    ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);

    commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;
    buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //
    // The request is one of the propriatary Ioctls for
    //
    // NB We ARE a filter driver, so we DO pass on the irp if we don't handle it
    //

    inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if (!commonData->IsFDO) {
        //
        // These commands are only allowed to go to the FDO.  Since they came
        // into the PDO, we need to fire them down to the serenum Fdo.
        //
        IoSkipCurrentIrpStackLocation (Irp);

        return IoCallDriver(
            ((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->ParentFdo,
            Irp );
//        status = STATUS_ACCESS_DENIED;
//        Irp->IoStatus.Status = status;
//        IoCompleteRequest (Irp, IO_NO_INCREMENT);
//        return status;
    }

    status = Serenum_IncIoCount (fdoData);

    if (!NT_SUCCESS (status)) {
        //
        // This bus has received the PlugPlay remove IRP.  It will no longer
        // respond to external requests.
        //
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_SERENUM_PORT_DESC:

        if ((sizeof (SERENUM_PORT_DESC) == inlen) &&
            (inlen == outlen) &&
            (((PSERENUM_PORT_DESC)buffer)->Size == inlen)) {

            status = Serenum_ListPorts ((PSERENUM_PORT_DESC) buffer, fdoData);
            Irp->IoStatus.Information = outlen;

        } else {
            status = STATUS_INVALID_PARAMETER;
        }
        break;

    case IOCTL_SERENUM_GET_PORT_NAME:
        //
        // Get the port name from the registry.

⌨️ 快捷键说明

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