📄 vdiskmp.c
字号:
// 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 + -