📄 ntdriver.c
字号:
/*
Legal Notice: Some portions of the source code contained in this file were
derived from the source code of Encryption for the Masses 2.02a, which is
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
Agreement for Encryption for the Masses'. Modifications and additions to
the original source code (contained in this file) and all other portions of
this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
by the TrueCrypt License 2.6 the full text of which is contained in the
file License.txt included in TrueCrypt binary and source code distribution
packages. */
#include "TCdefs.h"
#include <ntddk.h>
#include "Crypto.h"
#include "Fat.h"
#include "Tests.h"
#include "Apidrvr.h"
#include "Boot/Windows/BootDefs.h"
#include "EncryptedIoQueue.h"
#include "EncryptionThreadPool.h"
#include "Ntdriver.h"
#include "Ntvol.h"
#include "DriveFilter.h"
#include "Cache.h"
#include "Volumes.h"
#include "VolumeFilter.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)
PDRIVER_OBJECT TCDriverObject;
KMUTEX driverMutex; /* Sync mutex for the entire driver */
BOOL DriverShuttingDown = FALSE;
BOOL SelfTestsPassed;
int LastUniqueVolumeId;
ULONG OsMajorVersion;
ULONG OsMinorVersion;
BOOL ReferencedDeviceDeleted = FALSE;
BOOL TravelerMode = FALSE;
BOOL VolumeClassFilterRegistered = FALSE;
BOOL CacheBootPassword = FALSE;
NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PKEY_VALUE_PARTIAL_INFORMATION startKeyValue;
int i;
TCDriverObject = DriverObject;
KeInitializeMutex (&driverMutex, 0);
EncryptionThreadPoolStart();
SelfTestsPassed = AutoTestAlgorithms ();
PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL);
ReadRegistryConfigFlags();
// Enable device class filters and load boot arguments if the driver is set to start at system boot
if (NT_SUCCESS (TCReadRegistryKey (RegistryPath, L"Start", &startKeyValue)))
{
if (startKeyValue->Type == REG_DWORD && *((uint32 *) startKeyValue->Data) == SERVICE_BOOT_START)
{
if (!SelfTestsPassed)
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
LoadBootArguments();
VolumeClassFilterRegistered = IsVolumeClassFilterRegistered();
DriverObject->DriverExtension->AddDevice = DriverAddDevice;
}
TCfree (startKeyValue);
}
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
{
DriverObject->MajorFunction[i] = TCDispatchQueueIRP;
}
DriverObject->DriverUnload = TCUnloadDriver;
return TCCreateRootDeviceObject (DriverObject);
}
NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
BOOL volumeDevice = FALSE;
Dump ("DriverAddDevice type=%x\n", pdo->DeviceType);
if (!VolumeClassFilterRegistered && BootArgsValid && BootArgs.HiddenSystemPartitionStart == 0)
return DriveFilterAddDevice (driverObject, pdo);
if (pdo->Flags & DO_DEVICE_HAS_NAME)
{
char nameInfoBuffer[128];
POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION) nameInfoBuffer;
ULONG nameInfoSize;
if (NT_SUCCESS (ObQueryNameString (pdo, nameInfo, sizeof (nameInfoBuffer), &nameInfoSize)))
{
Dump ("Device name = %ws\n", nameInfo->Name.Buffer);
if (nameInfo->Name.Length >= 22 * sizeof (wchar_t)
&& memcmp (nameInfo->Name.Buffer, L"\\Device\\HarddiskVolume", 22 * sizeof (wchar_t)) == 0)
{
volumeDevice = TRUE;
}
if (nameInfo->Name.Length >= 14 * sizeof (wchar_t)
&& memcmp (nameInfo->Name.Buffer, L"\\Device\\Floppy", 14 * sizeof (wchar_t)) == 0)
{
volumeDevice = TRUE;
}
}
}
if (volumeDevice)
return VolumeFilterAddDevice (driverObject, pdo);
return DriveFilterAddDevice (driverObject, pdo);
}
// Dumps a memory region to debug output
void DumpMemory (void *mem, int size)
{
unsigned char str[20];
unsigned char *m = mem;
int i,j;
for (j = 0; j < size / 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%08p %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;
}
}
BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
BOOL input = (type == ValidateInput || type == ValidateInputOutput);
BOOL output = (type == ValidateOutput || type == ValidateInputOutput);
if ((input && irpSp->Parameters.DeviceIoControl.InputBufferLength < requiredBufferSize)
|| (output && irpSp->Parameters.DeviceIoControl.OutputBufferLength < requiredBufferSize))
{
Dump ("STATUS_BUFFER_TOO_SMALL ioctl=0x%x,%d in=%d out=%d reqsize=%d insize=%d outsize=%d\n", (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16), (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2), input, output, requiredBufferSize, irpSp->Parameters.DeviceIoControl.InputBufferLength, irpSp->Parameters.DeviceIoControl.OutputBufferLength);
irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
irp->IoStatus.Information = 0;
return FALSE;
}
if (!input && output)
memset (irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength);
return TRUE;
}
/* 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 _DEBUG
if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && (Extension->bRootDevice || Extension->IsVolumeDevice))
{
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case TC_IOCTL_GET_MOUNTED_VOLUMES:
case TC_IOCTL_GET_PASSWORD_CACHE_STATUS:
case TC_IOCTL_GET_TRAVELER_MODE_STATUS:
case TC_IOCTL_SET_TRAVELER_MODE_STATUS:
case TC_IOCTL_OPEN_TEST:
case TC_IOCTL_GET_RESOLVED_SYMLINK:
case TC_IOCTL_GET_DRIVE_PARTITION_INFO:
case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES:
case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS:
case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING:
case IOCTL_DISK_CHECK_VERIFY:
break;
default:
Dump ("%ls (0x%x %d)\n",
TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode),
(int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16),
(int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2));
}
}
#endif
if (!Extension->bRootDevice)
{
// Drive filter IRP
if (Extension->IsDriveFilterDevice)
return DriveFilterDispatchIrp (DeviceObject, Irp);
// Volume filter IRP
if (Extension->IsVolumeFilterDevice)
return VolumeFilterDispatchIrp (DeviceObject, Irp);
}
switch (irpSp->MajorFunction)
{
case IRP_MJ_CLOSE:
case IRP_MJ_CREATE:
case IRP_MJ_CLEANUP:
return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);
case IRP_MJ_SHUTDOWN:
if (Extension->bRootDevice)
{
DriverShuttingDown = TRUE;
if (IsBootEncryptionSetupInProgress())
AbortBootEncryptionSetup();
if (IsDecoySystemWipeInProgress())
AbortDecoySystemWipe();
UnmountAllDevices (NULL, DeviceObject, TRUE);
// Boot drive will be dismounted when IRP_MJ_POWER is received after IRP_MJ_SHUTDOWN
}
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)
{
if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
return ProcessMainDeviceControlIrp (DeviceObject, Extension, Irp);
break;
}
if (Extension->bShuttingDown)
{
Dump ("Device %d shutting down: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo);
return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0);
}
if (Extension->bRemovable
&& (DeviceObject->Flags & DO_VERIFY_VOLUME)
&& !(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME)
&& irpSp->MajorFunction != IRP_MJ_FLUSH_BUFFERS)
{
Dump ("Removable device %d has DO_VERIFY_VOLUME flag: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo);
return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0);
}
switch (irpSp->MajorFunction)
{
case IRP_MJ_READ:
case IRP_MJ_WRITE:
ntStatus = EncryptedIoQueueAddIrp (&Extension->Queue, Irp);
if (ntStatus != STATUS_PENDING)
TCCompleteDiskIrp (Irp, ntStatus, 0);
return ntStatus;
case IRP_MJ_DEVICE_CONTROL:
IoMarkIrpPending (Irp);
ExInterlockedInsertTailList (&Extension->ListEntry, &Irp->Tail.Overlay.ListEntry, &Extension->ListSpinLock);
KeReleaseSemaphore (&Extension->RequestSemaphore, IO_DISK_INCREMENT, 1, FALSE);
return STATUS_PENDING;
case IRP_MJ_FLUSH_BUFFERS:
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
}
}
return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 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");
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
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,
sizeof (BOOL),
&ntUnicodeString,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DeviceObject);
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;
ntStatus = IoCreateSymbolicLink (&Win32NameString, &ntUnicodeString);
if (!NT_SUCCESS (ntStatus))
{
Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
IoDeleteDevice (DeviceObject);
return ntStatus;
}
IoRegisterShutdownNotification (DeviceObject);
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");
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
TCGetDosNameFromNumber (dosname, mount->nDosDriveNo);
TCGetNTNameFromNumber (ntname, mount->nDosDriveNo);
RtlInitUnicodeString (&ntUnicodeString, ntname);
RtlInitUnicodeString (&Win32NameString, dosname);
devChars = FILE_DEVICE_SECURE_OPEN;
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)->StackSize += 2; // Reduce occurrence of NO_MORE_IRP_STACK_LOCATIONS bug check caused by buggy drivers
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -