📄 bulkpnp.c
字号:
BULKUSB_KdPrint( DBGLVL_MEDIUM,("BulkUsb_ProcessPnPIrp() IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n"));
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver (deviceExtension->TopOfStackDeviceObject, Irp);
BulkUsb_DecrementIoCount(DeviceObject);
return ntStatus;
}
// Reset this flag so new IOCTL and IO Irp processing will be re-enabled
deviceExtension->RemoveDeviceRequested = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break; // end, case IRP_MN_CANCEL_REMOVE_DEVICE
case IRP_MN_SURPRISE_REMOVAL:
BULKUSB_KdPrint( DBGLVL_MEDIUM,("BulkUsb_ProcessPnPIrp() IRP_MN_SURPRISE_REMOVAL\n"));
// For a surprise-style device removal ( i.e. sudden cord yank ),
// the physical device has already been removed so the PnP Manager sends
// the remove IRP without a prior query-remove. A device can be in any state
// when it receives a remove IRP as a result of a surprise-style removal.
// match the inc at the begining of the dispatch routine
BulkUsb_DecrementIoCount(DeviceObject);
//
// Once DeviceRemoved is set no new IOCTL or read/write irps will be passed
// down the stack to lower drivers; all will be quickly failed
//
deviceExtension->DeviceRemoved = TRUE;
// Cancel any pending io requests; we may not have gotten a query first!
BulkUsb_CancelPendingIo( DeviceObject );
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
BulkUsb_AbortPipes( DeviceObject );
//
// Mark this handled
//
Irp->IoStatus.Status = STATUS_SUCCESS;
// We don't explicitly wait for the below driver to complete, but just make
// the call and go on, finishing cleanup
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
return ntStatus;
case IRP_MN_REMOVE_DEVICE:
// The PnP Manager uses this IRP to direct drivers to remove a device.
// For a "polite" device removal, the PnP Manager sends an
// IRP_MN_QUERY_REMOVE_DEVICE prior to the remove IRP. In this case,
// the device is in the remove-pending state when the remove IRP arrives.
// For a surprise-style device removal ( i.e. sudden cord yank ),
// the physical device has already been removed and the PnP Manager may not
// have sent IRP_MN_SURPRISE_REMOVAL. A device can be in any state
// when it receives a remove IRP as a result of a surprise-style removal.
// match the inc at the begining of the dispatch routine
BulkUsb_DecrementIoCount(DeviceObject);
//
// Once DeviceRemoved is set no new IOCTL or read/write irps will be passed
// down the stack to lower drivers; all will be quickly failed
//
deviceExtension->DeviceRemoved = TRUE;
// Cancel any pending io requests; we may not have gotten a query first!
BulkUsb_CancelPendingIo( DeviceObject );
// If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
// This call will also close the pipes; if any user close calls get through,
// they will be noops
BulkUsb_AbortPipes( DeviceObject );
// We don't explicitly wait for the below driver to complete, but just make
// the call and go on, finishing cleanup
IoCopyCurrentIrpStackLocationToNext(Irp);
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
//
// The final decrement to device extension PendingIoCount == 0
// will set deviceExtension->RemoveEvent, enabling device removal.
// If there is no pending IO at this point, the below decrement will be it.
//
BulkUsb_DecrementIoCount(DeviceObject);
// wait for any io request pending in our driver to
// complete for finishing the remove
KeWaitForSingleObject(
&deviceExtension->RemoveEvent,
Suspended,
KernelMode,
FALSE,
NULL);
//
// Delete the link and FDO we created
//
BulkUsb_RemoveDevice(DeviceObject);
BULKUSB_KdPrint( DBGLVL_DEFAULT,("BulkUsb_ProcessPnPIrp() Detaching from %08X\n",
deviceExtension->TopOfStackDeviceObject));
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
BULKUSB_KdPrint( DBGLVL_DEFAULT,("BulkUsb_ProcessPnPIrp() Deleting %08X\n",
DeviceObject));
IoDeleteDevice (DeviceObject);
return ntStatus; // end, case IRP_MN_REMOVE_DEVICE
default:
//
// In this case we must not touch the status. As ntstatus is
// STATUS_SUCCESS, we will skip the failure case and pass down the IRP
// untouched.
//
BULKUSB_KdPrint( DBGLVL_MAXIMUM,("BulkUsb_ProcessPnPIrp() Minor PnP IOCTL not handled\n"));
} /* case MinorFunction */
if (!NT_SUCCESS(ntStatus)) {
// if anything went wrong, return failure without passing Irp down
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
BulkUsb_DecrementIoCount(DeviceObject);
BULKUSB_KdPrint( DBGLVL_MAXIMUM,("BulkUsb_ProcessPnPIrp() Exit BulkUsb_ProcessPnPIrp FAILURE %x\n", ntStatus));
return ntStatus;
}
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// All PNP_POWER messages get passed to the TopOfStackDeviceObject
// we were given in PnPAddDevice
//
BULKUSB_KdPrint( DBGLVL_MAXIMUM,("BulkUsb_ProcessPnPIrp() Passing PnP Irp down, status = %x\n", ntStatus));
ntStatus = IoCallDriver(stackDeviceObject,
Irp);
BulkUsb_DecrementIoCount(DeviceObject);
BULKUSB_KdPrint( DBGLVL_MAXIMUM,("BulkUsb_ProcessPnPIrp() Exit BulkUsb_ProcessPnPIrp %x\n", ntStatus));
return ntStatus;
}
NTSTATUS
BulkUsb_PnPAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine is called to create and initialize our Functional Device Object (FDO).
For monolithic drivers, this is done in DriverEntry(), but Plug and Play devices
wait for a PnP event
Arguments:
DriverObject - pointer to the driver object for this instance of BulkUsb
PhysicalDeviceObject - pointer to a device object created by the bus
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
USBD_VERSION_INFORMATION versionInformation;
ULONG i;
BULKUSB_KdPrint( DBGLVL_DEFAULT,("enter BulkUsb_PnPAddDevice()\n"));
//
// create our funtional device object (FDO)
//
ntStatus =
BulkUsb_CreateDeviceObject(DriverObject, PhysicalDeviceObject, &deviceObject);
if (NT_SUCCESS(ntStatus)) {
deviceExtension = deviceObject->DeviceExtension;
//
// we support direct io for read/write
//
deviceObject->Flags |= DO_DIRECT_IO;
//Set this flag causes the driver to not receive a IRP_MN_STOP_DEVICE
//during suspend and also not get an IRP_MN_START_DEVICE during resume.
//This is neccesary because during the start device call,
// the GetDescriptors() call will be failed by the USB stack.
deviceObject->Flags |= DO_POWER_PAGABLE;
// initialize our device extension
//
// remember the Physical device Object
//
deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
//
// Attach to the PDO
//
deviceExtension->TopOfStackDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
// Get a copy of the physical device's capabilities into a
// DEVICE_CAPABILITIES struct in our device extension;
// We are most interested in learning which system power states
// are to be mapped to which device power states for handling
// IRP_MJ_SET_POWER Irps.
BulkUsb_QueryCapabilities(deviceExtension->TopOfStackDeviceObject,
&deviceExtension->DeviceCapabilities);
// We want to determine what level to auto-powerdown to; This is the lowest
// sleeping level that is LESS than D3;
// If all are set to D3, auto powerdown/powerup will be disabled.
deviceExtension->PowerDownLevel = PowerDeviceUnspecified; // init to disabled
for (i=PowerSystemSleeping1; i<= PowerSystemSleeping3; i++) {
if ( deviceExtension->DeviceCapabilities.DeviceState[i] < PowerDeviceD3 )
deviceExtension->PowerDownLevel = deviceExtension->DeviceCapabilities.DeviceState[i];
}
#if DBG
// May want override auto power-down level from registry;
// ( CurrentControlSet\Services\BulkUsb\Parameters )
// Setting to 0 or 1 in registry disables auto power-down
BulkUsb_GetRegistryDword( BULKUSB_REGISTRY_PARAMETERS_PATH,
L"PowerDownLevel",
&(deviceExtension->PowerDownLevel) );
//
// display the device caps
//
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" >>>>>> DeviceCaps\n"));
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" SystemWake = %s\n",
BULKUSB_StringForSysState( deviceExtension->DeviceCapabilities.SystemWake ) ));
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" DeviceWake = %s\n",
BULKUSB_StringForDevState( deviceExtension->DeviceCapabilities.DeviceWake) ));
for (i=PowerSystemUnspecified; i< PowerSystemMaximum; i++) {
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" Device State Map: sysstate %s = devstate %s\n",
BULKUSB_StringForSysState( i ),
BULKUSB_StringForDevState( deviceExtension->DeviceCapabilities.DeviceState[i] ) ));
}
BULKUSB_KdPrint( DBGLVL_MEDIUM,(" <<<<<<<<DeviceCaps\n"));
#endif
// We keep a pending IO count ( extension->PendingIoCount ) in the device extension.
// The first increment of this count is done on adding the device.
// Subsequently, the count is incremented for each new IRP received and
// decremented when each IRP is completed or passed on.
// Transition to 'one' therefore indicates no IO is pending and signals
// deviceExtension->NoPendingIoEvent. This is needed for processing
// IRP_MN_QUERY_REMOVE_DEVICE
// Transition to 'zero' signals an event ( deviceExtension->RemoveEvent )
// to enable device removal. This is used in processing for IRP_MN_REMOVE_DEVICE
//
BulkUsb_IncrementIoCount(deviceObject);
}
USBD_GetUSBDIVersion(&versionInformation);
if( NT_SUCCESS( ntStatus ) )
{
NTSTATUS actStat;
// try to power down device until IO actually requested
actStat = BulkUsb_SelfSuspendOrActivate( deviceObject, TRUE );
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
BULKUSB_KdPrint( DBGLVL_DEFAULT,("exit BulkUsb_PnPAddDevice() (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -