📄 driverpn.c
字号:
{
/*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 + -