|
|
1.1.1.10 root 1: /*
1.1.1.12 root 2: Legal Notice: Some portions of the source code contained in this file were
3: derived from the source code of Encryption for the Masses 2.02a, which is
4: Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
5: Agreement for Encryption for the Masses'. Modifications and additions to
1.1.1.22 root 6: the original source code (contained in this file) and all other portions
1.1.1.25! root 7: of this file are Copyright (c) 2003-2011 TrueCrypt Developers Association
1.1.1.23 root 8: and are governed by the TrueCrypt License 3.0 the full text of which is
1.1.1.22 root 9: contained in the file License.txt included in TrueCrypt binary and source
10: code distribution packages. */
1.1 root 11:
12: #include "TCdefs.h"
1.1.1.12 root 13: #include <ntddk.h>
1.1.1.6 root 14: #include "Crypto.h"
15: #include "Fat.h"
16: #include "Tests.h"
17:
18: #include "Apidrvr.h"
1.1.1.15 root 19: #include "Boot/Windows/BootDefs.h"
1.1.1.12 root 20: #include "EncryptedIoQueue.h"
1.1.1.15 root 21: #include "EncryptionThreadPool.h"
1.1.1.6 root 22: #include "Ntdriver.h"
23: #include "Ntvol.h"
1.1.1.12 root 24: #include "DriveFilter.h"
1.1.1.23 root 25: #include "DumpFilter.h"
1.1.1.6 root 26: #include "Cache.h"
1.1.1.15 root 27: #include "Volumes.h"
28: #include "VolumeFilter.h"
1.1 root 29:
30: #include <tchar.h>
31: #include <initguid.h>
32: #include <mountmgr.h>
33: #include <mountdev.h>
34: #include <ntddvol.h>
35:
36: /* Init section, which is thrown away as soon as DriverEntry returns */
37: #pragma alloc_text(INIT,DriverEntry)
38: #pragma alloc_text(INIT,TCCreateRootDeviceObject)
39:
1.1.1.14 root 40: PDRIVER_OBJECT TCDriverObject;
1.1.1.25! root 41: PDEVICE_OBJECT RootDeviceObject = NULL;
! 42: static KMUTEX RootDeviceControlMutex;
1.1.1.12 root 43: BOOL DriverShuttingDown = FALSE;
1.1.1.6 root 44: BOOL SelfTestsPassed;
45: int LastUniqueVolumeId;
1.1.1.21 root 46: ULONG OsMajorVersion = 0;
1.1.1.14 root 47: ULONG OsMinorVersion;
1.1.1.25! root 48: BOOL DriverUnloadDisabled = FALSE;
1.1.1.21 root 49: BOOL PortableMode = FALSE;
1.1.1.15 root 50: BOOL VolumeClassFilterRegistered = FALSE;
1.1.1.17 root 51: BOOL CacheBootPassword = FALSE;
1.1.1.21 root 52: BOOL NonAdminSystemFavoritesAccessDisabled = FALSE;
1.1.1.23 root 53: static size_t EncryptionThreadPoolFreeCpuCountLimit = 0;
1.1.1.21 root 54: static BOOL SystemFavoriteVolumeDirty = FALSE;
1.1.1.23 root 55: static BOOL PagingFileCreationPrevented = FALSE;
1.1 root 56:
1.1.1.25! root 57: PDEVICE_OBJECT VirtualVolumeDeviceObjects[MAX_MOUNTED_VOLUME_DRIVE_NUMBER + 1];
! 58:
1.1.1.12 root 59:
60: NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1.1 root 61: {
1.1.1.15 root 62: PKEY_VALUE_PARTIAL_INFORMATION startKeyValue;
1.1.1.23 root 63: LONG version;
1.1.1.12 root 64: int i;
65:
1.1.1.19 root 66: Dump ("DriverEntry " TC_APP_NAME " " VERSION_STRING "\n");
67:
1.1.1.23 root 68: PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL);
69:
70: // Load dump filter if the main driver is already loaded
71: if (NT_SUCCESS (TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version))))
72: return DumpFilterEntry ((PFILTER_EXTENSION) DriverObject, (PFILTER_INITIALIZATION_DATA) RegistryPath);
73:
1.1.1.14 root 74: TCDriverObject = DriverObject;
1.1.1.25! root 75: memset (VirtualVolumeDeviceObjects, 0, sizeof (VirtualVolumeDeviceObjects));
1.1.1.15 root 76:
1.1.1.23 root 77: ReadRegistryConfigFlags (TRUE);
78: EncryptionThreadPoolStart (EncryptionThreadPoolFreeCpuCountLimit);
79: SelfTestsPassed = AutoTestAlgorithms();
1.1.1.17 root 80:
1.1.1.15 root 81: // Enable device class filters and load boot arguments if the driver is set to start at system boot
1.1.1.12 root 82:
1.1.1.15 root 83: if (NT_SUCCESS (TCReadRegistryKey (RegistryPath, L"Start", &startKeyValue)))
84: {
85: if (startKeyValue->Type == REG_DWORD && *((uint32 *) startKeyValue->Data) == SERVICE_BOOT_START)
1.1.1.12 root 86: {
1.1.1.15 root 87: if (!SelfTestsPassed)
88: TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
1.1.1.12 root 89:
1.1.1.15 root 90: LoadBootArguments();
91: VolumeClassFilterRegistered = IsVolumeClassFilterRegistered();
1.1.1.12 root 92:
1.1.1.15 root 93: DriverObject->DriverExtension->AddDevice = DriverAddDevice;
1.1.1.12 root 94: }
95:
1.1.1.15 root 96: TCfree (startKeyValue);
1.1.1.12 root 97: }
98:
99: for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i)
100: {
101: DriverObject->MajorFunction[i] = TCDispatchQueueIRP;
102: }
1.1 root 103:
104: DriverObject->DriverUnload = TCUnloadDriver;
105: return TCCreateRootDeviceObject (DriverObject);
106: }
107:
1.1.1.12 root 108:
1.1.1.15 root 109: NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
110: {
1.1.1.19 root 111: #ifdef DEBUG
112: char nameInfoBuffer[128];
113: POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION) nameInfoBuffer;
114: ULONG nameInfoSize;
115: Dump ("AddDevice pdo=%p type=%x name=%ws\n", pdo, pdo->DeviceType, NT_SUCCESS (ObQueryNameString (pdo, nameInfo, sizeof (nameInfoBuffer), &nameInfoSize)) ? nameInfo->Name.Buffer : L"?");
116: #endif
1.1.1.15 root 117:
1.1.1.19 root 118: if (VolumeClassFilterRegistered && BootArgsValid && BootArgs.HiddenSystemPartitionStart != 0)
1.1.1.15 root 119: {
1.1.1.19 root 120: PWSTR interfaceLinks;
121: if (NT_SUCCESS (IoGetDeviceInterfaces (&GUID_DEVINTERFACE_VOLUME, pdo, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &interfaceLinks)))
1.1.1.15 root 122: {
1.1.1.19 root 123: if (interfaceLinks[0] != UNICODE_NULL)
1.1.1.15 root 124: {
1.1.1.19 root 125: Dump ("Volume pdo=%p interface=%ws\n", pdo, interfaceLinks);
126: ExFreePool (interfaceLinks);
1.1.1.15 root 127:
1.1.1.19 root 128: return VolumeFilterAddDevice (driverObject, pdo);
1.1.1.15 root 129: }
1.1.1.19 root 130:
131: ExFreePool (interfaceLinks);
1.1.1.15 root 132: }
133: }
134:
1.1.1.16 root 135: return DriveFilterAddDevice (driverObject, pdo);
1.1.1.15 root 136: }
137:
138:
1.1 root 139: // Dumps a memory region to debug output
1.1.1.12 root 140: void DumpMemory (void *mem, int size)
1.1 root 141: {
142: unsigned char str[20];
143: unsigned char *m = mem;
144: int i,j;
145:
1.1.1.12 root 146: for (j = 0; j < size / 8; j++)
1.1 root 147: {
148: memset (str,0,sizeof str);
1.1.1.12 root 149: for (i = 0; i < 8; i++)
1.1 root 150: {
1.1.1.12 root 151: if (m[i] > ' ' && m[i] <= '~')
1.1 root 152: str[i]=m[i];
153: else
154: str[i]='.';
155: }
156:
1.1.1.12 root 157: Dump ("0x%08p %02x %02x %02x %02x %02x %02x %02x %02x %s\n",
1.1 root 158: m, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], str);
159:
160: m+=8;
161: }
162: }
1.1.1.12 root 163:
1.1 root 164:
1.1.1.17 root 165: BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type)
166: {
167: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp);
168: BOOL input = (type == ValidateInput || type == ValidateInputOutput);
169: BOOL output = (type == ValidateOutput || type == ValidateInputOutput);
170:
171: if ((input && irpSp->Parameters.DeviceIoControl.InputBufferLength < requiredBufferSize)
172: || (output && irpSp->Parameters.DeviceIoControl.OutputBufferLength < requiredBufferSize))
173: {
174: 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);
175:
176: irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
177: irp->IoStatus.Information = 0;
178: return FALSE;
179: }
180:
181: if (!input && output)
182: memset (irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength);
183:
184: return TRUE;
185: }
186:
187:
1.1.1.25! root 188: PDEVICE_OBJECT GetVirtualVolumeDeviceObject (int driveNumber)
! 189: {
! 190: if (driveNumber < MIN_MOUNTED_VOLUME_DRIVE_NUMBER || driveNumber > MAX_MOUNTED_VOLUME_DRIVE_NUMBER)
! 191: return NULL;
! 192:
! 193: return VirtualVolumeDeviceObjects[driveNumber];
! 194: }
! 195:
! 196:
1.1 root 197: /* TCDispatchQueueIRP queues any IRP's so that they can be processed later
198: by the thread -- or in some cases handles them immediately! */
1.1.1.17 root 199: NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp)
1.1 root 200: {
201: PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension;
202: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
203: NTSTATUS ntStatus;
204:
205: #ifdef _DEBUG
1.1.1.18 root 206: if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL && (Extension->bRootDevice || Extension->IsVolumeDevice))
1.1.1.12 root 207: {
208: switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
209: {
210: case TC_IOCTL_GET_MOUNTED_VOLUMES:
211: case TC_IOCTL_GET_PASSWORD_CACHE_STATUS:
1.1.1.21 root 212: case TC_IOCTL_GET_PORTABLE_MODE_STATUS:
213: case TC_IOCTL_SET_PORTABLE_MODE_STATUS:
1.1.1.12 root 214: case TC_IOCTL_OPEN_TEST:
215: case TC_IOCTL_GET_RESOLVED_SYMLINK:
1.1.1.23 root 216: case TC_IOCTL_GET_DEVICE_REFCOUNT:
1.1.1.12 root 217: case TC_IOCTL_GET_DRIVE_PARTITION_INFO:
218: case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES:
219: case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS:
1.1.1.21 root 220: case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS:
1.1.1.23 root 221: case TC_IOCTL_GET_WARNING_FLAGS:
1.1.1.15 root 222: case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING:
1.1.1.17 root 223: case IOCTL_DISK_CHECK_VERIFY:
1.1.1.12 root 224: break;
225:
226: default:
1.1.1.15 root 227: Dump ("%ls (0x%x %d)\n",
1.1.1.12 root 228: TCTranslateCode (irpSp->Parameters.DeviceIoControl.IoControlCode),
229: (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16),
230: (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2));
231: }
1.1.1.10 root 232: }
1.1 root 233: #endif
234:
1.1.1.15 root 235: if (!Extension->bRootDevice)
1.1 root 236: {
1.1.1.15 root 237: // Drive filter IRP
238: if (Extension->IsDriveFilterDevice)
239: return DriveFilterDispatchIrp (DeviceObject, Irp);
240:
241: // Volume filter IRP
242: if (Extension->IsVolumeFilterDevice)
243: return VolumeFilterDispatchIrp (DeviceObject, Irp);
1.1 root 244: }
245:
246: switch (irpSp->MajorFunction)
247: {
248: case IRP_MJ_CLOSE:
249: case IRP_MJ_CREATE:
250: case IRP_MJ_CLEANUP:
251: return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);
252:
253: case IRP_MJ_SHUTDOWN:
1.1.1.6 root 254: if (Extension->bRootDevice)
1.1.1.12 root 255: {
1.1.1.21 root 256: Dump ("Driver shutting down\n");
1.1.1.12 root 257: DriverShuttingDown = TRUE;
258:
1.1.1.21 root 259: if (EncryptionSetupThread)
1.1.1.12 root 260: AbortBootEncryptionSetup();
261:
1.1.1.21 root 262: if (DecoySystemWipeThread)
1.1.1.17 root 263: AbortDecoySystemWipe();
264:
1.1.1.25! root 265: OnShutdownPending();
1.1.1.12 root 266: }
1.1.1.4 root 267:
268: return COMPLETE_IRP (DeviceObject, Irp, STATUS_SUCCESS, 0);
269:
1.1 root 270: case IRP_MJ_FLUSH_BUFFERS:
271: case IRP_MJ_READ:
272: case IRP_MJ_WRITE:
273: case IRP_MJ_DEVICE_CONTROL:
274:
1.1.1.15 root 275: if (Extension->bRootDevice)
1.1 root 276: {
1.1.1.12 root 277: if (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1.1.1.25! root 278: {
! 279: NTSTATUS status = KeWaitForMutexObject (&RootDeviceControlMutex, Executive, KernelMode, FALSE, NULL);
! 280: if (!NT_SUCCESS (status))
! 281: return status;
! 282:
! 283: status = ProcessMainDeviceControlIrp (DeviceObject, Extension, Irp);
! 284:
! 285: KeReleaseMutex (&RootDeviceControlMutex, FALSE);
! 286: return status;
! 287: }
1.1.1.15 root 288: break;
1.1 root 289: }
290:
1.1.1.15 root 291: if (Extension->bShuttingDown)
292: {
1.1.1.21 root 293: Dump ("Device %d shutting down: STATUS_DELETE_PENDING\n", Extension->nDosDriveNo);
294: return TCCompleteDiskIrp (Irp, STATUS_DELETE_PENDING, 0);
1.1.1.15 root 295: }
1.1 root 296:
1.1.1.15 root 297: if (Extension->bRemovable
298: && (DeviceObject->Flags & DO_VERIFY_VOLUME)
299: && !(irpSp->Flags & SL_OVERRIDE_VERIFY_VOLUME)
300: && irpSp->MajorFunction != IRP_MJ_FLUSH_BUFFERS)
301: {
302: Dump ("Removable device %d has DO_VERIFY_VOLUME flag: STATUS_DEVICE_NOT_READY\n", Extension->nDosDriveNo);
303: return TCCompleteDiskIrp (Irp, STATUS_DEVICE_NOT_READY, 0);
304: }
1.1 root 305:
1.1.1.15 root 306: switch (irpSp->MajorFunction)
307: {
308: case IRP_MJ_READ:
309: case IRP_MJ_WRITE:
310: ntStatus = EncryptedIoQueueAddIrp (&Extension->Queue, Irp);
311:
312: if (ntStatus != STATUS_PENDING)
313: TCCompleteDiskIrp (Irp, ntStatus, 0);
314:
315: return ntStatus;
316:
317: case IRP_MJ_DEVICE_CONTROL:
1.1.1.21 root 318: ntStatus = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
319: if (!NT_SUCCESS (ntStatus))
320: return TCCompleteIrp (Irp, ntStatus, 0);
321:
1.1.1.15 root 322: IoMarkIrpPending (Irp);
323:
324: ExInterlockedInsertTailList (&Extension->ListEntry, &Irp->Tail.Overlay.ListEntry, &Extension->ListSpinLock);
325: KeReleaseSemaphore (&Extension->RequestSemaphore, IO_DISK_INCREMENT, 1, FALSE);
326:
327: return STATUS_PENDING;
328:
329: case IRP_MJ_FLUSH_BUFFERS:
330: return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
331: }
1.1.1.23 root 332:
333: break;
334:
335: case IRP_MJ_PNP:
336: if (!Extension->bRootDevice
337: && Extension->IsVolumeDevice
338: && irpSp->MinorFunction == IRP_MN_DEVICE_USAGE_NOTIFICATION
339: && irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging
340: && irpSp->Parameters.UsageNotification.InPath)
341: {
342: PagingFileCreationPrevented = TRUE;
343: return TCCompleteIrp (Irp, STATUS_UNSUCCESSFUL, 0);
344: }
345: break;
1.1.1.15 root 346: }
347:
348: return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
1.1 root 349: }
350:
1.1.1.17 root 351: NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject)
1.1 root 352: {
353: UNICODE_STRING Win32NameString, ntUnicodeString;
354: WCHAR dosname[32], ntname[32];
355: PDEVICE_OBJECT DeviceObject;
356: NTSTATUS ntStatus;
357: BOOL *bRootExtension;
358:
359: Dump ("TCCreateRootDeviceObject BEGIN\n");
1.1.1.15 root 360: ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
1.1 root 361:
362: wcscpy (dosname, (LPWSTR) DOS_ROOT_PREFIX);
363: wcscpy (ntname, (LPWSTR) NT_ROOT_PREFIX);
364: RtlInitUnicodeString (&ntUnicodeString, ntname);
365: RtlInitUnicodeString (&Win32NameString, dosname);
366:
367: Dump ("Creating root device nt=%ls dos=%ls\n", ntname, dosname);
1.1.1.3 root 368:
1.1 root 369: ntStatus = IoCreateDevice (
1.1.1.15 root 370: DriverObject,
371: sizeof (BOOL),
372: &ntUnicodeString,
373: FILE_DEVICE_UNKNOWN,
374: FILE_DEVICE_SECURE_OPEN,
375: FALSE,
376: &DeviceObject);
1.1 root 377:
378: if (!NT_SUCCESS (ntStatus))
379: {
380: Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
381: return ntStatus;/* Failed to create DeviceObject */
382: }
383:
384: DeviceObject->Flags |= DO_DIRECT_IO;
385: DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
386:
387: /* Setup the device extension */
388: bRootExtension = (BOOL *) DeviceObject->DeviceExtension;
389: *bRootExtension = TRUE;
390:
1.1.1.25! root 391: KeInitializeMutex (&RootDeviceControlMutex, 0);
! 392:
1.1 root 393: ntStatus = IoCreateSymbolicLink (&Win32NameString, &ntUnicodeString);
1.1.1.4 root 394:
1.1 root 395: if (!NT_SUCCESS (ntStatus))
396: {
397: Dump ("TCCreateRootDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
398: IoDeleteDevice (DeviceObject);
399: return ntStatus;
400: }
401:
1.1.1.4 root 402: IoRegisterShutdownNotification (DeviceObject);
1.1.1.25! root 403: RootDeviceObject = DeviceObject;
1.1.1.4 root 404:
1.1 root 405: Dump ("TCCreateRootDeviceObject STATUS_SUCCESS END\n");
406: return STATUS_SUCCESS;
407: }
408:
1.1.1.17 root 409: NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject,
1.1 root 410: PDEVICE_OBJECT * ppDeviceObject,
1.1.1.4 root 411: MOUNT_STRUCT * mount)
1.1 root 412: {
413: UNICODE_STRING Win32NameString, ntUnicodeString;
414: WCHAR dosname[32], ntname[32];
415: PEXTENSION Extension;
416: NTSTATUS ntStatus;
1.1.1.4 root 417: ULONG devChars = 0;
1.1 root 418:
419: Dump ("TCCreateDeviceObject BEGIN\n");
1.1.1.15 root 420: ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
1.1 root 421:
1.1.1.4 root 422: TCGetDosNameFromNumber (dosname, mount->nDosDriveNo);
423: TCGetNTNameFromNumber (ntname, mount->nDosDriveNo);
1.1 root 424: RtlInitUnicodeString (&ntUnicodeString, ntname);
425: RtlInitUnicodeString (&Win32NameString, dosname);
426:
1.1.1.15 root 427: devChars = FILE_DEVICE_SECURE_OPEN;
428: devChars |= mount->bMountReadOnly ? FILE_READ_ONLY_DEVICE : 0;
1.1.1.4 root 429: devChars |= mount->bMountRemovable ? FILE_REMOVABLE_MEDIA : 0;
430:
1.1 root 431: Dump ("Creating device nt=%ls dos=%ls\n", ntname, dosname);
432:
433: ntStatus = IoCreateDevice (
434: DriverObject, /* Our Driver Object */
435: sizeof (EXTENSION), /* Size of state information */
436: &ntUnicodeString, /* Device name "\Device\Name" */
437: FILE_DEVICE_DISK, /* Device type */
1.1.1.4 root 438: devChars, /* Device characteristics */
1.1 root 439: FALSE, /* Exclusive device */
440: ppDeviceObject); /* Returned ptr to Device Object */
441:
442: if (!NT_SUCCESS (ntStatus))
443: {
444: Dump ("TCCreateDeviceObject NTSTATUS = 0x%08x END\n", ntStatus);
445: return ntStatus;/* Failed to create DeviceObject */
446: }
447: /* Initialize device object and extension. */
448:
449: (*ppDeviceObject)->Flags |= DO_DIRECT_IO;
1.1.1.25! root 450: (*ppDeviceObject)->StackSize += 6; // Reduce occurrence of NO_MORE_IRP_STACK_LOCATIONS bug check caused by buggy drivers
1.1 root 451:
452: /* Setup the device extension */
453: Extension = (PEXTENSION) (*ppDeviceObject)->DeviceExtension;
454: memset (Extension, 0, sizeof (EXTENSION));
455:
1.1.1.15 root 456: Extension->IsVolumeDevice = TRUE;
1.1.1.4 root 457: Extension->nDosDriveNo = mount->nDosDriveNo;
458: Extension->bRemovable = mount->bMountRemovable;
1.1.1.21 root 459: Extension->PartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope;
460: Extension->SystemFavorite = mount->SystemFavorite;
1.1 root 461:
462: KeInitializeEvent (&Extension->keCreateEvent, SynchronizationEvent, FALSE);
463: KeInitializeSemaphore (&Extension->RequestSemaphore, 0L, MAXLONG);
464: KeInitializeSpinLock (&Extension->ListSpinLock);
465: InitializeListHead (&Extension->ListEntry);
1.1.1.21 root 466: IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0);
1.1 root 467:
1.1.1.25! root 468: VirtualVolumeDeviceObjects[mount->nDosDriveNo] = *ppDeviceObject;
! 469:
1.1 root 470: Dump ("TCCreateDeviceObject STATUS_SUCCESS END\n");
471:
472: return STATUS_SUCCESS;
473: }
474:
1.1.1.5 root 475:
1.1.1.25! root 476: BOOL RootDeviceControlMutexAcquireNoWait ()
1.1.1.21 root 477: {
478: NTSTATUS status;
479: LARGE_INTEGER timeout;
480: timeout.QuadPart = 0;
481:
1.1.1.25! root 482: status = KeWaitForMutexObject (&RootDeviceControlMutex, Executive, KernelMode, FALSE, &timeout);
1.1.1.21 root 483: return NT_SUCCESS (status) && status != STATUS_TIMEOUT;
1.1.1.5 root 484: }
485:
486:
1.1.1.25! root 487: void RootDeviceControlMutexRelease ()
1.1.1.5 root 488: {
1.1.1.25! root 489: KeReleaseMutex (&RootDeviceControlMutex, FALSE);
1.1.1.5 root 490: }
491:
492:
1.1.1.12 root 493: NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
1.1 root 494: {
495: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
496:
497: switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
498: {
499:
500: case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
1.1.1.17 root 501: if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_NAME), ValidateOutput))
1.1 root 502: {
503: Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);
504: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
505: }
506: else
507: {
508: ULONG outLength;
509: UNICODE_STRING ntUnicodeString;
1.1.1.7 root 510: WCHAR ntName[256];
1.1 root 511: PMOUNTDEV_NAME outputBuffer = (PMOUNTDEV_NAME) Irp->AssociatedIrp.SystemBuffer;
512:
513: TCGetNTNameFromNumber (ntName, Extension->nDosDriveNo);
514: RtlInitUnicodeString (&ntUnicodeString, ntName);
515:
516: outputBuffer->NameLength = ntUnicodeString.Length;
517: outLength = ntUnicodeString.Length + sizeof(USHORT);
518:
519: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
520: {
521: Irp->IoStatus.Information = sizeof (MOUNTDEV_NAME);
522: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
523:
524: break;
525: }
526:
527: RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length);
528:
529: Irp->IoStatus.Status = STATUS_SUCCESS;
530: Irp->IoStatus.Information = outLength;
531:
532: Dump ("name = %ls\n",ntName);
533: }
534: break;
535:
536: case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
1.1.1.17 root 537: if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_UNIQUE_ID), ValidateOutput))
1.1 root 538: {
539: Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID);
540: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
541: }
542: else
543: {
544: ULONG outLength;
545: UCHAR volId[128], tmp[] = { 0,0 };
546: PMOUNTDEV_UNIQUE_ID outputBuffer = (PMOUNTDEV_UNIQUE_ID) Irp->AssociatedIrp.SystemBuffer;
547:
548: strcpy (volId, TC_UNIQUE_ID_PREFIX);
1.1.1.21 root 549: tmp[0] = 'A' + (UCHAR) Extension->nDosDriveNo;
1.1 root 550: strcat (volId, tmp);
551:
1.1.1.6 root 552: outputBuffer->UniqueIdLength = (USHORT) strlen (volId);
1.1.1.21 root 553: outLength = (ULONG) (strlen (volId) + sizeof (USHORT));
1.1 root 554:
555: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
556: {
557: Irp->IoStatus.Information = sizeof (MOUNTDEV_UNIQUE_ID);
558: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
559: break;
560: }
561:
1.1.1.6 root 562: RtlCopyMemory ((PCHAR)outputBuffer->UniqueId, volId, strlen (volId));
1.1 root 563:
564: Irp->IoStatus.Status = STATUS_SUCCESS;
565: Irp->IoStatus.Information = outLength;
566:
567: Dump ("id = %s\n",volId);
568: }
569: break;
570:
1.1.1.14 root 571: case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME:
1.1 root 572: {
573: ULONG outLength;
574: UNICODE_STRING ntUnicodeString;
1.1.1.7 root 575: WCHAR ntName[256];
1.1 root 576: PMOUNTDEV_SUGGESTED_LINK_NAME outputBuffer = (PMOUNTDEV_SUGGESTED_LINK_NAME) Irp->AssociatedIrp.SystemBuffer;
1.1.1.14 root 577:
1.1.1.17 root 578: if (!ValidateIOBufferSize (Irp, sizeof (MOUNTDEV_SUGGESTED_LINK_NAME), ValidateOutput))
1.1.1.14 root 579: {
580: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
581: Irp->IoStatus.Information = 0;
582: break;
583: }
584:
1.1 root 585: TCGetDosNameFromNumber (ntName, Extension->nDosDriveNo);
586: RtlInitUnicodeString (&ntUnicodeString, ntName);
587:
588: outLength = FIELD_OFFSET(MOUNTDEV_SUGGESTED_LINK_NAME,Name) + ntUnicodeString.Length;
589:
1.1.1.14 root 590: outputBuffer->UseOnlyIfThereAreNoOtherLinks = FALSE;
591: outputBuffer->NameLength = ntUnicodeString.Length;
592:
1.1 root 593: if(irpSp->Parameters.DeviceIoControl.OutputBufferLength < outLength)
594: {
595: Irp->IoStatus.Information = sizeof (MOUNTDEV_SUGGESTED_LINK_NAME);
596: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
597: break;
598: }
599:
600: RtlCopyMemory ((PCHAR)outputBuffer->Name,ntUnicodeString.Buffer, ntUnicodeString.Length);
601:
602: Irp->IoStatus.Status = STATUS_SUCCESS;
603: Irp->IoStatus.Information = outLength;
604:
605: Dump ("link = %ls\n",ntName);
606: }
607: break;
608:
609: case IOCTL_DISK_GET_MEDIA_TYPES:
610: case IOCTL_DISK_GET_DRIVE_GEOMETRY:
611: /* Return the drive geometry for the disk. Note that we
612: return values which were made up to suit the disk size. */
1.1.1.17 root 613: if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY), ValidateOutput))
1.1 root 614: {
615: PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY)
616: Irp->AssociatedIrp.SystemBuffer;
617:
1.1.1.4 root 618: outputBuffer->MediaType = Extension->bRemovable ? RemovableMedia : FixedMedia;
1.1 root 619: outputBuffer->Cylinders.QuadPart = Extension->NumberOfCylinders;
620: outputBuffer->TracksPerCylinder = Extension->TracksPerCylinder;
621: outputBuffer->SectorsPerTrack = Extension->SectorsPerTrack;
622: outputBuffer->BytesPerSector = Extension->BytesPerSector;
623: Irp->IoStatus.Status = STATUS_SUCCESS;
624: Irp->IoStatus.Information = sizeof (DISK_GEOMETRY);
625: }
626: break;
627:
628: case IOCTL_DISK_GET_PARTITION_INFO:
1.1.1.17 root 629: if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION), ValidateOutput))
1.1 root 630: {
631: PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION)
632: Irp->AssociatedIrp.SystemBuffer;
633:
634: outputBuffer->PartitionType = Extension->PartitionType;
635: outputBuffer->BootIndicator = FALSE;
636: outputBuffer->RecognizedPartition = TRUE;
637: outputBuffer->RewritePartition = FALSE;
1.1.1.23 root 638: outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector;
1.1 root 639: outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
1.1.1.11 root 640: outputBuffer->HiddenSectors = 0;
1.1 root 641: Irp->IoStatus.Status = STATUS_SUCCESS;
642: Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION);
643: }
644: break;
1.1.1.10 root 645:
646: case IOCTL_DISK_GET_PARTITION_INFO_EX:
1.1.1.17 root 647: if (ValidateIOBufferSize (Irp, sizeof (PARTITION_INFORMATION_EX), ValidateOutput))
1.1.1.10 root 648: {
649: PPARTITION_INFORMATION_EX outputBuffer = (PPARTITION_INFORMATION_EX) Irp->AssociatedIrp.SystemBuffer;
650:
651: outputBuffer->PartitionStyle = PARTITION_STYLE_MBR;
652: outputBuffer->RewritePartition = FALSE;
1.1.1.23 root 653: outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector;
1.1.1.10 root 654: outputBuffer->PartitionLength.QuadPart= Extension->DiskLength;
655: outputBuffer->Mbr.PartitionType = Extension->PartitionType;
656: outputBuffer->Mbr.BootIndicator = FALSE;
657: outputBuffer->Mbr.RecognizedPartition = TRUE;
1.1.1.11 root 658: outputBuffer->Mbr.HiddenSectors = 0;
1.1.1.10 root 659: Irp->IoStatus.Status = STATUS_SUCCESS;
660: Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION_EX);
661: }
662: break;
663:
1.1.1.6 root 664: case IOCTL_DISK_GET_DRIVE_LAYOUT:
1.1.1.17 root 665: if (ValidateIOBufferSize (Irp, sizeof (DRIVE_LAYOUT_INFORMATION), ValidateOutput))
1.1.1.6 root 666: {
667: PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION)
668: Irp->AssociatedIrp.SystemBuffer;
669:
670: outputBuffer->PartitionCount = 1;
671: outputBuffer->Signature = 0;
672:
673: outputBuffer->PartitionEntry->PartitionType = Extension->PartitionType;
674: outputBuffer->PartitionEntry->BootIndicator = FALSE;
675: outputBuffer->PartitionEntry->RecognizedPartition = TRUE;
676: outputBuffer->PartitionEntry->RewritePartition = FALSE;
1.1.1.23 root 677: outputBuffer->PartitionEntry->StartingOffset.QuadPart = Extension->BytesPerSector;
1.1.1.11 root 678: outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength;
679: outputBuffer->PartitionEntry->HiddenSectors = 0;
1.1.1.6 root 680:
681: Irp->IoStatus.Status = STATUS_SUCCESS;
682: Irp->IoStatus.Information = sizeof (PARTITION_INFORMATION);
683: }
684: break;
685:
1.1 root 686: case IOCTL_DISK_GET_LENGTH_INFO:
1.1.1.17 root 687: if (!ValidateIOBufferSize (Irp, sizeof (GET_LENGTH_INFORMATION), ValidateOutput))
1.1 root 688: {
689: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
690: Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION);
691: }
692: else
693: {
694: PGET_LENGTH_INFORMATION outputBuffer = (PGET_LENGTH_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
695:
696: outputBuffer->Length.QuadPart = Extension->DiskLength;
697: Irp->IoStatus.Status = STATUS_SUCCESS;
698: Irp->IoStatus.Information = sizeof (GET_LENGTH_INFORMATION);
699: }
700: break;
701:
702: case IOCTL_DISK_VERIFY:
1.1.1.17 root 703: if (ValidateIOBufferSize (Irp, sizeof (VERIFY_INFORMATION), ValidateInput))
1.1 root 704: {
705: PVERIFY_INFORMATION pVerifyInformation;
706: pVerifyInformation = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
1.1.1.15 root 707:
708: if (pVerifyInformation->StartingOffset.QuadPart + pVerifyInformation->Length > Extension->DiskLength)
709: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
710: else
711: {
712: IO_STATUS_BLOCK ioStatus;
1.1.1.17 root 713: PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE));
1.1.1.15 root 714:
715: if (!buffer)
716: {
717: Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
718: }
719: else
720: {
721: LARGE_INTEGER offset = pVerifyInformation->StartingOffset;
722: offset.QuadPart += Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset;
723:
724: Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL);
725: TCfree (buffer);
726:
727: if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length)
728: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
729: }
730: }
731:
1.1.1.13 root 732: Irp->IoStatus.Information = 0;
1.1 root 733: }
734: break;
735:
736: case IOCTL_DISK_CHECK_VERIFY:
1.1.1.6 root 737: case IOCTL_STORAGE_CHECK_VERIFY:
1.1 root 738: {
739: Irp->IoStatus.Status = STATUS_SUCCESS;
740: Irp->IoStatus.Information = 0;
1.1.1.15 root 741:
742: if (irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof (ULONG))
743: {
744: *((ULONG *) Irp->AssociatedIrp.SystemBuffer) = 0;
745: Irp->IoStatus.Information = sizeof (ULONG);
746: }
1.1 root 747: }
748: break;
749:
750: case IOCTL_DISK_IS_WRITABLE:
751: {
1.1.1.6 root 752: if (Extension->bReadOnly)
1.1 root 753: Irp->IoStatus.Status = STATUS_MEDIA_WRITE_PROTECTED;
754: else
755: Irp->IoStatus.Status = STATUS_SUCCESS;
756: Irp->IoStatus.Information = 0;
757:
758: }
759: break;
1.1.1.15 root 760:
1.1.1.21 root 761: case IOCTL_VOLUME_ONLINE:
762: Irp->IoStatus.Status = STATUS_SUCCESS;
763: Irp->IoStatus.Information = 0;
764: break;
765:
1.1.1.15 root 766: case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
1.1.1.17 root 767:
1.1.1.15 root 768: // Vista's filesystem defragmenter fails if IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS does not succeed.
1.1.1.21 root 769: if (!(OsMajorVersion == 6 && OsMinorVersion == 0))
1.1.1.17 root 770: {
771: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
772: Irp->IoStatus.Information = 0;
773: }
774: else if (ValidateIOBufferSize (Irp, sizeof (VOLUME_DISK_EXTENTS), ValidateOutput))
775: {
776: VOLUME_DISK_EXTENTS *extents = (VOLUME_DISK_EXTENTS *) Irp->AssociatedIrp.SystemBuffer;
1.1.1.15 root 777:
1.1.1.17 root 778: // No extent data can be returned as this is not a physical drive.
779: memset (extents, 0, sizeof (*extents));
780: extents->NumberOfDiskExtents = 0;
781:
782: Irp->IoStatus.Status = STATUS_SUCCESS;
783: Irp->IoStatus.Information = sizeof (*extents);
784: }
1.1.1.15 root 785: break;
1.1 root 786:
1.1.1.12 root 787: default:
788: return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
789: }
1.1.1.15 root 790:
1.1.1.12 root 791: #ifdef DEBUG
792: if (!NT_SUCCESS (Irp->IoStatus.Status))
1.1.1.15 root 793: {
794: Dump ("IOCTL error 0x%08x (0x%x %d)\n",
795: Irp->IoStatus.Status,
796: (int) (irpSp->Parameters.DeviceIoControl.IoControlCode >> 16),
797: (int) ((irpSp->Parameters.DeviceIoControl.IoControlCode & 0x1FFF) >> 2));
798: }
1.1.1.12 root 799: #endif
800:
801: return TCCompleteDiskIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
802: }
803:
1.1.1.5 root 804:
1.1.1.12 root 805: NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
806: {
807: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
808: NTSTATUS ntStatus;
809:
810: switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
811: {
812: case TC_IOCTL_GET_DRIVER_VERSION:
813: case TC_IOCTL_LEGACY_GET_DRIVER_VERSION:
1.1.1.17 root 814: if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput))
1.1 root 815: {
816: LONG tmp = VERSION_NUM;
817: memcpy (Irp->AssociatedIrp.SystemBuffer, &tmp, 4);
1.1.1.6 root 818: Irp->IoStatus.Information = sizeof (LONG);
1.1 root 819: Irp->IoStatus.Status = STATUS_SUCCESS;
820: }
821: break;
822:
1.1.1.12 root 823: case TC_IOCTL_GET_DEVICE_REFCOUNT:
1.1.1.17 root 824: if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
1.1 root 825: {
1.1.1.6 root 826: *(int *) Irp->AssociatedIrp.SystemBuffer = DeviceObject->ReferenceCount;
827: Irp->IoStatus.Information = sizeof (int);
828: Irp->IoStatus.Status = STATUS_SUCCESS;
829: }
830: break;
831:
1.1.1.25! root 832: case TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED:
1.1.1.17 root 833: if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
1.1.1.11 root 834: {
1.1.1.25! root 835: LONG deviceObjectCount = 0;
! 836:
! 837: *(int *) Irp->AssociatedIrp.SystemBuffer = DriverUnloadDisabled;
! 838:
! 839: if (IoEnumerateDeviceObjectList (TCDriverObject, NULL, 0, &deviceObjectCount) == STATUS_BUFFER_TOO_SMALL && deviceObjectCount > 1)
! 840: *(int *) Irp->AssociatedIrp.SystemBuffer = TRUE;
! 841:
1.1.1.11 root 842: Irp->IoStatus.Information = sizeof (int);
843: Irp->IoStatus.Status = STATUS_SUCCESS;
844: }
845: break;
846:
1.1.1.12 root 847: case TC_IOCTL_IS_ANY_VOLUME_MOUNTED:
1.1.1.17 root 848: if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
1.1.1.12 root 849: {
1.1.1.25! root 850: int drive;
1.1.1.12 root 851: *(int *) Irp->AssociatedIrp.SystemBuffer = 0;
852:
1.1.1.25! root 853: for (drive = MIN_MOUNTED_VOLUME_DRIVE_NUMBER; drive <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; ++drive)
1.1.1.12 root 854: {
1.1.1.25! root 855: if (GetVirtualVolumeDeviceObject (drive))
1.1.1.12 root 856: {
857: *(int *) Irp->AssociatedIrp.SystemBuffer = 1;
858: break;
859: }
860: }
861:
862: if (IsBootDriveMounted())
863: *(int *) Irp->AssociatedIrp.SystemBuffer = 1;
864:
865: Irp->IoStatus.Information = sizeof (int);
866: Irp->IoStatus.Status = STATUS_SUCCESS;
867: }
868: break;
869:
870: case TC_IOCTL_OPEN_TEST:
1.1.1.6 root 871: {
1.1 root 872: OPEN_TEST_STRUCT *opentest = (OPEN_TEST_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
873: OBJECT_ATTRIBUTES ObjectAttributes;
874: HANDLE NtFileHandle;
875: UNICODE_STRING FullFileName;
876: IO_STATUS_BLOCK IoStatus;
1.1.1.14 root 877: LARGE_INTEGER offset;
1.1.1.21 root 878: ACCESS_MASK access = FILE_READ_ATTRIBUTES;
1.1 root 879:
1.1.1.19 root 880: if (!ValidateIOBufferSize (Irp, sizeof (OPEN_TEST_STRUCT), ValidateInputOutput))
1.1.1.15 root 881: break;
882:
883: EnsureNullTerminatedString (opentest->wszFileName, sizeof (opentest->wszFileName));
1.1 root 884: RtlInitUnicodeString (&FullFileName, opentest->wszFileName);
885:
1.1.1.21 root 886: InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
887:
888: if (opentest->bDetectTCBootLoader || opentest->DetectFilesystem)
889: access |= FILE_READ_DATA;
1.1 root 890:
891: ntStatus = ZwCreateFile (&NtFileHandle,
1.1.1.21 root 892: SYNCHRONIZE | access, &ObjectAttributes, &IoStatus, NULL,
893: 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
1.1 root 894:
895: if (NT_SUCCESS (ntStatus))
896: {
1.1.1.19 root 897: opentest->TCBootLoaderDetected = FALSE;
898: opentest->FilesystemDetected = FALSE;
899:
900: if (opentest->bDetectTCBootLoader || opentest->DetectFilesystem)
1.1.1.14 root 901: {
1.1.1.23 root 902: byte *readBuffer = TCalloc (TC_MAX_VOLUME_SECTOR_SIZE);
903: if (!readBuffer)
904: {
905: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
906: }
907: else
908: {
909: // Determine if the first sector contains a portion of the TrueCrypt Boot Loader
1.1.1.14 root 910:
1.1.1.23 root 911: offset.QuadPart = 0;
1.1.1.14 root 912:
1.1.1.23 root 913: ntStatus = ZwReadFile (NtFileHandle,
914: NULL,
915: NULL,
916: NULL,
917: &IoStatus,
918: readBuffer,
919: TC_MAX_VOLUME_SECTOR_SIZE,
920: &offset,
921: NULL);
1.1.1.14 root 922:
1.1.1.23 root 923: if (NT_SUCCESS (ntStatus))
1.1.1.19 root 924: {
1.1.1.23 root 925: size_t i;
926:
927: if (opentest->bDetectTCBootLoader && IoStatus.Information >= TC_SECTOR_SIZE_BIOS)
1.1.1.19 root 928: {
1.1.1.23 root 929: // Search for the string "TrueCrypt"
930: for (i = 0; i < TC_SECTOR_SIZE_BIOS - strlen (TC_APP_NAME); ++i)
1.1.1.19 root 931: {
1.1.1.23 root 932: if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
933: {
934: opentest->TCBootLoaderDetected = TRUE;
935: break;
936: }
1.1.1.19 root 937: }
938: }
939:
1.1.1.23 root 940: if (opentest->DetectFilesystem && IoStatus.Information >= sizeof (int64))
1.1.1.14 root 941: {
1.1.1.23 root 942: switch (BE64 (*(uint64 *) readBuffer))
943: {
944: case 0xEB52904E54465320: // NTFS
945: case 0xEB3C904D53444F53: // FAT16
946: case 0xEB58904D53444F53: // FAT32
947: case 0xEB76904558464154: // exFAT
1.1.1.19 root 948:
1.1.1.23 root 949: opentest->FilesystemDetected = TRUE;
950: break;
951: }
1.1.1.14 root 952: }
953: }
1.1.1.23 root 954:
955: TCfree (readBuffer);
1.1.1.14 root 956: }
957: }
958:
1.1 root 959: ZwClose (NtFileHandle);
960: Dump ("Open test on file %ls success.\n", opentest->wszFileName);
961: }
962: else
963: {
1.1.1.12 root 964: #if 0
1.1 root 965: Dump ("Open test on file %ls failed NTSTATUS 0x%08x\n", opentest->wszFileName, ntStatus);
1.1.1.12 root 966: #endif
1.1 root 967: }
968:
1.1.1.19 root 969: Irp->IoStatus.Information = NT_SUCCESS (ntStatus) ? sizeof (OPEN_TEST_STRUCT) : 0;
970: Irp->IoStatus.Status = ntStatus;
1.1 root 971: }
972: break;
973:
1.1.1.15 root 974: case TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG:
975: {
976: GetSystemDriveConfigurationRequest *request = (GetSystemDriveConfigurationRequest *) Irp->AssociatedIrp.SystemBuffer;
977: OBJECT_ATTRIBUTES ObjectAttributes;
978: HANDLE NtFileHandle;
979: UNICODE_STRING FullFileName;
980: IO_STATUS_BLOCK IoStatus;
981: LARGE_INTEGER offset;
1.1.1.23 root 982: byte readBuffer [TC_SECTOR_SIZE_BIOS];
1.1.1.15 root 983:
1.1.1.17 root 984: if (!ValidateIOBufferSize (Irp, sizeof (GetSystemDriveConfigurationRequest), ValidateInputOutput))
1.1.1.15 root 985: break;
986:
987: EnsureNullTerminatedString (request->DevicePath, sizeof (request->DevicePath));
988: RtlInitUnicodeString (&FullFileName, request->DevicePath);
989:
1.1.1.23 root 990: InitializeObjectAttributes (&ObjectAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
1.1.1.15 root 991:
992: ntStatus = ZwCreateFile (&NtFileHandle,
993: SYNCHRONIZE | GENERIC_READ, &ObjectAttributes, &IoStatus, NULL,
1.1.1.17 root 994: FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_RANDOM_ACCESS, NULL, 0);
1.1.1.15 root 995:
996: if (NT_SUCCESS (ntStatus))
997: {
998: // Determine if the first sector contains a portion of the TrueCrypt Boot Loader
999: offset.QuadPart = 0; // MBR
1000:
1001: ntStatus = ZwReadFile (NtFileHandle,
1002: NULL,
1003: NULL,
1004: NULL,
1005: &IoStatus,
1006: readBuffer,
1007: sizeof(readBuffer),
1008: &offset,
1009: NULL);
1010:
1011: if (NT_SUCCESS (ntStatus))
1012: {
1013: size_t i;
1014:
1015: // Check for dynamic drive
1016: request->DriveIsDynamic = FALSE;
1017:
1018: if (readBuffer[510] == 0x55 && readBuffer[511] == 0xaa)
1019: {
1020: int i;
1021: for (i = 0; i < 4; ++i)
1022: {
1023: if (readBuffer[446 + i * 16 + 4] == PARTITION_LDM)
1024: {
1025: request->DriveIsDynamic = TRUE;
1026: break;
1027: }
1028: }
1029: }
1030:
1.1.1.17 root 1031: request->BootLoaderVersion = 0;
1.1.1.15 root 1032: request->Configuration = 0;
1.1.1.17 root 1033: request->UserConfiguration = 0;
1034: request->CustomUserMessage[0] = 0;
1.1.1.15 root 1035:
1.1.1.17 root 1036: // Search for the string "TrueCrypt"
1.1.1.15 root 1037: for (i = 0; i < sizeof (readBuffer) - strlen (TC_APP_NAME); ++i)
1038: {
1039: if (memcmp (readBuffer + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
1040: {
1.1.1.17 root 1041: request->BootLoaderVersion = BE16 (*(uint16 *) (readBuffer + TC_BOOT_SECTOR_VERSION_OFFSET));
1.1.1.15 root 1042: request->Configuration = readBuffer[TC_BOOT_SECTOR_CONFIG_OFFSET];
1.1.1.17 root 1043:
1.1.1.19 root 1044: if (request->BootLoaderVersion != 0 && request->BootLoaderVersion <= VERSION_NUM)
1.1.1.17 root 1045: {
1046: request->UserConfiguration = readBuffer[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
1047: memcpy (request->CustomUserMessage, readBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
1048: }
1.1.1.15 root 1049: break;
1050: }
1051: }
1052:
1053: Irp->IoStatus.Status = STATUS_SUCCESS;
1054: Irp->IoStatus.Information = sizeof (*request);
1055: }
1056: else
1057: {
1058: Irp->IoStatus.Status = ntStatus;
1059: Irp->IoStatus.Information = 0;
1060: }
1061:
1062: ZwClose (NtFileHandle);
1063:
1064: }
1065: else
1066: {
1067: Irp->IoStatus.Status = ntStatus;
1068: Irp->IoStatus.Information = 0;
1069: }
1070: }
1071: break;
1072:
1.1.1.12 root 1073: case TC_IOCTL_WIPE_PASSWORD_CACHE:
1.1 root 1074: WipeCache ();
1075:
1076: Irp->IoStatus.Status = STATUS_SUCCESS;
1077: Irp->IoStatus.Information = 0;
1078: break;
1079:
1.1.1.12 root 1080: case TC_IOCTL_GET_PASSWORD_CACHE_STATUS:
1.1 root 1081: Irp->IoStatus.Status = cacheEmpty ? STATUS_PIPE_EMPTY : STATUS_SUCCESS;
1082: Irp->IoStatus.Information = 0;
1083: break;
1084:
1.1.1.21 root 1085: case TC_IOCTL_SET_PORTABLE_MODE_STATUS:
1.1.1.14 root 1086: if (!UserCanAccessDriveDevice())
1087: {
1088: Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
1089: Irp->IoStatus.Information = 0;
1090: }
1091: else
1092: {
1.1.1.21 root 1093: PortableMode = TRUE;
1094: Dump ("Setting portable mode\n");
1.1.1.14 root 1095: }
1096: break;
1097:
1.1.1.21 root 1098: case TC_IOCTL_GET_PORTABLE_MODE_STATUS:
1099: Irp->IoStatus.Status = PortableMode ? STATUS_SUCCESS : STATUS_PIPE_EMPTY;
1.1.1.14 root 1100: Irp->IoStatus.Information = 0;
1101: break;
1102:
1.1.1.12 root 1103: case TC_IOCTL_GET_MOUNTED_VOLUMES:
1.1.1.17 root 1104:
1105: if (ValidateIOBufferSize (Irp, sizeof (MOUNT_LIST_STRUCT), ValidateOutput))
1.1 root 1106: {
1107: MOUNT_LIST_STRUCT *list = (MOUNT_LIST_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1108: PDEVICE_OBJECT ListDevice;
1.1.1.25! root 1109: int drive;
1.1.1.5 root 1110:
1.1 root 1111: list->ulMountedDrives = 0;
1.1.1.17 root 1112:
1.1.1.25! root 1113: for (drive = MIN_MOUNTED_VOLUME_DRIVE_NUMBER; drive <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; ++drive)
1.1 root 1114: {
1.1.1.25! root 1115: PEXTENSION ListExtension;
! 1116:
! 1117: ListDevice = GetVirtualVolumeDeviceObject (drive);
! 1118: if (!ListDevice)
! 1119: continue;
! 1120:
! 1121: ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
! 1122: if (IsVolumeAccessibleByCurrentUser (ListExtension))
1.1 root 1123: {
1124: list->ulMountedDrives |= (1 << ListExtension->nDosDriveNo);
1125: wcscpy (list->wszVolume[ListExtension->nDosDriveNo], ListExtension->wszVolume);
1126: list->diskLength[ListExtension->nDosDriveNo] = ListExtension->DiskLength;
1.1.1.4 root 1127: list->ea[ListExtension->nDosDriveNo] = ListExtension->cryptoInfo->ea;
1.1.1.6 root 1128: if (ListExtension->cryptoInfo->hiddenVolume)
1129: list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_HIDDEN; // Hidden volume
1130: else if (ListExtension->cryptoInfo->bHiddenVolProtectionAction)
1131: list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED; // Normal/outer volume (hidden volume protected AND write already prevented)
1132: else if (ListExtension->cryptoInfo->bProtectHiddenVolume)
1133: list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER; // Normal/outer volume (hidden volume protected)
1134: else
1135: list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_NORMAL; // Normal volume
1.1 root 1136: }
1137: }
1138:
1139: Irp->IoStatus.Status = STATUS_SUCCESS;
1140: Irp->IoStatus.Information = sizeof (MOUNT_LIST_STRUCT);
1141: }
1142: break;
1143:
1.1.1.12 root 1144: case TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES:
1.1.1.17 root 1145: if (ValidateIOBufferSize (Irp, sizeof (uint32), ValidateOutput))
1.1.1.12 root 1146: {
1147: // Prevent the user from downgrading to versions lower than 5.0 by faking mounted volumes.
1148: // The user could render the system unbootable by downgrading when boot encryption
1149: // is active or being set up.
1.1.1.17 root 1150:
1151: memset (Irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength);
1.1.1.12 root 1152: *(uint32 *) Irp->AssociatedIrp.SystemBuffer = 0xffffFFFF;
1.1.1.17 root 1153:
1.1.1.12 root 1154: Irp->IoStatus.Status = STATUS_SUCCESS;
1155: Irp->IoStatus.Information = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
1156: }
1157: break;
1158:
1159: case TC_IOCTL_GET_VOLUME_PROPERTIES:
1.1.1.17 root 1160: if (ValidateIOBufferSize (Irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateInputOutput))
1.1 root 1161: {
1162: VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1.1.1.25! root 1163: PDEVICE_OBJECT ListDevice = GetVirtualVolumeDeviceObject (prop->driveNo);
1.1 root 1164:
1165: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1166: Irp->IoStatus.Information = 0;
1167:
1.1.1.25! root 1168: if (ListDevice)
1.1 root 1169: {
1170: PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
1.1.1.25! root 1171: if (IsVolumeAccessibleByCurrentUser (ListExtension))
1.1 root 1172: {
1.1.1.6 root 1173: prop->uniqueId = ListExtension->UniqueVolumeId;
1.1 root 1174: wcscpy (prop->wszVolume, ListExtension->wszVolume);
1175: prop->diskLength = ListExtension->DiskLength;
1.1.1.4 root 1176: prop->ea = ListExtension->cryptoInfo->ea;
1.1.1.7 root 1177: prop->mode = ListExtension->cryptoInfo->mode;
1.1 root 1178: prop->pkcs5 = ListExtension->cryptoInfo->pkcs5;
1179: prop->pkcs5Iterations = ListExtension->cryptoInfo->noIterations;
1.1.1.17 root 1180: #if 0
1.1 root 1181: prop->volumeCreationTime = ListExtension->cryptoInfo->volume_creation_time;
1182: prop->headerCreationTime = ListExtension->cryptoInfo->header_creation_time;
1.1.1.17 root 1183: #endif
1184: prop->volumeHeaderFlags = ListExtension->cryptoInfo->HeaderFlags;
1.1.1.6 root 1185: prop->readOnly = ListExtension->bReadOnly;
1.1.1.19 root 1186: prop->removable = ListExtension->bRemovable;
1.1.1.21 root 1187: prop->partitionInInactiveSysEncScope = ListExtension->PartitionInInactiveSysEncScope;
1.1.1.4 root 1188: prop->hiddenVolume = ListExtension->cryptoInfo->hiddenVolume;
1.1 root 1189:
1.1.1.6 root 1190: if (ListExtension->cryptoInfo->bProtectHiddenVolume)
1191: prop->hiddenVolProtection = ListExtension->cryptoInfo->bHiddenVolProtectionAction ? HIDVOL_PROT_STATUS_ACTION_TAKEN : HIDVOL_PROT_STATUS_ACTIVE;
1192: else
1193: prop->hiddenVolProtection = HIDVOL_PROT_STATUS_NONE;
1194:
1.1.1.12 root 1195: prop->totalBytesRead = ListExtension->Queue.TotalBytesRead;
1196: prop->totalBytesWritten = ListExtension->Queue.TotalBytesWritten;
1.1.1.6 root 1197:
1.1.1.15 root 1198: prop->volFormatVersion = ListExtension->cryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION;
1199:
1.1 root 1200: Irp->IoStatus.Status = STATUS_SUCCESS;
1201: Irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT);
1202: }
1203: }
1204: }
1205: break;
1206:
1.1.1.12 root 1207: case TC_IOCTL_GET_RESOLVED_SYMLINK:
1.1.1.17 root 1208: if (ValidateIOBufferSize (Irp, sizeof (RESOLVE_SYMLINK_STRUCT), ValidateInputOutput))
1.1 root 1209: {
1.1.1.4 root 1210: RESOLVE_SYMLINK_STRUCT *resolve = (RESOLVE_SYMLINK_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1211: {
1212: NTSTATUS ntStatus;
1213:
1.1.1.15 root 1214: EnsureNullTerminatedString (resolve->symLinkName, sizeof (resolve->symLinkName));
1215:
1.1.1.4 root 1216: ntStatus = SymbolicLinkToTarget (resolve->symLinkName,
1217: resolve->targetName,
1218: sizeof (resolve->targetName));
1219:
1220: Irp->IoStatus.Information = sizeof (RESOLVE_SYMLINK_STRUCT);
1221: Irp->IoStatus.Status = ntStatus;
1222: }
1223: }
1224: break;
1225:
1.1.1.12 root 1226: case TC_IOCTL_GET_DRIVE_PARTITION_INFO:
1.1.1.17 root 1227: if (ValidateIOBufferSize (Irp, sizeof (DISK_PARTITION_INFO_STRUCT), ValidateInputOutput))
1.1.1.10 root 1228: {
1229: DISK_PARTITION_INFO_STRUCT *info = (DISK_PARTITION_INFO_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1230: {
1231: PARTITION_INFORMATION_EX pi;
1232: NTSTATUS ntStatus;
1233:
1.1.1.15 root 1234: EnsureNullTerminatedString (info->deviceName, sizeof (info->deviceName));
1235:
1.1.1.10 root 1236: ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof (pi));
1237: if (NT_SUCCESS(ntStatus))
1238: {
1239: memset (&info->partInfo, 0, sizeof (info->partInfo));
1240:
1241: info->partInfo.PartitionLength = pi.PartitionLength;
1242: info->partInfo.PartitionNumber = pi.PartitionNumber;
1243: info->partInfo.StartingOffset = pi.StartingOffset;
1244:
1245: if (pi.PartitionStyle == PARTITION_STYLE_MBR)
1.1.1.15 root 1246: {
1.1.1.10 root 1247: info->partInfo.PartitionType = pi.Mbr.PartitionType;
1.1.1.15 root 1248: info->partInfo.BootIndicator = pi.Mbr.BootIndicator;
1249: }
1.1.1.12 root 1250:
1251: info->IsGPT = pi.PartitionStyle == PARTITION_STYLE_GPT;
1.1.1.10 root 1252: }
1253: else
1254: {
1255: // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX
1256: ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &info->partInfo, sizeof (info->partInfo));
1.1.1.12 root 1257: info->IsGPT = FALSE;
1.1.1.10 root 1258: }
1259:
1.1.1.17 root 1260: if (!NT_SUCCESS (ntStatus))
1261: {
1262: GET_LENGTH_INFORMATION lengthInfo;
1263: ntStatus = TCDeviceIoControl (info->deviceName, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &lengthInfo, sizeof (lengthInfo));
1264:
1265: if (NT_SUCCESS (ntStatus))
1266: {
1267: memset (&info->partInfo, 0, sizeof (info->partInfo));
1268: info->partInfo.PartitionLength = lengthInfo.Length;
1269: }
1270: }
1271:
1272: info->IsDynamic = FALSE;
1273:
1274: if (NT_SUCCESS (ntStatus) && OsMajorVersion >= 6)
1275: {
1276: # define IOCTL_VOLUME_IS_DYNAMIC CTL_CODE(IOCTL_VOLUME_BASE, 18, METHOD_BUFFERED, FILE_ANY_ACCESS)
1277: if (!NT_SUCCESS (TCDeviceIoControl (info->deviceName, IOCTL_VOLUME_IS_DYNAMIC, NULL, 0, &info->IsDynamic, sizeof (info->IsDynamic))))
1278: info->IsDynamic = FALSE;
1279: }
1280:
1.1.1.10 root 1281: Irp->IoStatus.Information = sizeof (DISK_PARTITION_INFO_STRUCT);
1282: Irp->IoStatus.Status = ntStatus;
1283: }
1284: }
1285: break;
1286:
1.1.1.12 root 1287: case TC_IOCTL_GET_DRIVE_GEOMETRY:
1.1.1.17 root 1288: if (ValidateIOBufferSize (Irp, sizeof (DISK_GEOMETRY_STRUCT), ValidateInputOutput))
1.1.1.10 root 1289: {
1290: DISK_GEOMETRY_STRUCT *g = (DISK_GEOMETRY_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1291: {
1292: NTSTATUS ntStatus;
1293:
1.1.1.15 root 1294: EnsureNullTerminatedString (g->deviceName, sizeof (g->deviceName));
1295:
1.1.1.10 root 1296: ntStatus = TCDeviceIoControl (g->deviceName,
1297: IOCTL_DISK_GET_DRIVE_GEOMETRY,
1298: NULL, 0, &g->diskGeometry, sizeof (g->diskGeometry));
1299:
1300: Irp->IoStatus.Information = sizeof (DISK_GEOMETRY_STRUCT);
1301: Irp->IoStatus.Status = ntStatus;
1302: }
1303: }
1304: break;
1305:
1.1.1.12 root 1306: case TC_IOCTL_PROBE_REAL_DRIVE_SIZE:
1.1.1.17 root 1307: if (ValidateIOBufferSize (Irp, sizeof (ProbeRealDriveSizeRequest), ValidateInputOutput))
1.1.1.12 root 1308: {
1309: ProbeRealDriveSizeRequest *request = (ProbeRealDriveSizeRequest *) Irp->AssociatedIrp.SystemBuffer;
1310: NTSTATUS status;
1311: UNICODE_STRING name;
1312: PFILE_OBJECT fileObject;
1313: PDEVICE_OBJECT deviceObject;
1314:
1.1.1.15 root 1315: EnsureNullTerminatedString (request->DeviceName, sizeof (request->DeviceName));
1316:
1.1.1.12 root 1317: RtlInitUnicodeString (&name, request->DeviceName);
1318: status = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
1319: if (!NT_SUCCESS (status))
1320: {
1321: Irp->IoStatus.Information = 0;
1322: Irp->IoStatus.Status = status;
1323: break;
1324: }
1325:
1326: status = ProbeRealDriveSize (deviceObject, &request->RealDriveSize);
1327: ObDereferenceObject (fileObject);
1328:
1.1.1.14 root 1329: if (status == STATUS_TIMEOUT)
1330: {
1331: request->TimeOut = TRUE;
1332: Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest);
1333: Irp->IoStatus.Status = STATUS_SUCCESS;
1334: }
1335: else if (!NT_SUCCESS (status))
1.1.1.12 root 1336: {
1337: Irp->IoStatus.Information = 0;
1338: Irp->IoStatus.Status = status;
1339: }
1340: else
1341: {
1.1.1.14 root 1342: request->TimeOut = FALSE;
1.1.1.12 root 1343: Irp->IoStatus.Information = sizeof (ProbeRealDriveSizeRequest);
1344: Irp->IoStatus.Status = status;
1345: }
1346: }
1347: break;
1348:
1349: case TC_IOCTL_MOUNT_VOLUME:
1.1.1.17 root 1350: if (ValidateIOBufferSize (Irp, sizeof (MOUNT_STRUCT), ValidateInputOutput))
1.1.1.4 root 1351: {
1352: MOUNT_STRUCT *mount = (MOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1353:
1.1.1.18 root 1354: if (mount->VolumePassword.Length > MAX_PASSWORD || mount->ProtectedHidVolPassword.Length > MAX_PASSWORD)
1.1.1.15 root 1355: {
1356: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1357: Irp->IoStatus.Information = 0;
1358: break;
1359: }
1360:
1361: EnsureNullTerminatedString (mount->wszVolume, sizeof (mount->wszVolume));
1362:
1.1.1.6 root 1363: Irp->IoStatus.Information = sizeof (MOUNT_STRUCT);
1.1.1.4 root 1364: Irp->IoStatus.Status = MountDevice (DeviceObject, mount);
1.1.1.18 root 1365:
1.1.1.6 root 1366: burn (&mount->VolumePassword, sizeof (mount->VolumePassword));
1367: burn (&mount->ProtectedHidVolPassword, sizeof (mount->ProtectedHidVolPassword));
1.1 root 1368: }
1369: break;
1370:
1.1.1.12 root 1371: case TC_IOCTL_DISMOUNT_VOLUME:
1.1.1.17 root 1372: if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput))
1.1 root 1373: {
1374: UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1.1.1.25! root 1375: PDEVICE_OBJECT ListDevice = GetVirtualVolumeDeviceObject (unmount->nDosDriveNo);
1.1 root 1376:
1377: unmount->nReturnCode = ERR_DRIVE_NOT_FOUND;
1378:
1.1.1.25! root 1379: if (ListDevice)
1.1 root 1380: {
1381: PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
1382:
1.1.1.25! root 1383: if (IsVolumeAccessibleByCurrentUser (ListExtension))
1.1.1.15 root 1384: unmount->nReturnCode = UnmountDevice (unmount, ListDevice, unmount->ignoreOpenFiles);
1.1.1.4 root 1385: }
1.1 root 1386:
1.1.1.4 root 1387: Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT);
1.1 root 1388: Irp->IoStatus.Status = STATUS_SUCCESS;
1389: }
1390: break;
1391:
1.1.1.12 root 1392: case TC_IOCTL_DISMOUNT_ALL_VOLUMES:
1.1.1.17 root 1393: if (ValidateIOBufferSize (Irp, sizeof (UNMOUNT_STRUCT), ValidateInputOutput))
1.1 root 1394: {
1.1.1.4 root 1395: UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) Irp->AssociatedIrp.SystemBuffer;
1.1 root 1396:
1.1.1.25! root 1397: unmount->nReturnCode = UnmountAllDevices (unmount, unmount->ignoreOpenFiles);
1.1 root 1398:
1.1.1.4 root 1399: Irp->IoStatus.Information = sizeof (UNMOUNT_STRUCT);
1400: Irp->IoStatus.Status = STATUS_SUCCESS;
1.1 root 1401: }
1402: break;
1403:
1.1.1.12 root 1404: case TC_IOCTL_BOOT_ENCRYPTION_SETUP:
1405: Irp->IoStatus.Status = StartBootEncryptionSetup (DeviceObject, Irp, irpSp);
1406: Irp->IoStatus.Information = 0;
1407: break;
1408:
1409: case TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP:
1410: Irp->IoStatus.Status = AbortBootEncryptionSetup();
1411: Irp->IoStatus.Information = 0;
1412: break;
1413:
1414: case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS:
1415: GetBootEncryptionStatus (Irp, irpSp);
1416: break;
1417:
1418: case TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT:
1419: Irp->IoStatus.Information = 0;
1420: Irp->IoStatus.Status = GetSetupResult();
1421: break;
1422:
1423: case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES:
1424: GetBootDriveVolumeProperties (Irp, irpSp);
1425: break;
1426:
1427: case TC_IOCTL_GET_BOOT_LOADER_VERSION:
1428: GetBootLoaderVersion (Irp, irpSp);
1429: break;
1430:
1431: case TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER:
1432: ReopenBootVolumeHeader (Irp, irpSp);
1433: break;
1434:
1.1.1.14 root 1435: case TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME:
1436: GetBootEncryptionAlgorithmName (Irp, irpSp);
1437: break;
1438:
1.1.1.15 root 1439: case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING:
1.1.1.17 root 1440: if (ValidateIOBufferSize (Irp, sizeof (int), ValidateOutput))
1.1.1.15 root 1441: {
1442: *(int *) Irp->AssociatedIrp.SystemBuffer = IsHiddenSystemRunning() ? 1 : 0;
1443: Irp->IoStatus.Information = sizeof (int);
1444: Irp->IoStatus.Status = STATUS_SUCCESS;
1445: }
1446: break;
1447:
1.1.1.17 root 1448: case TC_IOCTL_START_DECOY_SYSTEM_WIPE:
1449: Irp->IoStatus.Status = StartDecoySystemWipe (DeviceObject, Irp, irpSp);
1450: Irp->IoStatus.Information = 0;
1451: break;
1452:
1453: case TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE:
1454: Irp->IoStatus.Status = AbortDecoySystemWipe();
1455: Irp->IoStatus.Information = 0;
1456: break;
1457:
1458: case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT:
1459: Irp->IoStatus.Status = GetDecoySystemWipeResult();
1460: Irp->IoStatus.Information = 0;
1461: break;
1462:
1463: case TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS:
1464: GetDecoySystemWipeStatus (Irp, irpSp);
1465: break;
1466:
1467: case TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR:
1468: Irp->IoStatus.Status = WriteBootDriveSector (Irp, irpSp);
1469: Irp->IoStatus.Information = 0;
1470: break;
1471:
1.1.1.23 root 1472: case TC_IOCTL_GET_WARNING_FLAGS:
1473: if (ValidateIOBufferSize (Irp, sizeof (GetWarningFlagsRequest), ValidateOutput))
1.1.1.21 root 1474: {
1.1.1.23 root 1475: GetWarningFlagsRequest *flags = (GetWarningFlagsRequest *) Irp->AssociatedIrp.SystemBuffer;
1.1.1.21 root 1476:
1.1.1.23 root 1477: flags->PagingFileCreationPrevented = PagingFileCreationPrevented;
1478: PagingFileCreationPrevented = FALSE;
1479: flags->SystemFavoriteVolumeDirty = SystemFavoriteVolumeDirty;
1.1.1.21 root 1480: SystemFavoriteVolumeDirty = FALSE;
1.1.1.23 root 1481:
1482: Irp->IoStatus.Information = sizeof (GetWarningFlagsRequest);
1483: Irp->IoStatus.Status = STATUS_SUCCESS;
1.1.1.21 root 1484: }
1485: break;
1486:
1487: case TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY:
1488: if (UserCanAccessDriveDevice())
1489: {
1490: SystemFavoriteVolumeDirty = TRUE;
1491: Irp->IoStatus.Status = STATUS_SUCCESS;
1492: }
1493: else
1494: Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
1495:
1496: Irp->IoStatus.Information = 0;
1497: break;
1498:
1.1.1.23 root 1499: case TC_IOCTL_REREAD_DRIVER_CONFIG:
1500: Irp->IoStatus.Status = ReadRegistryConfigFlags (FALSE);
1501: Irp->IoStatus.Information = 0;
1502: break;
1503:
1504: case TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG:
1505: if (ValidateIOBufferSize (Irp, sizeof (GetSystemDriveDumpConfigRequest), ValidateOutput))
1506: {
1507: GetSystemDriveDumpConfigRequest *request = (GetSystemDriveDumpConfigRequest *) Irp->AssociatedIrp.SystemBuffer;
1508:
1509: request->BootDriveFilterExtension = GetBootDriveFilterExtension();
1510: if (IsBootDriveMounted() && request->BootDriveFilterExtension)
1511: {
1512: request->HwEncryptionEnabled = IsHwEncryptionEnabled();
1513: Irp->IoStatus.Status = STATUS_SUCCESS;
1514: Irp->IoStatus.Information = sizeof (*request);
1515: }
1516: else
1517: {
1518: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1519: Irp->IoStatus.Information = 0;
1520: }
1521: }
1522: break;
1523:
1.1.1.12 root 1524: default:
1525: return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
1526: }
1.1.1.10 root 1527:
1.1.1.12 root 1528:
1.1.1.10 root 1529: #ifdef DEBUG
1.1.1.12 root 1530: if (!NT_SUCCESS (Irp->IoStatus.Status))
1531: {
1532: switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
1533: {
1534: case TC_IOCTL_GET_MOUNTED_VOLUMES:
1535: case TC_IOCTL_GET_PASSWORD_CACHE_STATUS:
1.1.1.21 root 1536: case TC_IOCTL_GET_PORTABLE_MODE_STATUS:
1537: case TC_IOCTL_SET_PORTABLE_MODE_STATUS:
1.1.1.12 root 1538: case TC_IOCTL_OPEN_TEST:
1539: case TC_IOCTL_GET_RESOLVED_SYMLINK:
1540: case TC_IOCTL_GET_DRIVE_PARTITION_INFO:
1541: case TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES:
1542: case TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS:
1.1.1.15 root 1543: case TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING:
1.1.1.12 root 1544: break;
1545:
1546: default:
1547: Dump ("IOCTL error 0x%08x\n", Irp->IoStatus.Status);
1548: }
1549: }
1.1.1.10 root 1550: #endif
1.1.1.12 root 1551:
1552: return TCCompleteIrp (Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
1553: }
1554:
1555:
1556: NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread)
1557: {
1.1.1.13 root 1558: return TCStartThreadInProcess (threadProc, threadArg, kThread, NULL);
1559: }
1560:
1561:
1562: NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process)
1563: {
1.1.1.12 root 1564: NTSTATUS status;
1565: HANDLE threadHandle;
1.1.1.13 root 1566: HANDLE processHandle = NULL;
1.1.1.12 root 1567: OBJECT_ATTRIBUTES threadObjAttributes;
1568:
1.1.1.13 root 1569: if (process)
1570: {
1571: status = ObOpenObjectByPointer (process, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &processHandle);
1572: if (!NT_SUCCESS (status))
1573: return status;
1574: }
1575:
1.1.1.12 root 1576: InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
1577:
1.1.1.13 root 1578: status = PsCreateSystemThread (&threadHandle, THREAD_ALL_ACCESS, &threadObjAttributes, processHandle, NULL, threadProc, threadArg);
1.1.1.12 root 1579: if (!NT_SUCCESS (status))
1580: return status;
1581:
1582: status = ObReferenceObjectByHandle (threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) kThread, NULL);
1583: if (!NT_SUCCESS (status))
1584: {
1585: ZwClose (threadHandle);
1586: *kThread = NULL;
1587: return status;
1588: }
1589:
1.1.1.13 root 1590: if (processHandle)
1591: ZwClose (processHandle);
1592:
1.1.1.12 root 1593: ZwClose (threadHandle);
1594: return STATUS_SUCCESS;
1595: }
1596:
1597:
1598: void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent)
1599: {
1600: if (wakeUpEvent)
1601: KeSetEvent (wakeUpEvent, 0, FALSE);
1602:
1603: KeWaitForSingleObject (kThread, Executive, KernelMode, FALSE, NULL);
1604: ObDereferenceObject (kThread);
1.1 root 1605: }
1606:
1.1.1.6 root 1607:
1.1.1.17 root 1608: NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount)
1.1 root 1609: {
1610: PTHREAD_BLOCK pThreadBlock = TCalloc (sizeof (THREAD_BLOCK));
1611: HANDLE hThread;
1612: NTSTATUS ntStatus;
1.1.1.12 root 1613: OBJECT_ATTRIBUTES threadObjAttributes;
1.1.1.17 root 1614: SECURITY_QUALITY_OF_SERVICE qos;
1.1 root 1615:
1616: Dump ("Starting thread...\n");
1617:
1618: if (pThreadBlock == NULL)
1619: {
1620: return STATUS_INSUFFICIENT_RESOURCES;
1621: }
1622: else
1623: {
1624: pThreadBlock->DeviceObject = DeviceObject;
1625: pThreadBlock->mount = mount;
1626: }
1627:
1.1.1.17 root 1628: qos.Length = sizeof (qos);
1629: qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
1.1.1.19 root 1630: qos.EffectiveOnly = TRUE;
1.1.1.17 root 1631: qos.ImpersonationLevel = SecurityImpersonation;
1632:
1633: ntStatus = SeCreateClientSecurity (PsGetCurrentThread(), &qos, FALSE, &Extension->SecurityClientContext);
1634: if (!NT_SUCCESS (ntStatus))
1635: goto ret;
1636:
1637: Extension->SecurityClientContextValid = TRUE;
1.1.1.6 root 1638:
1.1 root 1639: Extension->bThreadShouldQuit = FALSE;
1640:
1.1.1.12 root 1641: InitializeObjectAttributes (&threadObjAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
1642:
1.1 root 1643: ntStatus = PsCreateSystemThread (&hThread,
1644: THREAD_ALL_ACCESS,
1.1.1.12 root 1645: &threadObjAttributes,
1.1.1.17 root 1646: NULL,
1.1 root 1647: NULL,
1.1.1.12 root 1648: VolumeThreadProc,
1.1 root 1649: pThreadBlock);
1650:
1651: if (!NT_SUCCESS (ntStatus))
1652: {
1653: Dump ("PsCreateSystemThread Failed END\n");
1.1.1.6 root 1654: goto ret;
1.1 root 1655: }
1656:
1.1.1.12 root 1657: ntStatus = ObReferenceObjectByHandle (hThread,
1.1 root 1658: THREAD_ALL_ACCESS,
1659: NULL,
1660: KernelMode,
1661: &Extension->peThread,
1662: NULL);
1.1.1.12 root 1663:
1.1 root 1664: ZwClose (hThread);
1665:
1.1.1.12 root 1666: if (!NT_SUCCESS (ntStatus))
1667: goto ret;
1668:
1.1 root 1669: Dump ("Waiting for thread to initialize...\n");
1670:
1671: KeWaitForSingleObject (&Extension->keCreateEvent,
1.1.1.12 root 1672: Executive,
1673: KernelMode,
1.1 root 1674: FALSE,
1675: NULL);
1676:
1677: Dump ("Waiting completed! Thread returns 0x%08x\n", pThreadBlock->ntCreateStatus);
1678: ntStatus = pThreadBlock->ntCreateStatus;
1.1.1.6 root 1679:
1680: ret:
1.1 root 1681: TCfree (pThreadBlock);
1682: return ntStatus;
1683: }
1684:
1.1.1.17 root 1685: void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
1.1 root 1686: {
1687: NTSTATUS ntStatus;
1688:
1689: if (DeviceObject); /* Remove compiler warning */
1690:
1691: Dump ("Signalling thread to quit...\n");
1692:
1693: Extension->bThreadShouldQuit = TRUE;
1694:
1695: KeReleaseSemaphore (&Extension->RequestSemaphore,
1696: 0,
1697: 1,
1698: TRUE);
1699:
1.1.1.4 root 1700: ntStatus = KeWaitForSingleObject (Extension->peThread,
1.1.1.12 root 1701: Executive,
1702: KernelMode,
1.1 root 1703: FALSE,
1704: NULL);
1.1.1.21 root 1705:
1706: ASSERT (NT_SUCCESS (ntStatus));
1.1 root 1707:
1.1.1.6 root 1708: ObDereferenceObject (Extension->peThread);
1.1 root 1709: Extension->peThread = NULL;
1710:
1.1.1.15 root 1711: Dump ("Thread exited\n");
1.1 root 1712: }
1713:
1.1.1.5 root 1714:
1715: // Suspend current thread for a number of milliseconds
1716: void TCSleep (int milliSeconds)
1717: {
1718: PKTIMER timer = (PKTIMER) TCalloc (sizeof (KTIMER));
1719: LARGE_INTEGER duetime;
1720:
1.1.1.14 root 1721: if (!timer)
1722: return;
1723:
1.1.1.5 root 1724: duetime.QuadPart = (__int64) milliSeconds * -10000;
1725: KeInitializeTimerEx(timer, NotificationTimer);
1726: KeSetTimerEx(timer, duetime, 0, NULL);
1727:
1.1.1.12 root 1728: KeWaitForSingleObject (timer, Executive, KernelMode, FALSE, NULL);
1.1.1.5 root 1729:
1730: TCfree (timer);
1731: }
1732:
1733:
1.1.1.12 root 1734: /* VolumeThreadProc does all the work of processing IRP's, and dispatching them
1.1 root 1735: to either the ReadWrite function or the DeviceControl function */
1.1.1.17 root 1736: VOID VolumeThreadProc (PVOID Context)
1.1 root 1737: {
1738: PTHREAD_BLOCK pThreadBlock = (PTHREAD_BLOCK) Context;
1739: PDEVICE_OBJECT DeviceObject = pThreadBlock->DeviceObject;
1740: PEXTENSION Extension = (PEXTENSION) DeviceObject->DeviceExtension;
1741: BOOL bDevice;
1742:
1743: /* Set thread priority to lowest realtime level. */
1744: KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY);
1745:
1746: Dump ("Mount THREAD OPENING VOLUME BEGIN\n");
1747:
1748: if (memcmp (pThreadBlock->mount->wszVolume, WIDE ("\\Device"), 14) != 0)
1749: {
1750: wcscpy (pThreadBlock->wszMountVolume, WIDE ("\\??\\"));
1.1.1.7 root 1751: wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume,
1752: sizeof (pThreadBlock->wszMountVolume) / 2 - 5);
1.1 root 1753: bDevice = FALSE;
1754: }
1755: else
1756: {
1.1.1.8 root 1757: pThreadBlock->wszMountVolume[0] = 0;
1758: wcsncat (pThreadBlock->wszMountVolume, pThreadBlock->mount->wszVolume,
1.1.1.7 root 1759: sizeof (pThreadBlock->wszMountVolume) / 2 - 1);
1.1 root 1760: bDevice = TRUE;
1761: }
1762:
1763: Dump ("Mount THREAD request for File %ls DriveNumber %d Device = %d\n",
1764: pThreadBlock->wszMountVolume, pThreadBlock->mount->nDosDriveNo, bDevice);
1765:
1766: pThreadBlock->ntCreateStatus = TCOpenVolume (DeviceObject,
1.1.1.7 root 1767: Extension,
1768: pThreadBlock->mount,
1769: pThreadBlock->wszMountVolume,
1770: bDevice);
1.1 root 1771:
1772: if (!NT_SUCCESS (pThreadBlock->ntCreateStatus) || pThreadBlock->mount->nReturnCode != 0)
1773: {
1774: KeSetEvent (&Extension->keCreateEvent, 0, FALSE);
1775: PsTerminateSystemThread (STATUS_SUCCESS);
1776: }
1.1.1.12 root 1777:
1778: // Start IO queue
1779: Extension->Queue.IsFilterDevice = FALSE;
1780: Extension->Queue.DeviceObject = DeviceObject;
1781: Extension->Queue.CryptoInfo = Extension->cryptoInfo;
1782: Extension->Queue.HostFileHandle = Extension->hDeviceFile;
1783: Extension->Queue.VirtualDeviceLength = Extension->DiskLength;
1.1.1.19 root 1784: Extension->Queue.MaxReadAheadOffset.QuadPart = Extension->HostLength;
1.1.1.12 root 1785:
1.1.1.17 root 1786: if (Extension->SecurityClientContextValid)
1787: Extension->Queue.SecurityClientContext = &Extension->SecurityClientContext;
1788: else
1789: Extension->Queue.SecurityClientContext = NULL;
1790:
1791: pThreadBlock->ntCreateStatus = EncryptedIoQueueStart (&Extension->Queue);
1.1.1.12 root 1792:
1793: if (!NT_SUCCESS (pThreadBlock->ntCreateStatus))
1.1 root 1794: {
1.1.1.12 root 1795: TCCloseVolume (DeviceObject, Extension);
1796:
1797: pThreadBlock->mount->nReturnCode = ERR_OS_ERROR;
1.1 root 1798: KeSetEvent (&Extension->keCreateEvent, 0, FALSE);
1.1.1.12 root 1799: PsTerminateSystemThread (STATUS_SUCCESS);
1.1 root 1800: }
1801:
1.1.1.12 root 1802: KeSetEvent (&Extension->keCreateEvent, 0, FALSE);
1803: /* From this point on pThreadBlock cannot be used as it will have been released! */
1804: pThreadBlock = NULL;
1805:
1.1 root 1806: for (;;)
1807: {
1808: /* Wait for a request from the dispatch routines. */
1.1.1.15 root 1809: KeWaitForSingleObject ((PVOID) & Extension->RequestSemaphore, Executive, KernelMode, FALSE, NULL);
1.1 root 1810:
1.1.1.15 root 1811: for (;;)
1.1 root 1812: {
1.1.1.15 root 1813: PIO_STACK_LOCATION irpSp;
1814: PLIST_ENTRY request;
1815: PIRP irp;
1.1 root 1816:
1.1.1.15 root 1817: request = ExInterlockedRemoveHeadList (&Extension->ListEntry, &Extension->ListSpinLock);
1818: if (request == NULL)
1819: break;
1.1 root 1820:
1.1.1.15 root 1821: irp = CONTAINING_RECORD (request, IRP, Tail.Overlay.ListEntry);
1822: irpSp = IoGetCurrentIrpStackLocation (irp);
1.1 root 1823:
1.1.1.21 root 1824: ASSERT (irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
1825:
1826: ProcessVolumeDeviceControlIrp (DeviceObject, Extension, irp);
1827: IoReleaseRemoveLock (&Extension->Queue.RemoveLock, irp);
1.1.1.15 root 1828: }
1.1.1.12 root 1829:
1.1.1.15 root 1830: if (Extension->bThreadShouldQuit)
1831: {
1832: Dump ("Closing volume\n");
1833: EncryptedIoQueueStop (&Extension->Queue);
1.1.1.12 root 1834:
1.1.1.15 root 1835: TCCloseVolume (DeviceObject, Extension);
1836: PsTerminateSystemThread (STATUS_SUCCESS);
1.1 root 1837: }
1.1.1.10 root 1838: }
1.1 root 1839: }
1840:
1.1.1.17 root 1841: void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo)
1.1 root 1842: {
1843: WCHAR tmp[3] =
1844: {0, ':', 0};
1845: int j = nDriveNo + (WCHAR) 'A';
1846:
1847: tmp[0] = (short) j;
1848: wcscpy (ntname, (LPWSTR) NT_MOUNT_PREFIX);
1849: wcsncat (ntname, tmp, 1);
1850: }
1851:
1.1.1.17 root 1852: void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo)
1.1 root 1853: {
1854: WCHAR tmp[3] =
1855: {0, ':', 0};
1856: int j = nDriveNo + (WCHAR) 'A';
1857:
1858: tmp[0] = (short) j;
1859: wcscpy (dosname, (LPWSTR) DOS_MOUNT_PREFIX);
1860: wcscat (dosname, tmp);
1861: }
1862:
1863: #ifdef _DEBUG
1.1.1.17 root 1864: LPWSTR TCTranslateCode (ULONG ulCode)
1.1 root 1865: {
1.1.1.12 root 1866: switch (ulCode)
1867: {
1868: #define TC_CASE_RET_NAME(CODE) case CODE : return L###CODE
1869:
1870: TC_CASE_RET_NAME (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
1.1.1.17 root 1871: TC_CASE_RET_NAME (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE);
1.1.1.12 root 1872: TC_CASE_RET_NAME (TC_IOCTL_BOOT_ENCRYPTION_SETUP);
1873: TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_ALL_VOLUMES);
1874: TC_CASE_RET_NAME (TC_IOCTL_DISMOUNT_VOLUME);
1875: TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES);
1.1.1.14 root 1876: TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME);
1.1.1.12 root 1877: TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_SETUP_RESULT);
1878: TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS);
1879: TC_CASE_RET_NAME (TC_IOCTL_GET_BOOT_LOADER_VERSION);
1.1.1.17 root 1880: TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT);
1881: TC_CASE_RET_NAME (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS);
1.1.1.12 root 1882: TC_CASE_RET_NAME (TC_IOCTL_GET_DEVICE_REFCOUNT);
1883: TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_GEOMETRY);
1884: TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVE_PARTITION_INFO);
1885: TC_CASE_RET_NAME (TC_IOCTL_GET_DRIVER_VERSION);
1886: TC_CASE_RET_NAME (TC_IOCTL_GET_MOUNTED_VOLUMES);
1887: TC_CASE_RET_NAME (TC_IOCTL_GET_PASSWORD_CACHE_STATUS);
1.1.1.15 root 1888: TC_CASE_RET_NAME (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG);
1.1.1.21 root 1889: TC_CASE_RET_NAME (TC_IOCTL_GET_PORTABLE_MODE_STATUS);
1890: TC_CASE_RET_NAME (TC_IOCTL_SET_PORTABLE_MODE_STATUS);
1.1.1.12 root 1891: TC_CASE_RET_NAME (TC_IOCTL_GET_RESOLVED_SYMLINK);
1.1.1.23 root 1892: TC_CASE_RET_NAME (TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG);
1.1.1.12 root 1893: TC_CASE_RET_NAME (TC_IOCTL_GET_VOLUME_PROPERTIES);
1.1.1.23 root 1894: TC_CASE_RET_NAME (TC_IOCTL_GET_WARNING_FLAGS);
1.1.1.15 root 1895: TC_CASE_RET_NAME (TC_IOCTL_DISK_IS_WRITABLE);
1.1.1.12 root 1896: TC_CASE_RET_NAME (TC_IOCTL_IS_ANY_VOLUME_MOUNTED);
1.1.1.25! root 1897: TC_CASE_RET_NAME (TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED);
1.1.1.15 root 1898: TC_CASE_RET_NAME (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING);
1.1.1.12 root 1899: TC_CASE_RET_NAME (TC_IOCTL_MOUNT_VOLUME);
1900: TC_CASE_RET_NAME (TC_IOCTL_OPEN_TEST);
1901: TC_CASE_RET_NAME (TC_IOCTL_PROBE_REAL_DRIVE_SIZE);
1902: TC_CASE_RET_NAME (TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER);
1.1.1.23 root 1903: TC_CASE_RET_NAME (TC_IOCTL_REREAD_DRIVER_CONFIG);
1.1.1.21 root 1904: TC_CASE_RET_NAME (TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY);
1.1.1.17 root 1905: TC_CASE_RET_NAME (TC_IOCTL_START_DECOY_SYSTEM_WIPE);
1.1.1.12 root 1906: TC_CASE_RET_NAME (TC_IOCTL_WIPE_PASSWORD_CACHE);
1.1.1.17 root 1907: TC_CASE_RET_NAME (TC_IOCTL_WRITE_BOOT_DRIVE_SECTOR);
1.1.1.12 root 1908:
1.1.1.15 root 1909: TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS);
1910:
1.1.1.12 root 1911: #undef TC_CASE_RET_NAME
1912: }
1913:
1.1 root 1914: if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY)
1915: return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY");
1916: else if (ulCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX)
1917: return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX");
1918: else if (ulCode == IOCTL_MOUNTDEV_QUERY_DEVICE_NAME)
1919: return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME");
1920: else if (ulCode == IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME)
1921: return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME");
1922: else if (ulCode == IOCTL_MOUNTDEV_QUERY_UNIQUE_ID)
1923: return (LPWSTR) _T ("IOCTL_MOUNTDEV_QUERY_UNIQUE_ID");
1924: else if (ulCode == IOCTL_VOLUME_ONLINE)
1925: return (LPWSTR) _T ("IOCTL_VOLUME_ONLINE");
1926: else if (ulCode == IOCTL_MOUNTDEV_LINK_CREATED)
1927: return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_CREATED");
1928: else if (ulCode == IOCTL_MOUNTDEV_LINK_DELETED)
1929: return (LPWSTR) _T ("IOCTL_MOUNTDEV_LINK_DELETED");
1930: else if (ulCode == IOCTL_MOUNTMGR_QUERY_POINTS)
1931: return (LPWSTR) _T ("IOCTL_MOUNTMGR_QUERY_POINTS");
1932: else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED)
1933: return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED");
1934: else if (ulCode == IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED)
1935: return (LPWSTR) _T ("IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED");
1936: else if (ulCode == IOCTL_DISK_GET_LENGTH_INFO)
1937: return (LPWSTR) _T ("IOCTL_DISK_GET_LENGTH_INFO");
1938: else if (ulCode == IOCTL_STORAGE_GET_DEVICE_NUMBER)
1939: return (LPWSTR) _T ("IOCTL_STORAGE_GET_DEVICE_NUMBER");
1940: else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO)
1941: return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO");
1942: else if (ulCode == IOCTL_DISK_GET_PARTITION_INFO_EX)
1943: return (LPWSTR) _T ("IOCTL_DISK_GET_PARTITION_INFO_EX");
1944: else if (ulCode == IOCTL_DISK_SET_PARTITION_INFO)
1945: return (LPWSTR) _T ("IOCTL_DISK_SET_PARTITION_INFO");
1946: else if (ulCode == IOCTL_DISK_GET_DRIVE_LAYOUT)
1947: return (LPWSTR) _T ("IOCTL_DISK_GET_DRIVE_LAYOUT");
1948: else if (ulCode == IOCTL_DISK_SET_DRIVE_LAYOUT_EX)
1949: return (LPWSTR) _T ("IOCTL_DISK_SET_DRIVE_LAYOUT_EX");
1950: else if (ulCode == IOCTL_DISK_VERIFY)
1951: return (LPWSTR) _T ("IOCTL_DISK_VERIFY");
1952: else if (ulCode == IOCTL_DISK_FORMAT_TRACKS)
1953: return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS");
1954: else if (ulCode == IOCTL_DISK_REASSIGN_BLOCKS)
1955: return (LPWSTR) _T ("IOCTL_DISK_REASSIGN_BLOCKS");
1956: else if (ulCode == IOCTL_DISK_PERFORMANCE)
1957: return (LPWSTR) _T ("IOCTL_DISK_PERFORMANCE");
1958: else if (ulCode == IOCTL_DISK_IS_WRITABLE)
1959: return (LPWSTR) _T ("IOCTL_DISK_IS_WRITABLE");
1960: else if (ulCode == IOCTL_DISK_LOGGING)
1961: return (LPWSTR) _T ("IOCTL_DISK_LOGGING");
1962: else if (ulCode == IOCTL_DISK_FORMAT_TRACKS_EX)
1963: return (LPWSTR) _T ("IOCTL_DISK_FORMAT_TRACKS_EX");
1964: else if (ulCode == IOCTL_DISK_HISTOGRAM_STRUCTURE)
1965: return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_STRUCTURE");
1966: else if (ulCode == IOCTL_DISK_HISTOGRAM_DATA)
1967: return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_DATA");
1968: else if (ulCode == IOCTL_DISK_HISTOGRAM_RESET)
1969: return (LPWSTR) _T ("IOCTL_DISK_HISTOGRAM_RESET");
1970: else if (ulCode == IOCTL_DISK_REQUEST_STRUCTURE)
1971: return (LPWSTR) _T ("IOCTL_DISK_REQUEST_STRUCTURE");
1972: else if (ulCode == IOCTL_DISK_REQUEST_DATA)
1973: return (LPWSTR) _T ("IOCTL_DISK_REQUEST_DATA");
1974: else if (ulCode == IOCTL_DISK_CONTROLLER_NUMBER)
1975: return (LPWSTR) _T ("IOCTL_DISK_CONTROLLER_NUMBER");
1976: else if (ulCode == SMART_GET_VERSION)
1977: return (LPWSTR) _T ("SMART_GET_VERSION");
1978: else if (ulCode == SMART_SEND_DRIVE_COMMAND)
1979: return (LPWSTR) _T ("SMART_SEND_DRIVE_COMMAND");
1980: else if (ulCode == SMART_RCV_DRIVE_DATA)
1981: return (LPWSTR) _T ("SMART_RCV_DRIVE_DATA");
1982: else if (ulCode == IOCTL_DISK_INTERNAL_SET_VERIFY)
1983: return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_SET_VERIFY");
1984: else if (ulCode == IOCTL_DISK_INTERNAL_CLEAR_VERIFY)
1985: return (LPWSTR) _T ("IOCTL_DISK_INTERNAL_CLEAR_VERIFY");
1986: else if (ulCode == IOCTL_DISK_CHECK_VERIFY)
1987: return (LPWSTR) _T ("IOCTL_DISK_CHECK_VERIFY");
1988: else if (ulCode == IOCTL_DISK_MEDIA_REMOVAL)
1989: return (LPWSTR) _T ("IOCTL_DISK_MEDIA_REMOVAL");
1990: else if (ulCode == IOCTL_DISK_EJECT_MEDIA)
1991: return (LPWSTR) _T ("IOCTL_DISK_EJECT_MEDIA");
1992: else if (ulCode == IOCTL_DISK_LOAD_MEDIA)
1993: return (LPWSTR) _T ("IOCTL_DISK_LOAD_MEDIA");
1994: else if (ulCode == IOCTL_DISK_RESERVE)
1995: return (LPWSTR) _T ("IOCTL_DISK_RESERVE");
1996: else if (ulCode == IOCTL_DISK_RELEASE)
1997: return (LPWSTR) _T ("IOCTL_DISK_RELEASE");
1998: else if (ulCode == IOCTL_DISK_FIND_NEW_DEVICES)
1999: return (LPWSTR) _T ("IOCTL_DISK_FIND_NEW_DEVICES");
2000: else if (ulCode == IOCTL_DISK_GET_MEDIA_TYPES)
2001: return (LPWSTR) _T ("IOCTL_DISK_GET_MEDIA_TYPES");
2002: else if (ulCode == IOCTL_STORAGE_SET_HOTPLUG_INFO)
2003: return (LPWSTR) _T ("IOCTL_STORAGE_SET_HOTPLUG_INFO");
2004: else if (ulCode == IRP_MJ_READ)
2005: return (LPWSTR) _T ("IRP_MJ_READ");
2006: else if (ulCode == IRP_MJ_WRITE)
2007: return (LPWSTR) _T ("IRP_MJ_WRITE");
2008: else if (ulCode == IRP_MJ_CREATE)
2009: return (LPWSTR) _T ("IRP_MJ_CREATE");
2010: else if (ulCode == IRP_MJ_CLOSE)
2011: return (LPWSTR) _T ("IRP_MJ_CLOSE");
2012: else if (ulCode == IRP_MJ_CLEANUP)
2013: return (LPWSTR) _T ("IRP_MJ_CLEANUP");
2014: else if (ulCode == IRP_MJ_FLUSH_BUFFERS)
2015: return (LPWSTR) _T ("IRP_MJ_FLUSH_BUFFERS");
2016: else if (ulCode == IRP_MJ_SHUTDOWN)
2017: return (LPWSTR) _T ("IRP_MJ_SHUTDOWN");
2018: else if (ulCode == IRP_MJ_DEVICE_CONTROL)
2019: return (LPWSTR) _T ("IRP_MJ_DEVICE_CONTROL");
2020: else
2021: {
1.1.1.12 root 2022: return (LPWSTR) _T ("IOCTL");
1.1 root 2023: }
2024: }
2025:
2026: #endif
2027:
1.1.1.25! root 2028: void TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
1.1 root 2029: {
2030: UNICODE_STRING Win32NameString;
2031: NTSTATUS ntStatus;
2032:
2033: Dump ("TCDeleteDeviceObject BEGIN\n");
2034:
1.1.1.6 root 2035: if (Extension->bRootDevice)
1.1 root 2036: {
2037: RtlInitUnicodeString (&Win32NameString, (LPWSTR) DOS_ROOT_PREFIX);
1.1.1.4 root 2038: ntStatus = IoDeleteSymbolicLink (&Win32NameString);
2039: if (!NT_SUCCESS (ntStatus))
2040: Dump ("IoDeleteSymbolicLink failed ntStatus = 0x%08x\n", ntStatus);
1.1.1.25! root 2041:
! 2042: RootDeviceObject = NULL;
1.1 root 2043: }
2044: else
2045: {
2046: if (Extension->peThread != NULL)
1.1.1.12 root 2047: TCStopVolumeThread (DeviceObject, Extension);
1.1.1.14 root 2048:
1.1.1.17 root 2049: if (Extension->UserSid)
2050: TCfree (Extension->UserSid);
2051:
2052: if (Extension->SecurityClientContextValid)
2053: {
2054: if (OsMajorVersion == 5 && OsMinorVersion == 0)
2055: {
2056: ObDereferenceObject (Extension->SecurityClientContext.ClientToken);
2057: }
2058: else
2059: {
2060: // Windows 2000 does not support PsDereferenceImpersonationToken() used by SeDeleteClientSecurity().
2061: // TODO: Use only SeDeleteClientSecurity() once support for Windows 2000 is dropped.
2062:
2063: VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken);
2064: UNICODE_STRING name;
2065: RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken");
2066:
2067: PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name);
2068: if (!PsDereferenceImpersonationTokenD)
2069: TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED);
2070:
2071: # define PsDereferencePrimaryToken
2072: # define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD
2073:
2074: SeDeleteClientSecurity (&Extension->SecurityClientContext);
2075:
2076: # undef PsDereferencePrimaryToken
2077: # undef PsDereferenceImpersonationToken
2078: }
2079: }
2080:
1.1.1.25! root 2081: VirtualVolumeDeviceObjects[Extension->nDosDriveNo] = NULL;
1.1 root 2082: }
2083:
1.1.1.25! root 2084: IoDeleteDevice (DeviceObject);
1.1 root 2085:
2086: Dump ("TCDeleteDeviceObject END\n");
2087: }
2088:
1.1.1.4 root 2089:
1.1.1.17 root 2090: VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject)
1.1 root 2091: {
2092: Dump ("TCUnloadDriver BEGIN\n");
2093:
1.1.1.25! root 2094: OnShutdownPending();
1.1.1.11 root 2095:
1.1.1.12 root 2096: if (IsBootDriveMounted())
2097: TC_BUG_CHECK (STATUS_INVALID_DEVICE_STATE);
2098:
1.1.1.15 root 2099: EncryptionThreadPoolStop();
1.1.1.25! root 2100: TCDeleteDeviceObject (RootDeviceObject, (PEXTENSION) RootDeviceObject->DeviceExtension);
1.1.1.15 root 2101:
1.1 root 2102: Dump ("TCUnloadDriver END\n");
2103: }
1.1.1.4 root 2104:
2105:
1.1.1.25! root 2106: void OnShutdownPending ()
! 2107: {
! 2108: UnmountAllDevices (NULL, TRUE);
! 2109: WipeCache ();
! 2110: }
! 2111:
! 2112:
1.1.1.21 root 2113: NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize)
1.1.1.4 root 2114: {
2115: IO_STATUS_BLOCK ioStatusBlock;
2116: NTSTATUS ntStatus;
2117: PIRP irp;
2118: PFILE_OBJECT fileObject;
2119: PDEVICE_OBJECT deviceObject;
2120: KEVENT event;
2121: UNICODE_STRING name;
2122:
2123: RtlInitUnicodeString(&name, deviceName);
1.1.1.10 root 2124: ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject);
1.1.1.4 root 2125:
1.1.1.21 root 2126: if (!NT_SUCCESS (ntStatus))
1.1.1.4 root 2127: return ntStatus;
2128:
2129: KeInitializeEvent(&event, NotificationEvent, FALSE);
2130:
2131: irp = IoBuildDeviceIoControlRequest (IoControlCode,
2132: deviceObject,
2133: InputBuffer, InputBufferSize,
2134: OutputBuffer, OutputBufferSize,
2135: FALSE,
2136: &event,
2137: &ioStatusBlock);
2138:
2139: if (irp == NULL)
2140: {
2141: Dump ("IRP allocation failed\n");
1.1.1.11 root 2142: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
2143: goto ret;
1.1.1.4 root 2144: }
2145:
1.1.1.21 root 2146: IoGetNextIrpStackLocation (irp)->FileObject = fileObject;
2147:
1.1.1.4 root 2148: ntStatus = IoCallDriver (deviceObject, irp);
2149: if (ntStatus == STATUS_PENDING)
2150: {
1.1.1.12 root 2151: KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
1.1.1.4 root 2152: ntStatus = ioStatusBlock.Status;
2153: }
2154:
1.1.1.11 root 2155: ret:
2156: ObDereferenceObject (fileObject);
1.1.1.4 root 2157: return ntStatus;
2158: }
2159:
2160:
1.1.1.12 root 2161: NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize)
2162: {
2163: IO_STATUS_BLOCK ioStatusBlock;
2164: NTSTATUS status;
2165: PIRP irp;
2166: KEVENT event;
2167:
1.1.1.15 root 2168: ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
1.1.1.12 root 2169:
2170: KeInitializeEvent (&event, NotificationEvent, FALSE);
2171:
2172: irp = IoBuildDeviceIoControlRequest (ioControlCode, deviceObject, inputBuffer, inputBufferSize,
2173: outputBuffer, outputBufferSize, FALSE, &event, &ioStatusBlock);
2174:
2175: if (!irp)
2176: return STATUS_INSUFFICIENT_RESOURCES;
2177:
2178: ObReferenceObject (deviceObject);
2179:
2180: status = IoCallDriver (deviceObject, irp);
2181: if (status == STATUS_PENDING)
2182: {
2183: KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
2184: status = ioStatusBlock.Status;
2185: }
2186:
2187: ObDereferenceObject (deviceObject);
2188: return status;
2189: }
2190:
2191:
2192: NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize)
2193: {
2194: NTSTATUS status;
2195: LARGE_INTEGER sysLength;
2196: LARGE_INTEGER offset;
1.1.1.15 root 2197: byte *sectorBuffer;
1.1.1.14 root 2198: ULONGLONG startTime;
1.1.1.12 root 2199:
1.1.1.15 root 2200: if (!UserCanAccessDriveDevice())
2201: return STATUS_ACCESS_DENIED;
2202:
1.1.1.23 root 2203: sectorBuffer = TCalloc (TC_SECTOR_SIZE_BIOS);
1.1.1.12 root 2204: if (!sectorBuffer)
2205: return STATUS_INSUFFICIENT_RESOURCES;
2206:
2207: status = SendDeviceIoControlRequest (driveDeviceObject, IOCTL_DISK_GET_LENGTH_INFO,
2208: NULL, 0, &sysLength, sizeof (sysLength));
2209:
2210: if (!NT_SUCCESS (status))
2211: {
2212: Dump ("Failed to get drive size - error %x\n", status);
1.1.1.14 root 2213: TCfree (sectorBuffer);
1.1.1.12 root 2214: return status;
2215: }
2216:
1.1.1.14 root 2217: startTime = KeQueryInterruptTime ();
1.1.1.23 root 2218: for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += TC_SECTOR_SIZE_BIOS)
1.1.1.12 root 2219: {
1.1.1.23 root 2220: status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS);
1.1.1.13 root 2221:
1.1.1.15 root 2222: if (NT_SUCCESS (status))
1.1.1.23 root 2223: status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS);
1.1.1.15 root 2224:
1.1.1.14 root 2225: if (!NT_SUCCESS (status))
1.1.1.12 root 2226: {
2227: driveSize->QuadPart = offset.QuadPart;
1.1.1.15 root 2228: Dump ("Real drive size = %I64d bytes (%I64d hidden)\n", driveSize->QuadPart, driveSize->QuadPart - sysLength.QuadPart);
1.1.1.12 root 2229: TCfree (sectorBuffer);
2230: return STATUS_SUCCESS;
2231: }
1.1.1.14 root 2232:
2233: if (KeQueryInterruptTime() - startTime > 3ULL * 60 * 1000 * 1000 * 10)
2234: {
2235: // Abort if probing for more than 3 minutes
2236: driveSize->QuadPart = sysLength.QuadPart;
2237: TCfree (sectorBuffer);
2238: return STATUS_TIMEOUT;
2239: }
1.1.1.12 root 2240: }
2241: }
2242:
2243:
1.1.1.17 root 2244: NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject)
1.1.1.4 root 2245: {
2246: NTSTATUS ntStatus;
2247: OBJECT_ATTRIBUTES objectAttributes;
2248: UNICODE_STRING fullFileName;
2249: IO_STATUS_BLOCK ioStatus;
1.1.1.7 root 2250: WCHAR volumeName[TC_MAX_PATH];
1.1.1.4 root 2251:
1.1.1.21 root 2252: TCGetNTNameFromNumber (volumeName, Extension->nDosDriveNo);
1.1.1.4 root 2253: RtlInitUnicodeString (&fullFileName, volumeName);
1.1.1.23 root 2254: InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
1.1.1.4 root 2255:
2256: ntStatus = ZwCreateFile (volumeHandle,
2257: SYNCHRONIZE | GENERIC_READ,
2258: &objectAttributes,
2259: &ioStatus,
2260: NULL,
2261: FILE_ATTRIBUTE_NORMAL,
2262: FILE_SHARE_READ | FILE_SHARE_WRITE,
2263: FILE_OPEN,
2264: FILE_SYNCHRONOUS_IO_NONALERT,
2265: NULL,
2266: 0);
2267:
2268: Dump ("Volume %ls open NTSTATUS 0x%08x\n", volumeName, ntStatus);
2269:
2270: if (!NT_SUCCESS (ntStatus))
2271: return ntStatus;
2272:
2273: ntStatus = ObReferenceObjectByHandle (*volumeHandle,
2274: FILE_READ_DATA,
2275: NULL,
2276: KernelMode,
2277: fileObject,
2278: NULL);
2279:
2280: if (!NT_SUCCESS (ntStatus))
1.1.1.21 root 2281: ZwClose (*volumeHandle);
1.1.1.4 root 2282:
2283: return ntStatus;
2284: }
2285:
2286:
1.1.1.17 root 2287: void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject)
1.1.1.4 root 2288: {
2289: ObDereferenceObject (fileObject);
2290: ZwClose (volumeHandle);
2291: }
2292:
2293:
1.1.1.12 root 2294: static NTSTATUS TCReadWriteDevice (BOOL write, PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
2295: {
2296: NTSTATUS status;
2297: IO_STATUS_BLOCK ioStatusBlock;
2298: PIRP irp;
2299: KEVENT completionEvent;
2300:
1.1.1.15 root 2301: ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
1.1.1.12 root 2302:
2303: KeInitializeEvent (&completionEvent, NotificationEvent, FALSE);
2304: irp = IoBuildSynchronousFsdRequest (write ? IRP_MJ_WRITE : IRP_MJ_READ, deviceObject, buffer, length, &offset, &completionEvent, &ioStatusBlock);
2305: if (!irp)
2306: return STATUS_INSUFFICIENT_RESOURCES;
2307:
2308: ObReferenceObject (deviceObject);
2309: status = IoCallDriver (deviceObject, irp);
2310:
2311: if (status == STATUS_PENDING)
2312: {
2313: status = KeWaitForSingleObject (&completionEvent, Executive, KernelMode, FALSE, NULL);
2314: if (NT_SUCCESS (status))
2315: status = ioStatusBlock.Status;
2316: }
2317:
2318: ObDereferenceObject (deviceObject);
2319: return status;
2320: }
2321:
2322:
2323: NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
2324: {
2325: return TCReadWriteDevice (FALSE, deviceObject, buffer, offset, length);
2326: }
2327:
2328:
2329: NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length)
2330: {
2331: return TCReadWriteDevice (TRUE, deviceObject, buffer, offset, length);
2332: }
2333:
2334:
1.1.1.17 root 2335: NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode,
1.1.1.4 root 2336: void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize)
2337: {
2338: IO_STATUS_BLOCK ioStatusBlock;
2339: NTSTATUS ntStatus;
2340: PIRP irp;
2341: KEVENT event;
2342: PIO_STACK_LOCATION stack;
2343: PDEVICE_OBJECT deviceObject = IoGetRelatedDeviceObject (fileObject);
2344:
2345: KeInitializeEvent(&event, NotificationEvent, FALSE);
2346:
2347: irp = IoBuildDeviceIoControlRequest (IoControlCode,
2348: deviceObject,
2349: InputBuffer, InputBufferSize,
2350: OutputBuffer, OutputBufferSize,
2351: FALSE,
2352: &event,
2353: &ioStatusBlock);
2354:
2355: if (irp == NULL)
2356: return STATUS_INSUFFICIENT_RESOURCES;
2357:
2358: stack = IoGetNextIrpStackLocation(irp);
2359:
2360: stack->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
2361: stack->MinorFunction = IRP_MN_USER_FS_REQUEST;
2362: stack->FileObject = fileObject;
2363:
2364: ntStatus = IoCallDriver (deviceObject, irp);
2365: if (ntStatus == STATUS_PENDING)
2366: {
1.1.1.12 root 2367: KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
1.1.1.4 root 2368: ntStatus = ioStatusBlock.Status;
2369: }
2370:
2371: return ntStatus;
2372: }
2373:
2374:
1.1.1.17 root 2375: NTSTATUS CreateDriveLink (int nDosDriveNo)
1.1.1.6 root 2376: {
1.1.1.15 root 2377: WCHAR dev[128], link[128];
1.1.1.6 root 2378: UNICODE_STRING deviceName, symLink;
2379: NTSTATUS ntStatus;
2380:
2381: TCGetNTNameFromNumber (dev, nDosDriveNo);
2382: TCGetDosNameFromNumber (link, nDosDriveNo);
2383:
2384: RtlInitUnicodeString (&deviceName, dev);
2385: RtlInitUnicodeString (&symLink, link);
2386:
2387: ntStatus = IoCreateSymbolicLink (&symLink, &deviceName);
2388: Dump ("IoCreateSymbolicLink returned %X\n", ntStatus);
2389: return ntStatus;
2390: }
2391:
2392:
1.1.1.17 root 2393: NTSTATUS RemoveDriveLink (int nDosDriveNo)
1.1.1.6 root 2394: {
1.1.1.7 root 2395: WCHAR link[256];
1.1.1.6 root 2396: UNICODE_STRING symLink;
2397: NTSTATUS ntStatus;
2398:
2399: TCGetDosNameFromNumber (link, nDosDriveNo);
2400: RtlInitUnicodeString (&symLink, link);
2401:
2402: ntStatus = IoDeleteSymbolicLink (&symLink);
2403: Dump ("IoDeleteSymbolicLink returned %X\n", ntStatus);
2404: return ntStatus;
2405: }
2406:
2407:
1.1.1.17 root 2408: NTSTATUS MountManagerMount (MOUNT_STRUCT *mount)
1.1.1.4 root 2409: {
2410: NTSTATUS ntStatus;
1.1.1.7 root 2411: WCHAR arrVolume[256];
1.1.1.4 root 2412: char buf[200];
2413: PMOUNTMGR_TARGET_NAME in = (PMOUNTMGR_TARGET_NAME) buf;
2414: PMOUNTMGR_CREATE_POINT_INPUT point = (PMOUNTMGR_CREATE_POINT_INPUT) buf;
2415: UNICODE_STRING symName, devName;
2416:
2417: TCGetNTNameFromNumber (arrVolume, mount->nDosDriveNo);
2418: in->DeviceNameLength = (USHORT) wcslen (arrVolume) * 2;
2419: wcscpy(in->DeviceName, arrVolume);
2420:
2421: ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
1.1.1.21 root 2422: in, (ULONG) (sizeof (in->DeviceNameLength) + wcslen (arrVolume) * 2), 0, 0);
1.1.1.4 root 2423:
2424: memset (buf, 0, sizeof buf);
2425: TCGetDosNameFromNumber ((PWSTR) &point[1], mount->nDosDriveNo);
2426:
2427: point->SymbolicLinkNameOffset = sizeof (MOUNTMGR_CREATE_POINT_INPUT);
2428: point->SymbolicLinkNameLength = (USHORT) wcslen ((PWSTR) &point[1]) * 2;
2429:
2430: RtlInitUnicodeString(&symName, (PWSTR) (buf + point->SymbolicLinkNameOffset));
2431:
2432: point->DeviceNameOffset = point->SymbolicLinkNameOffset + point->SymbolicLinkNameLength;
2433: TCGetNTNameFromNumber ((PWSTR) (buf + point->DeviceNameOffset), mount->nDosDriveNo);
2434: point->DeviceNameLength = (USHORT) wcslen ((PWSTR) (buf + point->DeviceNameOffset)) * 2;
2435:
2436: RtlInitUnicodeString(&devName, (PWSTR) (buf + point->DeviceNameOffset));
2437:
2438: ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_CREATE_POINT, point,
2439: point->DeviceNameOffset + point->DeviceNameLength, 0, 0);
2440:
2441: return ntStatus;
2442: }
2443:
2444:
1.1.1.17 root 2445: NTSTATUS MountManagerUnmount (int nDosDriveNo)
1.1.1.4 root 2446: {
2447: NTSTATUS ntStatus;
1.1.1.7 root 2448: char buf[256], out[300];
1.1.1.4 root 2449: PMOUNTMGR_MOUNT_POINT in = (PMOUNTMGR_MOUNT_POINT) buf;
2450:
2451: memset (buf, 0, sizeof buf);
2452:
2453: TCGetDosNameFromNumber ((PWSTR) &in[1], nDosDriveNo);
2454:
1.1.1.21 root 2455: // Only symbolic link can be deleted with IOCTL_MOUNTMGR_DELETE_POINTS. If any other entry is specified, the mount manager will ignore subsequent IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION for the same volume ID.
1.1.1.4 root 2456: in->SymbolicLinkNameOffset = sizeof (MOUNTMGR_MOUNT_POINT);
2457: in->SymbolicLinkNameLength = (USHORT) wcslen ((PWCHAR) &in[1]) * 2;
2458:
2459: ntStatus = TCDeviceIoControl (MOUNTMGR_DEVICE_NAME, IOCTL_MOUNTMGR_DELETE_POINTS,
2460: in, sizeof(MOUNTMGR_MOUNT_POINT) + in->SymbolicLinkNameLength, out, sizeof out);
2461:
2462: Dump ("IOCTL_MOUNTMGR_DELETE_POINTS returned 0x%08x\n", ntStatus);
2463:
2464: return ntStatus;
2465: }
2466:
2467:
1.1.1.17 root 2468: NTSTATUS MountDevice (PDEVICE_OBJECT DeviceObject, MOUNT_STRUCT *mount)
1.1.1.4 root 2469: {
2470: PDEVICE_OBJECT NewDeviceObject;
2471: NTSTATUS ntStatus;
2472:
1.1.1.17 root 2473: // Make sure the user is asking for a reasonable nDosDriveNo
1.1.1.15 root 2474: if (mount->nDosDriveNo >= 0 && mount->nDosDriveNo <= 25 && IsDriveLetterAvailable (mount->nDosDriveNo))
1.1.1.4 root 2475: {
2476: Dump ("Mount request looks valid\n");
2477: }
2478: else
2479: {
2480: Dump ("WARNING: MOUNT DRIVE LETTER INVALID\n");
1.1.1.10 root 2481: mount->nReturnCode = ERR_DRIVE_NOT_FOUND;
2482: return ERR_DRIVE_NOT_FOUND;
1.1.1.4 root 2483: }
2484:
1.1.1.6 root 2485: if (!SelfTestsPassed)
2486: {
2487: mount->nReturnCode = ERR_SELF_TESTS_FAILED;
2488: return ERR_SELF_TESTS_FAILED;
2489: }
2490:
1.1.1.17 root 2491: ntStatus = TCCreateDeviceObject (DeviceObject->DriverObject, &NewDeviceObject, mount);
2492:
1.1.1.4 root 2493: if (!NT_SUCCESS (ntStatus))
2494: {
2495: Dump ("Mount CREATE DEVICE ERROR, ntStatus = 0x%08x\n", ntStatus);
2496: return ntStatus;
2497: }
2498: else
2499: {
2500: PEXTENSION NewExtension = (PEXTENSION) NewDeviceObject->DeviceExtension;
1.1.1.17 root 2501: SECURITY_SUBJECT_CONTEXT subContext;
2502: PACCESS_TOKEN accessToken;
2503:
2504: SeCaptureSubjectContext (&subContext);
2505: accessToken = SeQuerySubjectContextToken (&subContext);
2506:
2507: if (!accessToken)
2508: {
2509: ntStatus = STATUS_INVALID_PARAMETER;
2510: }
2511: else
2512: {
2513: PTOKEN_USER tokenUser;
2514:
2515: ntStatus = SeQueryInformationToken (accessToken, TokenUser, &tokenUser);
2516: if (NT_SUCCESS (ntStatus))
2517: {
2518: ULONG sidLength = RtlLengthSid (tokenUser->User.Sid);
2519:
2520: NewExtension->UserSid = TCalloc (sidLength);
2521: if (!NewExtension->UserSid)
2522: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
2523: else
2524: ntStatus = RtlCopySid (sidLength, NewExtension->UserSid, tokenUser->User.Sid);
1.1.1.23 root 2525:
2526: ExFreePool (tokenUser); // Documented in newer versions of WDK
1.1.1.17 root 2527: }
2528: }
2529:
2530: SeReleaseSubjectContext (&subContext);
2531:
2532: if (NT_SUCCESS (ntStatus))
2533: ntStatus = TCStartVolumeThread (NewDeviceObject, NewExtension, mount);
2534:
1.1.1.4 root 2535: if (!NT_SUCCESS (ntStatus))
2536: {
2537: Dump ("Mount FAILURE NT ERROR, ntStatus = 0x%08x\n", ntStatus);
2538: TCDeleteDeviceObject (NewDeviceObject, NewExtension);
2539: return ntStatus;
2540: }
2541: else
2542: {
2543: if (mount->nReturnCode == 0)
2544: {
1.1.1.17 root 2545: HANDLE volumeHandle;
2546: PFILE_OBJECT volumeFileObject;
2547:
2548: Dump ("Mount SUCCESS TC code = 0x%08x READ-ONLY = %d\n", mount->nReturnCode, NewExtension->bReadOnly);
2549:
1.1.1.6 root 2550: if (NewExtension->bReadOnly)
1.1.1.4 root 2551: NewDeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1.1.17 root 2552:
1.1.1.4 root 2553: NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
2554:
1.1.1.6 root 2555: NewExtension->UniqueVolumeId = LastUniqueVolumeId++;
2556:
1.1.1.4 root 2557: if (mount->bMountManager)
2558: MountManagerMount (mount);
2559:
1.1.1.6 root 2560: NewExtension->bMountManager = mount->bMountManager;
1.1.1.4 root 2561:
1.1.1.6 root 2562: // We create symbolic link even if mount manager is notified of
2563: // arriving volume as it apparently sometimes fails to create the link
2564: CreateDriveLink (mount->nDosDriveNo);
1.1.1.17 root 2565:
2566: mount->FilesystemDirty = FALSE;
2567:
2568: if (NT_SUCCESS (TCOpenFsVolume (NewExtension, &volumeHandle, &volumeFileObject)))
2569: {
2570: __try
2571: {
2572: ULONG fsStatus;
2573:
2574: if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &fsStatus, sizeof (fsStatus)))
2575: && (fsStatus & VOLUME_IS_DIRTY))
2576: {
2577: mount->FilesystemDirty = TRUE;
2578: }
2579: }
2580: __except (EXCEPTION_EXECUTE_HANDLER)
2581: {
2582: mount->FilesystemDirty = TRUE;
2583: }
2584:
1.1.1.21 root 2585:
1.1.1.17 root 2586: TCCloseFsVolume (volumeHandle, volumeFileObject);
2587: }
1.1.1.4 root 2588: }
2589: else
2590: {
2591: Dump ("Mount FAILURE TC code = 0x%08x\n", mount->nReturnCode);
2592: TCDeleteDeviceObject (NewDeviceObject, NewExtension);
2593: }
2594:
2595: return STATUS_SUCCESS;
2596: }
2597: }
2598: }
2599:
1.1.1.17 root 2600: NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles)
1.1.1.4 root 2601: {
2602: PEXTENSION extension = deviceObject->DeviceExtension;
2603: NTSTATUS ntStatus;
2604: HANDLE volumeHandle;
2605: PFILE_OBJECT volumeFileObject;
2606:
1.1.1.8 root 2607: Dump ("UnmountDevice %d\n", extension->nDosDriveNo);
2608:
1.1.1.4 root 2609: ntStatus = TCOpenFsVolume (extension, &volumeHandle, &volumeFileObject);
1.1.1.6 root 2610:
1.1.1.8 root 2611: if (NT_SUCCESS (ntStatus))
2612: {
1.1.1.15 root 2613: int dismountRetry;
2614:
1.1.1.21 root 2615: // Dismounting a writable NTFS filesystem prevents the driver from being unloaded on Windows 7
2616: if (IsOSAtLeast (WIN_7) && !extension->bReadOnly)
2617: {
2618: NTFS_VOLUME_DATA_BUFFER ntfsData;
2619:
2620: if (NT_SUCCESS (TCFsctlCall (volumeFileObject, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsData, sizeof (ntfsData))))
1.1.1.25! root 2621: DriverUnloadDisabled = TRUE;
1.1.1.21 root 2622: }
2623:
1.1.1.8 root 2624: // Lock volume
1.1.1.21 root 2625: ntStatus = TCFsctlCall (volumeFileObject, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
1.1.1.8 root 2626: Dump ("FSCTL_LOCK_VOLUME returned %X\n", ntStatus);
2627:
2628: if (!NT_SUCCESS (ntStatus) && !ignoreOpenFiles)
2629: {
2630: TCCloseFsVolume (volumeHandle, volumeFileObject);
2631: return ERR_FILES_OPEN;
2632: }
1.1.1.4 root 2633:
1.1.1.8 root 2634: // Dismount volume
1.1.1.21 root 2635: for (dismountRetry = 0; dismountRetry < 200; ++dismountRetry)
1.1.1.15 root 2636: {
1.1.1.21 root 2637: ntStatus = TCFsctlCall (volumeFileObject, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
1.1.1.15 root 2638: Dump ("FSCTL_DISMOUNT_VOLUME returned %X\n", ntStatus);
2639:
1.1.1.17 root 2640: if (NT_SUCCESS (ntStatus) || ntStatus == STATUS_VOLUME_DISMOUNTED)
1.1.1.15 root 2641: break;
2642:
1.1.1.21 root 2643: if (!ignoreOpenFiles)
2644: {
2645: TCCloseFsVolume (volumeHandle, volumeFileObject);
2646: return ERR_FILES_OPEN;
2647: }
2648:
1.1.1.15 root 2649: TCSleep (100);
2650: }
1.1.1.8 root 2651: }
2652: else
1.1.1.4 root 2653: {
1.1.1.8 root 2654: // Volume cannot be opened => force dismount if allowed
2655: if (!ignoreOpenFiles)
2656: return ERR_FILES_OPEN;
2657: else
2658: volumeHandle = NULL;
1.1.1.4 root 2659: }
2660:
2661: if (extension->bMountManager)
2662: MountManagerUnmount (extension->nDosDriveNo);
1.1.1.8 root 2663:
1.1.1.6 root 2664: // We always remove symbolic link as mount manager might fail to do so
2665: RemoveDriveLink (extension->nDosDriveNo);
1.1.1.4 root 2666:
1.1.1.10 root 2667: extension->bShuttingDown = TRUE;
2668:
1.1.1.21 root 2669: ntStatus = IoAcquireRemoveLock (&extension->Queue.RemoveLock, NULL);
2670: ASSERT (NT_SUCCESS (ntStatus));
2671: IoReleaseRemoveLockAndWait (&extension->Queue.RemoveLock, NULL);
2672:
1.1.1.8 root 2673: if (volumeHandle != NULL)
2674: TCCloseFsVolume (volumeHandle, volumeFileObject);
1.1.1.4 root 2675:
1.1.1.15 root 2676: if (unmountRequest)
2677: {
2678: PCRYPTO_INFO cryptoInfo = ((PEXTENSION) deviceObject->DeviceExtension)->cryptoInfo;
2679: unmountRequest->HiddenVolumeProtectionTriggered = (cryptoInfo->bProtectHiddenVolume && cryptoInfo->bHiddenVolProtectionAction);
2680: }
2681:
1.1.1.4 root 2682: TCDeleteDeviceObject (deviceObject, (PEXTENSION) deviceObject->DeviceExtension);
2683: return 0;
2684: }
2685:
1.1.1.25! root 2686:
! 2687: static PDEVICE_OBJECT FindVolumeWithHighestUniqueId (int maxUniqueId)
! 2688: {
! 2689: PDEVICE_OBJECT highestIdDevice = NULL;
! 2690: int highestId = -1;
! 2691: int drive;
! 2692:
! 2693: for (drive = MIN_MOUNTED_VOLUME_DRIVE_NUMBER; drive <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; ++drive)
! 2694: {
! 2695: PDEVICE_OBJECT device = GetVirtualVolumeDeviceObject (drive);
! 2696: if (device)
! 2697: {
! 2698: PEXTENSION extension = (PEXTENSION) device->DeviceExtension;
! 2699: if (extension->UniqueVolumeId > highestId && extension->UniqueVolumeId <= maxUniqueId)
! 2700: {
! 2701: highestId = extension->UniqueVolumeId;
! 2702: highestIdDevice = device;
! 2703: }
! 2704: }
! 2705: }
! 2706:
! 2707: return highestIdDevice;
! 2708: }
! 2709:
! 2710:
! 2711: NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, BOOL ignoreOpenFiles)
1.1.1.4 root 2712: {
2713: NTSTATUS status = 0;
2714: PDEVICE_OBJECT ListDevice;
1.1.1.25! root 2715: int maxUniqueId = LastUniqueVolumeId;
1.1.1.4 root 2716:
2717: Dump ("Unmounting all volumes\n");
2718:
1.1.1.17 root 2719: if (unmountRequest)
2720: unmountRequest->HiddenVolumeProtectionTriggered = FALSE;
2721:
1.1.1.25! root 2722: // Dismount volumes in the reverse order they were mounted to properly dismount nested volumes
! 2723: while ((ListDevice = FindVolumeWithHighestUniqueId (maxUniqueId)) != NULL)
1.1.1.4 root 2724: {
2725: PEXTENSION ListExtension = (PEXTENSION) ListDevice->DeviceExtension;
1.1.1.25! root 2726: maxUniqueId = ListExtension->UniqueVolumeId - 1;
! 2727:
! 2728: if (IsVolumeAccessibleByCurrentUser (ListExtension))
1.1.1.4 root 2729: {
1.1.1.15 root 2730: NTSTATUS ntStatus;
2731:
2732: if (unmountRequest)
2733: unmountRequest->nDosDriveNo = ListExtension->nDosDriveNo;
1.1.1.10 root 2734:
1.1.1.15 root 2735: ntStatus = UnmountDevice (unmountRequest, ListDevice, ignoreOpenFiles);
1.1.1.12 root 2736: status = ntStatus == 0 ? status : ntStatus;
1.1.1.10 root 2737:
1.1.1.15 root 2738: if (unmountRequest && unmountRequest->HiddenVolumeProtectionTriggered)
2739: break;
1.1.1.4 root 2740: }
2741: }
2742:
2743: return status;
2744: }
2745:
2746: // Resolves symbolic link name to its target name
1.1.1.17 root 2747: NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength)
1.1.1.4 root 2748: {
2749: NTSTATUS ntStatus;
2750: OBJECT_ATTRIBUTES objectAttributes;
2751: UNICODE_STRING fullFileName;
2752: HANDLE handle;
2753:
2754: RtlInitUnicodeString (&fullFileName, symlinkName);
1.1.1.15 root 2755: InitializeObjectAttributes (&objectAttributes, &fullFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
1.1.1.4 root 2756:
2757: ntStatus = ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes);
2758:
2759: if (NT_SUCCESS (ntStatus))
2760: {
2761: UNICODE_STRING target;
2762: target.Buffer = targetName;
2763: target.Length = 0;
2764: target.MaximumLength = maxTargetNameLength;
2765: memset (targetName, 0, maxTargetNameLength);
2766:
2767: ntStatus = ZwQuerySymbolicLinkObject (handle, &target, NULL);
2768:
2769: ZwClose (handle);
2770: }
2771:
2772: return ntStatus;
2773: }
1.1.1.6 root 2774:
1.1.1.15 root 2775:
1.1.1.6 root 2776: // Checks if two regions overlap (borders are parts of regions)
2777: BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2)
2778: {
2779: return (start1 < start2) ? (end1 >= start2) : (start1 <= end2);
2780: }
1.1.1.12 root 2781:
2782:
2783: void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength)
2784: {
2785: uint64 end1 = start1 + length1 - 1;
2786: uint64 intersectEnd = (end1 <= end2) ? end1 : end2;
2787:
2788: *intersectStart = (start1 >= start2) ? start1 : start2;
2789: *intersectLength = (uint32) ((*intersectStart > intersectEnd) ? 0 : intersectEnd + 1 - *intersectStart);
2790:
2791: if (*intersectLength == 0)
2792: *intersectStart = start1;
2793: }
2794:
2795:
2796: BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly)
2797: {
2798: OBJECT_ATTRIBUTES fileObjAttributes;
2799: IO_STATUS_BLOCK ioStatusBlock;
2800: HANDLE fileHandle;
2801: NTSTATUS status;
2802:
2803: ASSERT (!IoIsSystemThread (PsGetCurrentThread()));
2804:
1.1.1.23 root 2805: InitializeObjectAttributes (&fileObjAttributes, objectFileName, OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK | OBJ_KERNEL_HANDLE, NULL, NULL);
1.1.1.12 root 2806:
2807: status = ZwCreateFile (&fileHandle,
2808: readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2809: &fileObjAttributes,
2810: &ioStatusBlock,
2811: NULL,
2812: FILE_ATTRIBUTE_NORMAL,
2813: FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2814: FILE_OPEN,
2815: FILE_SYNCHRONOUS_IO_NONALERT,
2816: NULL,
2817: 0);
2818:
2819: if (NT_SUCCESS (status))
2820: {
2821: ZwClose (fileHandle);
2822: return TRUE;
2823: }
2824:
2825: return FALSE;
2826: }
2827:
2828:
1.1.1.14 root 2829: BOOL UserCanAccessDriveDevice ()
2830: {
2831: UNICODE_STRING name;
2832: RtlInitUnicodeString (&name, L"\\Device\\MountPointManager");
2833:
2834: return IsAccessibleByUser (&name, FALSE);
2835: }
2836:
2837:
1.1.1.15 root 2838: BOOL IsDriveLetterAvailable (int nDosDriveNo)
2839: {
2840: OBJECT_ATTRIBUTES objectAttributes;
2841: UNICODE_STRING objectName;
2842: WCHAR link[128];
2843: HANDLE handle;
2844:
2845: TCGetDosNameFromNumber (link, nDosDriveNo);
2846: RtlInitUnicodeString (&objectName, link);
2847: InitializeObjectAttributes (&objectAttributes, &objectName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
2848:
2849: if (NT_SUCCESS (ZwOpenSymbolicLinkObject (&handle, GENERIC_READ, &objectAttributes)))
2850: {
2851: ZwClose (handle);
2852: return FALSE;
2853: }
2854:
2855: return TRUE;
2856: }
2857:
2858:
1.1.1.12 root 2859: NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information)
2860: {
2861: irp->IoStatus.Status = status;
2862: irp->IoStatus.Information = information;
2863: IoCompleteRequest (irp, IO_NO_INCREMENT);
2864: return status;
2865: }
2866:
2867:
2868: NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information)
2869: {
2870: irp->IoStatus.Status = status;
2871: irp->IoStatus.Information = information;
2872: IoCompleteRequest (irp, NT_SUCCESS (status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
2873: return status;
2874: }
1.1.1.15 root 2875:
2876:
2877: size_t GetCpuCount ()
2878: {
2879: KAFFINITY activeCpuMap = KeQueryActiveProcessors();
2880: size_t mapSize = sizeof (activeCpuMap) * 8;
2881: size_t cpuCount = 0;
2882:
2883: while (mapSize--)
2884: {
2885: if (activeCpuMap & 1)
2886: ++cpuCount;
2887:
2888: activeCpuMap >>= 1;
2889: }
2890:
2891: if (cpuCount == 0)
2892: return 1;
2893:
2894: return cpuCount;
2895: }
2896:
2897:
2898: void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes)
2899: {
2900: ASSERT ((maxSizeInBytes & 1) == 0);
2901: str[maxSizeInBytes / sizeof (wchar_t) - 1] = 0;
2902: }
2903:
2904:
2905: void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout)
2906: {
2907: LARGE_INTEGER waitInterval;
2908: waitInterval.QuadPart = retryDelay * -10000;
2909:
2910: ASSERT (KeGetCurrentIrql() <= APC_LEVEL);
2911: ASSERT (retryDelay > 0 && retryDelay <= timeout);
2912:
2913: while (TRUE)
2914: {
2915: void *memory = TCalloc (size);
2916: if (memory)
2917: return memory;
2918:
2919: timeout -= retryDelay;
2920: if (timeout <= 0)
2921: break;
2922:
2923: KeDelayExecutionThread (KernelMode, FALSE, &waitInterval);
2924: }
2925:
2926: return NULL;
2927: }
2928:
2929:
2930: NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData)
2931: {
2932: OBJECT_ATTRIBUTES regObjAttribs;
2933: HANDLE regKeyHandle;
2934: NTSTATUS status;
2935: UNICODE_STRING valName;
2936: ULONG size = 0;
2937: ULONG resultSize;
2938:
2939: InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
2940: status = ZwOpenKey (®KeyHandle, KEY_READ, ®ObjAttribs);
2941: if (!NT_SUCCESS (status))
2942: return status;
2943:
2944: RtlInitUnicodeString (&valName, keyValueName);
2945: status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, NULL, 0, &size);
2946:
1.1.1.21 root 2947: if (!NT_SUCCESS (status) && status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL)
1.1.1.15 root 2948: {
2949: ZwClose (regKeyHandle);
2950: return status;
2951: }
2952:
2953: if (size == 0)
2954: {
2955: ZwClose (regKeyHandle);
2956: return STATUS_NO_DATA_DETECTED;
2957: }
2958:
2959: *keyData = (PKEY_VALUE_PARTIAL_INFORMATION) TCalloc (size);
2960: if (!*keyData)
2961: {
2962: ZwClose (regKeyHandle);
2963: return STATUS_INSUFFICIENT_RESOURCES;
2964: }
2965:
2966: status = ZwQueryValueKey (regKeyHandle, &valName, KeyValuePartialInformation, *keyData, size, &resultSize);
2967:
2968: ZwClose (regKeyHandle);
2969: return status;
2970: }
2971:
2972:
2973: NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize)
2974: {
2975: OBJECT_ATTRIBUTES regObjAttribs;
2976: HANDLE regKeyHandle;
2977: NTSTATUS status;
2978: UNICODE_STRING valName;
2979:
2980: InitializeObjectAttributes (®ObjAttribs, keyPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
2981: status = ZwOpenKey (®KeyHandle, KEY_READ | KEY_WRITE, ®ObjAttribs);
2982: if (!NT_SUCCESS (status))
2983: return status;
2984:
2985: RtlInitUnicodeString (&valName, keyValueName);
2986:
1.1.1.23 root 2987: status = ZwSetValueKey (regKeyHandle, &valName, 0, keyValueType, valueData, valueSize);
1.1.1.15 root 2988:
2989: ZwClose (regKeyHandle);
2990: return status;
2991: }
2992:
2993:
2994: BOOL IsVolumeClassFilterRegistered ()
2995: {
2996: UNICODE_STRING name;
2997: NTSTATUS status;
2998: BOOL registered = FALSE;
2999:
3000: PKEY_VALUE_PARTIAL_INFORMATION data;
3001:
3002: RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}");
3003: status = TCReadRegistryKey (&name, L"UpperFilters", &data);
3004:
3005: if (NT_SUCCESS (status))
3006: {
3007: if (data->Type == REG_MULTI_SZ && data->DataLength >= 9 * sizeof (wchar_t))
3008: {
3009: // Search for the string "truecrypt"
3010: ULONG i;
3011: for (i = 0; i <= data->DataLength - 9 * sizeof (wchar_t); ++i)
3012: {
3013: if (memcmp (data->Data + i, L"truecrypt", 9 * sizeof (wchar_t)) == 0)
3014: {
3015: Dump ("Volume class filter active\n");
3016: registered = TRUE;
3017: break;
3018: }
3019: }
3020: }
3021:
3022: TCfree (data);
3023: }
3024:
3025: return registered;
3026: }
3027:
3028:
1.1.1.23 root 3029: NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry)
1.1.1.15 root 3030: {
3031: PKEY_VALUE_PARTIAL_INFORMATION data;
3032: UNICODE_STRING name;
3033: NTSTATUS status;
3034: uint32 flags = 0;
3035:
3036: RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt");
3037: status = TCReadRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, &data);
3038:
3039: if (NT_SUCCESS (status))
3040: {
3041: if (data->Type == REG_DWORD)
3042: {
3043: flags = *(uint32 *) data->Data;
3044: Dump ("Configuration flags = 0x%x\n", flags);
1.1.1.17 root 3045:
1.1.1.23 root 3046: if (driverEntry)
3047: {
3048: if (flags & (TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD | TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES))
3049: CacheBootPassword = TRUE;
3050:
3051: if (flags & TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS)
3052: NonAdminSystemFavoritesAccessDisabled = TRUE;
3053: }
1.1.1.21 root 3054:
1.1.1.23 root 3055: EnableHwEncryption ((flags & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? FALSE : TRUE);
1.1.1.15 root 3056: }
1.1.1.23 root 3057: else
3058: status = STATUS_INVALID_PARAMETER;
1.1.1.15 root 3059:
3060: TCfree (data);
3061: }
3062:
1.1.1.23 root 3063: if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, TC_ENCRYPTION_FREE_CPU_COUNT_REG_VALUE_NAME, &data)))
3064: {
3065: if (data->Type == REG_DWORD)
3066: EncryptionThreadPoolFreeCpuCountLimit = *(uint32 *) data->Data;
3067:
3068: TCfree (data);
3069: }
3070:
3071: return status;
1.1.1.15 root 3072: }
3073:
3074:
3075: NTSTATUS WriteRegistryConfigFlags (uint32 flags)
3076: {
3077: UNICODE_STRING name;
3078: RtlInitUnicodeString (&name, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\truecrypt");
3079:
3080: return TCWriteRegistryKey (&name, TC_DRIVER_CONFIG_REG_VALUE_NAME, REG_DWORD, &flags, sizeof (flags));
3081: }
1.1.1.17 root 3082:
3083:
3084: NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector)
3085: {
3086: NTSTATUS status;
3087: DISK_GEOMETRY geometry;
3088:
3089: status = SendDeviceIoControlRequest (deviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geometry, sizeof (geometry));
3090:
3091: if (!NT_SUCCESS (status))
3092: return status;
3093:
3094: *bytesPerSector = geometry.BytesPerSector;
3095: return STATUS_SUCCESS;
3096: }
3097:
3098:
3099: NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount)
3100: {
3101: NTSTATUS status;
3102: ULONG sectorSize;
3103: ULONG sectorCount;
3104: byte *sectorBuffer = NULL;
3105:
3106: *zeroedSectorCount = 0;
3107:
3108: status = GetDeviceSectorSize (deviceObject, §orSize);
3109: if (!NT_SUCCESS (status))
3110: return status;
3111:
3112: sectorBuffer = TCalloc (sectorSize);
3113: if (!sectorBuffer)
3114: return STATUS_INSUFFICIENT_RESOURCES;
3115:
3116: for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize)
3117: {
3118: status = TCReadDevice (deviceObject, sectorBuffer, startOffset, sectorSize);
3119: if (!NT_SUCCESS (status))
3120: {
3121: Dump ("Zeroing sector at %I64d\n", startOffset.QuadPart);
3122: memset (sectorBuffer, 0, sectorSize);
3123:
3124: status = TCWriteDevice (deviceObject, sectorBuffer, startOffset, sectorSize);
3125: if (!NT_SUCCESS (status))
3126: goto err;
3127:
3128: ++(*zeroedSectorCount);
3129: }
3130: }
3131:
3132: status = STATUS_SUCCESS;
3133:
3134: err:
3135: if (sectorBuffer)
3136: TCfree (sectorBuffer);
3137:
3138: return status;
3139: }
3140:
3141:
1.1.1.19 root 3142: NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount)
3143: {
3144: NTSTATUS status;
3145: ULONG sectorSize;
3146: ULONG sectorCount;
3147:
3148: *badSectorCount = 0;
3149:
3150: status = GetDeviceSectorSize (deviceObject, §orSize);
3151: if (!NT_SUCCESS (status))
3152: return status;
3153:
3154: for (sectorCount = size / sectorSize; sectorCount > 0; --sectorCount, startOffset.QuadPart += sectorSize, buffer += sectorSize)
3155: {
3156: status = TCReadDevice (deviceObject, buffer, startOffset, sectorSize);
3157: if (!NT_SUCCESS (status))
3158: {
3159: Dump ("Skipping bad sector at %I64d\n", startOffset.QuadPart);
3160: memset (buffer, 0, sectorSize);
3161: ++(*badSectorCount);
3162: }
3163: }
3164:
3165: return STATUS_SUCCESS;
3166: }
3167:
3168:
1.1.1.17 root 3169: BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension)
3170: {
3171: SECURITY_SUBJECT_CONTEXT subContext;
3172: PACCESS_TOKEN accessToken;
3173: PTOKEN_USER tokenUser;
3174: BOOL result = FALSE;
3175:
1.1.1.21 root 3176: if (IoIsSystemThread (PsGetCurrentThread())
3177: || UserCanAccessDriveDevice()
3178: || !volumeDeviceExtension->UserSid
3179: || (volumeDeviceExtension->SystemFavorite && !NonAdminSystemFavoritesAccessDisabled))
3180: {
1.1.1.17 root 3181: return TRUE;
1.1.1.21 root 3182: }
1.1.1.17 root 3183:
3184: SeCaptureSubjectContext (&subContext);
3185: accessToken = SeQuerySubjectContextToken (&subContext);
3186:
3187: if (!accessToken)
3188: goto ret;
3189:
3190: if (SeTokenIsAdmin (accessToken))
3191: {
3192: result = TRUE;
3193: goto ret;
3194: }
3195:
3196: if (!NT_SUCCESS (SeQueryInformationToken (accessToken, TokenUser, &tokenUser)))
3197: goto ret;
3198:
3199: result = RtlEqualSid (volumeDeviceExtension->UserSid, tokenUser->User.Sid);
1.1.1.23 root 3200: ExFreePool (tokenUser); // Documented in newer versions of WDK
1.1.1.17 root 3201:
3202: ret:
3203: SeReleaseSubjectContext (&subContext);
3204: return result;
3205: }
1.1.1.19 root 3206:
3207:
3208: void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter)
3209: {
3210: *lastPerfCounter = KeQueryPerformanceCounter (NULL);
3211: }
3212:
3213:
3214: // Returns elapsed time in microseconds since last call
3215: int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter)
3216: {
3217: LARGE_INTEGER freq;
3218: LARGE_INTEGER counter = KeQueryPerformanceCounter (&freq);
3219:
3220: int64 elapsed = (counter.QuadPart - lastPerfCounter->QuadPart) * 1000000LL / freq.QuadPart;
3221: *lastPerfCounter = counter;
3222:
3223: return elapsed;
3224: }
1.1.1.21 root 3225:
3226:
3227: BOOL IsOSAtLeast (OSVersionEnum reqMinOS)
3228: {
3229: /* When updating this function, update IsOSVersionAtLeast() in Dlgcode.c too. */
3230:
3231: ULONG major = 0, minor = 0;
3232:
3233: ASSERT (OsMajorVersion != 0);
3234:
3235: switch (reqMinOS)
3236: {
3237: case WIN_2000: major = 5; minor = 0; break;
3238: case WIN_XP: major = 5; minor = 1; break;
3239: case WIN_SERVER_2003: major = 5; minor = 2; break;
3240: case WIN_VISTA: major = 6; minor = 0; break;
3241: case WIN_7: major = 6; minor = 1; break;
3242:
3243: default:
3244: TC_THROW_FATAL_EXCEPTION;
3245: break;
3246: }
3247:
3248: return ((OsMajorVersion << 16 | OsMinorVersion << 8)
3249: >= (major << 16 | minor << 8));
3250: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.