📄 mavpnp.c
字号:
// quickly failed.
//
deviceExtension->RemoveDeviceRequested = TRUE;
//
// Wait for any io request pending in our driver to complete before
// returning success. This event is set when
// deviceExtension->PendingIoCount goes to 1.
//
KeWaitForSingleObject(&deviceExtension->NoPendingIoEvent,
Suspended, KernelMode, FALSE, NULL);
//
// Set the IRP status to success.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// We're done with this IRP.
//
break;
}
//
// The PnP Manager uses this IRP to inform the drivers for a device
// that the device will not be removed.
//
case IRP_MN_CANCEL_REMOVE_DEVICE:
{
//
// It is sent only after a successful IRP_MN_QUERY_REMOVE_DEVICE.
//
if(!deviceExtension->DeviceStarted)
{
//
// If we've never been started, just pass it on.
//
IoSkipCurrentIrpStackLocation(Irp);
ntStatus =
IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Reset this flag so new IOCTL and IO IRP processing will be
// re-enabled.
//
deviceExtension->RemoveDeviceRequested = FALSE;
//
// Set the IRP status to success.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// We're done with this IRP.
//
break;
}
//
// 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.
//
case IRP_MN_SURPRISE_REMOVAL:
{
//
// Match the increment at the begining of the dispatch routine.
//
MavUsb_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;
//
// 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.
//
MavUsb_AbortPipes(DeviceObject);
//
// Set the IRP status to success.
//
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 the status.
//
return(ntStatus);
}
//
// 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.
//
case IRP_MN_REMOVE_DEVICE:
{
//
// Match the increment at the begining of the dispatch routine.
//
MavUsb_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;
//
// 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.
//
MavUsb_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.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Wait for any io request pending in our driver to complete before
// finishing the remove.
//
KeWaitForSingleObject(&deviceExtension->RemoveEvent, Suspended,
KernelMode, FALSE, NULL);
//
// Delete the link and FDO we created.
//
MavUsb_RemoveDevice(DeviceObject);
//
// Detach from the PDO.
//
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
//
// Delete our FDO.
//
IoDeleteDevice(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Handle all other IRPs.
//
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.
//
}
}
//
// Handle any error conditions.
//
if(!NT_SUCCESS(ntStatus))
{
//
// Set the status in the IRP.
//
Irp->IoStatus.Status = ntStatus;
//
// Complete the IRP without passing it down.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//
// Prepare to send the IRP down by copying it to the next location on the
// IRP stack.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
//
// All PNP_POWER messages get passed to the TopOfStackDeviceObject we were
// given in PnPAddDevice
//
ntStatus = IoCallDriver(stackDeviceObject, Irp);
//
// Decrement the count of pending IRPs.
//
MavUsb_DecrementIoCount(DeviceObject);
//
// Return the status.
//
return(ntStatus);
}
//****************************************************************************
//
// 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
//
// PhysicalDeviceObject - pointer to a device object created by the bus
//
// Return Value:
//
// STATUS_SUCCESS if successful,
// STATUS_UNSUCCESSFUL otherwise
//
//****************************************************************************
NTSTATUS
MavUsb_PnPAddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_EXTENSION deviceExtension;
USBD_VERSION_INFORMATION versionInformation;
ULONG i;
//
// Create our funtional device object (FDO).
//
ntStatus = MavUsb_CreateDeviceObject(DriverObject, PhysicalDeviceObject,
&deviceObject);
if(NT_SUCCESS(ntStatus))
{
//
// Get the pointer to the device extension.
//
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.
//
MavUsb_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;
for(i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++)
{
if(deviceExtension->DeviceCapabilities.DeviceState[i] <
PowerDeviceD3)
{
deviceExtension->PowerDownLevel =
deviceExtension->DeviceCapabilities.DeviceState[i];
}
}
//
// 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -