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

📄 ntvol.c

📁 加密硬盘、分区、虚拟盘的程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -