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

📄 vscsidisk.c

📁 虚拟Scsi Disk源程序 版权归原作者
💻 C
📖 第 1 页 / 共 2 页
字号:
// VScsiDisk.c
//
// Generated by C DriverWizard 3.2.0 (Build 2485)
// Requires DDK Only
// File created on 5/18/2005
//

#include "pch.h"
#include "..\intrface.h"
#ifdef VSCSIDISK_WMI_TRACE
#include "VScsiDisk.tmh"
#endif

// global data
VSCSIDISK_DATA g_Data;

///////////////////////////////////////////////////////////////////////////////////////////////////
//  DriverEntry 
//      Installable driver initialization entry point.
//      This entry point is called directly by the I/O system.
//
//  Arguments:
//      IN  DriverObject
//              pointer to the driver object
//
//      IN  RegistryPath
//              pointer to a unicode string representing the path,
//              to driver-specific key in the registry.
//
//  Return Value:
//      Status
//
NTSTATUS DriverEntry(
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING RegistryPath
    )
{
    NTSTATUS    status;

    VScsiDiskDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"++");
    VScsiDiskDebugPrint(DBG_INIT, DBG_INFO, "Compiled at %s on %s", __TIME__, __DATE__);

#ifdef DBG
//    DbgBreakPoint();
#endif

#ifdef VSCSIDISK_WMI_TRACE 
    WPP_INIT_TRACING(DriverObject, RegistryPath);
#endif

    status = STATUS_SUCCESS;

    RtlZeroMemory(&g_Data, sizeof(VSCSIDISK_DATA));

    // save registry path for wmi
    g_Data.RegistryPath.Length = RegistryPath->Length;
    g_Data.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    g_Data.RegistryPath.Buffer = (PWCHAR)ExAllocatePoolWithTag(
                                            PagedPool,
                                            g_Data.RegistryPath.MaximumLength,
                                            VSCSIDISK_POOL_TAG
                                            );

    if (g_Data.RegistryPath.Buffer == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;

        VScsiDiskDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__": Failed to allocate memory for RegistryPath");

        return status;
    }

    RtlCopyUnicodeString(&g_Data.RegistryPath, RegistryPath);

    // detect current operating system
    if (IoIsWdmVersionAvailable(1, 0x30))
    {
        g_Data.WdmVersion = 0x0130;
    }
    else if (IoIsWdmVersionAvailable(1, 0x20))
    {
        g_Data.WdmVersion = 0x0120;
    }
    else if (IoIsWdmVersionAvailable(1, 0x10))
    {
        g_Data.WdmVersion = 0x0110;
    }
    else if (IoIsWdmVersionAvailable(1, 0x05))
    {
        g_Data.WdmVersion = 0x0105;
    }
    else
    {
        g_Data.WdmVersion = 0x0100;
    }

    // setup our dispatch function table in the driver object
    DriverObject->MajorFunction[IRP_MJ_PNP] = VScsiDiskPnpDispatch;
    DriverObject->MajorFunction[IRP_MJ_POWER] = VScsiDiskPowerDispatch;
    DriverObject->MajorFunction[IRP_MJ_CREATE] = VScsiDiskCreateDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = VScsiDiskCloseDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VScsiDiskDeviceIoControlDispatch;
    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VScsiDiskInternalDeviceIoControlDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = VScsiDiskCleanupDispatch;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = VScsiDiskSystemControlDispatch;

    DriverObject->DriverExtension->AddDevice = VScsiDiskAddDevice;
    DriverObject->DriverUnload = VScsiDiskUnload;

    VScsiDiskDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"--. STATUS %x", status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  VScsiDiskAddDevice 
//      The PnP manager new device callback
//
//  Arguments:
//      IN  DeviceObject
//              pointer to a device object.
//
//      IN  PhysicalDeviceObject
//              pointer to a device object created by the
//              underlying bus driver.
//
//  Return Value:
//      Status
//
NTSTATUS VScsiDiskAddDevice(
    IN PDRIVER_OBJECT   DriverObject,
    IN PDEVICE_OBJECT   PhysicalDeviceObject
    )
{
    NTSTATUS                            status;
    PDEVICE_OBJECT                      deviceObject;
    PVSCSIDISK_DEVICE_EXTENSION   deviceExtension;
    POWER_STATE                         powerState;
	UNICODE_STRING busFdoName;
    VScsiDiskDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"++: PDO %p", PhysicalDeviceObject);

    // Create our function device object.
	RtlInitUnicodeString(&busFdoName,BUS_FDO_NAME);
    status = IoCreateDevice(
                DriverObject,
                sizeof (VSCSIDISK_DEVICE_EXTENSION),
                &busFdoName,                    // device name
//              FILE_DEVICE_UNKNOWN,
				FILE_DEVICE_BUS_EXTENDER,//modified by zhu,2005-05-18
                FILE_DEVICE_SECURE_OPEN, // Do not use if binary intended for 9x
                FALSE,
                &deviceObject
                );

    if (!NT_SUCCESS(status)) 
    {
        VScsiDiskDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. IoCreateDevice STATUS %x", status);

        return status;
    }

    VScsiDiskDebugPrint(DBG_INIT, DBG_INFO, __FUNCTION__": Created FDO %p", deviceObject);

    // Initialize the device extension.
    deviceExtension = (PVSCSIDISK_DEVICE_EXTENSION)deviceObject->DeviceExtension;

    // Zero the memory
    RtlZeroMemory(deviceExtension, sizeof(VSCSIDISK_DEVICE_EXTENSION));

    deviceExtension->IsPdo = FALSE;

    // initialize list of PDO's
    ExInitializeFastMutex(&deviceExtension->PdoListLock);
    InitializeListHead(&deviceExtension->PdoListHead);

    // save the PDO pointer
    deviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;

    // save our device object
    deviceExtension->DeviceObject = deviceObject;

    // Initialize the powering down flag
    deviceExtension->bPowerStop = FALSE;

    // set RemoveCount to 1. Transition to zero
    // means IRP_MN_REMOVE_DEVICE was received
    deviceExtension->RemoveCount = 1;

    // Initialize Remove event
    KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent, FALSE);

    // initialize io lock
    VScsiDiskInitializeIoLock(&deviceExtension->IoLock, deviceObject);

    deviceExtension->PnpState = PnpStateNotStarted;
    deviceExtension->PreviousPnpState = PnpStateNotStarted;

    // allocate WorkItem for power processing
    deviceExtension->PowerWorkItem = IoAllocateWorkItem(deviceExtension->DeviceObject);
    if (deviceExtension->PowerWorkItem == NULL)
    {
        VScsiDiskDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. Failed to allocated PowerWorkItem");

        IoDeleteDevice(deviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // Initialize the device object flags

    // All WDM drivers are supposed to set this flag.  Devices
    // requiring a large amount of current at statup set the 
    // DO_POWER_INRUSH flag instead.  These flags are mutually
    // exclusive.
    if (PhysicalDeviceObject->Flags & DO_POWER_PAGABLE) 
    {
        deviceObject->Flags |= DO_POWER_PAGABLE;
    }

    // Typically, (almost always) the function driver for a device is the
    // power policy owner for that device.  In some cases
    // another driver or system component may assume this role.

    // Set the initial device power state of the device to powered down.
    deviceExtension->DevicePowerState = PowerDeviceD3;
    powerState.DeviceState = deviceExtension->DevicePowerState;

    // the initial system power state must be working or we wouldn't be here.
    deviceExtension->SystemPowerState = PowerSystemWorking;

    // Call PoSetPowerState to notify the power manager of our initial power state.
    PoSetPowerState(deviceObject, DevicePowerState, powerState);

    // Attach our device to the device stack and get the device object to 
    // which we send down IRPs to.
    deviceExtension->LowerDeviceObject = IoAttachDeviceToDeviceStack(
                                            deviceObject,
                                            PhysicalDeviceObject
                                            );

    if (deviceExtension->LowerDeviceObject == NULL) 
    {
        VScsiDiskDebugPrint(DBG_INIT, DBG_ERR, __FUNCTION__"--. IoAttachDeviceToDeviceStack failed");

        IoFreeWorkItem(deviceExtension->PowerWorkItem);
        IoDeleteDevice(deviceObject);
        return STATUS_DEVICE_REMOVED;
    }

    // increment device instance count
    ++g_Data.InstanceCount;

    // We are all done, so we need to clear the
    // DO_DEVICE_INITIALIZING flag.  This must be our
    // last action in AddDevice
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    VScsiDiskDebugPrint(DBG_INIT, DBG_TRACE, __FUNCTION__"--. VScsiDiskAddDevice--. STATUS %x", status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  VScsiDiskStartDevice
//      Start device handler, sets up resources
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//      IN  Irp
//              pointer to the Start IRP
//
//  Return Value:
//      NT status code
//
NTSTATUS VScsiDiskStartDevice(
    IN  PVSCSIDISK_DEVICE_EXTENSION    DeviceExtension,
    IN  PIRP                            Irp
    )
{
    NTSTATUS                        status = STATUS_SUCCESS;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resource;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceTrans;
    PCM_PARTIAL_RESOURCE_LIST       partialResourceList;
    PCM_PARTIAL_RESOURCE_LIST       partialResourceListTranslated;
    PIO_STACK_LOCATION              irpStack;
    POWER_STATE                     powerState;
    ULONG                           ii;

    VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++. IRP %p", Irp);

    // Get our current IRP stack location
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    // Do whatever initialization needed when starting the device:
    // gather information about it,  update the registry, etc.
    // At this point, the lower level drivers completed the IRP
    if ((irpStack->Parameters.StartDevice.AllocatedResources != NULL) &&
        (irpStack->Parameters.StartDevice.AllocatedResourcesTranslated != NULL)) 
    {
        // Parameters.StartDevice.AllocatedResources points to a
        // CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in raw form. Use the raw resources to program
        // the device.

        partialResourceList =
            &irpStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;

        resource = &partialResourceList->PartialDescriptors[0];

        // Parameters.StartDevice.AllocatedResourcesTranslated points
        // to a CM_RESOURCE_LIST describing the hardware resources that
        // the PnP Manager assigned to the device. This list contains
        // the resources in translated form. Use the translated resources
        // to connect the interrupt vector, map I/O space, and map memory.

        partialResourceListTranslated =
            &irpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;

        resourceTrans = &partialResourceListTranslated->PartialDescriptors[0];

        // search the resources
        for (ii = 0;
             ii < partialResourceList->Count;
             ++ii, ++resource, ++resourceTrans) 
        {

            switch (resource->Type) 
            {
            case CmResourceTypePort:
                VScsiDiskDebugPrint(DBG_PNP, DBG_INFO,  "Resource Type Port");
                VScsiDiskDebugPrint(DBG_PNP, DBG_INFO, "Port.Start %I64x", resource->u.Port.Start.QuadPart);
                VScsiDiskDebugPrint(DBG_PNP, DBG_INFO, "Port.Length %x", resource->u.Port.Length);
                break;
            case CmResourceTypeMemory:
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Memory");
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Memory.Start %I64x", resource->u.Memory.Start.QuadPart);
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Memory.Length %x", resource->u.Memory.Length);
                break;
            case CmResourceTypeInterrupt:
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Resource Type Interrupt");
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Level %x", resourceTrans->u.Interrupt.Level);
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Vector %x", resourceTrans->u.Interrupt.Vector);
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Interrupt.Affinity %x\n", resourceTrans->u.Interrupt.Affinity);
                break;
            default:
                VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, "Unknown Resource Type %x", resourceTrans->Type);
                break;
            }
        }
    }

    //*****************************************************************
    //*****************************************************************
    // TODO: check that all required resources have been allocated
    //*****************************************************************
    //*****************************************************************
    //*****************************************************************
    //*****************************************************************
    // TODO: allocate and initialize dma and shared memory resources
    //*****************************************************************
    //*****************************************************************


    //*****************************************************************
    //*****************************************************************
    // TODO: Reset and initialize your hardware
    //*****************************************************************
    //*****************************************************************

    //*****************************************************************
    //*****************************************************************
    // TODO: enable interrupts
    //*****************************************************************
    //*****************************************************************

    VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  VScsiDiskFreeResources
//      This routine returns all the resources acquired during
//      device startup.  Here we disconnect from any interrupt, 
//      unmap any I/O ports that are mapped in StartDevice, and 
//      disable any device interfaces or symbolic links.  
//      Before disconnecting an interrupt, be sure the device can
//      no longer generate interrupts.
//
//  Arguments:
//      IN  DeviceExtension
//              our device extension
//
//  Return Value:
//      NT status code
//
NTSTATUS VScsiDiskFreeResources(
    IN  PVSCSIDISK_DEVICE_EXTENSION DeviceExtension
    )
{
    NTSTATUS    status;

    VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"++");

    VScsiDiskDebugPrint(DBG_PNP, DBG_TRACE, __FUNCTION__"--");

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  VScsiDiskCreateDispatch
//      Dispatch routine for IRP_MJ_CREATE requests.
//
//  Arguments:
//      IN  DeviceObject
//              pointer to the device object for our device
//
//      IN  Irp
//              the create IRP
//
//  Return Value:
//      NT status code.
//
NTSTATUS VScsiDiskCreateDispatch(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    PVSCSIDISK_DEVICE_EXTENSION    deviceExtension;
    NTSTATUS                status;

    VScsiDiskDebugPrint(DBG_CREATECLOSE, DBG_TRACE, __FUNCTION__": IRP %p", Irp);

    // check if request is directed to PDO
    if (VScsiDiskIsPdo(DeviceObject))
    {
        status = STATUS_SUCCESS;

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        VScsiDiskDebugPrint(DBG_CREATECLOSE, DBG_WARN, __FUNCTION__"--. IRP %p, STATUS %x", Irp, status);

        return status;
    }

    deviceExtension = (PVSCSIDISK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if (!VScsiDiskAcquireRemoveLock(deviceExtension))
    {
        status = STATUS_NO_SUCH_DEVICE;

        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        VScsiDiskDebugPrint(DBG_CREATECLOSE, DBG_WARN, __FUNCTION__"$$--. IRP %p, STATUS %x", Irp, status);

        return status;
    }

    // increment open count
    InterlockedIncrement(&deviceExtension->OpenHandleCount);

    status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    VScsiDiskReleaseRemoveLock(deviceExtension);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -