📄 pnp.c
字号:
// pnp.c
//
// Generated by C DriverWizard 3.2.0 (Build 2485)
// Requires DDK Only
// File created on 5/18/2005
//
#include "pch.h"
#ifdef VSCSIDISK_WMI_TRACE
#include "pnp.tmh"
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskPnpDispatch
// Dispatch routine to handle PnP requests
//
// Arguments:
// IN DeviceObject
// pointer to our device object
//
// IN Irp
// pointer to the PnP IRP
//
// Return Value:
// NT status code
//
NTSTATUS VScsiDiskPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PVSCSIDISK_DEVICE_EXTENSION deviceExtension;
PIO_STACK_LOCATION irpStack;
NTSTATUS status;
PDEVICE_CAPABILITIES deviceCapabilities;
ULONG requestCount;
ULONG index;
PPNP_DEVICE_STATE deviceState;
PVSCSIDISK_PDO_DEVICE_EXTENSION pdoExtension;
PLIST_ENTRY listEntry;
PDEVICE_RELATIONS oldDeviceRelations;
PDEVICE_RELATIONS newDeviceRelations;
ULONG pdoCount;
ULONG oldCount;
POWER_STATE powerState;
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);
// check if the IRP is for PDO
if (VScsiDiskIsPdo(DeviceObject))
{
return VScsiDiskPdoPnpDispatch(DeviceObject, Irp);
}
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"fdo");
VScsiDiskDumpIrp(Irp);
// Get our device extension from the device object
deviceExtension = (PVSCSIDISK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// Get our current IRP stack location
irpStack = IoGetCurrentIrpStackLocation(Irp);
// Make sure we can accept IRPs
if (!VScsiDiskAcquireRemoveLock(deviceExtension))
{
status = STATUS_NO_SUCH_DEVICE;
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
VScsiDiskDebugPrint(DBG_PNP, DBG_WARN, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
}
switch (irpStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
// The device stack must be started from the bottom up.
// So, we send the IRP down the stack and wait so that
// all devices below ours have started before we process
// this IRP and start ourselves.
status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);
if (!NT_SUCCESS(status))
{
// Someone below us failed to start, so just complete with error
break;
}
// Lower drivers have finished their start operation, so now
// we process ours.
// Start is an implicit power-up so
// we set our device power state accordingly
deviceExtension->DevicePowerState = PowerDeviceD0;
powerState.DeviceState = deviceExtension->DevicePowerState;
PoSetPowerState(deviceExtension->DeviceObject, DevicePowerState, powerState);
status = VScsiDiskGetDeviceCapabilities(deviceExtension);
if (!NT_SUCCESS(status))
{
VScsiDiskFreeResources(deviceExtension);
break;
}
status = VScsiDiskStartDevice(deviceExtension, Irp);
if (!NT_SUCCESS(status))
{
VScsiDiskFreeResources(deviceExtension);
break;
}
// Update our PnP state
deviceExtension->PnpState = PnpStateStarted;
// restart any stalled queues
VScsiDiskRestartQueues(deviceExtension);
VScsiDiskCreatePdo(deviceExtension, g_Data.InstanceCount);
break;
case IRP_MN_QUERY_STOP_DEVICE:
if (VScsiDiskIsStoppable(deviceExtension))
{
// Device is stoppable.
// pause io request processing
VScsiDiskStallQueues(deviceExtension);
// Update our PnP state
deviceExtension->PreviousPnpState = deviceExtension->PnpState;
deviceExtension->PnpState = PnpStateStopPending;
// We must set Irp->IoStatus.Status to STATUS_SUCCESS before
// passing it down.
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
// Decrement the active I/O count
VScsiDiskReleaseRemoveLock(deviceExtension);
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
}
else
{
// device is not currently stoppable, fail the request
status = STATUS_UNSUCCESSFUL;
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
// Send this IRP down and wait for it to come back,
// restart our stall fifo,
// and process all the previously queued up IRPs.
// First check to see whether we received a query before this
// cancel. This could happen if someone above us failed a query
// and passed down the subsequent cancel.
if (deviceExtension->PnpState == PnpStateStopPending)
{
status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject,Irp);
if (NT_SUCCESS(status))
{
// restore previous pnp state
deviceExtension->PnpState = deviceExtension->PreviousPnpState;
// restart the queues
VScsiDiskRestartQueues(deviceExtension);
}
else
{
// Somebody below us failed the cancel
// this is a fatal error.
ASSERTMSG("Cancel stop failed!", FALSE);
VScsiDiskDebugPrint(DBG_PNP, DBG_ERR, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
}
}
else
{
// Spurious cancel so we just complete the request.
status = STATUS_SUCCESS;
}
break;
case IRP_MN_STOP_DEVICE:
// Mark the device as stopped.
deviceExtension->PnpState = PnpStateStopped;
// release our resources
VScsiDiskFreeResources(deviceExtension);
// send the request down, and we are done
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
VScsiDiskReleaseRemoveLock(deviceExtension);
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
case IRP_MN_QUERY_REMOVE_DEVICE:
if (VScsiDiskIsRemovable(deviceExtension))
{
// pause io request processing
VScsiDiskStallQueues(deviceExtension);
// Update our PnP state
deviceExtension->PreviousPnpState = deviceExtension->PnpState;
deviceExtension->PnpState = PnpStateRemovePending;
// Now just send the request down and we are done
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver(deviceExtension->LowerDeviceObject, Irp);
// decrement the I/O count
VScsiDiskReleaseRemoveLock(deviceExtension);
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
}
else
{
// Our device is not removable, just fail the request
status = STATUS_UNSUCCESSFUL;
}
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
// First check to see whether we have received a prior query
// remove request. It could happen that we did not if
// someone above us failed a query remove and passed down the
// subsequent cancel remove request.
if (PnpStateRemovePending == deviceExtension->PnpState)
{
status = VScsiDiskSubmitIrpSync(deviceExtension->LowerDeviceObject, Irp);
if (NT_SUCCESS(status))
{
// restore pnp state, since remove was canceled
deviceExtension->PnpState = deviceExtension->PreviousPnpState;
// restart the queues
VScsiDiskRestartQueues(deviceExtension);
}
else
{
// Nobody can fail this IRP. This is a fatal error.
ASSERTMSG("IRP_MN_CANCEL_REMOVE_DEVICE failed. Fatal error!", FALSE);
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
}
}
else
{
// Spurious cancel remove request so we just complete it
status = STATUS_SUCCESS;
}
break;
case IRP_MN_SURPRISE_REMOVAL:
// The device has been unexpectedly removed from the machine
// and is no longer available for I/O.
// We must return device and memory resources,
// disable interfaces. We will defer failing any outstanding
// request to IRP_MN_REMOVE.
// stall all the queues
VScsiDiskStallQueues(deviceExtension);
// flush pending io list
VScsiDiskInvalidateIo(&deviceExtension->IoLock, STATUS_NO_SUCH_DEVICE);
// update pnp state
deviceExtension->PnpState = PnpStateSurpriseRemoved;
ExAcquireFastMutex(&deviceExtension->PdoListLock);
while (!IsListEmpty(&deviceExtension->PdoListHead))
{
listEntry = RemoveHeadList(&deviceExtension->PdoListHead);
pdoExtension = CONTAINING_RECORD(listEntry, VSCSIDISK_PDO_DEVICE_EXTENSION, PdoListEntry);
InitializeListHead(&pdoExtension->PdoListEntry);
pdoExtension->ParentDeviceObject = NULL;
pdoExtension->DeleteOnRemove = TRUE;
}
ExReleaseFastMutex(&deviceExtension->PdoListLock);
// Return any resources acquired during device startup.
VScsiDiskFreeResources(deviceExtension);
// We must set Irp->IoStatus.Status to STATUS_SUCCESS before
// passing it down.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -