Annotation of truecrypt/driver/ntvol.c, revision 1.1.1.12

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
        !             6:  the original source code (contained in this file) and all other portions of
        !             7:  this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
        !             8:  by the TrueCrypt License 2.4 the full text of which is contained in the
        !             9:  file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10  root       10:  packages. */
1.1       root       11: 
                     12: #include "TCdefs.h"
1.1.1.6   root       13: #include "Crypto.h"
                     14: #include "Volumes.h"
1.1       root       15: 
1.1.1.6   root       16: #include "Apidrvr.h"
                     17: #include "Ntdriver.h"
                     18: #include "Ntvol.h"
1.1       root       19: 
1.1.1.6   root       20: #include "Cache.h"
1.1       root       21: 
1.1.1.10  root       22: #if 0 && _DEBUG
                     23: #define EXTRA_INFO 1
                     24: #endif
1.1       root       25: 
                     26: #pragma warning( disable : 4127 )
                     27: 
                     28: NTSTATUS
                     29: TCOpenVolume (PDEVICE_OBJECT DeviceObject,
                     30:               PEXTENSION Extension,
1.1.1.6   root       31:               MOUNT_STRUCT *mount,
1.1       root       32:               PWSTR pwszMountVolume,
                     33:               BOOL bRawDevice)
                     34: {
                     35:        FILE_STANDARD_INFORMATION FileStandardInfo;
                     36:        FILE_BASIC_INFORMATION FileBasicInfo;
                     37:        OBJECT_ATTRIBUTES oaFileAttributes;
                     38:        UNICODE_STRING FullFileName;
                     39:        IO_STATUS_BLOCK IoStatusBlock;
1.1.1.6   root       40:        PCRYPTO_INFO cryptoInfoPtr = NULL;
                     41:        PCRYPTO_INFO tmpCryptoInfo = NULL;
1.1       root       42:        LARGE_INTEGER lDiskLength;
1.1.1.6   root       43:        LARGE_INTEGER hiddenVolHeaderOffset;
                     44:        int volumeType;
1.1.1.4   root       45:        char *readBuffer = 0;
1.1.1.5   root       46:        NTSTATUS ntStatus = 0;
1.1       root       47: 
                     48:        Extension->pfoDeviceFile = NULL;
                     49:        Extension->hDeviceFile = NULL;
1.1.1.6   root       50:        Extension->bTimeStampValid = FALSE;
1.1       root       51: 
1.1.1.4   root       52:        RtlInitUnicodeString (&FullFileName, pwszMountVolume);
                     53:        InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE,     NULL, NULL);
                     54:        KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
                     55: 
                     56:        // If we are opening a device, query its size first
                     57:        if (bRawDevice)
1.1       root       58:        {
1.1.1.5   root       59:                PARTITION_INFORMATION pi;
1.1.1.10  root       60:                PARTITION_INFORMATION_EX pix;
1.1.1.4   root       61:                DISK_GEOMETRY dg;
1.1       root       62: 
1.1.1.4   root       63:                ntStatus = IoGetDeviceObjectPointer (&FullFileName,
                     64:                        FILE_READ_DATA,
                     65:                        &Extension->pfoDeviceFile,
                     66:                        &Extension->pFsdDevice);
                     67: 
                     68:                if (!NT_SUCCESS (ntStatus))
                     69:                        goto error;
                     70: 
1.1.1.12! root       71:                if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg))))
1.1.1.4   root       72:                {
1.1.1.10  root       73:                        lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector;
                     74:                        mount->BytesPerSector = dg.BytesPerSector;
1.1.1.4   root       75:                }
1.1.1.5   root       76:                else
1.1.1.10  root       77:                        lDiskLength.QuadPart = 0;
1.1.1.4   root       78: 
1.1.1.10  root       79:                // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails
1.1.1.12! root       80:                if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix))))
1.1.1.10  root       81:                        lDiskLength.QuadPart = pix.PartitionLength.QuadPart;
                     82:                // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX
1.1.1.12! root       83:                else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi))))
1.1.1.10  root       84:                        lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
1.1       root       85: 
1.1.1.12! root       86:                if (!mount->bMountReadOnly && TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED)
1.1.1.10  root       87:                {
                     88:                        mount->bMountReadOnly = TRUE;
                     89:                        DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1.1.4   root       90:                }
                     91:        }
1.1       root       92: 
1.1.1.10  root       93:        if (mount->BytesPerSector == 0)
                     94:                mount->BytesPerSector = SECTOR_SIZE;
                     95: 
                     96:        Extension->HostBytesPerSector = mount->BytesPerSector;
                     97: 
1.1.1.4   root       98:        // Open the volume hosting file/device
                     99:        if (!mount->bMountReadOnly)
                    100:        {
                    101:                ntStatus = ZwCreateFile (&Extension->hDeviceFile,
                    102:                        GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
                    103:                        &oaFileAttributes,
                    104:                        &IoStatusBlock,
                    105:                        NULL,
                    106:                        FILE_ATTRIBUTE_NORMAL |
                    107:                        FILE_ATTRIBUTE_SYSTEM,
                    108:                        mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
                    109:                        FILE_OPEN,
1.1.1.10  root      110:                        FILE_RANDOM_ACCESS |
1.1.1.4   root      111:                        FILE_WRITE_THROUGH |
1.1.1.10  root      112:                        (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4   root      113:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    114:                        NULL,
                    115:                        0);
                    116:        }
1.1       root      117: 
1.1.1.10  root      118:        /* 26-4-99 NT for some partitions returns this code, it is really a     access denied */
1.1       root      119:        if (ntStatus == 0xc000001b)
                    120:                ntStatus = STATUS_ACCESS_DENIED;
1.1.1.6   root      121:        
1.1.1.4   root      122:        if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
1.1       root      123:        {
                    124:                ntStatus = ZwCreateFile (&Extension->hDeviceFile,
1.1.1.4   root      125:                        GENERIC_READ | SYNCHRONIZE,
                    126:                        &oaFileAttributes,
                    127:                        &IoStatusBlock,
                    128:                        NULL,
                    129:                        FILE_ATTRIBUTE_NORMAL |
                    130:                        FILE_ATTRIBUTE_SYSTEM,
1.1.1.8   root      131:                        mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
1.1.1.4   root      132:                        FILE_OPEN,
1.1.1.10  root      133:                        FILE_RANDOM_ACCESS |
1.1.1.4   root      134:                        FILE_WRITE_THROUGH |
1.1.1.11  root      135:                        (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4   root      136:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    137:                        NULL,
                    138:                        0);
1.1.1.11  root      139: 
1.1       root      140:                Extension->bReadOnly = TRUE;
1.1.1.11  root      141:                DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1       root      142:        }
                    143:        else
                    144:                Extension->bReadOnly = FALSE;
                    145: 
                    146:        /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4   root      147:        access denied */
1.1       root      148:        if (ntStatus == 0xc000001b)
                    149:        {
                    150:                /* Partitions which return this code can still be opened with
1.1.1.4   root      151:                FILE_SHARE_READ but this causes NT problems elsewhere in
                    152:                particular if you do FILE_SHARE_READ NT will die later if
1.1.1.12! root      153:                anyone even tries to open the partition (or file for that
1.1.1.4   root      154:                matter...)  */
1.1       root      155:                ntStatus = STATUS_SHARING_VIOLATION;
                    156:        }
                    157: 
                    158:        if (!NT_SUCCESS (ntStatus))
                    159:        {
                    160:                goto error;
                    161:        }
                    162: 
1.1.1.4   root      163:        // If we have opened a file, query its size now
1.1       root      164:        if (bRawDevice == FALSE)
                    165:        {
                    166:                ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4   root      167:                        &IoStatusBlock,
                    168:                        &FileBasicInfo,
                    169:                        sizeof (FileBasicInfo),
                    170:                        FileBasicInformation);
1.1       root      171: 
                    172:                if (NT_SUCCESS (ntStatus))
1.1.1.4   root      173:                {
1.1.1.6   root      174:                        if (mount->bPreserveTimestamp)
                    175:                        {
                    176:                                /* Remember the container timestamp. (Used to reset access/modification file date/time
                    177:                                of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve
                    178:                                plausible deniability of hidden volumes.) */
                    179:                                Extension->fileCreationTime = FileBasicInfo.CreationTime;
                    180:                                Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
                    181:                                Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
                    182:                                Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
                    183:                                Extension->bTimeStampValid = TRUE;
                    184:                        }
1.1.1.4   root      185: 
1.1       root      186:                        ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4   root      187:                                &IoStatusBlock,
                    188:                                &FileStandardInfo,
                    189:                                sizeof (FileStandardInfo),
                    190:                                FileStandardInformation);
                    191:                }
1.1       root      192: 
                    193:                if (!NT_SUCCESS (ntStatus))
                    194:                {
                    195:                        Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
1.1.1.4   root      196:                                ntStatus);
1.1       root      197:                        goto error;
                    198:                }
1.1.1.4   root      199: 
                    200:                lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
1.1       root      201: 
                    202:                if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
                    203:                {
                    204:                        Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
                    205:                        mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
                    206:                        ntStatus = STATUS_SUCCESS;
                    207:                        goto error;
                    208:                }
                    209: 
                    210:                ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
1.1.1.4   root      211:                        FILE_ALL_ACCESS,
                    212:                        *IoFileObjectType,
                    213:                        KernelMode,
                    214:                        &Extension->pfoDeviceFile,
                    215:                        0);
1.1       root      216: 
                    217:                if (!NT_SUCCESS (ntStatus))
                    218:                {
                    219:                        goto error;
                    220:                }
                    221: 
1.1.1.4   root      222:                /* Get the FSD device for the file (probably either NTFS or     FAT) */
1.1       root      223:                Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
                    224:        }
                    225: 
1.1.1.4   root      226:        // Check volume size
                    227:        if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
                    228:        {
                    229:                mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    230:                ntStatus = STATUS_SUCCESS;
                    231:                goto error;
                    232:        }
1.1.1.6   root      233: 
1.1.1.4   root      234:        Extension->DiskLength = lDiskLength.QuadPart;
1.1       root      235: 
1.1.1.6   root      236:        hiddenVolHeaderOffset.QuadPart = lDiskLength.QuadPart - HIDDEN_VOL_HEADER_OFFSET;
                    237: 
1.1.1.4   root      238:        readBuffer = TCalloc (HEADER_SIZE);
                    239:        if (readBuffer == NULL)
                    240:        {
                    241:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    242:                goto error;
                    243:        }
1.1       root      244: 
1.1.1.6   root      245:        // Go through all volume types (e.g., normal, hidden)
                    246:        for (volumeType = VOLUME_TYPE_NORMAL;
                    247:                volumeType < NBR_VOLUME_TYPES;
                    248:                volumeType++)   
1.1.1.4   root      249:        {
1.1.1.6   root      250:                /* Read the volume header */
1.1       root      251: 
1.1.1.6   root      252:                ntStatus = ZwReadFile (Extension->hDeviceFile,
                    253:                        NULL,
                    254:                        NULL,
                    255:                        NULL,
                    256:                        &IoStatusBlock,
                    257:                        readBuffer,
                    258:                        HEADER_SIZE,
                    259:                        volumeType == VOLUME_TYPE_HIDDEN ? &hiddenVolHeaderOffset : NULL,
                    260:                        NULL);
                    261: 
                    262:                if (!NT_SUCCESS (ntStatus))
1.1       root      263:                {
1.1.1.6   root      264:                        Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
                    265:                }
                    266:                else if (IoStatusBlock.Information != HEADER_SIZE)
                    267:                {
                    268:                        Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, HEADER_SIZE);
                    269:                        ntStatus = STATUS_UNSUCCESSFUL;
1.1       root      270:                }
                    271: 
1.1.1.6   root      272:                if (!NT_SUCCESS (ntStatus))
                    273:                {
                    274:                        goto error;
                    275:                }
1.1       root      276: 
1.1.1.6   root      277:                /* Attempt to recognize the volume (decrypt the header) */
1.1       root      278: 
1.1.1.6   root      279:                if (volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)
                    280:                {
                    281:                        mount->nReturnCode = VolumeReadHeaderCache (
                    282:                                mount->bCache,
                    283:                                readBuffer,
                    284:                                &mount->ProtectedHidVolPassword,
                    285:                                &tmpCryptoInfo);
                    286:                }
                    287:                else
                    288:                {
                    289:                        mount->nReturnCode = VolumeReadHeaderCache (
                    290:                                mount->bCache,
                    291:                                readBuffer,
                    292:                                &mount->VolumePassword,
                    293:                                &Extension->cryptoInfo);
                    294:                }
1.1.1.4   root      295: 
1.1.1.6   root      296:                if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)
                    297:                {
                    298:                        /* Volume header successfully decrypted */
1.1       root      299: 
1.1.1.6   root      300:                        Extension->cryptoInfo->bProtectHiddenVolume = FALSE;
                    301:                        Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE;
1.1       root      302: 
1.1.1.6   root      303:                        switch (volumeType)
                    304:                        {
                    305:                        case VOLUME_TYPE_NORMAL:
1.1       root      306: 
1.1.1.6   root      307:                                // Correct the volume size for this volume type. Later on, this must be undone
                    308:                                // if Extension->DiskLength is used in deriving hidden volume offset
                    309:                                Extension->DiskLength -= HEADER_SIZE;   
                    310:                                Extension->cryptoInfo->hiddenVolume = FALSE;
                    311: 
                    312:                                break;
                    313: 
                    314:                        case VOLUME_TYPE_HIDDEN:
                    315: 
                    316:                                cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo;
                    317: 
                    318:                                // Validate the size of the hidden volume specified in the header
                    319:                                if (Extension->DiskLength < (__int64) cryptoInfoPtr->hiddenVolumeSize + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE
                    320:                                        || cryptoInfoPtr->hiddenVolumeSize <= 0)
                    321:                                {
                    322:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    323:                                        ntStatus = STATUS_SUCCESS;
                    324:                                        goto error;
                    325:                                }
                    326: 
                    327:                                // Determine the offset of the hidden volume
                    328:                                Extension->cryptoInfo->hiddenVolumeOffset = Extension->DiskLength - cryptoInfoPtr->hiddenVolumeSize - HIDDEN_VOL_HEADER_OFFSET;
                    329: 
                    330:                                Dump("Hidden volume size = %I64d", cryptoInfoPtr->hiddenVolumeSize);
                    331:                                Dump("Hidden volume offset = %I64d", Extension->cryptoInfo->hiddenVolumeOffset);
                    332: 
                    333:                                // Validate the offset
1.1.1.12! root      334:                                if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0)
1.1.1.6   root      335:                                {
                    336:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    337:                                        ntStatus = STATUS_SUCCESS;
                    338:                                        goto error;
                    339:                                }
                    340: 
                    341:                                // If we are supposed to actually mount the hidden volume (not just to protect it)
                    342:                                if (!mount->bProtectHiddenVolume)       
                    343:                                {
                    344:                                        Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize;
                    345:                                        Extension->cryptoInfo->hiddenVolume = TRUE;
                    346:                                }
                    347:                                else
                    348:                                {
                    349:                                        // Hidden volume protection
                    350:                                        Extension->cryptoInfo->hiddenVolume = FALSE;
                    351:                                        Extension->cryptoInfo->bProtectHiddenVolume = TRUE;
                    352:                                        Extension->cryptoInfo->hiddenVolumeOffset += HEADER_SIZE;       // Offset was incorrect due to loop processing
                    353:                                        Dump("Hidden volume protection active (offset = %I64d)", Extension->cryptoInfo->hiddenVolumeOffset);
                    354:                                }
1.1.1.4   root      355: 
1.1.1.6   root      356:                                break;
                    357:                        }
1.1.1.4   root      358: 
1.1.1.6   root      359:                        // If this is a hidden volume, make sure we are supposed to actually
                    360:                        // mount it (i.e. not just to protect it)
                    361:                        if (!(volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)) 
1.1.1.4   root      362:                        {
1.1.1.6   root      363:                                // Calculate virtual volume geometry
                    364:                                Extension->TracksPerCylinder = 1;
                    365:                                Extension->SectorsPerTrack = 1;
1.1.1.10  root      366:                                Extension->BytesPerSector = SECTOR_SIZE;
                    367:                                Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE;
1.1.1.6   root      368:                                Extension->PartitionType = 0;
                    369: 
                    370:                                Extension->bRawDevice = bRawDevice;
1.1.1.7   root      371:                                
1.1.1.8   root      372:                                memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume));
1.1.1.7   root      373:                                if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume)
                    374:                                {
                    375:                                        /* UNC path */
                    376:                                        _snwprintf (Extension->wszVolume,
                    377:                                                sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1,
                    378:                                                WIDE ("\\??\\\\%s"),
                    379:                                                pwszMountVolume + 7);
                    380:                                }
1.1.1.6   root      381:                                else
                    382:                                {
1.1.1.7   root      383:                                        wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1);
1.1.1.6   root      384:                                }
1.1.1.4   root      385:                        }
                    386: 
1.1.1.6   root      387:                        // If we are to protect a hidden volume we cannot exit yet, for we must also
                    388:                        // decrypt the hidden volume header.
                    389:                        if (!(volumeType == VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
1.1.1.4   root      390:                        {
1.1.1.6   root      391:                                TCfree (readBuffer);
1.1.1.4   root      392: 
1.1.1.6   root      393:                                if (tmpCryptoInfo != NULL)
                    394:                                        crypto_close (tmpCryptoInfo);
                    395:                                
                    396:                                return STATUS_SUCCESS;
                    397:                        }
1.1.1.4   root      398:                }
1.1.1.6   root      399:                else if (mount->bProtectHiddenVolume
                    400:                          || mount->nReturnCode != ERR_PASSWORD_WRONG)
1.1.1.4   root      401:                {
1.1.1.6   root      402:                         /* If we are not supposed to protect a hidden volume, the only error that is
                    403:                                tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). 
1.1.1.4   root      404: 
1.1.1.6   root      405:                                If we _are_ supposed to protect a hidden volume, we do not tolerate any error
                    406:                                (both volume headers must be successfully decrypted). */
1.1       root      407: 
1.1.1.6   root      408:                        break;
1.1       root      409:                }
                    410:        }
                    411: 
                    412:        /* Failed due to some non-OS reason so we drop through and return NT
                    413:           SUCCESS then nReturnCode is checked later in user-mode */
                    414: 
                    415:        if (mount->nReturnCode == ERR_OUTOFMEMORY)
                    416:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    417:        else
                    418:                ntStatus = STATUS_SUCCESS;
                    419: 
1.1.1.4   root      420: error:
1.1.1.6   root      421:        if (Extension->bTimeStampValid)
1.1.1.4   root      422:        {
                    423:                /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    424:                RestoreTimeStamp (Extension);
                    425:        }
1.1       root      426: 
                    427:        /* Close the hDeviceFile */
                    428:        if (Extension->hDeviceFile != NULL)
                    429:                ZwClose (Extension->hDeviceFile);
                    430: 
                    431:        /* The cryptoInfo pointer is deallocated if the readheader routines
                    432:           fail so there is no need to deallocate here  */
                    433: 
                    434:        /* Dereference the user-mode file object */
                    435:        if (Extension->pfoDeviceFile != NULL)
                    436:                ObDereferenceObject (Extension->pfoDeviceFile);
                    437: 
1.1.1.4   root      438:        /* Free the tmp IO buffers */
1.1       root      439:        if (readBuffer != NULL)
                    440:                TCfree (readBuffer);
                    441: 
                    442:        return ntStatus;
                    443: }
                    444: 
                    445: void
                    446: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
                    447: {
                    448:        if (DeviceObject);      /* Remove compiler warning */
                    449: 
                    450:        if (Extension->hDeviceFile != NULL)
1.1.1.4   root      451:        {
1.1.1.6   root      452:                if (Extension->bRawDevice == FALSE
                    453:                        && Extension->bTimeStampValid)
1.1.1.4   root      454:                {
                    455:                        /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    456:                        RestoreTimeStamp (Extension);
                    457:                }
1.1.1.6   root      458:                ZwClose (Extension->hDeviceFile);
1.1.1.4   root      459:        }
1.1       root      460:        ObDereferenceObject (Extension->pfoDeviceFile);
                    461:        crypto_close (Extension->cryptoInfo);
                    462: }
                    463: 
                    464: 
                    465: NTSTATUS
1.1.1.12! root      466: TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
1.1       root      467:                               PEXTENSION Extension,
                    468:                               ULONG IoControlCode,
                    469:                               char *OutputBuffer,
                    470:                               int OutputBufferSize)
                    471: {
                    472:        IO_STATUS_BLOCK IoStatusBlock;
                    473:        NTSTATUS ntStatus;
                    474:        PIRP Irp;
                    475: 
                    476:        if (DeviceObject);      /* Remove compiler warning */
                    477: 
                    478:        KeClearEvent (&Extension->keVolumeEvent);
                    479: 
                    480:        Irp = IoBuildDeviceIoControlRequest (IoControlCode,
                    481:                                             Extension->pFsdDevice,
                    482:                                             NULL, 0,
                    483:                                             OutputBuffer, OutputBufferSize,
                    484:                                             FALSE,
                    485:                                             &Extension->keVolumeEvent,
                    486:                                             &IoStatusBlock);
                    487: 
                    488:        if (Irp == NULL)
                    489:        {
                    490:                Dump ("IRP allocation failed\n");
                    491:                return STATUS_INSUFFICIENT_RESOURCES;
                    492:        }
                    493: 
1.1.1.5   root      494:        // Disk device may be used by filesystem driver which needs file object
                    495:        IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
                    496: 
1.1       root      497:        ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
                    498:        if (ntStatus == STATUS_PENDING)
                    499:        {
1.1.1.12! root      500:                KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL);
1.1       root      501:                ntStatus = IoStatusBlock.Status;
                    502:        }
                    503: 
                    504:        return ntStatus;
                    505: }
                    506: 
                    507: NTSTATUS
                    508: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
                    509:              PIRP Irp,
                    510:              NTSTATUS IrpStatus,
1.1.1.4   root      511:              ULONG_PTR IrpInformation)
1.1       root      512: {
                    513:        Irp->IoStatus.Status = IrpStatus;
                    514:        Irp->IoStatus.Information = IrpInformation;
                    515: 
                    516:        if (DeviceObject);      /* Remove compiler warning */
                    517: 
1.1.1.10  root      518: #if EXTRA_INFO
                    519:        if (!NT_SUCCESS (IrpStatus))
                    520:        {
                    521:                PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    522:                Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    523:                      (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    524:        }
                    525:        else
                    526:        {
                    527:                PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    528:                Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    529:                      (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    530:        }
1.1       root      531: #endif
                    532:        IoCompleteRequest (Irp, IO_NO_INCREMENT);
                    533:        return IrpStatus;
                    534: }
1.1.1.4   root      535: 
                    536: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
                    537: static void RestoreTimeStamp (PEXTENSION Extension)
                    538: {
                    539:        NTSTATUS ntStatus;
                    540:        FILE_BASIC_INFORMATION FileBasicInfo;
                    541:        IO_STATUS_BLOCK IoStatusBlock;
                    542: 
1.1.1.6   root      543:        if (Extension->hDeviceFile != NULL 
                    544:                && Extension->bRawDevice == FALSE 
                    545:                && Extension->bReadOnly == FALSE
                    546:                && Extension->bTimeStampValid)
1.1.1.4   root      547:        {
                    548:                ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
                    549:                        &IoStatusBlock,
                    550:                        &FileBasicInfo,
                    551:                        sizeof (FileBasicInfo),
                    552:                        FileBasicInformation); 
                    553: 
                    554:                if (!NT_SUCCESS (ntStatus))
                    555:                {
                    556:                        Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
                    557:                                ntStatus);
                    558:                }
                    559:                else
                    560:                {
                    561:                        FileBasicInfo.CreationTime = Extension->fileCreationTime;
                    562:                        FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
                    563:                        FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
                    564:                        FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
                    565: 
                    566:                        ntStatus = ZwSetInformationFile(
                    567:                                Extension->hDeviceFile,
                    568:                                &IoStatusBlock,
                    569:                                &FileBasicInfo,
                    570:                                sizeof (FileBasicInfo),
                    571:                                FileBasicInformation); 
                    572: 
                    573:                        if (!NT_SUCCESS (ntStatus))
                    574:                                Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
                    575:                }
                    576:        }
                    577: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.