vdkdrv.c

来自「Virtual Disk Driver」· C语言 代码 · 共 434 行

C
434
字号
/*	vdkdrv.c	Virtual Disk kernel-mode driver for Windows NT platform	Standard driver routines other than ioctl dispatch routine	Copyright (C) 2003 Ken Kato*/#include "vdkbase.h"#include "vdkutil.h"#include "vdkver.h"#include "vdkioctl.h"#include "vdkaccess.h"#include "imports.h"#include "vdkdrv.h"#ifdef ALLOC_PRAGMA#pragma alloc_text(INIT, DriverEntry)#pragma alloc_text(PAGE, VdkShutdown)#pragma alloc_text(PAGE, VdkCreateClose)#pragma alloc_text(PAGE, VdkUnloadDriver)#endif	// ALLOC_PRAGMA////	runtime operating system version//extern ULONG OsMajorVersion = 0;extern ULONG OsMinorVersion = 0;extern ULONG OsBuildNumber 	= 0;//// Driver Entry routine//NTSTATUSDriverEntry (	IN PDRIVER_OBJECT	DriverObject,	IN PUNICODE_STRING	RegistryPath){	ULONG		idx;	ULONG		disk_num = 0;	PWCHAR 		reg_path = NULL;	NTSTATUS	status;	VDKTRACE(0, ("[VDK] " VDK_PRODUCT_NAME " version "		VDK_DRIVER_VERSION_STR " by " VDK_COMPANY_NAME "\n"));	// Store running OS version into global variables	StoreCurrentOsVersion();	VDKTRACE(0,		("[VDK] Running on Windows NT %lu.%lu build %lu\n",		OsMajorVersion, OsMinorVersion, OsBuildNumber));	// Get driver config data from registry	reg_path = ExAllocatePool(		PagedPool, RegistryPath->Length + sizeof(WCHAR));	if (reg_path) {#if DBG		RTL_QUERY_REGISTRY_TABLE	reg_param[3];		ULONG default_trace = (ULONG)~(VDKINFO | VDKWARN);#else		RTL_QUERY_REGISTRY_TABLE	reg_param[2];#endif		idx = 0;		RtlZeroMemory(reg_path, RegistryPath->Length + sizeof(WCHAR));		RtlMoveMemory(reg_path, RegistryPath->Buffer, RegistryPath->Length);		RtlZeroMemory(reg_param, sizeof(reg_param));		reg_param[0].Flags			= RTL_QUERY_REGISTRY_DIRECT;		reg_param[0].Name			= VDK_REG_DISKNUM_VALUE;		reg_param[0].EntryContext 	= &disk_num;		reg_param[0].DefaultType	= REG_DWORD;		reg_param[0].DefaultData	= &idx;		reg_param[0].DefaultLength	= sizeof(ULONG);#if DBG		reg_param[1].Flags			= RTL_QUERY_REGISTRY_DIRECT;		reg_param[1].Name			= L"TraceFlags";		reg_param[1].EntryContext	= &TraceFlags;		reg_param[1].DefaultType	= REG_DWORD;		reg_param[1].DefaultData	= &default_trace;		reg_param[1].DefaultLength	= sizeof(ULONG);#endif		status = RtlQueryRegistryValues(			RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,			reg_path, reg_param, NULL, NULL);		ExFreePool(reg_path);		if (!NT_SUCCESS(status)) {			VDKTRACE(0,				("[VDK] Failed to get config dat from registry - %s\n",				VdkStatusStr(status)));			disk_num = VDK_DEFAULT_DISK_NUM;		}		if (disk_num == 0 || disk_num > VDK_MAXIMUM_DISK_NUM) {			VDKTRACE(0,				("[VDK] Invalid disk device number - %lu\n", disk_num));			disk_num = VDK_DEFAULT_DISK_NUM;		}	}	else {		//		// Failed to allocate regstry path buffer		//		VDKTRACE(0,			("[VDK] Failed to allocate registry path buffer.\n"));		disk_num = VDK_DEFAULT_DISK_NUM;	}	VDKTRACE(0,		("[VDK] Number of Disks = %lu, TraceFlags = 0x%08x\n",		disk_num, TraceFlags));	// Create disk device objects	idx = 0;	do {		status = VdkCreateDisk(DriverObject, idx);		if (!NT_SUCCESS(status)) {			if (DriverObject->DeviceObject) {				// at least one disk device was created				status = STATUS_SUCCESS;			}			break;		}	}	while (++idx < disk_num);	if (NT_SUCCESS(status)) {		// Setup dispatch table		DriverObject->MajorFunction[IRP_MJ_CREATE]			= VdkCreateClose;		DriverObject->MajorFunction[IRP_MJ_CLOSE]			= VdkCreateClose;		DriverObject->MajorFunction[IRP_MJ_READ]			= VdkReadWrite;		DriverObject->MajorFunction[IRP_MJ_WRITE]			= VdkReadWrite;		DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]	= VdkDeviceControl;		DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]		= VdkShutdown;		DriverObject->DriverUnload = VdkUnloadDriver;		VDKTRACE(0, ("[VDK] %lu virtual disks successfully initialized.\n", idx));	}	return status;}////	Device shutdown routine//NTSTATUSVdkShutdown (	IN PDEVICE_OBJECT	DeviceObject,	IN PIRP				Irp){	PDISK_EXTENSION	disk_extension;	UNREFERENCED_PARAMETER(Irp);	VDKTRACE(VDKDISPATCH | VDKINFO,		("[VDK] VdkShutdown\n"));	disk_extension =		(PDISK_EXTENSION)DeviceObject->DeviceExtension;	if (disk_extension &&		disk_extension == disk_extension->FirstPartition &&		disk_extension->DiskInfo.DiskType) {		// close if virtual disk is opened		disk_extension->DiskInfo.DiskType = VDK_DISKTYPE_NONE;		VdkCloseDisk(&disk_extension->DiskInfo);	}	Irp->IoStatus.Information = 0;	Irp->IoStatus.Status = STATUS_SUCCESS;	IoCompleteRequest(Irp, IO_NO_INCREMENT);	return STATUS_SUCCESS;}//// IRP_MJ_CREATE and IRP_MJ_CLOSE handler// Really nothing to do here...//NTSTATUSVdkCreateClose (	IN PDEVICE_OBJECT	DeviceObject,	IN PIRP 			Irp){	UNREFERENCED_PARAMETER(DeviceObject);	VDKTRACE(VDKDISPATCH | VDKINFO,		("[VDK] %ws %s\n",		((PPART_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer,		IoGetCurrentIrpStackLocation(Irp)->MajorFunction ==			IRP_MJ_CLOSE ? "IRP_MJ_CLOSE" : "IRP_MJ_CREATE"));	//	// Information value for MJ_CLOSE is not defined so it's OK to	// return FILE_OPEND as defined for MJ_OPEN	//	Irp->IoStatus.Information = FILE_OPENED;	Irp->IoStatus.Status = STATUS_SUCCESS;	IoCompleteRequest(Irp, IO_NO_INCREMENT);	return STATUS_SUCCESS;}//// Driver unload routine//VOIDVdkUnloadDriver (	IN PDRIVER_OBJECT DriverObject){	PDEVICE_OBJECT	device_object;	PDEVICE_OBJECT	next_device;	VDKTRACE(VDKDISPATCH | VDKINFO,		("[VDK] VdkUnloadDriver\n"));	device_object = DriverObject->DeviceObject;	// Delete all device objects	while (device_object) {		next_device = device_object->NextDevice;		VdkDeleteDevice(device_object);		device_object = next_device;	}	VDKTRACE(0, ("[VDK] driver unloaded\n"));}//// IRP_MJ_READ and IRP_MJ_WRITE handler// Insert the IRP into queue list.// Actual read/write operation is performed by device thread//#define IO_READ_OFF(p)	(p)->Parameters.Read.ByteOffset.QuadPart#define IO_READ_LEN(p)	(p)->Parameters.Read.LengthNTSTATUSVdkReadWrite (	IN PDEVICE_OBJECT	DeviceObject,	IN PIRP 			Irp){	PPART_EXTENSION		part_extension;	PDISK_EXTENSION		disk_extension;	PIO_STACK_LOCATION	io_stack;	//	// Set up necessary object and extension pointers.	//	part_extension =		(PPART_EXTENSION)DeviceObject->DeviceExtension;	disk_extension =		(PDISK_EXTENSION)part_extension->FirstPartition;	io_stack = IoGetCurrentIrpStackLocation(Irp);	//	//	Check if the device is a zombie -- closed but not released	//	READ / WRITE request must succeed or NTFS driver cannot release	//	the device.	//	if (part_extension->PartitionOrdinal == VDK_ZOMBIE) {		VDKTRACE(0,			("[VDK] %ws %s: ZOMBIE DEVICE\n",			part_extension->DeviceName.Buffer,			io_stack->MajorFunction == IRP_MJ_WRITE ? "IRP_MJ_WRITE" : "IRP_MJ_READ"));		Irp->IoStatus.Status = STATUS_SUCCESS;		Irp->IoStatus.Information = IO_READ_LEN(io_stack);		IoCompleteRequest(Irp, IO_NO_INCREMENT);		return STATUS_SUCCESS;	}	//	// Check if image is opened	//	if (!disk_extension || !disk_extension->DiskInfo.DiskType ||		!part_extension->PartitionInfo.PartitionLength.QuadPart)	{		VDKTRACE(VDKWARN,			("[VDK] %ws %s: STATUS_DEVICE_NOT_READY\n",			part_extension->DeviceName.Buffer,			io_stack->MajorFunction == IRP_MJ_WRITE ? "IRP_MJ_WRITE" : "IRP_MJ_READ"));		Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;		Irp->IoStatus.Information = 0;		IoCompleteRequest(Irp, IO_NO_INCREMENT);		return STATUS_DEVICE_NOT_READY;	}	//	// Check for invalid parameters.  It is an error for the starting offset	// + length to go past the end of the partition, or for the length or	// offset to not be a proper multiple of the sector size.	//	// Others are possible, but we don't check them since we trust the	// file system and they aren't deadly.	//	if (IO_READ_OFF(io_stack) + IO_READ_LEN(io_stack) >		part_extension->PartitionInfo.PartitionLength.QuadPart) {		VDKTRACE(0,			("[VDK] %ws Offset:%I64u + Length:%u goes past partition size:%I64u\n",			part_extension->DeviceName.Buffer,			IO_READ_OFF(io_stack),			IO_READ_LEN(io_stack),			part_extension->PartitionInfo.PartitionLength.QuadPart));		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;		Irp->IoStatus.Information = 0;		IoCompleteRequest(Irp, IO_NO_INCREMENT);		return STATUS_INVALID_PARAMETER;	}	if ((IO_READ_LEN(io_stack) & VDK_SECTOR_ALIGNMENT_MASK) ||		(IO_READ_OFF(io_stack) & VDK_SECTOR_ALIGNMENT_MASK)) {		VDKTRACE(0,			("[VDK] %ws Invalid Alignment Offset:%I64u Length:%u\n",			part_extension->DeviceName.Buffer,			IO_READ_OFF(io_stack), IO_READ_LEN(io_stack)));		Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;		Irp->IoStatus.Information = 0;		IoCompleteRequest(Irp, IO_NO_INCREMENT);		return STATUS_INVALID_PARAMETER;	}	//	// Check if write operation is allowed	//	if (io_stack->MajorFunction == IRP_MJ_WRITE) {		if (disk_extension->DiskInfo.DiskType == VDK_DISKTYPE_READONLY) {			VDKTRACE(VDKWRITE | VDKWARN,				("[VDK] %ws IRP_MJ_WRITE: STATUS_MEDIA_WRITE_PROTECTED\n",				disk_extension->DeviceName.Buffer));			Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;			Irp->IoStatus.Information = 0;			IoCompleteRequest(Irp, IO_NO_INCREMENT);			return STATUS_MEDIA_WRITE_PROTECTED;		}		else if (disk_extension->DiskInfo.DiskType == VDK_DISKTYPE_WRITEBLOCK) {			VDKTRACE(VDKWRITE | VDKINFO,				("[VDK] %ws IRP_MJ_WRITE: Blocked write operation\n",				disk_extension->DeviceName.Buffer));			Irp->IoStatus.Status = STATUS_SUCCESS;			Irp->IoStatus.Information = IO_READ_LEN(io_stack);			IoCompleteRequest(Irp, IO_NO_INCREMENT);			return STATUS_SUCCESS;		}	}	//	// If read/write data length is 0, we are done	//	if (IO_READ_LEN(io_stack) == 0) {		Irp->IoStatus.Status = STATUS_SUCCESS;		Irp->IoStatus.Information = 0;		IoCompleteRequest(Irp, IO_NO_INCREMENT);		return STATUS_SUCCESS;	}	//	// The offset passed in is relative to the start of the partition.	// We always work from partition 0 (the whole disk) so adjust the	// offset.	//	IO_READ_OFF(io_stack) +=		part_extension->PartitionInfo.StartingOffset.QuadPart;	//	// Mark the IRP as pending, insert the IRP into queue list	// then signal the device thread to perform the operation	//	IoMarkIrpPending(Irp);	ExInterlockedInsertTailList(		&disk_extension->ListHead,		&Irp->Tail.Overlay.ListEntry,		&disk_extension->ListLock);	KeSetEvent(		&disk_extension->RequestEvent,		(KPRIORITY) 0,		FALSE);	return STATUS_PENDING;}

⌨️ 快捷键说明

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