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

📄 driverpn.c

📁 profibus-dp主站源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{
  /*stub*/
};
NTSTATUS        StartDevice( IN PPROFIM_DEVICE_EXTENSION devExt,
                             IN PIO_STACK_LOCATION IrpSp );
NTSTATUS        CanStopDevice( PPROFIM_DEVICE_EXTENSION devExt, PIRP Irp );
NTSTATUS        CanRemoveDevice( PPROFIM_DEVICE_EXTENSION devExt, PIRP Irp );
static NTSTATUS PnpComplete( IN PDEVICE_OBJECT DeviceObject,
                             IN PIRP Irp,
                             IN PVOID Context );


static PSTR pnpMinorCodes[] ={"IRP_MN_START_DEVICE",
                              "IRP_MN_QUERY_REMOVE_DEVICE",
                              "IRP_MN_REMOVE_DEVICE",
                              "IRP_MN_CANCEL_REMOVE_DEVICE",
                              "IRP_MN_STOP_DEVICE",
                              "IRP_MN_QUERY_STOP_DEVICE",
                              "IRP_MN_CANCEL_STOP_DEVICE",
                              "IRP_MN_QUERY_DEVICE_RELATIONS",
                              "IRP_MN_QUERY_INTERFACE",
                              "IRP_MN_QUERY_CAPABILITIES",
                              "IRP_MN_QUERY_RESOURCES",
                              "IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
                              "IRP_MN_QUERY_DEVICE_TEXT",
                              "IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
                              "***** FUNCTION 0x0e",
                              "IRP_MN_READ_CONFIG",
                              "IRP_MN_WRITE_CONFIG",
                              "IRP_MN_EJECT",
                              "IRP_MN_SET_LOCK",
                              "IRP_MN_QUERY_ID",
                              "IRP_MN_QUERY_PNP_DEVICE_STATE",
                              "IRP_MN_QUERY_BUS_INFORMATION",
                              "IRP_MN_DEVICE_USAGE_NOTIFICATION",
                              "IRP_MN_SURPRISE_REMOVAL",
                              "IRP_MN_QUERY_LEGACY_BUS_INFORMATION"};


#if PnP_DBG
VOID            PrintResourceList( PCM_RESOURCE_LIST );
VOID            PrintConfig( PPCI_COMMON_CONFIG  configInfo );
#endif

//
// Global variable
//
int         ProfiMInstanceCounter = 0;


///////////////////////////////////////////////////////////////////////////////
//
//  AddDevice
//
//      We are called at this entry point by the Plug and Play Manager
//      to add a Functional Device Object for a Physical Device Object.
//      Note that we may NOT access the device in this routine, as the
//      Plug and Play Manager has not yet given us any hardware resoruces.
//      We get these hardware resources via the IRP_MJ_PNP IRP with
//      a minor function IRP_MN_START_DEVICE.
//
//
//  INPUTS:
//
//      DriverObj - Address of our DRIVER_OBJECT.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//    This routine is called at IRQL_PASSIVE_LEVEL.
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS AddDevice( IN PDRIVER_OBJECT DriverObject,
                    IN PDEVICE_OBJECT PhysicalDeviceObject )
{
  PPROFIM_DEVICE_EXTENSION  devExt;
  PDEVICE_OBJECT            functionalDeviceObject;
  UNICODE_STRING            devName;
  UNICODE_STRING            linkName;
  UNICODE_STRING            tempName;
  NTSTATUS                  code  = STATUS_SUCCESS;
  HANDLE                    regKeyHandle;  
  KEY_FULL_INFORMATION     *KeyInfo;
  ULONG                     length;
  char                      Buffer[256];

  DbgPrint( "ProfiM PnP: AddDevice: entered for instance %d\n",
            ProfiMInstanceCounter );

  PB_DbgPrintL1( "ProfiM PnP: AddDevice: PDO = 0x%0x\n", PhysicalDeviceObject );

  // Only up to 10 instances are handled 
  if ( ProfiMInstanceCounter >= 10 )
  {
    DbgPrint( "ProfiM PnP: Too many instances, no more added\n" );
    return( STATUS_UNSUCCESSFUL );
  }

  //
  // Initialize the UNICODE device name.  This will be the "native NT" name
  // for our device.
  //

  RtlInitUnicodeString( &tempName, NT_DEVICE_NAME );
  code = MyAllocUnicodeString( &devName, &tempName, (USHORT) (tempName.Length + 4) );
  if ( ProfiMInstanceCounter )
  {
    devName.Buffer[devName.Length / 2] = '0' + ProfiMInstanceCounter;
    devName.Length += 2;
  }
  PB_DbgPrintL1( "ProfiM PnP: Ready to Call IoCreateDevice for DevName=\"%ws\" Len=%d\n",
                 devName.Buffer,
                 devName.Length );


  PB_DbgPrintL1( "ProfiM PnP: Size of Device Extension = %dB",
                 sizeof( PROFIM_DEVICE_EXTENSION ) );

  //
  // Ask the I/O Manager to create the device object and
  // device extension.  In PnP terms, this is the FUNCTIONAL
  // Device Object (FDO) for the device.
  //    
  code = IoCreateDevice( DriverObject,
                         sizeof( PROFIM_DEVICE_EXTENSION ),
                         &devName,
                         FILE_DEVICE_UNKNOWN,
                         0,
                         FALSE,
                         &functionalDeviceObject );


  if ( !NT_SUCCESS( code ) )
  {
    if ( devName.Buffer )
      ExFreePool( devName.Buffer );
    DbgPrint( "ProfiM PnP: IoCreateDevice failed. Dev=%ws Status = 0x%0x\n",
              devName.Buffer,
              code );
    return( STATUS_UNSUCCESSFUL );
  }    


  //
  // Get a pointer to our device extension
  //
  devExt = ( PPROFIM_DEVICE_EXTENSION )
           functionalDeviceObject->DeviceExtension;

  if ( !devExt )
  {
    DbgPrint( "ProfiM PnP: AddDevice Error - DeviceExtension is NULL!" );
    return STATUS_UNSUCCESSFUL;
  }        


  PB_DbgPrintL1( "ProfiM PnP: AddDevice: FDO = 0x%0x\n",
                 functionalDeviceObject );

  //
  // Zero out the device extension.  While not strictly necessary
  // (the documentation says the device extension is zeroed) it's
  // better to be safe.
  //
  RtlZeroMemory( devExt, sizeof( PROFIM_DEVICE_EXTENSION ) );

  //
  // Initialize structure control identificator
  //
  devExt->magic = PROFIM_MAGIC; 
  devExt->PB.AllInitialized = FALSE;             
  devExt->ContinueFrame = FALSE;

  //
  // Save the device object pointer away for future reference
  //
  devExt->DeviceObject = functionalDeviceObject;

  //
  // Save the address of the physical device object away for future reference
  //
  devExt->PhysicalDeviceObject = PhysicalDeviceObject;


  
  //************************************************    
  //
  // Get Starup configuration from reqistry
  //
  code = GetPnPConfiguration( devExt );  

  if ( !NT_SUCCESS( code ) )
  {
    RS_DbgPrint( "PnP: GetConfiguration failed\n" );
    return code;
  }    
  
  //************************************************

  //
  //  Clear the Device Initializing bit since the Device Object was created
  //  outside of DriverEntry.
  //
  functionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

  //
  // Create a familiar name for this device, so that non-kernel mode
  // programs can open the device.
  //
  // NOTE: WDM Drivers on Win98 MUST create this link in the 
  // \DosDevices directory.  \?? will NOT work.
  //

  RtlInitUnicodeString( &tempName, DOS_DEVICE_NAME );
  code = MyAllocUnicodeString( &linkName, &tempName, (USHORT) (tempName.Length + 4) );
  if ( ProfiMInstanceCounter )
  {
    linkName.Buffer[linkName.Length / 2] = '0' + ProfiMInstanceCounter;
    linkName.Length += 2;
  }


  PB_DbgPrintL1( "ProfiM PnP: AddDevice: Dev=%ws Link=%ws\n",
                 devName.Buffer,
                 linkName.Buffer );

  //
  // IoCreateSymbolicLink IS a WDM function...
  //
  code = IoCreateSymbolicLink( &linkName, &devName );

  if ( !NT_SUCCESS( code ) )
  {
    DbgPrint( "ProfiM PnP: IoCreateSymbolicLink failed.  Status = 0x%x\n",
              code );

    code = STATUS_UNSUCCESSFUL;

    //
    // Clean up the mess
    //
    IoDeleteDevice( functionalDeviceObject );
    if ( linkName.Buffer )
      ExFreePool( linkName.Buffer );
    if ( devName.Buffer )
      ExFreePool( devName.Buffer );;

    //
    // Indicate load failure to the I/O manager; driver image is deleted...
    //
    return( code );
  }

  devExt->link_name = linkName;
  devExt->ntdev_name = devName;

  //
  // Ask the I/O Manager to use buffered I/O
  //
  functionalDeviceObject->Flags |= DO_BUFFERED_IO;

  //
  // Set up the "Remove Event" and "Stop Event".
  //
  // Note that we can't use an official "Remove Lock" here, because
  // the Remove Lock related calls are not in WDM.
  //
  KeInitializeEvent( &devExt->RemoveEvent, NotificationEvent, FALSE );
  // KeInitializeEvent(&devExt->StopEvent, NotificationEvent, TRUE);

  //
  // Init the count of in-progress I/O requests to zero.  We use this
  // to keep track of when we can remove the device.
  //
  // devExt->OutstandingIO = 0;

  //
  // Internal device state flags, used for managing PnP state of device
  //
  // devExt->Started = FALSE;
  // devExt->HoldNewRequests = TRUE;
  // devExt->Removed = FALSE;

  //
  // Set initial state
  //
  devExt->State = STATE_NEVER_STARTED;

  // Initial ProfiM state
  //**    ul_drv_new_init_state(devExt,2);

  //
  // Attach our FDO to the underlying PDO
  //
  devExt->DeviceToSendIrpsTo = IoAttachDeviceToDeviceStack( functionalDeviceObject,
                                                            PhysicalDeviceObject );

  //
  // If that didn't work...
  //
  if ( !devExt->DeviceToSendIrpsTo )
  {
    DbgPrint( "ProfiM PnP: IoAttachDeviceToDeviceStack failed to attach to Target Device" );

    //
    // Clean up the mess
    //
    IoDeleteDevice( functionalDeviceObject );

    //
    // Indicate load failure to the I/O manager; driver image is deleted...
    //
    return( STATUS_UNSUCCESSFUL );
  }

  // Successfully added device, prepare number for next instance
  ProfiMInstanceCounter++;

  PB_DbgPrintL1( "ProfiM PnP: AddDevice: done\n" );

  return code;
}

///////////////////////////////////////////////////////////////////////////////
//
//  DispatchPnp
//
//    This is the dispatch entry point for IRP_MJ_PNP requests.  The
//    driver processes these requets, based on the current state of
//    the device.
//
//
//  INPUTS:
//
//      DeviceObject - Address of the Functional DEVICE_OBJECT for our device.
//  
//      Irp - Address of the IRP representing the IRP_MJ_PNP request.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//
//  IRQL:
//
//    This routine is called at IRQL_PASSIVE_LEVEL.
//
//  NOTES:
//
//      There are several difficulties implementing Plug and Play.
//      Perhaps the greatest difficulty is deciding precisely how you
//      want your device to work, given the various requests the driver
//      can receive and the states the device can be in.  In our driver,
//      we've decided to implement the following policies:
//
//      1) When a removal of the device is requested, we will reject
//         any new IRPs we receive (completing them with an error
//         status in the dispatch routine).  We will wait until all IRPs
//         that are already present on the device's queue are complete
//         and then allow the remove.
//
//      2) When a stop of the device is requested, we'll queue any
//         newly received IRPs, but not initiate them.  We will wait
//         until any IRPs that are presently ACTIVE in progress on the
//         device complete, and then allow the stop.
//
//      3) When a SUPRISE removal of the device is indicated, we
//         immediately cancel any requests that are queued, reject any
//         newly arriving requests.
//
//      Of course, the second complexity in implementing plug and play
//      is getting the logic in your driver correct, so that it works
//      as you intend. According to our experience, this is easier said
//      than done.
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DispatchPnp( PDEVICE_OBJECT DeviceObject, PIRP Irp )
{
  PIO_STACK_LOCATION        ioStackLocation;
  NTSTATUS                  code  = STATUS_SUCCESS;
  PPROFIM_DEVICE_EXTENSION  devExt;
  KEVENT                    eventWaitLowerDrivers;
  PDEVICE_OBJECT            targetDevice;

  PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: called\n" );

  //
  // Get a pointer to our (FUNCTIONAL) device object's device
  // extension.
  //
  devExt = ( PPROFIM_DEVICE_EXTENSION ) DeviceObject->DeviceExtension;

  //
  // Up the count of in-progress requests
  //
  RequestIncrement( devExt );

  ioStackLocation = IoGetCurrentIrpStackLocation( Irp );

  KeInitializeEvent( &eventWaitLowerDrivers, NotificationEvent, FALSE );

  PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Current state: " );
  PrintState( devExt );

  PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: MINOR 0x%0X\n",
                 ioStackLocation->MinorFunction );
  if ( ioStackLocation->MinorFunction <= IRP_MN_SURPRISE_REMOVAL + 1 )
    PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: *** PNP Minor Function is %s\n",
                   pnpMinorCodes[ioStackLocation->MinorFunction] );


  switch ( devExt->State + ioStackLocation->MinorFunction )
  {
      //
      // STATE:   STOPPED or NEVER_STARTED
      // IRP_MN:  _START_DEVICE
      //
      // We're here if we've received an AddDevice() call, but we

⌨️ 快捷键说明

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