📄 vdiskmp.c
字号:
/////////////////////////////////////////////////////////////////////////////
//
// This source code (including its associated software) is owned by
// StorageCraft and is protected by United States and international
// intellectual property law, including copyright laws, patent laws,
// and treaty provisions.
//
// vdiskmp.c
//
// StorageCraft Virtual SCSI miniport
//
// Harddisk in a file. Emulate new SCSI disk.
// Created as example of using VSPORT.LIB
//
// www.storagecraft.com
//
/////////////////////////////////////////////////////////////////////////////
//
// Install:
//
// 1. Save to the Registry:
//
// \Registry\Machine\SYSTEM\CurrentControlSet\Services\vdiskmp\Target0\LUN0
//
// Filename SZ "\??\C:\VDISK\Files\My Documents.dsk"
// or
// Filename SZ "C:\VDISK\Files\My Documents.dsk"
// Size DW 100 (In Megabytes)
// ReadOnly DW 0
//
// 2. Use Add Hardware wizard to add new SCSI device and select vdiskmp.inf.
//
// Notice:
//
// You must go to Disk Administrator to partition and format this new disk.
// After it you will see new drive letter(s) in the My Computer window.
//
// If driver can't start LUN from the Registry path it will remove this LUN from
// the Registry
//
//////////////////////////////////////////////////////////////////////////////
//
// Functions:
// VdiskReadRegistryParameters
// VdiskRemoveLunFromRegistry
// VdiskInquiryLun
// VdiskMpInitialize
// VdiskMpStartIo
// VdiskMpInquiry
// VdiskMpNewDevice
// VdiskShutdownLun
// VdiskMpResetBus
// DriverEntry
// VdiskRequestExecute
// VdiskRequestThread
// VdiskRequestSubmit
// VdiskRequestDeleteAll
// VdiskFillSenseData
//
// PnP functions for W2K:
// VdiskMpStopDevice
// VdiskMpRestartDevice
// VdiskMpDestroyLun
//
// Functions for WMI support:
// VdiskMpWmiAdapterQueryDataBlock
// VdiskMpWmiAdapterExecuteMethod
// VdiskMpWmiLunQueryDataBlock
// VdiskMpWmiLunExecuteMethod
// VdiskMpWmiStartIo
// VdiskSetRegistryParameters
// VdiskMpWmiCreateDisk
//
/////////////////////////////////////////////////////////////////////////////
#if DBG
// Time-stamp the object module in the debug build.
#pragma comment (user, __FILE__ " compiled on " __TIMESTAMP__)
#endif
#pragma warning (disable : 4115 4214 4514)
#ifdef VSPORT_PNP
#include <initguid.h>
#endif
#include <wchar.h>
#include <ntddk.h>
#include <scsi.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#ifdef VSPORT_PNP
#include <wmistr.h>
#endif
#include <vsport.h>
#include "vdiskmp.h"
#pragma warning (default : 4115 4214)
// Path in the Registry to save disks' parameters
const WCHAR szVdiskLunPath[] = L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\vdiskmp\\Target%u\\LUN%u";
#ifdef VSPORT_PNP
// WMI GUID for adapter
// Same as in MOF file
// {DF64F3DC-C38B-47ee-86EE-A6E1E194D036}
DEFINE_GUID(VDISKMP_WMI_ADAPTER_GUID,
0xDF64F3DC, 0xC38B, 0x47ee, 0x86, 0xee, 0xa6, 0xe1, 0xe1, 0x94, 0xd0, 0x36);
// WMI GUID for LUN
// Same as in MOF file
// {88289602-D30C-4aec-8DF3-22D998440CE4}
DEFINE_GUID(VDISKMP_WMI_LUN_GUID,
0x88289602, 0xd30c, 0x4aec, 0x8d, 0xf3, 0x22, 0xd9, 0x98, 0x44, 0x0c, 0xe4);
// WMI functions
// WMI callback to query the adapter data block
static NTSTATUS VdiskMpWmiAdapterQueryDataBlock(PVOID DeviceOrLunExtension,
PVSPORT_WMI_REQUEST Request,
ULONG BufferAvail, PUCHAR Buffer);
// WMI callback to execute the adapter method
static NTSTATUS VdiskMpWmiAdapterExecuteMethod(PVOID DeviceOrLunExtension,
PVSPORT_WMI_REQUEST Request,
ULONG InBufferSize, PUCHAR Buffer);
// WMI callback to query the LUN data block
static NTSTATUS VdiskMpWmiLunQueryDataBlock(PVOID DeviceOrLunExtension,
PVSPORT_WMI_REQUEST Request,
ULONG BufferAvail, PUCHAR Buffer);
// WMI callback to execute the LUN method
static NTSTATUS VdiskMpWmiLunExecuteMethod(PVOID DeviceOrLunExtension,
PVSPORT_WMI_REQUEST Request,
ULONG InBufferSize, PUCHAR Buffer);
// WMI SRB processing function
static VOID VdiskMpWmiStartIo(PVOID DeviceExtension, PSCSI_WMI_REQUEST_BLOCK Srb);
// CreateDisk WMI method body
static NTSTATUS VdiskMpWmiCreateDisk(PVOID MiniportDeviceExtension, PWSTR Name, ULONG NameLengthInBytes, UINT32 SizeInMegs);
// WMI constant structures
// Adapter GUID array
static VSPORT_WMI_GUID VdiskMpWmiAdapterGuid =
{
// Guid
&VDISKMP_WMI_ADAPTER_GUID,
// InstanceCount
1,
// Flags
WMIREG_FLAG_INSTANCE_PDO
};
// LUN GUID array
static VSPORT_WMI_GUID VdiskMpWmiLunGuid =
{
// Guid
&VDISKMP_WMI_LUN_GUID,
// InstanceCount
1,
// Flags
WMIREG_FLAG_INSTANCE_PDO
};
// Adapter WMI descriptor
static VSPORT_WMI_CONTEXT VdiskMpWmiAdapter =
{
// DefaultFlags
WMIREG_FLAG_INSTANCE_PDO,
// BaseInstanceName
NULL,
// MofResourceName
L"WmiResource",
// GuidCount
1,
// GuidList
&VdiskMpWmiAdapterGuid,
// QueryDataBlock
VdiskMpWmiAdapterQueryDataBlock,
// SetDataBlock
NULL,
// SetDataItem
NULL,
// ExecuteMethod
VdiskMpWmiAdapterExecuteMethod,
// FunctionControl
NULL
};
// LUN WMI descriptor
static VSPORT_WMI_CONTEXT VdiskMpWmiLun =
{
// DefaultFlags
WMIREG_FLAG_INSTANCE_PDO,
// BaseInstanceName
NULL,
// MofResourceName
L"WmiResource",
// GuidCount
1,
// GuidList
&VdiskMpWmiLunGuid,
// QueryDataBlock
VdiskMpWmiLunQueryDataBlock,
// SetDataBlock
NULL,
// SetDataItem
NULL,
// ExecuteMethod
VdiskMpWmiLunExecuteMethod,
// FunctionControl
NULL
};
#endif
// Miniport initilization routine.
static BOOLEAN VdiskMpInitialize(PVOID DeviceExtension);
// Device drivers entry routine.
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
#ifdef ALLOC_PRAGMA
// Throw these functions away.
#pragma alloc_text(INIT, DriverEntry)
#endif
// Functions internal for this file
// 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);
// The system thread function to process requests
// Context is not used
static VOID VdiskRequestThread(PVOID Context);
// Submits the request to the system thread
// Request will be executed asynchronously
static VOID VdiskRequestSubmit(PVDISK_LUN_REQUEST Request, PVDISK_LUN_EXTENSION Lun);
// Fill inquiry data
static VOID VdiskInquiry(PINQUIRYDATA InquiryData);
// Delete all requests
static VOID VdiskRequestDeleteAll(PVDISK_LUN_EXTENSION Lun);
// Fills the SENSE INFO for a CHECK CONDITION failure
static VOID VdiskFillSenseData(PSENSE_DATA SenseData, PSCSI_REQUEST_BLOCK Srb, ULONG Asc);
// Process shutdown LUN
static VOID VdiskShutdownLun(PVDISK_LUN_EXTENSION Lun, BOOLEAN WaitForThread);
// Reset BUS
static BOOLEAN VdiskMpResetBus(PVOID DeviceExtension, ULONG PathId);
// Put bytes back to front, big-endian to little-endian and vice versa
static ULONG VdiskChangeBytes(ULONG Size)
{
return (((PUCHAR)&Size)[0] << 24) | (((PUCHAR)&Size)[1] << 16 ) |
(((PUCHAR)&Size)[2] << 8) | ((PUCHAR)&Size)[3];
}
// Calculate index of array
static ULONG VdiskLun2Index(UCHAR TargetId, UCHAR Lun)
{
ASSERT(TargetId < NUMBER_OF_TARGETS);
ASSERT(Lun < NUMBER_OF_LUNS);
return (ULONG)TargetId * NUMBER_OF_LUNS + Lun;
}
///////////////////////////////////////////////////////////////////////////////
// Read data from the Registry for the LUN
//
static NTSTATUS VdiskReadRegistryParameters(UCHAR TargetId, UCHAR LunId, PWSTR SzFileName,
ULONG * DiskSize, BOOLEAN * ReadOnly)
{
NTSTATUS Status;
ULONG Length;
ULONG BufferSize;
PVOID Buffer;
UNICODE_STRING Str;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE DiskKeyHandle;
union {PVOID buffer; PKEY_VALUE_PARTIAL_INFORMATION valueKeyPartialInf;} u;
// Start out with one page of buffer
BufferSize = PAGE_SIZE;
// Allocate this buffer
u.buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, 'Den1');
// Check status
if (u.buffer == NULL)
{
KdPrint(("VdiskReadRegistryParameters: Can't allocate buffer!\r\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Format Registry path
swprintf(u.buffer, szVdiskLunPath, TargetId, LunId);
KdPrint(("VdiskReadRegistryParameters: %ls\r\n", u.buffer));
// Open the key
RtlInitUnicodeString(&Str, u.buffer);
InitializeObjectAttributes(&ObjectAttributes, &Str, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwOpenKey(&DiskKeyHandle, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
KdPrint(("VdiskReadRegistryParameters: Can't open disk key! 0x%X\r\n", Status));
ExFreePool(u.buffer);
return Status;
}
// Query the filename value
RtlInitUnicodeString(&Str, L"Filename");
Status = ZwQueryValueKey(DiskKeyHandle, &Str, KeyValuePartialInformation,
u.valueKeyPartialInf, BufferSize, &Length);
if (!NT_SUCCESS(Status) || (u.valueKeyPartialInf->Type != REG_SZ))
{
KdPrint(("VdiskReadRegistryParameters: Can't get file name!\r\n"));
ZwClose(DiskKeyHandle);
ExFreePool(u.buffer);
return Status;
}
// Retrieve the value
if ((((PWSTR)u.valueKeyPartialInf->Data)[0] == L'\\') &&
(((PWSTR)u.valueKeyPartialInf->Data)[1] == L'?'))
{
// Filename in the Reqistry already contains "\??\" prefix
wcscpy( SzFileName, (PWSTR)&(u.valueKeyPartialInf->Data));
}
else
{
// Insert prefix
wcscpy(SzFileName, L"\\??\\");
wcscat(SzFileName, (PWSTR)&(u.valueKeyPartialInf->Data));
}
// Query the disk size value
RtlInitUnicodeString(&Str, L"Size");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -