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

📄 ntdriver.c

📁 加密硬盘、分区、虚拟盘的程序源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
   This product uses components written by Paul Le Roux <pleroux@swprofessionals.com> */

#include "TCdefs.h"
#include "crypto.h"
#include "fat.h"

#include "apidrvr.h"
#include "ntdriver.h"
#include "ntvol.h"
#include "ntrawdv.h"
#include "ntfiledv.h"
#include "cache.h"

#include <tchar.h>
#include <initguid.h>
#include <mountmgr.h>
#include <mountdev.h>
#include <ntddvol.h>

/* Init section, which is thrown away as soon as DriverEntry returns */
#pragma alloc_text(INIT,DriverEntry)
#pragma alloc_text(INIT,TCCreateRootDeviceObject)

/* Sync. mutex for above password data */
KMUTEX driverMutex;

/* DriverEntry initialize's the dispatch addresses to be passed back to NT.
   RUNS AT IRQL = PASSIVE_LEVEL(0) */
NTSTATUS
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	if (RegistryPath);	/* Remove warning */

	DriverObject->MajorFunction[IRP_MJ_CREATE] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_READ] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_WRITE] = TCDispatchQueueIRP;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TCDispatchQueueIRP;

	DriverObject->DriverUnload = TCUnloadDriver;

	KeInitializeMutex (&driverMutex, 1);

	return TCCreateRootDeviceObject (DriverObject);
}

#ifdef _DEBUG
// Dumps a memory region to debug output
void DumpMem(unsigned char *mem, int len)
{
	unsigned char str[20];
	unsigned char *m = mem;
	int i,j;

	for (j=0;j<len/8;j++)
	{
		memset (str,0,sizeof str);
		for (i=0;i<8;i++) 
		{
			if (m[i] > ' ' && m[i] < '~')
				str[i]=m[i];
			else
				str[i]='.';
		}

		Dump ("0x%08x  %02x %02x %02x %02x %02x %02x %02x %02x  %s",
			m, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], str);

		m+=8;
	}
}
#endif

/* TCDispatchQueueIRP queues any IRP's so that they can be processed later
   by the thread -- or in some cases handles them immediately! */
NTSTATUS
TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension;
	PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
	NTSTATUS ntStatus;

#ifdef USE_KERNEL_MUTEX
	if (Extension->bRootDevice == FALSE)
		KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode,
				      FALSE, NULL);
#endif

#ifdef _DEBUG
	if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
		Dump ("TCDispatchQueueIRP BEGIN MajorFunction = %ls 0x%08x IoControlCode = %ls 0x%08x\n",
		      TCTranslateCode (irpSp->MajorFunction), (int) irpSp->MajorFunction,
		      TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode),
		      (int) irpSp->Parameters.DeviceIoControl.IoControlCode);
	//else
	//	Dump ("TCDispatchQueueIRP BEGIN MajorFunction = %ls 0x%08x\n",
	//	      TCTranslateCode (irpSp->MajorFunction), (int) irpSp->MajorFunction);
#endif

	if (Extension->bRootDevice == FALSE)
	{
		if (irpSp->MajorFunction == IRP_MJ_READ || irpSp->MajorFunction == IRP_MJ_WRITE ||
		    irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
		{
			if ((DeviceObject->Flags & DO_VERIFY_VOLUME))
			{
				if (!(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME))
				{
					Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
					Irp->IoStatus.Information = 0;
					if (!NT_SUCCESS (Irp->IoStatus.Status) &&
					    IoIsErrorUserInduced (Irp->IoStatus.Status))
					{
						IoSetHardErrorOrVerifyDevice (Irp, DeviceObject);
					}
					ntStatus = Irp->IoStatus.Status;
					IoCompleteRequest (Irp, IO_NO_INCREMENT);
					//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
					if (Extension->bRootDevice == FALSE)
						KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
					return ntStatus;
				}
				else if (Extension->bShuttingDown == TRUE)
				{
					Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
					Irp->IoStatus.Information = 0;
					if (!NT_SUCCESS (Irp->IoStatus.Status) &&
					    IoIsErrorUserInduced (Irp->IoStatus.Status))
					{
						IoSetHardErrorOrVerifyDevice (Irp, DeviceObject);
					}
					ntStatus = Irp->IoStatus.Status;
					IoCompleteRequest (Irp, IO_NO_INCREMENT);
					//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
					if (Extension->bRootDevice == FALSE)
						KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
					return ntStatus;
				}
			}
			else if (Extension->bShuttingDown == TRUE)
			{
				if (DeviceObject->Vpb && DeviceObject->Vpb->Flags & VPB_MOUNTED)
				{
					Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;
					Irp->IoStatus.Information = 0;
					if (!NT_SUCCESS (Irp->IoStatus.Status) &&
					    IoIsErrorUserInduced (Irp->IoStatus.Status))
					{
						IoSetHardErrorOrVerifyDevice (Irp, DeviceObject);
					}
					DeviceObject->Flags |= DO_VERIFY_VOLUME;
				}
				else
				{
					Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
					Irp->IoStatus.Information = 0;
				}

				ntStatus = Irp->IoStatus.Status;
				IoCompleteRequest (Irp, IO_NO_INCREMENT);
				//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
				if (Extension->bRootDevice == FALSE)
					KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
				return ntStatus;
			}
		}
		else if ((DeviceObject->Flags & DO_VERIFY_VOLUME))
		{		/* If shutting down or media removed */
			if (Extension->bShuttingDown == TRUE)
			{
				Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
				Irp->IoStatus.Information = 0;
				if (!NT_SUCCESS (Irp->IoStatus.Status) &&
				IoIsErrorUserInduced (Irp->IoStatus.Status))
				{
					IoSetHardErrorOrVerifyDevice (Irp, DeviceObject);
				}
				ntStatus = Irp->IoStatus.Status;
				IoCompleteRequest (Irp, IO_NO_INCREMENT);
				//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
				if (Extension->bRootDevice == FALSE)
					KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
				return ntStatus;
			}
			else
			{
				Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
				Irp->IoStatus.Information = 0;
				ntStatus = Irp->IoStatus.Status;
				IoCompleteRequest (Irp, IO_NO_INCREMENT);
				//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
				if (Extension->bRootDevice == FALSE)
					KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
				return ntStatus;
			}
		}
	}

	switch (irpSp->MajorFunction)
	{
	case IRP_MJ_CLOSE:
	case IRP_MJ_CREATE:
	case IRP_MJ_CLEANUP:
#ifdef USE_KERNEL_MUTEX
		if (Extension->bRootDevice == FALSE)
			KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
		return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);

	case IRP_MJ_SHUTDOWN:
	case IRP_MJ_FLUSH_BUFFERS:
	case IRP_MJ_READ:
	case IRP_MJ_WRITE:
	case IRP_MJ_DEVICE_CONTROL:
		if (Extension->bRootDevice == FALSE)
		{
			ASSERT (Extension->bShuttingDown == FALSE);

			IoMarkIrpPending (Irp);

			ASSERT (KeGetCurrentIrql ()== PASSIVE_LEVEL ||
				KeGetCurrentIrql ()== APC_LEVEL);

			ExInterlockedInsertTailList (
						      &Extension->ListEntry,
					       &Irp->Tail.Overlay.ListEntry,
						  &Extension->ListSpinLock);

			ASSERT (KeGetCurrentIrql ()== PASSIVE_LEVEL ||
				KeGetCurrentIrql ()== APC_LEVEL);

			KeReleaseSemaphore (
					       &Extension->RequestSemaphore,
						   (KPRIORITY) 0,
						   1,
						   FALSE);

			//Dump ("TCDispatchQueueIRP STATUS_PENDING END\n");
#ifdef USE_KERNEL_MUTEX
			if (Extension->bRootDevice == FALSE)
				KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
			return STATUS_PENDING;
		}
		else
		{
			if (irpSp->Parameters.DeviceIoControl.IoControlCode >= TC_FIRST_PRIVATE &&
			    irpSp->Parameters.DeviceIoControl.IoControlCode <= TC_LAST_PRIVATE)
			{
				ntStatus = TCDeviceControl (DeviceObject, Extension, Irp);
				//Dump ("TCDispatchQueueIRP NTSTATUS = 0x%08x END\n", ntStatus);
#ifdef USE_KERNEL_MUTEX
				if (Extension->bRootDevice == FALSE)
					KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
				return ntStatus;
			}

			if (irpSp->MajorFunction == IRP_MJ_FLUSH_BUFFERS || irpSp->MajorFunction == IRP_MJ_SHUTDOWN)
			{
#ifdef USE_KERNEL_MUTEX
				if (Extension->bRootDevice == FALSE)
					KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
				return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);
			}
		}

#ifdef USE_KERNEL_MUTEX
		if (Extension->bRootDevice == FALSE)
			KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif

		return COMPLETE_IRP (DeviceObject, Irp, STATUS_DRIVER_INTERNAL_ERROR, 0);
	}

#ifdef _DEBUG
	Dump ("ERROR: Unknown irpSp->MajorFunction in TCDispatchQueueIRP %ls 0x%08x END\n",
	TCTranslateCode (irpSp->MajorFunction), (int) irpSp->MajorFunction);
#endif

#ifdef USE_KERNEL_MUTEX
	if (Extension->bRootDevice == FALSE)
		KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
	return COMPLETE_IRP (DeviceObject, Irp, STATUS_DRIVER_INTERNAL_ERROR, 0);
}

NTSTATUS
TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING Win32NameString, ntUnicodeString;
	WCHAR dosname[32], ntname[32];
	PDEVICE_OBJECT DeviceObject;
	NTSTATUS ntStatus;
	BOOL *bRootExtension;

	Dump ("TCCreateRootDeviceObject BEGIN\n");

	wcscpy (dosname, (LPWSTR) DOS_ROOT_PREFIX);
	wcscpy (ntname, (LPWSTR) NT_ROOT_PREFIX);
	RtlInitUnicodeString (&ntUnicodeString, ntname);
	RtlInitUnicodeString (&Win32NameString, dosname);

	Dump ("Creating root device nt=%ls dos=%ls\n", ntname, dosname);

	ntStatus = IoCreateDevice (
					  DriverObject,		/* Our Driver Object */
					  sizeof (BOOL),	/* Size of state information */
					  &ntUnicodeString,	/* Device name "\Device\Name" */
					  FILE_DEVICE_DISK,	/* Device type */
					  0,				/* Device characteristics */
					  FALSE,			/* Exclusive device */
					  &DeviceObject);	/* Returned ptr to Device Object */

	if (!NT_SUCCESS (ntStatus))
	{
		Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
		return ntStatus;/* Failed to create DeviceObject */
	}

	DeviceObject->Flags |= DO_DIRECT_IO;
	DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;

	/* Setup the device extension */
	bRootExtension = (BOOL *) DeviceObject->DeviceExtension;
	*bRootExtension = TRUE;

	/* The symlinks for mount devices are created from user-mode */
	ntStatus = IoCreateSymbolicLink (&Win32NameString, &ntUnicodeString);
	if (!NT_SUCCESS (ntStatus))
	{
		Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
		IoDeleteDevice (DeviceObject);
		return ntStatus;
	}

	ASSERT (KeGetCurrentIrql ()== PASSIVE_LEVEL);
	Dump ("TCCreateRootDeviceObject STATUS_SUCCESS END\n");
	return STATUS_SUCCESS;
}

NTSTATUS
TCCreateDeviceObject (PDRIVER_OBJECT DriverObject,
		       PDEVICE_OBJECT * ppDeviceObject,
		       int nDosDriveNo)
{
	UNICODE_STRING Win32NameString, ntUnicodeString;
	WCHAR dosname[32], ntname[32];
	PEXTENSION Extension;
	NTSTATUS ntStatus;

	Dump ("TCCreateDeviceObject BEGIN\n");

	TCGetDosNameFromNumber (dosname, nDosDriveNo);
	TCGetNTNameFromNumber (ntname, nDosDriveNo);
	RtlInitUnicodeString (&ntUnicodeString, ntname);
	RtlInitUnicodeString (&Win32NameString, dosname);

	Dump ("Creating device nt=%ls dos=%ls\n", ntname, dosname);

	ntStatus = IoCreateDevice (
					  DriverObject,			/* Our Driver Object */
					  sizeof (EXTENSION),	/* Size of state information */
					  &ntUnicodeString,		/* Device name "\Device\Name" */
					  FILE_DEVICE_DISK,		/* Device type */
					  0,					/* Device characteristics */
					  FALSE,				/* Exclusive device */
					  ppDeviceObject);		/* Returned ptr to Device Object */

	if (!NT_SUCCESS (ntStatus))
	{
		Dump ("TCCreateDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
		return ntStatus;/* Failed to create DeviceObject */
	}
	/* Initialize device object and extension. */

	(*ppDeviceObject)->Flags |= DO_DIRECT_IO;
	(*ppDeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT;

	/* Setup the device extension */
	Extension = (PEXTENSION) (*ppDeviceObject)->DeviceExtension;
	memset (Extension, 0, sizeof (EXTENSION));

	Extension->lMagicNumber = 0xabfeacde;
	Extension->nDosDriveNo = nDosDriveNo;

	KeInitializeEvent (&Extension->keCreateEvent, SynchronizationEvent, FALSE);
	KeInitializeSemaphore (&Extension->RequestSemaphore, 0L, MAXLONG);
#ifdef USE_KERNEL_MUTEX
	KeInitializeMutex (&Extension->KernelMutex, 1);
#endif
	KeInitializeSpinLock (&Extension->ListSpinLock);
	InitializeListHead (&Extension->ListEntry);

	ASSERT (KeGetCurrentIrql ()== PASSIVE_LEVEL);
	Dump ("TCCreateDeviceObject STATUS_SUCCESS END\n");

	return STATUS_SUCCESS;
}

/* TCDeviceControl handles certain requests from NT, these are needed for NT
   to recognize the drive, also this function handles  our device specific
   function codes, such as mount/unmount */
NTSTATUS
TCDeviceControl (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
{
	PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
	NTSTATUS ntStatus;

#ifdef _DEBUG
	 Dump ("TCDeviceControl BEGIN IoControlCode = %ls 0x%08x\n",
	 TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode),
	      irpSp->Parameters.DeviceIoControl.IoControlCode);
#endif

	Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;	/* Assume failure. */

	/* Determine which I/O control code was specified.  */
	switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
	{

	case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
		if(irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof (MOUNTDEV_NAME))
		{
			Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);
			Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
		}
		else
		{
			ULONG outLength;
			UNICODE_STRING ntUnicodeString;
			WCHAR ntName[64];
			PMOUNTDEV_NAME outputBuffer = (PMOUNTDEV_NAME) Irp->AssociatedIrp.SystemBuffer;

			Dump("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:");

			TCGetNTNameFromNumber (ntName, Extension->nDosDriveNo);
			RtlInitUnicodeString (&ntUnicodeString, ntName);

			outputBuffer->NameLength = ntUnicodeString.Length;
			outLength = ntUnicodeString.Length + sizeof(USHORT);

			if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
			{
				Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);

⌨️ 快捷键说明

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