⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdo.c

📁 虚拟Scsi Disk源程序 版权归原作者
💻 C
📖 第 1 页 / 共 3 页
字号:
        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 + -