VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Driver/Ntdriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Driver/Ntdriver.c')
-rw-r--r--src/Driver/Ntdriver.c693
1 files changed, 520 insertions, 173 deletions
diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c
index 7293de2d..b337ad86 100644
--- a/src/Driver/Ntdriver.c
+++ b/src/Driver/Ntdriver.c
@@ -13,6 +13,8 @@
#include "TCdefs.h"
#include <ntddk.h>
+#include <initguid.h>
+#include <Ntddstor.h>
#include "Crypto.h"
#include "Fat.h"
#include "Tests.h"
@@ -133,6 +135,7 @@ BOOL CacheBootPim = FALSE;
BOOL NonAdminSystemFavoritesAccessDisabled = FALSE;
BOOL BlockSystemTrimCommand = FALSE;
BOOL AllowWindowsDefrag = FALSE;
+BOOL EraseKeysOnShutdown = TRUE; // by default, we erase encryption keys on system shutdown
static size_t EncryptionThreadPoolFreeCpuCountLimit = 0;
static BOOL SystemFavoriteVolumeDirty = FALSE;
static BOOL PagingFileCreationPrevented = FALSE;
@@ -142,12 +145,43 @@ static BOOL RamEncryptionActivated = FALSE;
static KeSaveExtendedProcessorStateFn KeSaveExtendedProcessorStatePtr = NULL;
static KeRestoreExtendedProcessorStateFn KeRestoreExtendedProcessorStatePtr = NULL;
static ExGetFirmwareEnvironmentVariableFn ExGetFirmwareEnvironmentVariablePtr = NULL;
+static KeQueryInterruptTimePreciseFn KeQueryInterruptTimePrecisePtr = NULL;
+static KeAreAllApcsDisabledFn KeAreAllApcsDisabledPtr = NULL;
+static KeSetSystemGroupAffinityThreadFn KeSetSystemGroupAffinityThreadPtr = NULL;
+static KeQueryActiveGroupCountFn KeQueryActiveGroupCountPtr = NULL;
+static KeQueryActiveProcessorCountExFn KeQueryActiveProcessorCountExPtr = NULL;
+int EncryptionIoRequestCount = 0;
+int EncryptionItemCount = 0;
+int EncryptionFragmentSize = 0;
POOL_TYPE ExDefaultNonPagedPoolType = NonPagedPool;
ULONG ExDefaultMdlProtection = 0;
PDEVICE_OBJECT VirtualVolumeDeviceObjects[MAX_MOUNTED_VOLUME_DRIVE_NUMBER + 1];
+BOOL AlignValue (ULONG ulValue, ULONG ulAlignment, ULONG *pulResult)
+{
+ BOOL bRet = FALSE;
+ HRESULT hr;
+ if (ulAlignment == 0)
+ {
+ *pulResult = ulValue;
+ bRet = TRUE;
+ }
+ else
+ {
+ ulAlignment -= 1;
+ hr = ULongAdd (ulValue, ulAlignment, &ulValue);
+ if (S_OK == hr)
+ {
+ *pulResult = ulValue & (~ulAlignment);
+ bRet = TRUE;
+ }
+ }
+
+ return bRet;
+}
+
BOOL IsUefiBoot ()
{
BOOL bStatus = FALSE;
@@ -205,8 +239,17 @@ void GetDriverRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed)
iSeed = KeQueryPerformanceCounter (&iSeed2);
WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
WHIRLPOOL_add ((unsigned char *) &(iSeed2.QuadPart), sizeof(iSeed2.QuadPart), &tctx);
- iSeed.QuadPart = KeQueryInterruptTime ();
- WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
+ if (KeQueryInterruptTimePrecisePtr)
+ {
+ iSeed.QuadPart = KeQueryInterruptTimePrecisePtr (&iSeed2.QuadPart);
+ WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
+ WHIRLPOOL_add ((unsigned char *) &(iSeed2.QuadPart), sizeof(iSeed2.QuadPart), &tctx);
+ }
+ else
+ {
+ iSeed.QuadPart = KeQueryInterruptTime ();
+ WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
+ }
/* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */
if (0 == jent_entropy_init ())
@@ -272,14 +315,30 @@ NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
ExDefaultMdlProtection = MdlMappingNoExecute;
}
+ // KeAreAllApcsDisabled is available starting from Windows Server 2003
+ if ((OsMajorVersion > 5) || (OsMajorVersion == 5 && OsMinorVersion >= 2))
+ {
+ UNICODE_STRING KeAreAllApcsDisabledFuncName;
+ RtlInitUnicodeString(&KeAreAllApcsDisabledFuncName, L"KeAreAllApcsDisabled");
+
+ KeAreAllApcsDisabledPtr = (KeAreAllApcsDisabledFn) MmGetSystemRoutineAddress(&KeAreAllApcsDisabledFuncName);
+ }
+
// KeSaveExtendedProcessorState/KeRestoreExtendedProcessorState are available starting from Windows 7
+ // KeQueryActiveGroupCount/KeQueryActiveProcessorCountEx/KeSetSystemGroupAffinityThread are available starting from Windows 7
if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 1))
{
- UNICODE_STRING saveFuncName, restoreFuncName;
+ UNICODE_STRING saveFuncName, restoreFuncName, groupCountFuncName, procCountFuncName, setAffinityFuncName;
RtlInitUnicodeString(&saveFuncName, L"KeSaveExtendedProcessorState");
RtlInitUnicodeString(&restoreFuncName, L"KeRestoreExtendedProcessorState");
+ RtlInitUnicodeString(&groupCountFuncName, L"KeQueryActiveGroupCount");
+ RtlInitUnicodeString(&procCountFuncName, L"KeQueryActiveProcessorCountEx");
+ RtlInitUnicodeString(&setAffinityFuncName, L"KeSetSystemGroupAffinityThread");
KeSaveExtendedProcessorStatePtr = (KeSaveExtendedProcessorStateFn) MmGetSystemRoutineAddress(&saveFuncName);
KeRestoreExtendedProcessorStatePtr = (KeRestoreExtendedProcessorStateFn) MmGetSystemRoutineAddress(&restoreFuncName);
+ KeSetSystemGroupAffinityThreadPtr = (KeSetSystemGroupAffinityThreadFn) MmGetSystemRoutineAddress(&setAffinityFuncName);
+ KeQueryActiveGroupCountPtr = (KeQueryActiveGroupCountFn) MmGetSystemRoutineAddress(&groupCountFuncName);
+ KeQueryActiveProcessorCountExPtr = (KeQueryActiveProcessorCountExFn) MmGetSystemRoutineAddress(&procCountFuncName);
}
// ExGetFirmwareEnvironmentVariable is available starting from Windows 8
@@ -290,6 +349,14 @@ NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
ExGetFirmwareEnvironmentVariablePtr = (ExGetFirmwareEnvironmentVariableFn) MmGetSystemRoutineAddress(&funcName);
}
+ // KeQueryInterruptTimePrecise is available starting from Windows 8.1
+ if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 3))
+ {
+ UNICODE_STRING funcName;
+ RtlInitUnicodeString(&funcName, L"KeQueryInterruptTimePrecise");
+ KeQueryInterruptTimePrecisePtr = (KeQueryInterruptTimePreciseFn) MmGetSystemRoutineAddress(&funcName);
+ }
+
// Load dump filter if the main driver is already loaded
if (NT_SUCCESS (TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version))))
return DumpFilterEntry ((PFILTER_EXTENSION) DriverObject, (PFILTER_INITIALIZATION_DATA) RegistryPath);
@@ -966,8 +1033,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
outputBuffer->Geometry.TracksPerCylinder = Extension->TracksPerCylinder;
outputBuffer->Geometry.SectorsPerTrack = Extension->SectorsPerTrack;
outputBuffer->Geometry.BytesPerSector = Extension->BytesPerSector;
- /* add one sector to DiskLength since our partition size is DiskLength and its offset if BytesPerSector */
- outputBuffer->DiskSize.QuadPart = Extension->DiskLength + Extension->BytesPerSector;
+ // Add 1MB to the disk size to emulate the geometry of a real MBR disk
+ outputBuffer->DiskSize.QuadPart = Extension->DiskLength + BYTES_PER_MB;
if (bFullBuffer)
{
@@ -1238,7 +1305,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
outputBuffer->BootIndicator = FALSE;
outputBuffer->RecognizedPartition = TRUE;
outputBuffer->RewritePartition = FALSE;
- outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector;
+ outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk
outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
outputBuffer->PartitionNumber = 1;
outputBuffer->HiddenSectors = 0;
@@ -1255,7 +1322,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
outputBuffer->PartitionStyle = PARTITION_STYLE_MBR;
outputBuffer->RewritePartition = FALSE;
- outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector;
+ outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk
outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
outputBuffer->PartitionNumber = 1;
outputBuffer->Mbr.PartitionType = Extension->PartitionType;
@@ -1283,7 +1350,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
outputBuffer->PartitionEntry->BootIndicator = FALSE;
outputBuffer->PartitionEntry->RecognizedPartition = TRUE;
outputBuffer->PartitionEntry->RewritePartition = FALSE;
- outputBuffer->PartitionEntry->StartingOffset.QuadPart = Extension->BytesPerSector;
+ outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk
outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength;
outputBuffer->PartitionEntry->PartitionNumber = 1;
outputBuffer->PartitionEntry->HiddenSectors = 0;
@@ -1319,7 +1386,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
outputBuffer->PartitionEntry->Mbr.BootIndicator = FALSE;
outputBuffer->PartitionEntry->Mbr.RecognizedPartition = TRUE;
outputBuffer->PartitionEntry->RewritePartition = FALSE;
- outputBuffer->PartitionEntry->StartingOffset.QuadPart = Extension->BytesPerSector;
+ outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk
outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength;
outputBuffer->PartitionEntry->PartitionNumber = 1;
outputBuffer->PartitionEntry->Mbr.HiddenSectors = 0;
@@ -1374,7 +1441,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
else
{
IO_STATUS_BLOCK ioStatus;
- PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE));
+ DWORD dwBuffersize = min (pVerifyInformation->Length, 16 * PAGE_SIZE);
+ PVOID buffer = TCalloc (dwBuffersize);
if (!buffer)
{
@@ -1382,14 +1450,29 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
}
else
{
- LARGE_INTEGER offset = pVerifyInformation->StartingOffset;
+ LARGE_INTEGER offset;
+ DWORD dwRemainingBytes = pVerifyInformation->Length, dwReadCount;
offset.QuadPart = ullNewOffset;
- Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL);
- TCfree (buffer);
+ while (dwRemainingBytes)
+ {
+ dwReadCount = min (dwBuffersize, dwRemainingBytes);
+ Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, dwReadCount, &offset, NULL);
- if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length)
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != dwReadCount)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ else if (!NT_SUCCESS (Irp->IoStatus.Status))
+ break;
+
+ dwRemainingBytes -= dwReadCount;
+ offset.QuadPart += (ULONGLONG) dwReadCount;
+ }
+
+ burn (buffer, dwBuffersize);
+ TCfree (buffer);
}
}
@@ -1464,7 +1547,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
// of the underlaying physical disk and we report a single extent
extents->NumberOfDiskExtents = 1;
extents->Extents[0].DiskNumber = Extension->DeviceNumber;
- extents->Extents[0].StartingOffset.QuadPart = Extension->BytesPerSector;
+ extents->Extents[0].StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk
extents->Extents[0].ExtentLength.QuadPart = Extension->DiskLength;
}
else
@@ -1492,8 +1575,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
capacity->Version = sizeof (STORAGE_READ_CAPACITY);
capacity->Size = sizeof (STORAGE_READ_CAPACITY);
capacity->BlockLength = Extension->BytesPerSector;
- capacity->NumberOfBlocks.QuadPart = (Extension->DiskLength / Extension->BytesPerSector) + 1;
- capacity->DiskLength.QuadPart = Extension->DiskLength + Extension->BytesPerSector;
+ capacity->DiskLength.QuadPart = Extension->DiskLength + BYTES_PER_MB; // Add 1MB to the disk size to emulate the geometry of a real MBR disk
+ capacity->NumberOfBlocks.QuadPart = capacity->DiskLength.QuadPart / capacity->BlockLength;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof (STORAGE_READ_CAPACITY);
@@ -1652,7 +1735,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
ULONG ulNewInputLength = 0;
BOOL bForwardIoctl = FALSE;
- if (inputLength >= minSizeGeneric && inputLength >= minSizedataSet && inputLength >= minSizeParameter)
+ if (((ULONGLONG) inputLength) >= minSizeGeneric && ((ULONGLONG) inputLength) >= minSizedataSet && ((ULONGLONG) inputLength) >= minSizeParameter)
{
if (bEntireSet)
{
@@ -1664,36 +1747,53 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION
}
else
{
- DWORD dwDataSetOffset = ALIGN_VALUE (inputLength, sizeof(DEVICE_DATA_SET_RANGE));
+ DWORD dwDataSetOffset;
DWORD dwDataSetLength = sizeof(DEVICE_DATA_SET_RANGE);
- Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set. Setting data range to all volume.\n");
-
- ulNewInputLength = dwDataSetOffset + dwDataSetLength;
- pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (ulNewInputLength);
- if (pNewSetAttrs)
+ if (AlignValue (inputLength, sizeof(DEVICE_DATA_SET_RANGE), &dwDataSetOffset))
{
- PDEVICE_DATA_SET_RANGE pRange = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + dwDataSetOffset);
+ Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set. Setting data range to all volume.\n");
+
+ if (S_OK == ULongAdd(dwDataSetOffset, dwDataSetLength, &ulNewInputLength))
+ {
+ pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (ulNewInputLength);
+ if (pNewSetAttrs)
+ {
+ PDEVICE_DATA_SET_RANGE pRange = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + dwDataSetOffset);
- memcpy (pNewSetAttrs, pInputAttrs, inputLength);
+ memcpy (pNewSetAttrs, pInputAttrs, inputLength);
- pRange->StartingOffset = (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset;
- pRange->LengthInBytes = Extension->DiskLength;
+ pRange->StartingOffset = (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset;
+ pRange->LengthInBytes = Extension->DiskLength;
- pNewSetAttrs->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
- pNewSetAttrs->Action = action;
- pNewSetAttrs->Flags = pInputAttrs->Flags & (~DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE);
- pNewSetAttrs->ParameterBlockOffset = pInputAttrs->ParameterBlockOffset;
- pNewSetAttrs->ParameterBlockLength = pInputAttrs->ParameterBlockLength;
- pNewSetAttrs->DataSetRangesOffset = dwDataSetOffset;
- pNewSetAttrs->DataSetRangesLength = dwDataSetLength;
+ pNewSetAttrs->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
+ pNewSetAttrs->Action = action;
+ pNewSetAttrs->Flags = pInputAttrs->Flags & (~DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE);
+ pNewSetAttrs->ParameterBlockOffset = pInputAttrs->ParameterBlockOffset;
+ pNewSetAttrs->ParameterBlockLength = pInputAttrs->ParameterBlockLength;
+ pNewSetAttrs->DataSetRangesOffset = dwDataSetOffset;
+ pNewSetAttrs->DataSetRangesLength = dwDataSetLength;
- bForwardIoctl = TRUE;
+ bForwardIoctl = TRUE;
+ }
+ else
+ {
+ Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n");
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ Irp->IoStatus.Information = 0;
+ }
+ }
+ else
+ {
+ Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set but data range length computation overflowed.\n");
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ Irp->IoStatus.Information = 0;
+ }
}
else
{
- Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n");
- Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set but data set offset computation overflowed.\n");
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
}
}
@@ -1859,7 +1959,7 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
{
case TC_IOCTL_GET_DRIVER_VERSION:
- case TC_IOCTL_LEGACY_GET_DRIVER_VERSION:
+
if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput))
{
LONG tmp = VERSION_NUM;
@@ -2293,7 +2393,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER; // Normal/outer volume (hidden volume protected)
else
list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_NORMAL; // Normal volume
- list->truecryptMode[ListExtension->nDosDriveNo] = ListExtension->cryptoInfo->bTrueCryptMode;
}
}
@@ -2302,21 +2401,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
}
break;
- case TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES:
- if (ValidateIOBufferSize (Irp, sizeof (uint32), ValidateOutput))
- {
- // Prevent the user from downgrading to versions lower than 5.0 by faking mounted volumes.
- // The user could render the system unbootable by downgrading when boot encryption
- // is active or being set up.
-
- memset (Irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength);
- *(uint32 *) Irp->AssociatedIrp.SystemBuffer = 0xffffFFFF;
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
- }
- break;
-
case TC_IOCTL_GET_VOLUME_PROPERTIES:
if (ValidateIOBufferSize (Irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateInputOutput))
{
@@ -2592,7 +2676,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
|| mount->pkcs5_prf < 0 || mount->pkcs5_prf > LAST_PRF_ID
|| mount->VolumePim < -1 || mount->VolumePim == INT_MAX
|| mount->ProtectedHidVolPkcs5Prf < 0 || mount->ProtectedHidVolPkcs5Prf > LAST_PRF_ID
- || (mount->bTrueCryptMode != FALSE && mount->bTrueCryptMode != TRUE)
)
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
@@ -2610,7 +2693,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
burn (&mount->ProtectedHidVolPassword, sizeof (mount->ProtectedHidVolPassword));
burn (&mount->pkcs5_prf, sizeof (mount->pkcs5_prf));
burn (&mount->VolumePim, sizeof (mount->VolumePim));
- burn (&mount->bTrueCryptMode, sizeof (mount->bTrueCryptMode));
burn (&mount->ProtectedHidVolPkcs5Prf, sizeof (mount->ProtectedHidVolPkcs5Prf));
burn (&mount->ProtectedHidVolPim, sizeof (mount->ProtectedHidVolPim));
}
@@ -2805,6 +2887,18 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
}
break;
+ case VC_IOCTL_ENCRYPTION_QUEUE_PARAMS:
+ if (ValidateIOBufferSize (Irp, sizeof (EncryptionQueueParameters), ValidateOutput))
+ {
+ EncryptionQueueParameters* pParams = (EncryptionQueueParameters*) Irp->AssociatedIrp.SystemBuffer;
+ pParams->EncryptionFragmentSize = EncryptionFragmentSize;
+ pParams->EncryptionIoRequestCount = EncryptionIoRequestCount;
+ pParams->EncryptionItemCount = EncryptionItemCount;
+ Irp->IoStatus.Information = sizeof (EncryptionQueueParameters);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ }
+ break;
+
default:
return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
}
@@ -3080,6 +3174,21 @@ VOID VolumeThreadProc (PVOID Context)
Extension->Queue.HostFileHandle = Extension->hDeviceFile;
Extension->Queue.VirtualDeviceLength = Extension->DiskLength;
Extension->Queue.MaxReadAheadOffset.QuadPart = Extension->HostLength;
+ if (bDevice && pThreadBlock->mount->bPartitionInInactiveSysEncScope
+ && (!Extension->cryptoInfo->hiddenVolume)
+ && (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value)
+ )
+ {
+ // Support partial encryption only in the case of system encryption
+ Extension->Queue.EncryptedAreaStart = 0;
+ Extension->Queue.EncryptedAreaEnd = Extension->cryptoInfo->EncryptedAreaLength.Value - 1;
+ if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0)
+ {
+ Extension->Queue.EncryptedAreaStart = -1;
+ Extension->Queue.EncryptedAreaEnd = -1;
+ }
+ Extension->Queue.bSupportPartialEncryption = TRUE;
+ }
if (Extension->SecurityClientContextValid)
Extension->Queue.SecurityClientContext = &Extension->SecurityClientContext;
@@ -3215,6 +3324,7 @@ LPWSTR TCTranslateCode (ULONG ulCode)
TC_CASE_RET_NAME (VC_IOCTL_GET_DRIVE_GEOMETRY_EX);
TC_CASE_RET_NAME (VC_IOCTL_EMERGENCY_CLEAR_ALL_KEYS);
TC_CASE_RET_NAME (VC_IOCTL_IS_RAM_ENCRYPTION_ENABLED);
+ TC_CASE_RET_NAME (VC_IOCTL_ENCRYPTION_QUEUE_PARAMS);
TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS);
@@ -3343,6 +3453,8 @@ LPWSTR TCTranslateCode (ULONG ulCode)
return (LPWSTR) _T ("IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT");
else if (ulCode == IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES)
return (LPWSTR) _T ("IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES");
+ else if (ulCode == IOCTL_DISK_GROW_PARTITION)
+ return (LPWSTR) _T ("IOCTL_DISK_GROW_PARTITION");
else if (ulCode == IRP_MJ_READ)
return (LPWSTR) _T ("IRP_MJ_READ");
else if (ulCode == IRP_MJ_WRITE)
@@ -3393,31 +3505,21 @@ void TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
if (Extension->SecurityClientContextValid)
{
- if (OsMajorVersion == 5 && OsMinorVersion == 0)
- {
- ObDereferenceObject (Extension->SecurityClientContext.ClientToken);
- }
- else
- {
- // Windows 2000 does not support PsDereferenceImpersonationToken() used by SeDeleteClientSecurity().
- // TODO: Use only SeDeleteClientSecurity() once support for Windows 2000 is dropped.
-
- VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken);
- UNICODE_STRING name;
- RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken");
+ VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken);
+ UNICODE_STRING name;
+ RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken");
- PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name);
- if (!PsDereferenceImpersonationTokenD)
- TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED);
+ PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name);
+ if (!PsDereferenceImpersonationTokenD)
+ TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED);
-# define PsDereferencePrimaryToken
-# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD
+# define PsDereferencePrimaryToken
+# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD
- SeDeleteClientSecurity (&Extension->SecurityClientContext);
+ SeDeleteClientSecurity (&Extension->SecurityClientContext);
-# undef PsDereferencePrimaryToken
-# undef PsDereferenceImpersonationToken
- }
+# undef PsDereferencePrimaryToken
+# undef PsDereferenceImpersonationToken
}
VirtualVolumeDeviceObjects[Extension->nDosDriveNo] = NULL;
@@ -3457,6 +3559,18 @@ void OnShutdownPending ()
while (SendDeviceIoControlRequest (RootDeviceObject, TC_IOCTL_WIPE_PASSWORD_CACHE, NULL, 0, NULL, 0) == STATUS_INSUFFICIENT_RESOURCES);
}
+typedef struct
+{
+ PWSTR deviceName; ULONG IoControlCode; void *InputBuffer; ULONG InputBufferSize; void *OutputBuffer; ULONG OutputBufferSize;
+ NTSTATUS Status;
+ KEVENT WorkItemCompletedEvent;
+} TCDeviceIoControlWorkItemArgs;
+
+static VOID TCDeviceIoControlWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, TCDeviceIoControlWorkItemArgs *arg)
+{
+ arg->Status = TCDeviceIoControl (arg->deviceName, arg->IoControlCode, arg->InputBuffer, arg->InputBufferSize, arg->OutputBuffer, arg->OutputBufferSize);
+ KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
+}
NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize)
{
@@ -3468,6 +3582,30 @@ NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBu
KEVENT event;
UNICODE_STRING name;
+ if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
+ {
+ TCDeviceIoControlWorkItemArgs args;
+
+ PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
+ if (!workItem)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ args.deviceName = deviceName;
+ args.IoControlCode = IoControlCode;
+ args.InputBuffer = InputBuffer;
+ args.InputBufferSize = InputBufferSize;
+ args.OutputBuffer = OutputBuffer;
+ args.OutputBufferSize = OutputBufferSize;
+
+ KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
+ IoQueueWorkItem (workItem, TCDeviceIoControlWorkItemRoutine, DelayedWorkQueue, &args);
+
+ KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
+ IoFreeWorkItem (workItem);
+
+ return args.Status;
+ }
+
RtlInitUnicodeString(&name, deviceName);
ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
@@ -3528,7 +3666,7 @@ NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioContro
PIRP irp;
KEVENT event;
- if (KeGetCurrentIrql() > APC_LEVEL)
+ if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
{
SendDeviceIoControlRequestWorkItemArgs args;
@@ -3581,11 +3719,16 @@ NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *dr
LARGE_INTEGER offset;
byte *sectorBuffer;
ULONGLONG startTime;
+ ULONG sectorSize;
if (!UserCanAccessDriveDevice())
return STATUS_ACCESS_DENIED;
- sectorBuffer = TCalloc (TC_SECTOR_SIZE_BIOS);
+ status = GetDeviceSectorSize (driveDeviceObject, &sectorSize);
+ if (!NT_SUCCESS (status))
+ return status;
+
+ sectorBuffer = TCalloc (sectorSize);
if (!sectorBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
@@ -3600,12 +3743,12 @@ NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *dr
}
startTime = KeQueryInterruptTime ();
- for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += TC_SECTOR_SIZE_BIOS)
+ for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += sectorSize)
{
- status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS);
+ status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, sectorSize);
if (NT_SUCCESS (status))
- status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS);
+ status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, sectorSize);
if (!NT_SUCCESS (status))
{
@@ -3844,6 +3987,136 @@ NTSTATUS MountManagerUnmount (int nDosDriveNo)
return ntStatus;
}
+typedef struct
+{
+ MOUNT_STRUCT* mount; PEXTENSION NewExtension;
+ NTSTATUS Status;
+ KEVENT WorkItemCompletedEvent;
+} UpdateFsVolumeInformationWorkItemArgs;
+
+static NTSTATUS UpdateFsVolumeInformation (MOUNT_STRUCT* mount, PEXTENSION NewExtension);
+
+static VOID UpdateFsVolumeInformationWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, UpdateFsVolumeInformationWorkItemArgs *arg)
+{
+ arg->Status = UpdateFsVolumeInformation (arg->mount, arg->NewExtension);
+ KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
+}
+
+static NTSTATUS UpdateFsVolumeInformation (MOUNT_STRUCT* mount, PEXTENSION NewExtension)
+{
+ HANDLE volumeHandle;
+ PFILE_OBJECT volumeFileObject;
+ ULONG labelLen = (ULONG) wcslen (mount->wszLabel);
+ BOOL bIsNTFS = FALSE;
+ ULONG labelMaxLen, labelEffectiveLen;
+
+ if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
+ {
+ UpdateFsVolumeInformationWorkItemArgs args;
+
+ PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
+ if (!workItem)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ args.mount = mount;
+ args.NewExtension = NewExtension;
+
+ KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
+ IoQueueWorkItem (workItem, UpdateFsVolumeInformationWorkItemRoutine, DelayedWorkQueue, &args);
+
+ KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
+ IoFreeWorkItem (workItem);
+
+ return args.Status;
+ }
+
+ __try
+ {
+ if (NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject)))
+ {
+ __try
+ {
+ ULONG fsStatus;
+
+ if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus)))
+ && (fsStatus & VOLUME_IS_DIRTY))
+ {
+ mount->FilesystemDirty = TRUE;
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ mount->FilesystemDirty = TRUE;
+ }
+
+ // detect if the filesystem is NTFS or FAT
+ __try
+ {
+ NTFS_VOLUME_DATA_BUFFER ntfsData;
+ if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData))))
+ {
+ bIsNTFS = TRUE;
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ bIsNTFS = FALSE;
+ }
+
+ NewExtension->bIsNTFS = bIsNTFS;
+ mount->bIsNTFS = bIsNTFS;
+
+ if (labelLen > 0)
+ {
+ if (bIsNTFS)
+ labelMaxLen = 32; // NTFS maximum label length
+ else
+ labelMaxLen = 11; // FAT maximum label length
+
+ // calculate label effective length
+ labelEffectiveLen = labelLen > labelMaxLen? labelMaxLen : labelLen;
+
+ // correct the label in the device
+ memset (&NewExtension->wszLabel[labelEffectiveLen], 0, 33 - labelEffectiveLen);
+ memcpy (mount->wszLabel, NewExtension->wszLabel, 33);
+
+ // set the volume label
+ __try
+ {
+ IO_STATUS_BLOCK ioblock;
+ ULONG labelInfoSize = sizeof(FILE_FS_LABEL_INFORMATION) + (labelEffectiveLen * sizeof(WCHAR));
+ FILE_FS_LABEL_INFORMATION* labelInfo = (FILE_FS_LABEL_INFORMATION*) TCalloc (labelInfoSize);
+ if (labelInfo)
+ {
+ labelInfo->VolumeLabelLength = labelEffectiveLen * sizeof(WCHAR);
+ memcpy (labelInfo->VolumeLabel, mount->wszLabel, labelInfo->VolumeLabelLength);
+
+ if (STATUS_SUCCESS == ZwSetVolumeInformationFile (volumeHandle, &ioblock, labelInfo, labelInfoSize, FileFsLabelInformation))
+ {
+ mount->bDriverSetLabel = TRUE;
+ NewExtension->bDriverSetLabel = TRUE;
+ }
+
+ TCfree(labelInfo);
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+
+ }
+ }
+
+ TCCloseFsVolume (volumeHandle, volumeFileObject);
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+
+ }
+
+ return STATUS_SUCCESS;
+}
+
NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
{
@@ -3931,12 +4204,6 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
{
if (mount->nReturnCode == 0)
{
- HANDLE volumeHandle;
- PFILE_OBJECT volumeFileObject;
- ULONG labelLen = (ULONG) wcslen (mount->wszLabel);
- BOOL bIsNTFS = FALSE;
- ULONG labelMaxLen, labelEffectiveLen;
-
Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly);
if (NewExtension->bReadOnly)
@@ -3968,81 +4235,13 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
mount->FilesystemDirty = FALSE;
- if (mount->bMountManager && NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject)))
+ if (mount->bMountManager)
{
- __try
- {
- ULONG fsStatus;
-
- if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus)))
- && (fsStatus & VOLUME_IS_DIRTY))
- {
- mount->FilesystemDirty = TRUE;
- }
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
- mount->FilesystemDirty = TRUE;
- }
-
- // detect if the filesystem is NTFS or FAT
- __try
- {
- NTFS_VOLUME_DATA_BUFFER ntfsData;
- if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData))))
- {
- bIsNTFS = TRUE;
- }
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
+ NTSTATUS updateStatus = UpdateFsVolumeInformation (mount, NewExtension);
+ if (!NT_SUCCESS (updateStatus))
{
- bIsNTFS = FALSE;
+ Dump ("MountDevice: UpdateFsVolumeInformation failed with status 0x%08x\n", updateStatus);
}
-
- NewExtension->bIsNTFS = bIsNTFS;
- mount->bIsNTFS = bIsNTFS;
-
- if (labelLen > 0)
- {
- if (bIsNTFS)
- labelMaxLen = 32; // NTFS maximum label length
- else
- labelMaxLen = 11; // FAT maximum label length
-
- // calculate label effective length
- labelEffectiveLen = labelLen > labelMaxLen? labelMaxLen : labelLen;
-
- // correct the label in the device
- memset (&NewExtension->wszLabel[labelEffectiveLen], 0, 33 - labelEffectiveLen);
- memcpy (mount->wszLabel, NewExtension->wszLabel, 33);
-
- // set the volume label
- __try
- {
- IO_STATUS_BLOCK ioblock;
- ULONG labelInfoSize = sizeof(FILE_FS_LABEL_INFORMATION) + (labelEffectiveLen * sizeof(WCHAR));
- FILE_FS_LABEL_INFORMATION* labelInfo = (FILE_FS_LABEL_INFORMATION*) TCalloc (labelInfoSize);
- if (labelInfo)
- {
- labelInfo->VolumeLabelLength = labelEffectiveLen * sizeof(WCHAR);
- memcpy (labelInfo->VolumeLabel, mount->wszLabel, labelInfo->VolumeLabelLength);
-
- if (STATUS_SUCCESS == ZwSetVolumeInformationFile (volumeHandle, &ioblock, labelInfo, labelInfoSize, FileFsLabelInformation))
- {
- mount->bDriverSetLabel = TRUE;
- NewExtension->bDriverSetLabel = TRUE;
- }
-
- TCfree(labelInfo);
- }
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {
-
- }
- }
-
- TCCloseFsVolume (volumeHandle, volumeFileObject);
}
}
else
@@ -4056,6 +4255,20 @@ NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
}
}
+typedef struct
+{
+ UNMOUNT_STRUCT *unmountRequest; PDEVICE_OBJECT deviceObject; BOOL ignoreOpenFiles;
+ NTSTATUS Status;
+ KEVENT WorkItemCompletedEvent;
+} UnmountDeviceWorkItemArgs;
+
+
+static VOID UnmountDeviceWorkItemRoutine (PDEVICE_OBJECT rootDeviceObject, UnmountDeviceWorkItemArgs *arg)
+{
+ arg->Status = UnmountDevice (arg->unmountRequest, arg->deviceObject, arg->ignoreOpenFiles);
+ KeSetEvent (&arg->WorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
+}
+
NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles)
{
PEXTENSION extension = deviceObject->DeviceExtension;
@@ -4063,6 +4276,27 @@ NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObj
HANDLE volumeHandle;
PFILE_OBJECT volumeFileObject;
+ if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
+ {
+ UnmountDeviceWorkItemArgs args;
+
+ PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
+ if (!workItem)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ args.deviceObject = deviceObject;
+ args.unmountRequest = unmountRequest;
+ args.ignoreOpenFiles = ignoreOpenFiles;
+
+ KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE);
+ IoQueueWorkItem (workItem, UnmountDeviceWorkItemRoutine, DelayedWorkQueue, &args);
+
+ KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
+ IoFreeWorkItem (workItem);
+
+ return args.Status;
+ }
+
Dump ("UnmountDevice %d\n", extension->nDosDriveNo);
ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
@@ -4333,18 +4567,35 @@ NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information)
}
-size_t GetCpuCount ()
+size_t GetCpuCount (WORD* pGroupCount)
{
- KAFFINITY activeCpuMap = KeQueryActiveProcessors();
- size_t mapSize = sizeof (activeCpuMap) * 8;
size_t cpuCount = 0;
+ if (KeQueryActiveGroupCountPtr && KeQueryActiveProcessorCountExPtr)
+ {
+ USHORT i, groupCount = KeQueryActiveGroupCountPtr ();
+ for (i = 0; i < groupCount; i++)
+ {
+ cpuCount += (size_t) KeQueryActiveProcessorCountExPtr (i);
+ }
- while (mapSize--)
+ if (pGroupCount)
+ *pGroupCount = groupCount;
+ }
+ else
{
- if (activeCpuMap & 1)
- ++cpuCount;
+ KAFFINITY activeCpuMap = KeQueryActiveProcessors();
+ size_t mapSize = sizeof (activeCpuMap) * 8;
+
+ while (mapSize--)
+ {
+ if (activeCpuMap & 1)
+ ++cpuCount;
- activeCpuMap >>= 1;
+ activeCpuMap >>= 1;
+ }
+
+ if (pGroupCount)
+ *pGroupCount = 1;
}
if (cpuCount == 0)
@@ -4353,6 +4604,35 @@ size_t GetCpuCount ()
return cpuCount;
}
+USHORT GetCpuGroup (size_t index)
+{
+ if (KeQueryActiveGroupCountPtr && KeQueryActiveProcessorCountExPtr)
+ {
+ USHORT i, groupCount = KeQueryActiveGroupCountPtr ();
+ size_t cpuCount = 0;
+ for (i = 0; i < groupCount; i++)
+ {
+ cpuCount += (size_t) KeQueryActiveProcessorCountExPtr (i);
+ if (cpuCount >= index)
+ {
+ return i;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void SetThreadCpuGroupAffinity (USHORT index)
+{
+ if (KeSetSystemGroupAffinityThreadPtr)
+ {
+ GROUP_AFFINITY groupAffinity = {0};
+ groupAffinity.Mask = ~0ULL;
+ groupAffinity.Group = index;
+ KeSetSystemGroupAffinityThreadPtr (&groupAffinity, NULL);
+ }
+}
void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes)
{
@@ -4364,7 +4644,7 @@ void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes)
void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout)
{
LARGE_INTEGER waitInterval;
- waitInterval.QuadPart = retryDelay * -10000;
+ waitInterval.QuadPart = ((LONGLONG)retryDelay) * -10000;
ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
ASSERT (retryDelay > 0 && retryDelay <= timeout);
@@ -4547,6 +4827,65 @@ NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry)
TCfree (data);
}
+ if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_IO_REQUEST_COUNT, &data)))
+ {
+ if (data->Type == REG_DWORD)
+ EncryptionIoRequestCount = *(uint32 *) data->Data;
+
+ TCfree (data);
+ }
+
+ if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_ITEM_COUNT, &data)))
+ {
+ if (data->Type == REG_DWORD)
+ EncryptionItemCount = *(uint32 *) data->Data;
+
+ TCfree (data);
+ }
+
+ if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_FRAGMENT_SIZE, &data)))
+ {
+ if (data->Type == REG_DWORD)
+ EncryptionFragmentSize = *(uint32 *) data->Data;
+
+ TCfree (data);
+ }
+
+ if (driverEntry)
+ {
+ if (EncryptionIoRequestCount < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT)
+ EncryptionIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT;
+ else if (EncryptionIoRequestCount > TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_MAX_COUNT)
+ EncryptionIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_MAX_COUNT;
+
+ if ((EncryptionItemCount == 0) || (EncryptionItemCount > (EncryptionIoRequestCount / 2)))
+ EncryptionItemCount = EncryptionIoRequestCount / 2;
+
+ /* EncryptionFragmentSize value in registry is expressed in KiB */
+ /* Maximum allowed value for EncryptionFragmentSize is 2048 KiB */
+ EncryptionFragmentSize *= 1024;
+ if (EncryptionFragmentSize == 0)
+ EncryptionFragmentSize = TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
+ else if (EncryptionFragmentSize > (8 * TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE))
+ EncryptionFragmentSize = 8 * TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE;
+
+
+ }
+
+ if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ERASE_KEYS_SHUTDOWN, &data)))
+ {
+ if (data->Type == REG_DWORD)
+ {
+ if (*((uint32 *) data->Data))
+ EraseKeysOnShutdown = TRUE;
+ else
+ EraseKeysOnShutdown = FALSE;
+ }
+
+ TCfree (data);
+ }
+
+
return status;
}
@@ -4736,7 +5075,7 @@ BOOL IsOSAtLeast (OSVersionEnum reqMinOS)
>= (major << 16 | minor << 8));
}
-NTSTATUS NTAPI KeSaveExtendedProcessorState (
+NTSTATUS NTAPI KeSaveExtendedProcessorStateVC (
__in ULONG64 Mask,
PXSTATE_SAVE XStateSave
)
@@ -4751,7 +5090,7 @@ NTSTATUS NTAPI KeSaveExtendedProcessorState (
}
}
-VOID NTAPI KeRestoreExtendedProcessorState (
+VOID NTAPI KeRestoreExtendedProcessorStateVC (
PXSTATE_SAVE XStateSave
)
{
@@ -4759,4 +5098,12 @@ VOID NTAPI KeRestoreExtendedProcessorState (
{
(KeRestoreExtendedProcessorStatePtr) (XStateSave);
}
-} \ No newline at end of file
+}
+
+BOOLEAN VC_KeAreAllApcsDisabled (VOID)
+{
+ if (KeAreAllApcsDisabledPtr)
+ return (KeAreAllApcsDisabledPtr) ();
+ else
+ return FALSE;
+}