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

1.1.1.6 ! root        1: /* Legal Notice: The source code contained in this file has been derived from
        !             2:    the source code of Encryption for the Masses 2.02a, which is Copyright (c)
        !             3:    1998-99 Paul Le Roux and which is covered by the 'License Agreement for
        !             4:    Encryption for the Masses'. Modifications and additions to that source code
        !             5:    contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and
        !             6:    Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0
        !             7:    the full text of which is contained in the file License.txt included in
        !             8:    TrueCrypt binary and source code distribution archives.  */
1.1       root        9: 
                     10: #include "TCdefs.h"
1.1.1.6 ! root       11: #include "Crypto.h"
        !            12: #include "Volumes.h"
1.1       root       13: 
1.1.1.6 ! root       14: #include "Apidrvr.h"
        !            15: #include "Ntdriver.h"
        !            16: #include "Ntvol.h"
        !            17: #include "Ntrawdv.h"
        !            18: #include "Ntfiledv.h"
1.1       root       19: 
1.1.1.6 ! root       20: #include "Cache.h"
1.1       root       21: 
                     22: //#ifdef _DEBUG
                     23: //#define EXTRA_INFO 1
                     24: //#endif
                     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.4   root       60:                DISK_GEOMETRY dg;
1.1       root       61: 
1.1.1.4   root       62:                ntStatus = IoGetDeviceObjectPointer (&FullFileName,
                     63:                        FILE_READ_DATA,
                     64:                        &Extension->pfoDeviceFile,
                     65:                        &Extension->pFsdDevice);
                     66: 
                     67:                if (!NT_SUCCESS (ntStatus))
                     68:                {
                     69:                        goto error;
                     70:                }
                     71: 
                     72:                DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
                     73: 
1.1.1.5   root       74:                // Query partition size
1.1.1.4   root       75:                ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
1.1.1.5   root       76:                        Extension, IOCTL_DISK_GET_PARTITION_INFO,
                     77:                        (char *) &pi, sizeof (pi));
1.1.1.4   root       78: 
1.1.1.5   root       79:                if (NT_SUCCESS (ntStatus))
1.1.1.4   root       80:                {
1.1.1.5   root       81:                        lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
1.1.1.4   root       82:                }
1.1.1.5   root       83:                else
1.1.1.4   root       84:                {
1.1.1.5   root       85:                        // Drive geometry info is used only when IOCTL_DISK_GET_PARTITION_INFO fails
1.1.1.4   root       86:                        ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
1.1.1.5   root       87:                                Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY,
                     88:                                (char *) &dg, sizeof (dg));
1.1.1.4   root       89: 
                     90:                        if (!NT_SUCCESS (ntStatus))
                     91:                                goto error;
1.1       root       92: 
1.1.1.4   root       93:                        lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack *
                     94:                                dg.TracksPerCylinder * dg.BytesPerSector;
                     95:                }
                     96:        }
1.1       root       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,
                    110:                        FILE_WRITE_THROUGH |
                    111:                        FILE_NO_INTERMEDIATE_BUFFERING |
                    112:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    113:                        NULL,
                    114:                        0);
                    115:        }
1.1       root      116: 
                    117:        /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4   root      118:        access denied */
1.1       root      119:        if (ntStatus == 0xc000001b)
                    120:        {
                    121:                ntStatus = STATUS_ACCESS_DENIED;
                    122:        }
1.1.1.6 ! root      123:        
1.1.1.4   root      124:        if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
1.1       root      125:        {
                    126:                ntStatus = ZwCreateFile (&Extension->hDeviceFile,
1.1.1.4   root      127:                        GENERIC_READ | SYNCHRONIZE,
                    128:                        &oaFileAttributes,
                    129:                        &IoStatusBlock,
                    130:                        NULL,
                    131:                        FILE_ATTRIBUTE_NORMAL |
                    132:                        FILE_ATTRIBUTE_SYSTEM,
                    133:                        mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
                    134:                        FILE_OPEN,
                    135:                        FILE_WRITE_THROUGH |
                    136:                        FILE_NO_INTERMEDIATE_BUFFERING |
                    137:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    138:                        NULL,
                    139:                        0);
1.1       root      140:                Extension->bReadOnly = TRUE;
                    141:        }
                    142:        else
                    143:                Extension->bReadOnly = FALSE;
                    144: 
                    145:        /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4   root      146:        access denied */
1.1       root      147:        if (ntStatus == 0xc000001b)
                    148:        {
                    149:                /* Partitions which return this code can still be opened with
1.1.1.4   root      150:                FILE_SHARE_READ but this causes NT problems elsewhere in
                    151:                particular if you do FILE_SHARE_READ NT will die later if
                    152:                anyone even tries to open the partition  (or file for that
                    153:                matter...)  */
1.1       root      154:                ntStatus = STATUS_SHARING_VIOLATION;
                    155:        }
                    156: 
                    157:        if (!NT_SUCCESS (ntStatus))
                    158:        {
                    159:                goto error;
                    160:        }
                    161: 
1.1.1.4   root      162:        // If we have opened a file, query its size now
1.1       root      163:        if (bRawDevice == FALSE)
                    164:        {
                    165:                ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4   root      166:                        &IoStatusBlock,
                    167:                        &FileBasicInfo,
                    168:                        sizeof (FileBasicInfo),
                    169:                        FileBasicInformation);
1.1       root      170: 
                    171:                if (NT_SUCCESS (ntStatus))
1.1.1.4   root      172:                {
1.1.1.6 ! root      173:                        if (mount->bPreserveTimestamp)
        !           174:                        {
        !           175:                                /* Remember the container timestamp. (Used to reset access/modification file date/time
        !           176:                                of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve
        !           177:                                plausible deniability of hidden volumes.) */
        !           178:                                Extension->fileCreationTime = FileBasicInfo.CreationTime;
        !           179:                                Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
        !           180:                                Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
        !           181:                                Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
        !           182:                                Extension->bTimeStampValid = TRUE;
        !           183:                        }
1.1.1.4   root      184: 
1.1       root      185:                        ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4   root      186:                                &IoStatusBlock,
                    187:                                &FileStandardInfo,
                    188:                                sizeof (FileStandardInfo),
                    189:                                FileStandardInformation);
                    190:                }
1.1       root      191: 
                    192:                if (!NT_SUCCESS (ntStatus))
                    193:                {
                    194:                        Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
1.1.1.4   root      195:                                ntStatus);
1.1       root      196:                        goto error;
                    197:                }
1.1.1.4   root      198: 
                    199:                lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
1.1       root      200: 
                    201:                if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
                    202:                {
                    203:                        Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
                    204:                        mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
                    205:                        ntStatus = STATUS_SUCCESS;
                    206:                        goto error;
                    207:                }
                    208: 
                    209:                ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
1.1.1.4   root      210:                        FILE_ALL_ACCESS,
                    211:                        *IoFileObjectType,
                    212:                        KernelMode,
                    213:                        &Extension->pfoDeviceFile,
                    214:                        0);
1.1       root      215: 
                    216:                if (!NT_SUCCESS (ntStatus))
                    217:                {
                    218:                        goto error;
                    219:                }
                    220: 
1.1.1.4   root      221:                /* Get the FSD device for the file (probably either NTFS or     FAT) */
1.1       root      222:                Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
                    223: 
                    224:                DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
                    225:        }
                    226: 
1.1.1.4   root      227:        // Check volume size
                    228:        if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
                    229:        {
                    230:                mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    231:                ntStatus = STATUS_SUCCESS;
                    232:                goto error;
                    233:        }
1.1.1.6 ! root      234: 
1.1.1.4   root      235:        Extension->DiskLength = lDiskLength.QuadPart;
1.1       root      236: 
1.1.1.6 ! root      237:        hiddenVolHeaderOffset.QuadPart = lDiskLength.QuadPart - HIDDEN_VOL_HEADER_OFFSET;
        !           238: 
1.1.1.4   root      239:        readBuffer = TCalloc (HEADER_SIZE);
                    240:        if (readBuffer == NULL)
                    241:        {
                    242:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    243:                goto error;
                    244:        }
1.1       root      245: 
1.1.1.6 ! root      246:        // Go through all volume types (e.g., normal, hidden)
        !           247:        for (volumeType = VOLUME_TYPE_NORMAL;
        !           248:                volumeType < NBR_VOLUME_TYPES;
        !           249:                volumeType++)   
1.1.1.4   root      250:        {
1.1.1.6 ! root      251:                /* Read the volume header */
1.1       root      252: 
1.1.1.6 ! root      253:                ntStatus = ZwReadFile (Extension->hDeviceFile,
        !           254:                        NULL,
        !           255:                        NULL,
        !           256:                        NULL,
        !           257:                        &IoStatusBlock,
        !           258:                        readBuffer,
        !           259:                        HEADER_SIZE,
        !           260:                        volumeType == VOLUME_TYPE_HIDDEN ? &hiddenVolHeaderOffset : NULL,
        !           261:                        NULL);
        !           262: 
        !           263:                if (!NT_SUCCESS (ntStatus))
1.1       root      264:                {
1.1.1.6 ! root      265:                        Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
        !           266:                }
        !           267:                else if (IoStatusBlock.Information != HEADER_SIZE)
        !           268:                {
        !           269:                        Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, HEADER_SIZE);
        !           270:                        ntStatus = STATUS_UNSUCCESSFUL;
1.1       root      271:                }
                    272: 
1.1.1.6 ! root      273:                if (!NT_SUCCESS (ntStatus))
        !           274:                {
        !           275:                        goto error;
        !           276:                }
1.1       root      277: 
1.1.1.6 ! root      278:                /* Attempt to recognize the volume (decrypt the header) */
1.1       root      279: 
1.1.1.6 ! root      280:                if (volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)
        !           281:                {
        !           282:                        mount->nReturnCode = VolumeReadHeaderCache (
        !           283:                                mount->bCache,
        !           284:                                readBuffer,
        !           285:                                &mount->ProtectedHidVolPassword,
        !           286:                                &tmpCryptoInfo);
        !           287:                }
        !           288:                else
        !           289:                {
        !           290:                        mount->nReturnCode = VolumeReadHeaderCache (
        !           291:                                mount->bCache,
        !           292:                                readBuffer,
        !           293:                                &mount->VolumePassword,
        !           294:                                &Extension->cryptoInfo);
        !           295:                }
1.1.1.4   root      296: 
1.1.1.6 ! root      297:                if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)
        !           298:                {
        !           299:                        /* Volume header successfully decrypted */
1.1       root      300: 
1.1.1.6 ! root      301:                        Extension->cryptoInfo->bProtectHiddenVolume = FALSE;
        !           302:                        Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE;
1.1       root      303: 
1.1.1.6 ! root      304:                        switch (volumeType)
        !           305:                        {
        !           306:                        case VOLUME_TYPE_NORMAL:
1.1       root      307: 
1.1.1.6 ! root      308:                                // Correct the volume size for this volume type. Later on, this must be undone
        !           309:                                // if Extension->DiskLength is used in deriving hidden volume offset
        !           310:                                Extension->DiskLength -= HEADER_SIZE;   
        !           311:                                Extension->cryptoInfo->hiddenVolume = FALSE;
        !           312: 
        !           313:                                break;
        !           314: 
        !           315:                        case VOLUME_TYPE_HIDDEN:
        !           316: 
        !           317:                                cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo;
        !           318: 
        !           319:                                // Validate the size of the hidden volume specified in the header
        !           320:                                if (Extension->DiskLength < (__int64) cryptoInfoPtr->hiddenVolumeSize + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE
        !           321:                                        || cryptoInfoPtr->hiddenVolumeSize <= 0)
        !           322:                                {
        !           323:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
        !           324:                                        ntStatus = STATUS_SUCCESS;
        !           325:                                        goto error;
        !           326:                                }
        !           327: 
        !           328:                                // Determine the offset of the hidden volume
        !           329:                                Extension->cryptoInfo->hiddenVolumeOffset = Extension->DiskLength - cryptoInfoPtr->hiddenVolumeSize - HIDDEN_VOL_HEADER_OFFSET;
        !           330: 
        !           331:                                Dump("Hidden volume size = %I64d", cryptoInfoPtr->hiddenVolumeSize);
        !           332:                                Dump("Hidden volume offset = %I64d", Extension->cryptoInfo->hiddenVolumeOffset);
        !           333: 
        !           334:                                // Validate the offset
        !           335:                                if (Extension->cryptoInfo->hiddenVolumeOffset % SECTOR_SIZE != 0)
        !           336:                                {
        !           337:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
        !           338:                                        ntStatus = STATUS_SUCCESS;
        !           339:                                        goto error;
        !           340:                                }
        !           341: 
        !           342:                                // If we are supposed to actually mount the hidden volume (not just to protect it)
        !           343:                                if (!mount->bProtectHiddenVolume)       
        !           344:                                {
        !           345:                                        Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize;
        !           346:                                        Extension->cryptoInfo->hiddenVolume = TRUE;
        !           347:                                }
        !           348:                                else
        !           349:                                {
        !           350:                                        // Hidden volume protection
        !           351:                                        Extension->cryptoInfo->hiddenVolume = FALSE;
        !           352:                                        Extension->cryptoInfo->bProtectHiddenVolume = TRUE;
        !           353:                                        Extension->cryptoInfo->hiddenVolumeOffset += HEADER_SIZE;       // Offset was incorrect due to loop processing
        !           354:                                        Dump("Hidden volume protection active (offset = %I64d)", Extension->cryptoInfo->hiddenVolumeOffset);
        !           355:                                }
1.1.1.4   root      356: 
1.1.1.6 ! root      357:                                break;
        !           358:                        }
1.1.1.4   root      359: 
1.1.1.6 ! root      360:                        // If this is a hidden volume, make sure we are supposed to actually
        !           361:                        // mount it (i.e. not just to protect it)
        !           362:                        if (!(volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)) 
1.1.1.4   root      363:                        {
1.1.1.6 ! root      364:                                // Calculate virtual volume geometry
        !           365:                                Extension->TracksPerCylinder = 1;
        !           366:                                Extension->SectorsPerTrack = 1;
        !           367:                                Extension->BytesPerSector = 512;
        !           368:                                Extension->NumberOfCylinders = Extension->DiskLength / 512;
        !           369:                                Extension->PartitionType = 0;
        !           370: 
        !           371:                                Extension->bRawDevice = bRawDevice;
        !           372: 
        !           373:                                if (wcslen (pwszMountVolume) < 64)
        !           374:                                        wcscpy (Extension->wszVolume, pwszMountVolume);
        !           375:                                else
        !           376:                                {
        !           377:                                        memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2);
        !           378:                                        Extension->wszVolume[60] = (WCHAR) '.';
        !           379:                                        Extension->wszVolume[61] = (WCHAR) '.';
        !           380:                                        Extension->wszVolume[62] = (WCHAR) '.';
        !           381:                                        Extension->wszVolume[63] = (WCHAR) 0;
        !           382:                                }
1.1.1.4   root      383:                        }
                    384: 
1.1.1.6 ! root      385:                        // If we are to protect a hidden volume we cannot exit yet, for we must also
        !           386:                        // decrypt the hidden volume header.
        !           387:                        if (!(volumeType == VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
1.1.1.4   root      388:                        {
1.1.1.6 ! root      389:                                TCfree (readBuffer);
1.1.1.4   root      390: 
1.1.1.6 ! root      391:                                if (tmpCryptoInfo != NULL)
        !           392:                                        crypto_close (tmpCryptoInfo);
        !           393:                                
        !           394:                                return STATUS_SUCCESS;
        !           395:                        }
1.1.1.4   root      396:                }
1.1.1.6 ! root      397:                else if (mount->bProtectHiddenVolume
        !           398:                          || mount->nReturnCode != ERR_PASSWORD_WRONG)
1.1.1.4   root      399:                {
1.1.1.6 ! root      400:                         /* If we are not supposed to protect a hidden volume, the only error that is
        !           401:                                tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). 
1.1.1.4   root      402: 
1.1.1.6 ! root      403:                                If we _are_ supposed to protect a hidden volume, we do not tolerate any error
        !           404:                                (both volume headers must be successfully decrypted). */
1.1       root      405: 
1.1.1.6 ! root      406:                        break;
1.1       root      407:                }
                    408:        }
                    409: 
                    410:        /* Failed due to some non-OS reason so we drop through and return NT
                    411:           SUCCESS then nReturnCode is checked later in user-mode */
                    412: 
                    413:        if (mount->nReturnCode == ERR_OUTOFMEMORY)
                    414:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    415:        else
                    416:                ntStatus = STATUS_SUCCESS;
                    417: 
1.1.1.4   root      418: error:
1.1.1.6 ! root      419:        if (Extension->bTimeStampValid)
1.1.1.4   root      420:        {
                    421:                /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    422:                RestoreTimeStamp (Extension);
                    423:        }
1.1       root      424: 
                    425:        /* Close the hDeviceFile */
                    426:        if (Extension->hDeviceFile != NULL)
                    427:                ZwClose (Extension->hDeviceFile);
                    428: 
                    429:        /* The cryptoInfo pointer is deallocated if the readheader routines
                    430:           fail so there is no need to deallocate here  */
                    431: 
                    432:        /* Dereference the user-mode file object */
                    433:        if (Extension->pfoDeviceFile != NULL)
                    434:                ObDereferenceObject (Extension->pfoDeviceFile);
                    435: 
1.1.1.4   root      436:        /* Free the tmp IO buffers */
1.1       root      437:        if (readBuffer != NULL)
                    438:                TCfree (readBuffer);
                    439: 
                    440:        return ntStatus;
                    441: }
                    442: 
                    443: void
                    444: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
                    445: {
                    446:        if (DeviceObject);      /* Remove compiler warning */
                    447: 
                    448:        if (Extension->hDeviceFile != NULL)
1.1.1.4   root      449:        {
1.1.1.6 ! root      450:                if (Extension->bRawDevice == FALSE
        !           451:                        && Extension->bTimeStampValid)
1.1.1.4   root      452:                {
                    453:                        /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    454:                        RestoreTimeStamp (Extension);
                    455:                }
1.1.1.6 ! root      456:                ZwClose (Extension->hDeviceFile);
1.1.1.4   root      457:        }
1.1       root      458:        ObDereferenceObject (Extension->pfoDeviceFile);
                    459:        crypto_close (Extension->cryptoInfo);
                    460: }
                    461: 
                    462: /* This rountine can be called at any IRQL so we need to tread carefully. Not
                    463:    even DbgPrint or KdPrint are called here as the kernel sometimes faults if
                    464:    they are called at high IRQL */
                    465: 
                    466: NTSTATUS
                    467: TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer)
                    468: {
                    469:        PIO_STACK_LOCATION irpSp;
                    470:        PEXTENSION Extension;
                    471:        NTSTATUS ntStatus;
                    472: 
                    473:        Extension = (PEXTENSION) DeviceObject->DeviceExtension;
                    474: 
                    475:        /* Check to make sure the DeviceObject passed in is actually ours! */
                    476:        if (Extension->lMagicNumber != 0xabfeacde)
                    477:                KeBugCheck ((ULONG) 0xabfeacde);
                    478: 
                    479:        ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19);
                    480: 
                    481: #ifdef USE_KERNEL_MUTEX
                    482:        KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode,
                    483:                              FALSE, NULL);
                    484: #endif
                    485: 
                    486: #if EXTRA_INFO
                    487:        Dump ("Completing IRP...BEGIN\n");
                    488:        Dump ("COMPLETION USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
                    489:        Dump ("COMPLETION Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
                    490:        Dump ("Completing DeviceObject 0x%08x Irp 0x%08x\n", DeviceObject, Irp);
                    491: #endif
                    492: 
                    493:        /* Note: The Irp stack location we get back here is our one, we setup
                    494:           the next stack location with a copy of this stack data in the send
                    495:           function... here we always get back our own stack location, so
                    496:           it's possible to use Read.Key to store extra pointers if needed. */
                    497:        irpSp = IoGetCurrentIrpStackLocation (Irp);
                    498: 
                    499:        ntStatus = Irp->IoStatus.Status;
                    500: 
                    501:        if (ntStatus == STATUS_TOO_LATE)
                    502:                KeBugCheck ((ULONG) 0x50ff);
                    503: 
                    504:        if (Irp->PendingReturned)       /* From Windows NT File System
                    505:                                           Internals */
                    506:                IoMarkIrpPending (Irp);
                    507: 
                    508:        if (Extension->bRawDevice == FALSE)
                    509:        {
                    510:                /* Note: For some reason even though we used DIRECT_IO
                    511:                   sometimes the Irp's come back to use with MDLs !! if we
                    512:                   get an MDL here we need to free it up otherwise later when
                    513:                   we call IoFreeIrp the system will trap */
                    514: 
                    515:                PMDL pMdl, pNextMdl;
                    516: 
                    517:                pMdl = Irp->MdlAddress;
                    518: 
                    519:                while (pMdl != NULL)
                    520:                {
                    521:                        pNextMdl = pMdl->Next;
                    522: 
                    523:                        MmUnmapLockedPages (MmGetSystemAddressForMdlSafe (pMdl, HighPagePriority), pMdl);
                    524:                        MmUnlockPages (pMdl);
                    525:                        IoFreeMdl (pMdl);
                    526: 
                    527:                        pMdl = pNextMdl;
                    528:                }
                    529:        }
                    530: 
                    531:        if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_READ)
                    532:        {
                    533:                __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
                    534:                ULONG tmpLength = irpSp->Parameters.Read.Length;
                    535:                PUCHAR CurrentAddress;
                    536: 
1.1.1.6 ! root      537:                if (Extension->bRawDevice)
1.1       root      538:                        CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
                    539:                else
                    540:                        CurrentAddress = Irp->UserBuffer;
                    541: 
                    542:                if (tmpLength > 0)
                    543:                {
                    544:                        /* Decrypt the data on read */
1.1.1.4   root      545:                        DecryptSectors ((ULONG *) CurrentAddress,
1.1       root      546:                                tmpOffset / SECTOR_SIZE,
                    547:                                tmpLength / SECTOR_SIZE,
1.1.1.4   root      548:                                Extension->cryptoInfo->ks,
1.1       root      549:                                Extension->cryptoInfo->iv,
1.1.1.4   root      550:                                Extension->cryptoInfo->ea);
1.1       root      551:                }
                    552: 
                    553:                if (Extension->bRawDevice == FALSE)
                    554:                {
                    555:                        PIRP OldIrp = (PIRP) pUserBuffer;
                    556:                        PUCHAR OriginalAddress;
                    557:                        CurrentAddress = Irp->UserBuffer;
                    558:                        OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
                    559:                        memcpy (OriginalAddress, CurrentAddress, Irp->IoStatus.Information);
                    560:                }
                    561: 
                    562:        }
                    563: 
                    564:        if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_WRITE)
                    565:        {
                    566:                PUCHAR CurrentAddress;
                    567:                PUCHAR OriginalAddress;
                    568: 
1.1.1.6 ! root      569:                if (Extension->bRawDevice)
1.1       root      570:                {
                    571:                        CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
                    572:                        OriginalAddress = MmGetSystemAddressForMdlSafe ((PMDL) pUserBuffer, HighPagePriority);
                    573:                }
                    574:                else
                    575:                {
                    576:                        PIRP OldIrp = (PIRP) pUserBuffer;
                    577:                        CurrentAddress = Irp->UserBuffer;
                    578:                        OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
                    579:                }
                    580:        }
                    581: 
1.1.1.6 ! root      582:        if (Extension->bRawDevice && irpSp->MajorFunction == IRP_MJ_WRITE)
1.1       root      583:        {
                    584:                PUCHAR tmpBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
                    585:                /* Free the temp buffer we allocated */
                    586:                TCfree (tmpBuffer);
                    587:                /* Free the Mdl we allocated */
                    588:                IoFreeMdl (Irp->MdlAddress);
                    589:                /* Reset the Irp */
                    590:                Irp->MdlAddress = pUserBuffer;
                    591:        }
                    592: 
1.1.1.6 ! root      593:        if (Extension->bRawDevice && irpSp->MajorFunction == IRP_MJ_READ)
1.1       root      594:        {
                    595:                /* Nothing to do */
                    596:        }
                    597: 
                    598: #if EXTRA_INFO
                    599:        Dump ("COMPLETION OLD USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
                    600:        Dump ("COMPLETION OLD Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
                    601:        Dump ("Completing IRP 0x%08x NTSTATUS 0x%08x information %lu END\n", (ULONG) irpSp->MajorFunction,
                    602:              Irp->IoStatus.Status, Irp->IoStatus.Information);
                    603: #endif
                    604: 
                    605:        if (Extension->bRawDevice == FALSE)
                    606:        {
                    607:                PIRP OldIrp = (PIRP) pUserBuffer;
                    608:                PVOID tmpBuffer = Irp->UserBuffer;
                    609:                BOOL bFreeBuffer = irpSp->MajorFunction == IRP_MJ_WRITE || irpSp->MajorFunction == IRP_MJ_READ;
                    610: 
                    611:                OldIrp->IoStatus.Status = Irp->IoStatus.Status;
                    612:                OldIrp->IoStatus.Information = Irp->IoStatus.Information;
                    613: 
                    614:                IoCompleteRequest (OldIrp, IO_DISK_INCREMENT);
                    615: 
                    616: #if EXTRA_INFO
                    617:                Dump ("About to free allocated IRP\n");
                    618: #endif
                    619: 
                    620:                Irp->UserBuffer = NULL;
                    621: 
                    622:                /* Free the allocated IRP. Note: This must be done before we
                    623:                   free tmpBuffer! */
                    624:                IoFreeIrp (Irp);
                    625: 
                    626:                /* Note: From here on we cannot touch the Irp or irpSp */
                    627: 
                    628: #if EXTRA_INFO
                    629:                Dump ("Free allocated buffer = %d\n", bFreeBuffer);
                    630: #endif
                    631: 
1.1.1.6 ! root      632:                if (bFreeBuffer)
1.1       root      633:                        TCfree (tmpBuffer);
                    634: 
                    635:                ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
                    636:        }
                    637: 
                    638: #ifdef USE_KERNEL_MUTEX
                    639:        KeReleaseMutex (&Extension->KernelMutex, FALSE);
                    640: #endif
                    641: 
                    642:        return ntStatus;
                    643: }
                    644: 
                    645: NTSTATUS
                    646: TCReadWrite (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
                    647: {
                    648:        PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    649:        PUCHAR tmpBuffer = NULL;/* Remove compiler warning */
                    650:        NTSTATUS ntStatus;
                    651: 
                    652: //     Dump ("TCReadWrite BEGIN\n");
                    653: 
                    654:        /* Check for invalid parameters.  It is an error for the starting
                    655:           offset + length to go past the end of the buffer, or for the
                    656:           length to not be a proper multiple of the sector size. Others are
                    657:           possible, but we don't check them since we trust the file system
                    658:           and they aren't deadly.  */
                    659:        if (irpSp->Parameters.Read.ByteOffset.QuadPart + irpSp->Parameters.Read.Length > Extension->DiskLength
                    660:                || (irpSp->Parameters.Read.Length & (Extension->BytesPerSector - 1)))
                    661:        {
                    662:                return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
                    663:        }
                    664:        else
                    665:        {
                    666:                if (irpSp->Parameters.Read.Length == 0)
                    667:                {
                    668:                        return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
                    669:                }
                    670:        }
                    671: 
                    672: #if EXTRA_INFO
                    673:        Dump ("USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
                    674:        Dump ("Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
                    675:        Dump ("irpSp->FileObject = 0x%08x\n", irpSp->FileObject);
                    676: 
                    677:        if (Irp->Tail.Overlay.OriginalFileObject != NULL)
                    678:        {
                    679:                if (Irp->Tail.Overlay.OriginalFileObject->FileName.Length != 0)
                    680:                        Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", Irp->Tail.Overlay.OriginalFileObject->FileName.Buffer);
                    681:                else
                    682:                        Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", WIDE ("null value"));
                    683: 
                    684:        }
                    685: 
                    686:        if (irpSp->FileObject != NULL)
                    687:        {
                    688:                if (irpSp->FileObject->FileName.Length != 0)
                    689:                        Dump ("irpSp->FileObject = %ls\n", irpSp->FileObject->FileName.Buffer);
                    690:                else
                    691:                        Dump ("irpSp->FileObject = %ls\n", WIDE ("null value"));
                    692: 
                    693:        }
                    694: #endif
                    695: 
1.1.1.6 ! root      696:        // Volume protection
        !           697:        if (irpSp->MajorFunction == IRP_MJ_WRITE)
        !           698:        {
        !           699:                // Read-only mode
        !           700:                if (Extension->bReadOnly)
        !           701:                        return COMPLETE_IRP (DeviceObject, Irp, STATUS_MEDIA_WRITE_PROTECTED, 0);
        !           702: 
        !           703:                // Hidden volume protection
        !           704:                if (Extension->cryptoInfo->bProtectHiddenVolume)
        !           705:                {
        !           706:                        // If there has already been a write operation denied in order to protect the
        !           707:                        // hidden volume (since the volume mount time)
        !           708:                        if (Extension->cryptoInfo->bHiddenVolProtectionAction)  
        !           709:                        {
        !           710:                                Dump("Write operation denied due to a previous hidden volume protection action");
        !           711: 
        !           712:                                // Do not allow writing to this volume anymore. This is to fake a complete volume
        !           713:                                // or system failure (otherwise certain kinds of inconsistency within the file
        !           714:                                // system could indicate that this volume has used hidden volume protection).
        !           715:                                return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
        !           716:                        }
        !           717: 
        !           718:                        // Verify that no byte is going to be written to the hidden volume area
        !           719:                        if (RegionsOverlap ((unsigned __int64) irpSp->Parameters.Read.ByteOffset.QuadPart + HEADER_SIZE,
        !           720:                                                                (unsigned __int64) irpSp->Parameters.Read.ByteOffset.QuadPart + HEADER_SIZE + irpSp->Parameters.Read.Length - 1,
        !           721:                                                                Extension->cryptoInfo->hiddenVolumeOffset,
        !           722:                                                                (unsigned __int64) Extension->DiskLength + HEADER_SIZE - (HIDDEN_VOL_HEADER_OFFSET - HEADER_SIZE) - 1))
        !           723:                        {
        !           724:                                Extension->cryptoInfo->bHiddenVolProtectionAction = TRUE;
        !           725:                                Dump("Write operation denied (offset = %I64d) to protect hidden volume", irpSp->Parameters.Read.ByteOffset.QuadPart);
        !           726: 
        !           727:                                // Deny this write operation to prevent the hidden volume from being overwritten
        !           728:                                return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
        !           729:                        }
        !           730: 
        !           731:                }
        !           732:        }
1.1       root      733: 
                    734:        if (Extension->bRawDevice == FALSE || irpSp->MajorFunction == IRP_MJ_WRITE)
                    735:        {
                    736:                tmpBuffer = TCalloc (irpSp->Parameters.Read.Length);
                    737:                if (tmpBuffer == NULL)
                    738:                        return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
                    739:        }
                    740: 
                    741:        if (irpSp->MajorFunction == IRP_MJ_READ)
                    742:        {
                    743: //             Dump ("Read: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
                    744: //                   irpSp->Parameters.Read.Length);
                    745: 
1.1.1.6 ! root      746:                Extension->TotalBytesRead += irpSp->Parameters.Read.Length;
1.1.1.4   root      747: 
                    748:                if (Extension->cryptoInfo->hiddenVolume)
                    749:                {
                    750:                        /* Hidden volume offset */
                    751:                        irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
                    752:                }
                    753:                else
                    754:                {
                    755:                        /* Fixup the parameters to handle this particular volume type */
                    756:                        irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;  
                    757:                }
1.1       root      758: 
1.1.1.6 ! root      759:                if (Extension->bRawDevice)
1.1       root      760:                        ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
                    761:                                     NULL, IRP_READ_OPERATION | IRP_NOCACHE,
1.1.1.6 ! root      762:                                                       irpSp->MajorFunction, Irp);
1.1       root      763:                else
                    764:                        ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
                    765:                                tmpBuffer, IRP_READ_OPERATION | IRP_NOCACHE,
1.1.1.6 ! root      766:                                                       irpSp->MajorFunction, Irp);
1.1       root      767:        }
                    768:        else
                    769:        {
                    770:                PUCHAR CurrentAddress;
                    771: 
                    772: //             Dump ("Write: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
                    773: //                   irpSp->Parameters.Read.Length);
                    774: 
1.1.1.6 ! root      775:                Extension->TotalBytesWritten += irpSp->Parameters.Read.Length;
1.1       root      776: 
1.1.1.6 ! root      777:                CurrentAddress = (PUCHAR) MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
1.1.1.4   root      778: 
                    779:                if (Extension->cryptoInfo->hiddenVolume)
                    780:                {
                    781:                        /* Hidden volume offset */
                    782:                        irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
                    783:                }
                    784:                else
                    785:                {
                    786:                        /* Fixup the parameters to handle this particular volume type */
                    787:                        irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;
                    788:                }
1.1       root      789: 
                    790:                memcpy (tmpBuffer, CurrentAddress, irpSp->Parameters.Read.Length);
                    791: 
                    792:                /* Encrypt the data */
1.1.1.4   root      793:                EncryptSectors ((ULONG *) tmpBuffer,
1.1       root      794:                        irpSp->Parameters.Read.ByteOffset.QuadPart / SECTOR_SIZE,
                    795:                        irpSp->Parameters.Read.Length / SECTOR_SIZE,
1.1.1.4   root      796:                        Extension->cryptoInfo->ks,
1.1       root      797:                        Extension->cryptoInfo->iv,
1.1.1.4   root      798:                        Extension->cryptoInfo->ea);
                    799: 
1.1.1.6 ! root      800:                if (Extension->bRawDevice)
1.1       root      801:                {
                    802:                        PMDL tmpBufferMdl = IoAllocateMdl (tmpBuffer, irpSp->Parameters.Read.Length, FALSE, FALSE, NULL);
                    803:                        PMDL pTrueMdl = Irp->MdlAddress;
                    804: 
                    805:                        if (tmpBufferMdl == NULL)
                    806:                        {
                    807:                                TCfree (tmpBuffer);
                    808:                                return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
                    809:                        }
                    810: 
                    811:                        MmBuildMdlForNonPagedPool (tmpBufferMdl);
                    812: 
                    813:                        Irp->MdlAddress = tmpBufferMdl;
                    814: 
                    815: #if EXTRA_INFO
                    816:                        Dump ("NEW MDL ADDRESS IS 0x%08x UserBuffer = 0x%08x\n", Irp->MdlAddress, Irp->UserBuffer);
                    817: #endif
                    818: 
                    819:                        ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
                    820:                                pTrueMdl, IRP_WRITE_OPERATION | IRP_NOCACHE,
1.1.1.6 ! root      821:                                                       irpSp->MajorFunction, Irp);
1.1       root      822:                }
                    823:                else
                    824:                {
                    825:                        ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
                    826:                               tmpBuffer, IRP_WRITE_OPERATION | IRP_NOCACHE,
1.1.1.6 ! root      827:                                                       irpSp->MajorFunction, Irp);
1.1       root      828:                }
                    829:        }
                    830: 
                    831: //     Dump ("TCReadWrite END\n");
                    832:        return ntStatus;
                    833: }
                    834: 
                    835: NTSTATUS
                    836: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
                    837:                               PEXTENSION Extension,
                    838:                               ULONG IoControlCode,
                    839:                               char *OutputBuffer,
                    840:                               int OutputBufferSize)
                    841: {
                    842:        IO_STATUS_BLOCK IoStatusBlock;
                    843:        NTSTATUS ntStatus;
                    844:        PIRP Irp;
                    845: 
                    846:        if (DeviceObject);      /* Remove compiler warning */
                    847: 
                    848:        KeClearEvent (&Extension->keVolumeEvent);
                    849: 
                    850:        Irp = IoBuildDeviceIoControlRequest (IoControlCode,
                    851:                                             Extension->pFsdDevice,
                    852:                                             NULL, 0,
                    853:                                             OutputBuffer, OutputBufferSize,
                    854:                                             FALSE,
                    855:                                             &Extension->keVolumeEvent,
                    856:                                             &IoStatusBlock);
                    857: 
                    858:        if (Irp == NULL)
                    859:        {
                    860:                Dump ("IRP allocation failed\n");
                    861:                return STATUS_INSUFFICIENT_RESOURCES;
                    862:        }
                    863: 
1.1.1.5   root      864:        // Disk device may be used by filesystem driver which needs file object
                    865:        IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
                    866: 
1.1       root      867:        ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
                    868:        if (ntStatus == STATUS_PENDING)
                    869:        {
                    870:                KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL);
                    871:                ntStatus = IoStatusBlock.Status;
                    872:        }
                    873: 
                    874:        return ntStatus;
                    875: }
                    876: 
                    877: NTSTATUS
                    878: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
                    879:              PIRP Irp,
                    880:              NTSTATUS IrpStatus,
1.1.1.4   root      881:              ULONG_PTR IrpInformation)
1.1       root      882: {
                    883:        Irp->IoStatus.Status = IrpStatus;
                    884:        Irp->IoStatus.Information = IrpInformation;
                    885: 
                    886:        if (DeviceObject);      /* Remove compiler warning */
                    887: 
                    888: #ifdef _DEBUG
1.1.1.4   root      889:        //if (!NT_SUCCESS (IrpStatus))
                    890:        //{
                    891:        //      PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    892:        //      Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    893:        //            (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    894:        //}
1.1       root      895:        //else
                    896:        //{
                    897:        //      PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    898:        //      Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    899:        //            (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    900:        //}
                    901: #endif
                    902:        IoCompleteRequest (Irp, IO_NO_INCREMENT);
                    903:        return IrpStatus;
                    904: }
1.1.1.4   root      905: 
                    906: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
                    907: static void RestoreTimeStamp (PEXTENSION Extension)
                    908: {
                    909:        NTSTATUS ntStatus;
                    910:        FILE_BASIC_INFORMATION FileBasicInfo;
                    911:        IO_STATUS_BLOCK IoStatusBlock;
                    912: 
1.1.1.6 ! root      913:        if (Extension->hDeviceFile != NULL 
        !           914:                && Extension->bRawDevice == FALSE 
        !           915:                && Extension->bReadOnly == FALSE
        !           916:                && Extension->bTimeStampValid)
1.1.1.4   root      917:        {
                    918:                ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
                    919:                        &IoStatusBlock,
                    920:                        &FileBasicInfo,
                    921:                        sizeof (FileBasicInfo),
                    922:                        FileBasicInformation); 
                    923: 
                    924:                if (!NT_SUCCESS (ntStatus))
                    925:                {
                    926:                        Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
                    927:                                ntStatus);
                    928:                }
                    929:                else
                    930:                {
                    931:                        FileBasicInfo.CreationTime = Extension->fileCreationTime;
                    932:                        FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
                    933:                        FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
                    934:                        FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
                    935: 
                    936:                        ntStatus = ZwSetInformationFile(
                    937:                                Extension->hDeviceFile,
                    938:                                &IoStatusBlock,
                    939:                                &FileBasicInfo,
                    940:                                sizeof (FileBasicInfo),
                    941:                                FileBasicInformation); 
                    942: 
                    943:                        if (!NT_SUCCESS (ntStatus))
                    944:                                Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
                    945:                }
                    946:        }
                    947: }

unix.superglobalmegacorp.com

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