📄 ntdriver.c
字号:
/* The source code contained in this file has been derived from the source code
of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
additions to that source code contained in this file are Copyright (c) 2004-2005
TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
release. Please see the file license.txt for full license details. */
#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 the entire driver */
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(void *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\n",
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:
#ifdef USE_KERNEL_MUTEX
if (Extension->bRootDevice == FALSE)
KeReleaseMutex (&Extension->KernelMutex, FALSE);
#endif
if (Extension->bRootDevice == TRUE)
UnmountAllDevices (DeviceObject, TRUE);
return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);
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)
{
#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_UNKNOWN, /* 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;
}
IoRegisterShutdownNotification (DeviceObject);
ASSERT (KeGetCurrentIrql ()== PASSIVE_LEVEL);
Dump ("TCCreateRootDeviceObject STATUS_SUCCESS END\n");
return STATUS_SUCCESS;
}
NTSTATUS
TCCreateDeviceObject (PDRIVER_OBJECT DriverObject,
PDEVICE_OBJECT * ppDeviceObject,
MOUNT_STRUCT * mount)
{
UNICODE_STRING Win32NameString, ntUnicodeString;
WCHAR dosname[32], ntname[32];
PEXTENSION Extension;
NTSTATUS ntStatus;
ULONG devChars = 0;
Dump ("TCCreateDeviceObject BEGIN\n");
TCGetDosNameFromNumber (dosname, mount->nDosDriveNo);
TCGetNTNameFromNumber (ntname, mount->nDosDriveNo);
RtlInitUnicodeString (&ntUnicodeString, ntname);
RtlInitUnicodeString (&Win32NameString, dosname);
devChars = mount->bMountReadOnly ? FILE_READ_ONLY_DEVICE : 0;
devChars |= mount->bMountRemovable ? FILE_REMOVABLE_MEDIA : 0;
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 */
devChars, /* 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 = mount->nDosDriveNo;
Extension->bRemovable = mount->bMountRemovable;
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;
}
void DriverMutexWait ()
{
KeWaitForMutexObject (&driverMutex, Executive, KernelMode, FALSE, NULL);
}
void DriverMutexRelease ()
{
KeReleaseMutex (&driverMutex, FALSE);
}
/* 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -