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