📄 pdo.c
字号:
status = STATUS_INSUFFICIENT_RESOURCES;
}
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskPdoForwardComplete
// Completion routine for VScsiDiskPdoForwardRequestToParent call.
//
// Arguments:
// IN DeviceObject
// Target Device Object
//
// IN Irp
// pointer to completed IRP
//
// IN Context
// MustHandle value
//
// Return Value:
// NT status code.
//
// Comments:
// This routine just releases the allocated resources and
// completes the original IRP.
//
NTSTATUS VScsiDiskPdoForwardComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PIRP originalIrp;
PIO_STACK_LOCATION irpStack;
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);
ObDereferenceObject(DeviceObject);
irpStack = IoGetCurrentIrpStackLocation(Irp);
originalIrp = (PIRP)irpStack->Parameters.Others.Argument1;
if (Irp->IoStatus.Status == STATUS_NOT_SUPPORTED)
{
if (Context)
{
originalIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
}
else
{
originalIrp->IoStatus = Irp->IoStatus;
}
IoFreeIrp(Irp);
IoCompleteRequest(originalIrp, IO_NO_INCREMENT);
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--");
return STATUS_MORE_PROCESSING_REQUIRED;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskPdoPowerDispatch
// IRP_MJ_POWER dispatch handler for PDO.
//
// Arguments:
// IN DeviceObject
// PDO
//
// IN Irp
// IRP_MJ_POWER Irp
//
// Return Value:
// NT status code.
//
NTSTATUS VScsiDiskPdoPowerDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PVSCSIDISK_PDO_DEVICE_EXTENSION pdoExtension;
PVSCSIDISK_DEVICE_EXTENSION fdoExtension;
NTSTATUS status;
PIO_STACK_LOCATION irpStack;
KIRQL oldIrql;
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);
VScsiDiskDumpIrp(Irp);
pdoExtension =
(PVSCSIDISK_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
// Get our current IRP stack location
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MinorFunction)
{
case IRP_MN_SET_POWER:
if (irpStack->Parameters.Power.Type == SystemPowerState)
{
pdoExtension->SystemPowerState =
irpStack->Parameters.Power.State.SystemState;
PoSetPowerState(pdoExtension->DeviceObject, DevicePowerState, irpStack->Parameters.Power.State);
status = STATUS_SUCCESS;
}
else
{
fdoExtension =
(PVSCSIDISK_DEVICE_EXTENSION)
pdoExtension->ParentDeviceObject->DeviceExtension;
pdoExtension->DevicePowerState =
irpStack->Parameters.Power.State.DeviceState;
status = VScsiDiskPdoPowerParent(fdoExtension, Irp);
}
break;
case IRP_MN_QUERY_POWER:
status = STATUS_SUCCESS;
break;
case IRP_MN_WAIT_WAKE:
status = Irp->IoStatus.Status;
break;
case IRP_MN_POWER_SEQUENCE:
status = Irp->IoStatus.Status;
break;
default:
status = Irp->IoStatus.Status;
break;
}
if (status != STATUS_PENDING)
{
Irp->IoStatus.Status = status;
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskPdoPowerParent
// This routine powers up or down parent bus.
//
// Arguments:
// IN DeviceExtension
// our device extension
//
// IN Irp
// PDO power irp
//
// Return Value:
// NT status code.
//
NTSTATUS VScsiDiskPdoPowerParent(
IN PVSCSIDISK_DEVICE_EXTENSION DeviceExtension,
IN PIRP Irp
)
{
PVSCSIDISK_PDO_DEVICE_EXTENSION pdoExtension;
NTSTATUS status;
PLIST_ENTRY listEntry;
DEVICE_POWER_STATE devicePowerState;
POWER_STATE powerState;
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);
devicePowerState = PowerDeviceD3;
ExAcquireFastMutex(&DeviceExtension->PdoListLock);
for (listEntry = DeviceExtension->PdoListHead.Flink;
listEntry != &DeviceExtension->PdoListHead;
listEntry = listEntry->Flink)
{
pdoExtension = CONTAINING_RECORD(listEntry, VSCSIDISK_PDO_DEVICE_EXTENSION, PdoListEntry);
if (pdoExtension->DevicePowerState < devicePowerState)
{
devicePowerState = pdoExtension->DevicePowerState;
}
}
ExReleaseFastMutex(&DeviceExtension->PdoListLock);
if (devicePowerState < DeviceExtension->DevicePowerState)
{
powerState.DeviceState = PowerDeviceD0;
IoMarkIrpPending(Irp);
status = PoRequestPowerIrp(
DeviceExtension->DeviceObject,
IRP_MN_SET_POWER,
powerState,
VScsiDiskPdoPowerParentComplete,
Irp,
NULL
);
}
else if ((devicePowerState > DeviceExtension->DevicePowerState) &&
(DeviceExtension->DevicePowerState == PowerDeviceD0))
{
powerState.DeviceState = devicePowerState;
PoRequestPowerIrp(
DeviceExtension->DeviceObject,
IRP_MN_SET_POWER,
powerState,
NULL,
NULL,
NULL
);
}
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--. STATUS %x", status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskPdoPowerParentComplete
// Completion routine for powering up the parent FDO.
//
// Arguments:
// IN DeviceObject
// pointer to parent FDO
//
// IN MinorFunction
// IRP_MJ_POWER minor code
//
// IN PowerState
// new power state
//
// IN Context
// pointer to pdo power irp
//
// IN IoStatus
// status of IRP
//
// Return Value:
// None.
//
VOID VScsiDiskPdoPowerParentComplete(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
{
NTSTATUS status;
PIRP irp;
status = IoStatus->Status;
irp = (PIRP)Context;
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++");
PoStartNextPowerIrp(irp);
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
VScsiDiskDebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--");
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskCreatePdo
// This routine creates a new pdo.
//
// Arguments:
// IN DeviceExtension
// our device extension
//
// IN DeviceId
// unique id of a new device
//
// Return Value:
// NT status code.
//
NTSTATUS VScsiDiskCreatePdo(
IN PVSCSIDISK_DEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceId
)
{
PVSCSIDISK_PDO_DEVICE_EXTENSION pdoExtension;
PDEVICE_OBJECT pdo;
NTSTATUS status;
BOOLEAN bFound;
PLIST_ENTRY listEntry;
ULONG size;
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. DeviceId %x", DeviceId);
bFound = FALSE;
ExAcquireFastMutex(&DeviceExtension->PdoListLock);
for (listEntry = DeviceExtension->PdoListHead.Flink;
listEntry != &DeviceExtension->PdoListHead;
listEntry = listEntry->Flink)
{
pdoExtension = CONTAINING_RECORD(listEntry, VSCSIDISK_PDO_DEVICE_EXTENSION, PdoListEntry);
if ((pdoExtension->DeviceId == DeviceId) &&
(pdoExtension->PnpState != PnpStateSurpriseRemoved))
{
bFound = TRUE;
break;
}
}
ExReleaseFastMutex(&DeviceExtension->PdoListLock);
if (!bFound)
{
status = IoCreateDevice(
DeviceExtension->DeviceObject->DriverObject,
sizeof(VSCSIDISK_PDO_DEVICE_EXTENSION),
NULL,
// FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_DISK,
FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
FALSE,
&pdo
);
if (NT_SUCCESS(status))
{
pdoExtension = (PVSCSIDISK_PDO_DEVICE_EXTENSION)pdo->DeviceExtension;
RtlZeroMemory(pdoExtension, sizeof(VSCSIDISK_PDO_DEVICE_EXTENSION));
size = sizeof(L"SCSI\\Disk\0GenDisk\0");
pdoExtension->HardwareId =
(PWCHAR)ExAllocatePoolWithTag(NonPagedPool, size, VSCSIDISK_POOL_TAG);
if (pdoExtension->HardwareId != NULL)
{
RtlCopyMemory(
pdoExtension->HardwareId,
L"SCSI\\Disk\0GenDisk\0",
size
);
pdoExtension->DeviceId = DeviceId;
pdoExtension->IsPdo = TRUE;
pdoExtension->DeviceObject = pdo;
pdoExtension->ParentDeviceObject = DeviceExtension->DeviceObject;
pdoExtension->IsExist = TRUE;
pdoExtension->DeleteOnRemove = FALSE;
pdoExtension->PnpState = PnpStateNotStarted;
pdoExtension->PreviousPnpState = PnpStateNotStarted;
// Set the initial device power state of the device to powered down.
pdoExtension->DevicePowerState = PowerDeviceD3;
// the initial system power state must be working or we wouldn't be here.
pdoExtension->SystemPowerState = PowerSystemWorking;
pdo->Flags |= DO_POWER_PAGABLE;
ExAcquireFastMutex(&DeviceExtension->PdoListLock);
InsertTailList(&DeviceExtension->PdoListHead, &pdoExtension->PdoListEntry);
ExReleaseFastMutex(&DeviceExtension->PdoListLock);
// This should be the last step in initialization.
pdo->Flags &= ~DO_DEVICE_INITIALIZING;
IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations);
}
else
{
status = STATUS_INSUFFICIENT_RESOURCES;
IoDeleteDevice(pdo);
}
}
}
else
{
status = STATUS_INVALID_PARAMETER;
}
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. DeviceId %x STATUS %x", DeviceId, status);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// VScsiDiskRemovePdo
// This routine removes pdo.
//
// Arguments:
// IN DeviceExtension
// our device extension
//
// IN DeviceId
// id of a pdo to remove
//
// Return Value:
// NT status code.
//
NTSTATUS VScsiDiskRemovePdo(
IN PVSCSIDISK_DEVICE_EXTENSION DeviceExtension,
IN ULONG DeviceId
)
{
PVSCSIDISK_PDO_DEVICE_EXTENSION pdoExtension;
NTSTATUS status;
BOOLEAN bFound;
PLIST_ENTRY listEntry;
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. DeviceId %x", DeviceId);
bFound = FALSE;
ExAcquireFastMutex(&DeviceExtension->PdoListLock);
for (listEntry = DeviceExtension->PdoListHead.Flink;
listEntry != &DeviceExtension->PdoListHead;
listEntry = listEntry->Flink)
{
pdoExtension = CONTAINING_RECORD(listEntry, VSCSIDISK_PDO_DEVICE_EXTENSION, PdoListEntry);
if (pdoExtension->DeviceId == DeviceId)
{
pdoExtension->IsExist = FALSE;
bFound = TRUE;
break;
}
}
ExReleaseFastMutex(&DeviceExtension->PdoListLock);
if (bFound)
{
IoInvalidateDeviceRelations(DeviceExtension->PhysicalDeviceObject, BusRelations);
status = STATUS_SUCCESS;
}
else
{
status = STATUS_NO_SUCH_DEVICE;
}
VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. DeviceId %x STATUS %x", DeviceId, status);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -