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

📄 vdiskmp.c

📁 SCSI 的虚拟磁盘驱动 需要 windows DDK 很易懂的 DDK 文件结构
💻 C
📖 第 1 页 / 共 5 页
字号:
            // Shutdown the Lun
            VdiskShutdownLun(((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[Index], TRUE);
            // Clear  pointer            
            ((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[Index] = NULL;
        }
}

///////////////////////////////////////////////////////////////////////////////
//
static NTSTATUS VdiskMpRestartDevice(PVOID DeviceExtension)
{
    UCHAR TargetId;
    UCHAR LunId;
    KdPrint(("VdiskMpRestartDevice enter...\r\n"));
    for (TargetId=0;TargetId<NUMBER_OF_TARGETS;TargetId++)
        for (LunId=0;LunId<NUMBER_OF_LUNS;LunId++)
            // Reload Registry and restart threads if needed
            VdiskInquiryLun(DeviceExtension, TargetId, LunId);
    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
//
static VOID VdiskMpDestroyLun(PVOID DeviceExtension, PVOID LunExtension)
{
    KdPrint(("VdiskMpDestroyLun enter... Lun %X\r\n", LunExtension));
    // If thread is working call shutdown
    if ((LunExtension != NULL) && ((((PVDISK_LUN_EXTENSION)LunExtension)->Flags & VDISK_LUN_THREAD_FINISHED) == 0))
    {
        if (((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[VdiskLun2Index(((PVDISK_LUN_EXTENSION)LunExtension)->TargetId,
            ((PVDISK_LUN_EXTENSION)LunExtension)->LunId)] == NULL)
        {
            KdPrint(( "VdiskMpDestroyLun: (%d,%d) Marked as shutdowned. Skip func.\r\n",
                    ((PVDISK_LUN_EXTENSION)LunExtension)->TargetId, 
                    ((PVDISK_LUN_EXTENSION)LunExtension)->LunId ));
        }
        else
        {
            // Avoid processing shutdown twice
            VdiskShutdownLun((PVDISK_LUN_EXTENSION)LunExtension, TRUE);
            // Clear pointer 
            ((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[VdiskLun2Index(((PVDISK_LUN_EXTENSION)LunExtension)->TargetId, 
                ((PVDISK_LUN_EXTENSION)LunExtension)->LunId)] = NULL;
        }
		// Erase sign
		((PVDISK_LUN_EXTENSION)LunExtension)->Sign = 0;
    }
    else
    {
        if (LunExtension != NULL) 
		{
			// This case appears when work thread couldn't create file.
			// So thread finished but LunExtension was initialized.
			KdPrint(("VdiskMpDestroyLun: Already destroyed. Flag %X Sign %s\r\n", 
				(((PVDISK_LUN_EXTENSION)LunExtension)->Flags & VDISK_LUN_THREAD_FINISHED),
				(((PVDISK_LUN_EXTENSION)LunExtension)->Sign == VDISK_LUN_SIGN?"Ok":"Wrong")));
			// Erase sign
			((PVDISK_LUN_EXTENSION)LunExtension)->Sign = 0;
		} 
		else
		{
			KdPrint(("VdiskMpDestroyLun: Strange case.\r\n")); 
		}
    }
}

// MN_QUERY_PNP_DEVICE_STATE handler for a adapter
static VOID VdiskMpAdapterPnPDeviceState(IN PVOID DeviceExtension,
                                                            IN OUT PNP_DEVICE_STATE* State)
{
    // DEMO for a hidden adapter:
    // *State |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
    KdPrint(("VdiskMpAdapterPnPDeviceState: adapter %p state %08lx\r\n",
                                                                DeviceExtension, *State)); 
    UNREFERENCED_PARAMETER(State);
}

// MN_QUERY_PNP_DEVICE_STATE handler for a LUN
static VOID VdiskMpLunPnPDeviceState(IN PVOID Lun, IN OUT PNP_DEVICE_STATE* State)
{
    // DEMO for a hidden LUN:
    // *State |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
    KdPrint(("VdiskMpLunPnPDeviceState: LUN %p state %08lx\r\n", Lun, *State)); 
    UNREFERENCED_PARAMETER(State);
}

#endif // VSPORT_PNP

///////////////////////////////////////////////////////////////////////////////
//
static VOID VdiskShutdownLun(PVDISK_LUN_EXTENSION Lun, BOOLEAN WaitForThread)
{		    
    KdPrint(("VdiskShutdownLun: enter...\r\n"));
    // We can call this function twice
    if ((Lun != NULL) && ((Lun->Flags & VDISK_LUN_THREAD_FINISHED) == 0))
    {
        KdPrint(("VdiskShutdownLun: Lun 0x%X (%u,%u) needed shutdown. \r\n",
                    Lun, Lun->TargetId, Lun->LunId));
        // If thread is not finshed yet
        // Set flags
        Lun->Flags |= VDISK_LUN_SHUTDOWN;
        // FInish pending requests.
        VdiskRequestDeleteAll(Lun);
        Lun->Flags |= VDISK_LUN_THREAD_FINISHED;
        // Shut down the thread by signal shutdown event
        KeSetEvent((PKEVENT)(&Lun->ShutdownEvent), IO_NO_INCREMENT, FALSE);
        if( WaitForThread )
            // Wait for the thread to terminate
    	    KeWaitForSingleObject(Lun->ThreadObject, Executive, KernelMode, FALSE, NULL);
	    ObDereferenceObject(Lun->ThreadObject);
    }
}            

///////////////////////////////////////////////////////////////////////////////
//
static BOOLEAN VdiskMpResetBus(PVOID DeviceExtension, ULONG PathId)
{
    PVDISK_LUN_EXTENSION Lun;
    ULONG Index;
    KdPrint(("VdiskMpResetBus enter...\r\n"));
    ASSERT(DeviceExtension);
    // Clear all requests lists in the all LUNs
    for(Index=0;Index<NUMBER_OF_TARGETS*NUMBER_OF_LUNS;Index++)
    {
        // Get LUN
        Lun = ((PVDISK_DEVICE_EXTENSION)DeviceExtension)->Luns[Index];
        // Remove all pending requests
        if ((Lun != NULL) && ((Lun->Flags & VDISK_LUN_THREAD_FINISHED) == 0))
        {
            // If thread is working finish all requests
            // but don't finish thread
            VdiskRequestDeleteAll(Lun);
        }
    }
    KdPrint(("VdiskMpResetBus finish...\r\n"));
    return TRUE;
	UNREFERENCED_PARAMETER(PathId);
	UNREFERENCED_PARAMETER(DeviceExtension);
}

///////////////////////////////////////////////////////////////////////////////
//
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    VSP_INITIALIZATION_DATA InitializationData;
	ULONG i;
	// Dump copyright information in the debug build
	KdPrint(("\r\nStorageCraft Virtual SCSI Miniport. Disk in a file 3. WMI support.\r\n"
		"Copyright 2002 StorageCraft, inc.\r\n\r\n"));
	// Zero the initilization data
	for (i = 0; i < sizeof (VSP_INITIALIZATION_DATA); i++)
		((PUCHAR)&InitializationData)[i] = 0;
    // Fill the initialization data
    InitializationData.VsInitialize = VdiskMpInitialize;
    InitializationData.VsStartIo = VdiskMpStartIo;
    InitializationData.VsNewDevice = VdiskMpNewDevice;
    InitializationData.VsResetBus = VdiskMpResetBus;
    InitializationData.VsInquiry = VdiskMpInquiry;
#ifdef VSPORT_PNP
    // W2K support
    InitializationData.VsStopDevice = VdiskMpStopDevice;
    InitializationData.VsRestartDevice = VdiskMpRestartDevice;
    InitializationData.VsDestroyLun = VdiskMpDestroyLun;
    InitializationData.VsAdapterPnPDeviceState = VdiskMpAdapterPnPDeviceState;
    InitializationData.VsLunPnPDeviceState = VdiskMpLunPnPDeviceState;
    InitializationData.PnPMiniport = TRUE;
#endif
    InitializationData.DeviceExtensionSize = sizeof (VDISK_DEVICE_EXTENSION);
    InitializationData.LuExtensionSize = sizeof (VDISK_LUN_EXTENSION);
    InitializationData.SrbExtensionSize = sizeof (VDISK_LUN_REQUEST);
    InitializationData.MapBuffers = TRUE;
    InitializationData.TaggedQueuing = FALSE;
    InitializationData.AutoRequestSense = TRUE;
    InitializationData.MultipleRequestPerLu = TRUE;
    InitializationData.ReceiveEvent = FALSE;
    KdPrint(("Sizes:%u %u %u\r\n", InitializationData.DeviceExtensionSize,
                InitializationData.LuExtensionSize, InitializationData.SrbExtensionSize));
    // Register the miniport in VSPORT
    return VsPortInitialize(DriverObject, RegistryPath,	&InitializationData, NULL);
}

///////////////////////////////////////////////////////////////////////////////
// Executes a single system thread request
// Called by the system thread
// Returns TRUE if the system thread must quit
static BOOLEAN VdiskRequestExecute(PVDISK_LUN_REQUEST Request, PVDISK_LUN_EXTENSION Lun, PTHREAD_STORAGE Storage)
{
    typedef NTSTATUS (*PREAD_WRITE_TYPE)(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine,
                                            PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock,
                                            PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
                                            PULONG Key); 
    PREAD_WRITE_TYPE TransferFunc = ZwReadFile;
	NTSTATUS Status;
	IO_STATUS_BLOCK Iosb;
    PVOID Buf;
    ASSERT(Request);
    // ATTENTION! Lun corrupted during shutdown
    ASSERT(Lun || (Request->RequestCode == VDISK_REQUEST_SHUTDOWN));

    IF_1(KdPrint(("VdiskRequestExecute: start.\r\n"));)
    // Switch on request code
	switch (Request->RequestCode)
	{
    case VDISK_REQUEST_INIT:
	{	
    	OBJECT_ATTRIBUTES ObjAttr;
    	UNICODE_STRING StrFileName;
    	LARGE_INTEGER FileSizeOffset;
    	PVOID Buf;
        KdPrint(("VdiskRequestExecute: VDISK_REQUEST_INIT\r\n"));
        // If Storage not allocated
        if (Storage == NULL)
        {
            KdPrint(("VdiskRequestExecute: Storage not allocated\r\n"));
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto CompleteInit;
        }
        // If file is already opened return
        if (Storage->FileHandle)
        {
            KdPrint(("VdiskRequestExecute: File already opened\r\n"));
            // Status success
            Status = STATUS_SUCCESS;
            goto CompleteInit;
        }
        RtlInitUnicodeString(&StrFileName, (PWSTR)Lun->SzFileName);
        // Cals file size in bytes
        FileSizeOffset.QuadPart = Lun->DiskSize * 512;
        // Open or create the file
		InitializeObjectAttributes(&ObjAttr, &StrFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
        Status = ZwCreateFile(&Storage->FileHandle, GENERIC_READ | GENERIC_WRITE, &ObjAttr,
                    			&Iosb, &FileSizeOffset, FILE_ATTRIBUTE_ARCHIVE,
                    			0, FILE_OPEN_IF, 
                                FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS, 
                                NULL, 0);
        // Will close all handles on failure
		if (NT_SUCCESS(Status) && (Iosb.Information == FILE_CREATED))
        {
            // Zero the partition table if this is a newly created file
			KdPrint(("VdiskRequestExecute: New file created - will zeroing the partition table\r\n"));
            Buf = ExAllocatePool(PagedPool, 512);
            if (Buf != NULL)
            {
                RtlZeroMemory(Buf, 512);
                FileSizeOffset.QuadPart = 0;
                Status = ZwWriteFile(Storage->FileHandle, NULL, NULL, NULL, &Iosb, Buf, 512, &FileSizeOffset, NULL); 
                // TODO: status code check
                KdPrint(("VdiskRequestExecute: Sector 0 have written. Status = 0x%X\r\n", Status));
                // Extends the file and updates the end-of-file mark
                FileSizeOffset.QuadPart = (Lun->DiskSize-1) * 512;
                Status = ZwWriteFile(Storage->FileHandle, NULL, NULL, NULL, &Iosb, Buf, 512, &FileSizeOffset, NULL); 
                // TODO: status code check
                KdPrint(("VdiskRequestExecute: Sector %u have written. Status = 0x%X\r\n", Lun->DiskSize-1, Status));
                ExFreePool(Buf);
            }
            else
            {
                KdPrint(("VdiskRequestExecute: Can't allocate buffer\r\n"));
                // Close file
                ZwClose(Storage->FileHandle);
                Storage->FileHandle = 0;
                // Failed
                Status = STATUS_INSUFFICIENT_RESOURCES;
            }
		}
        // If file succesfully exists
        if (NT_SUCCESS(Status))
        {
            // Query alignment information
            Status = ZwQueryInformationFile(Storage->FileHandle, &Iosb, &Lun->AlignmentInfo,
                                            sizeof (FILE_ALIGNMENT_INFORMATION),
                                            FileAlignmentInformation);
            // Always return FILE_BYTE_ALIGNMENT. May be other values on difeferent computers.
            KdPrint(("VdiskRequestExecute: Status = 0x%X ALIGNMENT 0x%08x\r\n",
                        Status, Lun->AlignmentInfo.AlignmentRequirement));
            // Allocate buffer if align neded
            if (NT_SUCCESS(Status) && (Lun->AlignmentInfo.AlignmentRequirement != FILE_BYTE_ALIGNMENT)) 
            {
                // Allocate one page
                Lun->AlignedBuf = ExAllocatePool( NonPagedPool, PAGE_SIZE );
                // check status
                if (Lun->AlignedBuf == NULL)
                {
                    KdPrint(("VdiskRequestExecute: Can't allocate buffer\r\n"));
                    // Close file
                    ZwClose(Storage->FileHandle);
                    Storage->FileHandle = 0;
                    // Failed
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
        }
        else
        {
            KdPrint(("VdiskRequestExecute: CreateFile failed. Strange\r\n"));
        }
        Storage->AlignedBuf = Lun->AlignedBuf;
CompleteInit:
        // Signal the completion
        Request->ParamInitStatus = Status;
        KeSetEvent((PKEVENT)(Request->ParamInitEvent), IO_NO_INCREMENT, FALSE);
        // Return TRUE if initialization failed
		return (NT_SUCCESS(Status) ? FALSE : TRUE);
	}
    case VDISK_REQUEST_SHUTDOWN:
        KdPrint(("VdiskRequestExecute: VDISK_REQUEST_SHUTDOWN\r\n"));
        if (Storage!=NULL)
        {
            // Close the file
		    if (Storage->FileHandle)
            {
                KdPrint(("VdiskRequestExecute: File closed\r\n"));
                ZwClose(Storage->FileHandle);
            }
            Storage->FileHandle = 0;
            // Free buffer
            if (Storage->AlignedBuf)
                ExFreePool(Storage->AlignedBuf);
        }
		break;
    case VDISK_REQUEST_WRITE:
        // Redefine function
        TransferFunc = ZwWriteFile;

    case VDISK_REQUEST_READ:

⌨️ 快捷键说明

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