📄 ntvol.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 "volumes.h"
#include "apidrvr.h"
#include "ntdriver.h"
#include "ntvol.h"
#include "ntrawdv.h"
#include "ntfiledv.h"
#include "cache.h"
//#ifdef _DEBUG
//#define EXTRA_INFO 1
//#endif
#pragma warning( disable : 4127 )
#define FIRST_READ_SIZE SECTOR_SIZE*2
NTSTATUS
TCOpenVolume (PDEVICE_OBJECT DeviceObject,
PEXTENSION Extension,
MOUNT_STRUCT * mount,
PWSTR pwszMountVolume,
BOOL bRawDevice)
{
struct msdos_boot_sector *boot_sector = NULL;
FILE_STANDARD_INFORMATION FileStandardInfo;
FILE_BASIC_INFORMATION FileBasicInfo;
OBJECT_ATTRIBUTES oaFileAttributes;
UNICODE_STRING FullFileName;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER lDiskLength;
char *readBuffer;
NTSTATUS ntStatus;
Extension->pfoDeviceFile = NULL;
Extension->hDeviceFile = NULL;
readBuffer = TCalloc (FIRST_READ_SIZE);
if (readBuffer == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto error;
}
RtlInitUnicodeString (&FullFileName, pwszMountVolume);
InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE,
NULL, NULL);
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
&oaFileAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL |
FILE_ATTRIBUTE_SYSTEM,
0,
FILE_OPEN,
FILE_WRITE_THROUGH |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
/* 26-4-99 NT for some partitions returns this code, it is really a
access denied */
if (ntStatus == 0xc000001b)
{
ntStatus = STATUS_ACCESS_DENIED;
}
if (ntStatus == STATUS_ACCESS_DENIED)
{
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
GENERIC_READ | SYNCHRONIZE,
&oaFileAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL |
FILE_ATTRIBUTE_SYSTEM,
0,
FILE_OPEN,
FILE_WRITE_THROUGH |
FILE_NO_INTERMEDIATE_BUFFERING |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
Extension->bReadOnly = TRUE;
}
else
Extension->bReadOnly = FALSE;
/* 26-4-99 NT for some partitions returns this code, it is really a
access denied */
if (ntStatus == 0xc000001b)
{
/* Partitions which return this code can still be opened with
FILE_SHARE_READ but this causes NT problems elsewhere in
particular if you do FILE_SHARE_READ NT will die later if
anyone even tries to open the partition (or file for that
matter...) */
ntStatus = STATUS_SHARING_VIOLATION;
}
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL,
&IoStatusBlock, readBuffer, FIRST_READ_SIZE, NULL, NULL);
if (!NT_SUCCESS (ntStatus))
{
Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
}
else if (IoStatusBlock.Information != FIRST_READ_SIZE)
{
Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, FIRST_READ_SIZE);
ntStatus = STATUS_UNSUCCESSFUL;
}
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
if (bRawDevice == FALSE)
{
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
&IoStatusBlock,
&FileBasicInfo,
sizeof (FileBasicInfo),
FileBasicInformation);
if (NT_SUCCESS (ntStatus))
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
&IoStatusBlock,
&FileStandardInfo,
sizeof (FileStandardInfo),
FileStandardInformation);
if (!NT_SUCCESS (ntStatus))
{
Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
ntStatus);
goto error;
}
else
lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
{
Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
ntStatus = STATUS_SUCCESS;
goto error;
}
ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
FILE_ALL_ACCESS,
*IoFileObjectType,
KernelMode,
&Extension->pfoDeviceFile,
0);
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
/* Get the FSD device for the file (probably either NTFS or
FAT) */
Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
}
else
{
DISK_GEOMETRY dg;
ZwClose (Extension->hDeviceFile);
Extension->hDeviceFile = NULL;
if (Extension->bReadOnly == TRUE)
ntStatus = IoGetDeviceObjectPointer (&FullFileName,
FILE_READ_DATA,
&Extension->pfoDeviceFile,
&Extension->pFsdDevice);
else
ntStatus = IoGetDeviceObjectPointer (&FullFileName,
FILE_ALL_ACCESS,
&Extension->pfoDeviceFile,
&Extension->pFsdDevice);
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
if (wcscmp (Extension->pFsdDevice->DriverObject->DriverName.Buffer, WIDE ("\\FileSystem\\RAW")) != 0)
{
/* FAT/NTFS "knows" about this device */
ntStatus = STATUS_SHARING_VIOLATION;
goto error;
}
ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY,
(char *) &dg, sizeof (dg));
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
if (dg.MediaType == FixedMedia)
{
PARTITION_INFORMATION pi;
ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
Extension, IOCTL_DISK_GET_PARTITION_INFO,
(char *) &pi, sizeof (pi));
if (!NT_SUCCESS (ntStatus))
{
goto error;
}
else
lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
}
else
{
lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack *
dg.TracksPerCylinder * dg.BytesPerSector;
}
}
if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
{
/* Volume too large or too small for us to handle... */
mount->nReturnCode = ERR_VOL_SIZE_WRONG;
ntStatus = STATUS_SUCCESS;
goto error;
}
else
Extension->DiskLength = lDiskLength.QuadPart;
/* Attempt to recognize the volume */
KeWaitForMutexObject (&driverMutex, Executive, KernelMode,
FALSE, NULL);
mount->nReturnCode = VolumeReadHeaderCache (
mount->bCache,
readBuffer,
mount->szPassword,
strlen (mount->szPassword),
&Extension->cryptoInfo);
KeReleaseMutex (&driverMutex, FALSE);
if (mount->nReturnCode == 0)
{
/* Handle the volume setup for TC */
boot_sector = (struct msdos_boot_sector *) (readBuffer + SECTOR_SIZE);
/* It's in the volume file so we must decrypt it */
Extension->cryptoInfo->decrypt_sector ((ULONG *) boot_sector, 1, 1,
&Extension->cryptoInfo->ks[0],
Extension->cryptoInfo->iv,
Extension->cryptoInfo->cipher);
/* There's one extra sector than there should be */
Extension->DiskLength -= SECTOR_SIZE;
/* Volume setup end */
//Extension->TracksPerCylinder = boot_sector->heads;
//Extension->SectorsPerTrack = boot_sector->secs_track;
//Extension->NumberOfCylinders = (ULONG) (Extension->DiskLength / Extension->BytesPerSector /
// Extension->SectorsPerTrack / Extension->TracksPerCylinder);
Extension->TracksPerCylinder = 1;
Extension->SectorsPerTrack = 1;
Extension->BytesPerSector = *((unsigned short *) boot_sector->sector_size);
Extension->NumberOfCylinders = Extension->DiskLength / Extension->BytesPerSector;
Extension->PartitionType = (UCHAR) ((boot_sector->fs_type[4] == '6') ?
PARTITION_FAT_16 : PARTITION_FAT_12);
if(boot_sector->fs_type[3] == '3') Extension->PartitionType = (UCHAR) PARTITION_FAT32;
Extension->bRawDevice = bRawDevice;
if (wcslen (pwszMountVolume) < 64)
wcscpy (Extension->wszVolume, pwszMountVolume);
else
{
memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2);
Extension->wszVolume[60] = (WCHAR) '.';
Extension->wszVolume[61] = (WCHAR) '.';
Extension->wszVolume[62] = (WCHAR) '.';
Extension->wszVolume[63] = (WCHAR) 0;
}
Extension->mountTime = mount->time;
TCfree (readBuffer);
return STATUS_SUCCESS;
}
/* Failed due to some non-OS reason so we drop through and return NT
SUCCESS then nReturnCode is checked later in user-mode */
if (mount->nReturnCode == ERR_OUTOFMEMORY)
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
else
ntStatus = STATUS_SUCCESS;
error:
/* Close the hDeviceFile */
if (Extension->hDeviceFile != NULL)
ZwClose (Extension->hDeviceFile);
/* The cryptoInfo pointer is deallocated if the readheader routines
fail so there is no need to deallocate here */
/* Dereference the user-mode file object */
if (Extension->pfoDeviceFile != NULL)
ObDereferenceObject (Extension->pfoDeviceFile);
/* Free the tmp IO buffer */
if (readBuffer != NULL)
TCfree (readBuffer);
return ntStatus;
}
void
TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
{
if (DeviceObject); /* Remove compiler warning */
if (Extension->hDeviceFile != NULL)
ZwClose (Extension->hDeviceFile);
ObDereferenceObject (Extension->pfoDeviceFile);
crypto_close (Extension->cryptoInfo);
}
/* This rountine can be called at any IRQL so we need to tread carefully. Not
even DbgPrint or KdPrint are called here as the kernel sometimes faults if
they are called at high IRQL */
NTSTATUS
TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer)
{
PIO_STACK_LOCATION irpSp;
PEXTENSION Extension;
NTSTATUS ntStatus;
Extension = (PEXTENSION) DeviceObject->DeviceExtension;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -