Annotation of truecrypt/common/format.c, revision 1.1.1.16

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
1.1.1.16! root        8:  by the TrueCrypt License 2.6 the full text of which is contained in the
1.1.1.12  root        9:  file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10  root       10:  packages. */
                     11: 
                     12: #include <stdlib.h>
                     13: #include <string.h>
1.1.1.6   root       14: 
                     15: #include "Tcdefs.h"
                     16: 
1.1.1.9   root       17: #include "Common.h"
1.1.1.6   root       18: #include "Crypto.h"
                     19: #include "Fat.h"
                     20: #include "Format.h"
1.1.1.9   root       21: #include "Random.h"
1.1.1.6   root       22: #include "Volumes.h"
1.1.1.8   root       23: 
1.1.1.6   root       24: #include "Apidrvr.h"
                     25: #include "Dlgcode.h"
                     26: #include "Language.h"
1.1.1.8   root       27: #include "Progress.h"
1.1.1.6   root       28: #include "Resource.h"
1.1.1.16! root       29: #include "Format/FormatCom.h"
        !            30: #include "Format/Tcformat.h"
1.1.1.3   root       31: 
1.1.1.14  root       32: 
                     33: uint64 GetVolumeDataAreaSize (BOOL hiddenVolume, uint64 volumeSize)
                     34: {
                     35:        uint64 reservedSize;
                     36: 
                     37:        if (hiddenVolume)
                     38:        {
                     39:                // Reserve free space at the end of the host filesystem
                     40:                if (volumeSize < TC_VOLUME_SMALL_SIZE_THRESHOLD)
                     41:                        reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE;
                     42:                else
                     43:                        reservedSize = TC_HIDDEN_VOLUME_HOST_FS_RESERVED_END_AREA_SIZE_HIGH; // Ensure size of a hidden volume larger than TC_VOLUME_SMALL_SIZE_THRESHOLD is a multiple of the maximum supported sector size
                     44:        }
                     45:        else
                     46:        {
                     47:                reservedSize = TC_TOTAL_VOLUME_HEADERS_SIZE;
                     48:        }
                     49: 
                     50:        if (volumeSize < reservedSize)
                     51:                return 0;
                     52: 
                     53:        return volumeSize - reservedSize;
                     54: }
                     55: 
                     56: 
1.1.1.16! root       57: int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
1.1       root       58: {
                     59:        int nStatus;
1.1.1.12  root       60:        PCRYPTO_INFO cryptoInfo = NULL;
1.1.1.4   root       61:        HANDLE dev = INVALID_HANDLE_VALUE;
1.1.1.10  root       62:        DWORD dwError;
1.1.1.14  root       63:        char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1.1.4   root       64:        unsigned __int64 num_sectors, startSector;
1.1.1.3   root       65:        fatparams ft;
1.1.1.4   root       66:        FILETIME ftCreationTime;
                     67:        FILETIME ftLastWriteTime;
                     68:        FILETIME ftLastAccessTime;
                     69:        BOOL bTimeStampValid = FALSE;
1.1.1.12  root       70:        BOOL bInstantRetryOtherFilesys = FALSE;
1.1.1.10  root       71:        char dosDev[TC_MAX_PATH] = { 0 };
                     72:        char devName[MAX_PATH] = { 0 };
                     73:        int driveLetter = -1;
                     74:        WCHAR deviceName[MAX_PATH];
1.1.1.16! root       75:        uint64 dataOffset, dataAreaSize;
1.1.1.14  root       76:        LARGE_INTEGER offset;
1.1.1.16! root       77:        BOOL bFailedRequiredDASD = FALSE;
        !            78: 
1.1.1.10  root       79: 
1.1.1.12  root       80:        /* WARNING: Note that if Windows fails to format the volume as NTFS and the volume size is
1.1.1.14  root       81:        less than TC_MAX_FAT_FS_SIZE, the user is asked within this function whether he wants to instantly
1.1.1.12  root       82:        retry FAT format instead (to avoid having to re-create the whole container again). If the user
                     83:        answers yes, some of the input parameters are modified, the code below 'begin_format' is re-executed 
                     84:        and some destructive operations that were performed during the first attempt must be (and are) skipped. 
                     85:        Therefore, whenever adding or modifying any potentially destructive operations below 'begin_format',
                     86:        determine whether they (or their portions) need to be skipped during such a second attempt; if so, 
                     87:        use the 'bInstantRetryOtherFilesys' flag to skip them. */
                     88: 
1.1.1.15  root       89:        if (volParams->hiddenVol)
1.1.1.14  root       90:        {
1.1.1.15  root       91:                dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
1.1.1.14  root       92:        }
                     93:        else
                     94:        {
1.1.1.15  root       95:                if (volParams->size <= TC_TOTAL_VOLUME_HEADERS_SIZE)
1.1.1.14  root       96:                        return ERR_VOL_SIZE_WRONG;
                     97: 
                     98:                dataOffset = TC_VOLUME_DATA_OFFSET;
                     99:        }
                    100: 
1.1.1.16! root      101:        dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);
1.1       root      102: 
1.1.1.16! root      103:        num_sectors = dataAreaSize / SECTOR_SIZE;
1.1.1.10  root      104: 
1.1.1.15  root      105:        if (volParams->bDevice)
1.1.1.10  root      106:        {
1.1.1.15  root      107:                strcpy ((char *)deviceName, volParams->volumePath);
1.1.1.10  root      108:                ToUNICODE ((char *)deviceName);
                    109: 
                    110:                driveLetter = GetDiskDeviceDriveLetter (deviceName);
                    111:        }
                    112: 
1.1.1.3   root      113:        VirtualLock (header, sizeof (header));
1.1       root      114: 
1.1.1.16! root      115:        nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.12  root      116:                                     header,
1.1.1.15  root      117:                                     volParams->ea,
1.1.1.12  root      118:                                         FIRST_MODE_OF_OPERATION_ID,
1.1.1.15  root      119:                                     volParams->password,
                    120:                                     volParams->pkcs5,
1.1.1.12  root      121:                                         NULL,
1.1.1.4   root      122:                                     &cryptoInfo,
1.1.1.16! root      123:                                         dataAreaSize,
        !           124:                                         volParams->hiddenVol ? dataAreaSize : 0,
1.1.1.14  root      125:                                         dataOffset,
1.1.1.16! root      126:                                         dataAreaSize,
1.1.1.14  root      127:                                         0,
1.1.1.15  root      128:                                         volParams->headerFlags,
1.1.1.6   root      129:                                         FALSE);
1.1       root      130: 
                    131:        if (nStatus != 0)
1.1.1.3   root      132:        {
                    133:                burn (header, sizeof (header));
                    134:                VirtualUnlock (header, sizeof (header));
1.1       root      135:                return nStatus;
1.1.1.3   root      136:        }
                    137: 
1.1.1.12  root      138: begin_format:
                    139: 
1.1.1.15  root      140:        if (volParams->bDevice)
1.1.1.3   root      141:        {
1.1.1.10  root      142:                /* Device-hosted volume */
1.1.1.14  root      143: 
1.1.1.11  root      144:                DWORD dwResult;
1.1.1.10  root      145:                int nPass;
                    146: 
1.1.1.15  root      147:                if (FakeDosNameForDevice (volParams->volumePath, dosDev, devName, FALSE) != 0)
1.1.1.14  root      148:                        return ERR_OS_ERROR;
1.1.1.10  root      149: 
                    150:                if (IsDeviceMounted (devName))
                    151:                {
1.1.1.16! root      152:                        if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
1.1.1.4   root      153:                        {
1.1.1.11  root      154:                                Error ("FORMAT_CANT_DISMOUNT_FILESYS");
                    155:                                nStatus = ERR_DONT_REPORT; 
                    156:                                goto error;
1.1.1.10  root      157:                        }
1.1.1.16! root      158: 
        !           159:                        /* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver 
        !           160:                        would otherwise prevent us from writing to hidden sectors). */
        !           161: 
        !           162:                        if (!DeviceIoControl (dev,
        !           163:                                FSCTL_ALLOW_EXTENDED_DASD_IO,
        !           164:                                NULL,
        !           165:                                0,   
        !           166:                                NULL,
        !           167:                                0,
        !           168:                                &dwResult,
        !           169:                                NULL))
        !           170:                        {
        !           171:                                bFailedRequiredDASD = TRUE;
        !           172:                        }
1.1.1.10  root      173:                }
                    174:                else if (nCurrentOS == WIN_VISTA_OR_LATER && driveLetter == -1)
                    175:                {
                    176:                        // Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition 
                    177:                        // to which no drive letter has been assigned under the system. This problem can be worked
                    178:                        // around by assigning a drive letter to the partition temporarily.
                    179: 
                    180:                        char szDriveLetter[] = { 'A', ':', 0 };
                    181:                        char rootPath[] = { 'A', ':', '\\', 0 };
                    182:                        char uniqVolName[MAX_PATH+1] = { 0 };
                    183:                        int tmpDriveLetter = -1;
                    184:                        BOOL bResult = FALSE;
                    185: 
                    186:                        tmpDriveLetter = GetFirstAvailableDrive ();
                    187:  
                    188:                        if (tmpDriveLetter != -1)
                    189:                        {
                    190:                                rootPath[0] += tmpDriveLetter;
                    191:                                szDriveLetter[0] += tmpDriveLetter;
                    192: 
1.1.1.15  root      193:                                if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
1.1.1.10  root      194:                                {
                    195:                                        bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
                    196: 
                    197:                                        DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
                    198:                                                szDriveLetter,
1.1.1.15  root      199:                                                volParams->volumePath);
1.1.1.10  root      200: 
                    201:                                        if (bResult 
                    202:                                                && SetVolumeMountPoint (rootPath, uniqVolName))
                    203:                                        {
1.1.1.14  root      204:                                                // The drive letter can be removed now
1.1.1.10  root      205:                                                DeleteVolumeMountPoint (rootPath);
                    206:                                        }
                    207:                                }
                    208:                        }
                    209:                }
                    210: 
1.1.1.16! root      211:                // For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be
        !           212:                // redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed,
        !           213:                // bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However, 
        !           214:                // for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly
        !           215:                // send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result.
        !           216: 
        !           217:                DeviceIoControl (dev,
        !           218:                        FSCTL_ALLOW_EXTENDED_DASD_IO,
        !           219:                        NULL,
        !           220:                        0,   
        !           221:                        NULL,
        !           222:                        0,
        !           223:                        &dwResult,
        !           224:                        NULL);
        !           225: 
        !           226: 
        !           227:                // If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open 
        !           228:                // so that the filesystem driver does not prevent us from formatting hidden sectors.
        !           229:                for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++)
1.1.1.10  root      230:                {
1.1.1.14  root      231:                        int retryCount;
                    232: 
                    233:                        retryCount = 0;
                    234: 
1.1.1.10  root      235:                        // Try exclusive access mode first
1.1.1.14  root      236:                        // Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
                    237:                        while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
                    238:                        {
1.1.1.10  root      239:                                dev = CreateFile (devName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
                    240: 
1.1.1.14  root      241:                                if (retryCount > 1)
                    242:                                        Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
                    243:                        }
                    244: 
1.1.1.10  root      245:                        if (dev == INVALID_HANDLE_VALUE)
                    246:                        {
1.1.1.14  root      247:                                // Exclusive access denied -- retry in shared mode
1.1.1.10  root      248:                                dev = CreateFile (devName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                    249:                                if (dev != INVALID_HANDLE_VALUE)
                    250:                                {
1.1.1.15  root      251:                                        if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
1.1.1.10  root      252:                                        {
                    253:                                                nStatus = ERR_DONT_REPORT; 
                    254:                                                goto error;
                    255:                                        }
                    256:                                }
                    257:                                else
                    258:                                {
1.1.1.16! root      259:                                        handleWin32Error (volParams->hwndDlg);
        !           260:                                        Error ("CANT_ACCESS_VOL");
        !           261:                                        nStatus = ERR_DONT_REPORT; 
1.1.1.10  root      262:                                        goto error;
                    263:                                }
                    264:                        }
                    265: 
1.1.1.15  root      266:                        if (volParams->hiddenVol || bInstantRetryOtherFilesys)
1.1.1.10  root      267:                                break;  // The following "quick format" operation would damage the outer volume
                    268: 
                    269:                        if (nPass == 0)
                    270:                        {
1.1.1.16! root      271:                                char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
1.1.1.10  root      272:                                DWORD bw;
                    273: 
1.1.1.16! root      274:                                // Perform pseudo "quick format" so that the filesystem driver does not prevent us from 
        !           275:                                // formatting hidden sectors
1.1.1.10  root      276:                                memset (buf, 0, sizeof (buf));
1.1.1.16! root      277: 
        !           278:                                if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
        !           279:                                {
        !           280:                                        nStatus = ERR_OS_ERROR; 
        !           281:                                        goto error;
        !           282:                                }
        !           283: 
1.1.1.10  root      284:                                FlushFileBuffers (dev);
                    285:                                CloseHandle (dev);
                    286:                                dev = INVALID_HANDLE_VALUE;
1.1.1.4   root      287:                        }
                    288:                }
1.1.1.11  root      289: 
                    290:                if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
                    291:                {
                    292:                        Error ("FORMAT_CANT_DISMOUNT_FILESYS");
                    293:                        nStatus = ERR_DONT_REPORT; 
                    294:                        goto error;
                    295:                }
1.1.1.3   root      296:        }
                    297:        else
                    298:        {
1.1.1.10  root      299:                /* File-hosted volume */
                    300: 
1.1.1.4   root      301:                // We could support FILE_ATTRIBUTE_HIDDEN as an option
                    302:                // (Now if the container has hidden or system file attribute, the OS will not allow
                    303:                // overwritting it; so the user will have to delete it manually).
1.1.1.15  root      304:                dev = CreateFile (volParams->volumePath, GENERIC_WRITE,
                    305:                        (volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
                    306:                        NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
1.1.1.6   root      307: 
1.1.1.8   root      308:                if (dev == INVALID_HANDLE_VALUE)
                    309:                {
1.1.1.14  root      310:                        nStatus = ERR_OS_ERROR; 
1.1.1.8   root      311:                        goto error;
                    312:                }
                    313: 
1.1.1.15  root      314:                if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
1.1.1.6   root      315:                {
                    316:                        LARGE_INTEGER volumeSize;
1.1.1.16! root      317:                        volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.6   root      318: 
1.1.1.15  root      319:                        if (volParams->sparseFileSwitch && volParams->quickFormat)
1.1.1.8   root      320:                        {
                    321:                                // Create as sparse file container
                    322:                                DWORD tmp;
                    323:                                if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
                    324:                                {
1.1.1.14  root      325:                                        nStatus = ERR_OS_ERROR; 
1.1.1.8   root      326:                                        goto error;
                    327:                                }
                    328:                        }
                    329: 
                    330:                        // Preallocate the file
1.1.1.6   root      331:                        if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
                    332:                                || !SetEndOfFile (dev)
                    333:                                || SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
                    334:                        {
1.1.1.14  root      335:                                nStatus = ERR_OS_ERROR;
1.1.1.7   root      336:                                goto error;
1.1.1.6   root      337:                        }
                    338:                }
1.1.1.3   root      339:        }
                    340: 
1.1.1.15  root      341:        if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
1.1.1.4   root      342:        {
                    343:                /* Remember the container timestamp (used to reset file date and time of file-hosted
                    344:                containers to preserve plausible deniability of hidden volume)  */
                    345:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    346:                {
                    347:                        bTimeStampValid = FALSE;
1.1.1.15  root      348:                        MessageBoxW (volParams->hwndDlg, GetString ("GETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      349:                }
                    350:                else
                    351:                        bTimeStampValid = TRUE;
1.1.1.3   root      352:        }
1.1       root      353: 
1.1.1.16! root      354:        KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
1.1       root      355: 
1.1.1.6   root      356:        /* Volume header */
1.1.1.4   root      357: 
                    358:        // Hidden volume setup
1.1.1.15  root      359:        if (volParams->hiddenVol)
1.1.1.4   root      360:        {
1.1.1.14  root      361:                LARGE_INTEGER headerOffset;
                    362: 
1.1.1.16! root      363:                // Check hidden volume size
1.1.1.15  root      364:                if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
1.1.1.4   root      365:                {               
1.1.1.7   root      366:                        nStatus = ERR_VOL_SIZE_WRONG;
                    367:                        goto error;
1.1.1.4   root      368:                }
                    369: 
                    370:                // Seek to hidden volume header location
1.1.1.14  root      371:                
                    372:                headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
                    373: 
                    374:                if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.4   root      375:                {
1.1.1.14  root      376:                        nStatus = ERR_OS_ERROR;
1.1.1.7   root      377:                        goto error;
1.1.1.4   root      378:                }
                    379:        }
1.1.1.12  root      380:        else if (bInstantRetryOtherFilesys)
                    381:        {
                    382:                // The previous file system format failed and the user wants to try again with a different file system.
                    383:                // The volume header had been written successfully so we need to seek to the byte after the header.
                    384: 
1.1.1.14  root      385:                LARGE_INTEGER offset;
                    386:                offset.QuadPart = TC_VOLUME_DATA_OFFSET;
                    387:                if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
1.1.1.12  root      388:                {
1.1.1.14  root      389:                        nStatus = ERR_OS_ERROR;
1.1.1.12  root      390:                        goto error;
                    391:                }
                    392:        }
1.1.1.4   root      393: 
1.1.1.12  root      394:        if (!bInstantRetryOtherFilesys)
1.1.1.10  root      395:        {
1.1.1.12  root      396:                // Write the volume header
1.1.1.14  root      397:                if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
1.1.1.12  root      398:                {
1.1.1.14  root      399:                        nStatus = ERR_OS_ERROR;
1.1.1.12  root      400:                        goto error;
                    401:                }
1.1.1.4   root      402: 
1.1.1.14  root      403:                // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
1.1.1.15  root      404:                if (!volParams->hiddenVol)
1.1.1.14  root      405:                {
                    406:                        byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
                    407:                        ZeroMemory (buf, sizeof (buf));
                    408:                        if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR)
                    409:                        {
                    410:                                nStatus = ERR_OS_ERROR;
                    411:                                goto error;
                    412:                        }
                    413:                }
                    414:        }
1.1.1.4   root      415: 
1.1.1.15  root      416:        if (volParams->hiddenVol)
1.1.1.4   root      417:        {
                    418:                // Calculate data area position of hidden volume
1.1.1.14  root      419:                cryptoInfo->hiddenVolumeOffset = dataOffset;
1.1.1.4   root      420: 
                    421:                // Validate the offset
1.1.1.14  root      422:                if (dataOffset % SECTOR_SIZE != 0)
1.1.1.4   root      423:                {
1.1.1.6   root      424:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    425:                        goto error;
1.1.1.4   root      426:                }
                    427: 
1.1.1.15  root      428:                volParams->quickFormat = TRUE;          // To entirely format a hidden volume would be redundant
1.1.1.4   root      429:        }
                    430: 
1.1.1.14  root      431:        /* Data area */
                    432:        startSector = dataOffset / SECTOR_SIZE;
                    433: 
1.1.1.4   root      434:        // Format filesystem
                    435: 
1.1.1.15  root      436:        switch (volParams->fileSystem)
1.1.1.3   root      437:        {
                    438:        case FILESYS_NONE:
1.1.1.10  root      439:        case FILESYS_NTFS:
1.1.1.16! root      440: 
        !           441:                if (volParams->bDevice && !StartFormatWriteThread())
        !           442:                {
        !           443:                        nStatus = ERR_OS_ERROR; 
        !           444:                        goto error;
        !           445:                }
        !           446: 
1.1.1.15  root      447:                nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
1.1.1.16! root      448: 
        !           449:                if (volParams->bDevice)
        !           450:                        StopFormatWriteThread();
        !           451: 
1.1.1.3   root      452:                break;
1.1.1.10  root      453:                
1.1.1.3   root      454:        case FILESYS_FAT:
1.1.1.4   root      455:                if (num_sectors > 0xFFFFffff)
                    456:                {
1.1.1.6   root      457:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    458:                        goto error;
1.1.1.4   root      459:                }
                    460: 
                    461:                // Calculate the fats, root dir etc
                    462:                ft.num_sectors = (unsigned int) (num_sectors);
1.1.1.15  root      463:                ft.cluster_size = volParams->clusterSize;
1.1.1.6   root      464:                memcpy (ft.volume_name, "NO NAME    ", 11);
1.1.1.4   root      465:                GetFatParams (&ft); 
1.1.1.15  root      466:                *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE;
1.1.1.4   root      467: 
1.1.1.16! root      468:                if (volParams->bDevice && !StartFormatWriteThread())
        !           469:                {
        !           470:                        nStatus = ERR_OS_ERROR; 
        !           471:                        goto error;
        !           472:                }
        !           473: 
1.1.1.15  root      474:                nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
1.1.1.16! root      475: 
        !           476:                if (volParams->bDevice)
        !           477:                        StopFormatWriteThread();
        !           478: 
1.1.1.3   root      479:                break;
1.1.1.13  root      480: 
                    481:        default:
                    482:                nStatus = ERR_PARAMETER_INCORRECT; 
                    483:                goto error;
1.1.1.3   root      484:        }
1.1       root      485: 
1.1.1.15  root      486:        if (nStatus != ERR_SUCCESS)
                    487:                goto error;
                    488: 
1.1.1.14  root      489:        // Write header backup
1.1.1.16! root      490:        offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.14  root      491: 
                    492:        if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
                    493:        {
                    494:                nStatus = ERR_OS_ERROR;
                    495:                goto error;
                    496:        }
                    497: 
1.1.1.16! root      498:        nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.14  root      499:                header,
1.1.1.15  root      500:                volParams->ea,
1.1.1.14  root      501:                FIRST_MODE_OF_OPERATION_ID,
1.1.1.15  root      502:                volParams->password,
                    503:                volParams->pkcs5,
1.1.1.14  root      504:                cryptoInfo->master_keydata,
                    505:                &cryptoInfo,
1.1.1.16! root      506:                dataAreaSize,
        !           507:                volParams->hiddenVol ? dataAreaSize : 0,
1.1.1.14  root      508:                dataOffset,
1.1.1.16! root      509:                dataAreaSize,
1.1.1.14  root      510:                0,
1.1.1.15  root      511:                volParams->headerFlags,
1.1.1.14  root      512:                FALSE);
                    513: 
                    514:        if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
                    515:        {
                    516:                nStatus = ERR_OS_ERROR;
                    517:                goto error;
                    518:        }
                    519: 
1.1.1.16! root      520:        // Fill reserved header sectors (including the backup header area) with random data
1.1.1.15  root      521:        if (!volParams->hiddenVol)
1.1.1.14  root      522:        {
1.1.1.16! root      523:                nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
1.1.1.14  root      524: 
                    525:                if (nStatus != ERR_SUCCESS)
                    526:                        goto error;
                    527:        }
                    528: 
1.1.1.10  root      529: error:
                    530:        dwError = GetLastError();
1.1.1.3   root      531: 
                    532:        burn (header, sizeof (header));
                    533:        VirtualUnlock (header, sizeof (header));
1.1       root      534: 
1.1.1.11  root      535:        if (dev != INVALID_HANDLE_VALUE)
1.1.1.4   root      536:        {
1.1.1.15  root      537:                if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
1.1.1.11  root      538:                {
                    539:                        // Remove preallocated part before closing file handle if format failed
                    540:                        if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
                    541:                                SetEndOfFile (dev);
                    542:                }
1.1.1.6   root      543: 
1.1.1.11  root      544:                FlushFileBuffers (dev);
1.1.1.4   root      545: 
1.1.1.11  root      546:                if (bTimeStampValid)
                    547:                {
                    548:                        // Restore the container timestamp (to preserve plausible deniability of the hidden volume) 
                    549:                        if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.15  root      550:                                MessageBoxW (volParams->hwndDlg, GetString ("SETFILETIME_FAILED_IMPLANT"), lpszTitle, MB_OK | MB_ICONEXCLAMATION);
1.1.1.11  root      551:                }
                    552: 
                    553:                CloseHandle (dev);
                    554:                dev = INVALID_HANDLE_VALUE;
                    555:        }
1.1       root      556: 
1.1.1.6   root      557:        if (nStatus != 0)
1.1.1.3   root      558:        {
1.1.1.10  root      559:                SetLastError(dwError);
1.1.1.12  root      560:                goto fv_end;
1.1.1.10  root      561:        }
1.1.1.6   root      562: 
1.1.1.15  root      563:        if (volParams->fileSystem == FILESYS_NTFS)
1.1.1.10  root      564:        {
                    565:                // Quick-format volume as NTFS
                    566:                int driveNo = GetLastAvailableDrive ();
                    567:                MountOptions mountOptions;
                    568:                int retCode;
1.1.1.3   root      569: 
1.1.1.10  root      570:                ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5   root      571: 
1.1.1.10  root      572:                if (driveNo == -1)
                    573:                {
1.1.1.15  root      574:                        MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
                    575:                        MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3   root      576: 
1.1.1.12  root      577:                        nStatus = ERR_NO_FREE_DRIVES;
                    578:                        goto fv_end;
1.1.1.10  root      579:                }
1.1.1.4   root      580: 
1.1.1.10  root      581:                mountOptions.ReadOnly = FALSE;
                    582:                mountOptions.Removable = FALSE;
                    583:                mountOptions.ProtectHiddenVolume = FALSE;
                    584:                mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.13  root      585:                mountOptions.PartitionInInactiveSysEncScope = FALSE;
1.1.1.14  root      586:                mountOptions.UseBackupHeader = FALSE;
1.1.1.3   root      587: 
1.1.1.15  root      588:                if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
1.1.1.10  root      589:                {
1.1.1.15  root      590:                        MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
                    591:                        MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.12  root      592:                        nStatus = ERR_VOL_MOUNT_FAILED;
                    593:                        goto fv_end;
1.1.1.10  root      594:                }
1.1.1.3   root      595: 
1.1.1.10  root      596:                if (!IsAdmin () && IsUacSupported ())
1.1.1.15  root      597:                        retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
1.1.1.10  root      598:                else
1.1.1.15  root      599:                        retCode = FormatNtfs (driveNo, volParams->clusterSize);
1.1.1.3   root      600: 
1.1.1.10  root      601:                if (retCode != TRUE)
                    602:                {
1.1.1.15  root      603:                        if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
                    604:                                MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      605: 
1.1.1.16! root      606:                        if (dataAreaSize <= TC_MAX_FAT_FS_SIZE)
1.1.1.12  root      607:                        {
                    608:                                if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
                    609:                                {
                    610:                                        // NTFS format failed and the user wants to try FAT format immediately
1.1.1.15  root      611:                                        volParams->fileSystem = FILESYS_FAT;
1.1.1.12  root      612:                                        bInstantRetryOtherFilesys = TRUE;
1.1.1.15  root      613:                                        volParams->quickFormat = TRUE;          // Volume has already been successfully TC-formatted
                    614:                                        volParams->clusterSize = 0;             // Default cluster size
1.1.1.12  root      615:                                        goto begin_format;
                    616:                                }
                    617:                        }
                    618:                        else
                    619:                                Error ("FORMAT_NTFS_FAILED");
                    620: 
                    621:                        nStatus = ERR_DONT_REPORT;
                    622:                        goto fv_end;
1.1.1.3   root      623:                }
1.1.1.10  root      624: 
1.1.1.15  root      625:                if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
                    626:                        MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      627:        }
                    628: 
1.1.1.12  root      629: fv_end:
                    630: 
                    631:        if (dosDev[0])
1.1.1.15  root      632:                RemoveFakeDosName (volParams->volumePath, dosDev);
1.1.1.12  root      633: 
                    634:        crypto_close (cryptoInfo);
                    635: 
1.1       root      636:        return nStatus;
1.1.1.3   root      637: }
1.1       root      638: 
1.1.1.3   root      639: 
1.1.1.8   root      640: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3   root      641: {
                    642:        int write_buf_cnt = 0;
1.1.1.14  root      643:        char sector[SECTOR_SIZE], write_buf[WRITE_BUF_SIZE];
1.1.1.4   root      644:        unsigned __int64 nSecNo = startSector;
1.1.1.12  root      645:        int retVal = 0;
1.1.1.16! root      646:        DWORD err;
1.1.1.12  root      647:        char temporaryKey[MASTER_KEYDATA_SIZE];
                    648:        char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4   root      649: 
1.1.1.8   root      650:        LARGE_INTEGER startOffset;
                    651:        LARGE_INTEGER newOffset;
                    652: 
1.1.1.4   root      653:        // Seek to start sector
                    654:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6   root      655:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    656:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      657:        {
1.1.1.14  root      658:                return ERR_OS_ERROR;
1.1.1.4   root      659:        }
1.1.1.12  root      660: 
                    661:        VirtualLock (temporaryKey, sizeof (temporaryKey));
                    662:        VirtualLock (originalK2, sizeof (originalK2));
1.1.1.3   root      663: 
                    664:        memset (sector, 0, sizeof (sector));
                    665: 
1.1.1.12  root      666:        // Remember the original secondary key (XTS mode) before generating a temporary one
                    667:        memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
                    668: 
1.1.1.7   root      669:        /* Fill the rest of the data area with random data */
                    670: 
1.1.1.3   root      671:        if(!quickFormat)
                    672:        {
1.1.1.7   root      673:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    674:                the free disk space (data area) with random data.  This is necessary for plausible
1.1.1.12  root      675:                deniability of hidden volumes. */
1.1.1.6   root      676: 
1.1.1.9   root      677:                // Temporary master key
                    678:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    679:                        goto fail;
1.1.1.12  root      680: 
                    681:                // Temporary secondary key (XTS mode)
                    682:                if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9   root      683:                        goto fail;
1.1.1.7   root      684: 
                    685:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12  root      686:                if (retVal != ERR_SUCCESS)
                    687:                        goto fail;
                    688: 
1.1.1.7   root      689:                if (!EAInitMode (cryptoInfo))
                    690:                {
1.1.1.12  root      691:                        retVal = ERR_MODE_INIT_FAILED;
                    692:                        goto fail;
1.1.1.7   root      693:                }
1.1.1.4   root      694: 
1.1.1.3   root      695:                while (num_sectors--)
                    696:                {
1.1.1.12  root      697:                        /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
                    698:                        since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do 
                    699:                        occur commonly on media in the "real world", so it might actually be a fatal mistake
                    700:                        to try to avoid them completely. */
1.1.1.9   root      701: 
1.1.1.12  root      702: #if RNG_POOL_SIZE < SECTOR_SIZE
                    703: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7   root      704: #endif
                    705: 
1.1.1.12  root      706:                        if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9   root      707:                                goto fail;
1.1.1.14  root      708: 
1.1.1.7   root      709:                        // Encrypt the random plaintext and write it to the disk
1.1.1.6   root      710:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      711:                                cryptoInfo) == FALSE)
1.1.1.3   root      712:                                goto fail;
                    713:                }
1.1.1.14  root      714: 
                    715:                if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1.1.3   root      716:                        goto fail;
                    717:        }
                    718:        else
                    719:                nSecNo = num_sectors;
                    720: 
                    721:        UpdateProgressBar (nSecNo);
                    722: 
1.1.1.12  root      723:        // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
                    724:        memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
                    725: 
                    726:        // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
                    727:        retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
                    728:        if (retVal != ERR_SUCCESS)
                    729:                goto fail;
                    730:        if (!EAInitMode (cryptoInfo))
                    731:        {
                    732:                retVal = ERR_MODE_INIT_FAILED;
                    733:                goto fail;
                    734:        }
                    735: 
1.1.1.7   root      736:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      737:        burn (originalK2, sizeof(originalK2));
                    738:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    739:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.3   root      740:        return 0;
                    741: 
                    742: fail:
1.1.1.16! root      743:        err = GetLastError();
1.1.1.3   root      744: 
1.1.1.7   root      745:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      746:        burn (originalK2, sizeof(originalK2));
                    747:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    748:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.16! root      749: 
        !           750:        SetLastError (err);
1.1.1.12  root      751:        return (retVal ? retVal : ERR_OS_ERROR);
1.1       root      752: }
1.1.1.3   root      753: 
                    754: 
                    755: volatile BOOLEAN FormatExResult;
                    756: 
                    757: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    758: {
                    759:        if (command == FMIFS_DONE)
                    760:                FormatExResult = *(BOOLEAN *) parameter;
                    761:        return TRUE;
                    762: }
                    763: 
                    764: BOOL FormatNtfs (int driveNo, int clusterSize)
                    765: {
                    766:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    767:        PFORMATEX FormatEx;
                    768:        HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10  root      769:        int i;
1.1.1.3   root      770: 
                    771:        if (hModule == NULL)
                    772:                return FALSE;
                    773: 
                    774:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    775:        {
                    776:                FreeLibrary (hModule);
                    777:                return FALSE;
                    778:        }
                    779: 
                    780:        wcscat (dir, L":\\");
                    781: 
                    782:        FormatExResult = FALSE;
                    783: 
1.1.1.12  root      784:        // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10  root      785:        // It often helps to retry several times.
                    786:        for (i = 0; i < 10 && FormatExResult != TRUE; i++)
                    787:        {
1.1.1.11  root      788:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10  root      789:        }
1.1.1.3   root      790: 
                    791:        FreeLibrary (hModule);
                    792:        return FormatExResult;
                    793: }
                    794: 
1.1.1.8   root      795: 
1.1.1.12  root      796: BOOL WriteSector (void *dev, char *sector,
1.1.1.3   root      797:             char *write_buf, int *write_buf_cnt,
1.1.1.8   root      798:             __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3   root      799: {
1.1.1.8   root      800:        static __int32 updateTime = 0;
1.1.1.4   root      801: 
1.1.1.12  root      802:        (*nSecNo)++;
1.1.1.4   root      803: 
1.1.1.3   root      804:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    805:        (*write_buf_cnt) += SECTOR_SIZE;
                    806: 
1.1.1.14  root      807:        if (*write_buf_cnt == WRITE_BUF_SIZE && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
                    808:                return FALSE;
1.1.1.6   root      809:        
                    810:        if (GetTickCount () - updateTime > 25)
1.1.1.3   root      811:        {
1.1.1.6   root      812:                if (UpdateProgressBar (*nSecNo))
1.1.1.3   root      813:                        return FALSE;
1.1.1.6   root      814: 
                    815:                updateTime = GetTickCount ();
1.1.1.3   root      816:        }
                    817: 
                    818:        return TRUE;
                    819: 
                    820: }
1.1.1.14  root      821: 
                    822: 
1.1.1.16! root      823: static volatile BOOL WriteThreadRunning;
        !           824: static volatile BOOL WriteThreadExitRequested;
        !           825: static HANDLE WriteThreadHandle;
        !           826: 
        !           827: static byte *WriteThreadBuffer;
        !           828: static HANDLE WriteBufferEmptyEvent;
        !           829: static HANDLE WriteBufferFullEvent;
        !           830: 
        !           831: static volatile HANDLE WriteRequestHandle;
        !           832: static volatile int WriteRequestSize; 
        !           833: static volatile DWORD WriteRequestResult;
        !           834: 
        !           835: 
        !           836: static void __cdecl FormatWriteThreadProc (void *arg)
        !           837: {
        !           838:        DWORD bytesWritten;
        !           839: 
        !           840:        SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
        !           841: 
        !           842:        while (!WriteThreadExitRequested)
        !           843:        {
        !           844:                if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
        !           845:                {
        !           846:                        handleWin32Error (NULL);
        !           847:                        break;
        !           848:                }
        !           849: 
        !           850:                if (WriteThreadExitRequested)
        !           851:                        break;
        !           852: 
        !           853:                if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
        !           854:                        WriteRequestResult = GetLastError();
        !           855:                else            
        !           856:                        WriteRequestResult = ERROR_SUCCESS;
        !           857: 
        !           858:                if (!SetEvent (WriteBufferEmptyEvent))
        !           859:                {
        !           860:                        handleWin32Error (NULL);
        !           861:                        break;
        !           862:                }
        !           863:        }
        !           864: 
        !           865:        WriteThreadRunning = FALSE;
        !           866:        _endthread();
        !           867: }
        !           868: 
        !           869: 
        !           870: static BOOL StartFormatWriteThread ()
        !           871: {
        !           872:        DWORD sysErr;
        !           873: 
        !           874:        WriteBufferEmptyEvent = NULL;
        !           875:        WriteBufferFullEvent = NULL;
        !           876:        WriteThreadBuffer = NULL;
        !           877: 
        !           878:        WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
        !           879:        if (!WriteBufferEmptyEvent)
        !           880:                goto err;
        !           881: 
        !           882:        WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
        !           883:        if (!WriteBufferFullEvent)
        !           884:                goto err;
        !           885: 
        !           886:        WriteThreadBuffer = TCalloc (WRITE_BUF_SIZE);
        !           887:        if (!WriteThreadBuffer)
        !           888:        {
        !           889:                SetLastError (ERROR_OUTOFMEMORY);
        !           890:                goto err;
        !           891:        }
        !           892: 
        !           893:        WriteThreadExitRequested = FALSE;
        !           894:        WriteRequestResult = ERROR_SUCCESS;
        !           895: 
        !           896:        WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL);
        !           897:        if ((uintptr_t) WriteThreadHandle == -1L)
        !           898:                goto err;
        !           899: 
        !           900:        WriteThreadRunning = TRUE;
        !           901:        return TRUE;
        !           902: 
        !           903: err:
        !           904:        sysErr = GetLastError();
        !           905: 
        !           906:        if (WriteBufferEmptyEvent)
        !           907:                CloseHandle (WriteBufferEmptyEvent);
        !           908:        if (WriteBufferFullEvent)
        !           909:                CloseHandle (WriteBufferFullEvent);
        !           910:        if (WriteThreadBuffer)
        !           911:                TCfree (WriteThreadBuffer);
        !           912: 
        !           913:        SetLastError (sysErr);
        !           914:        return FALSE;
        !           915: }
        !           916: 
        !           917: 
        !           918: static void StopFormatWriteThread ()
        !           919: {
        !           920:        if (WriteThreadRunning)
        !           921:        {
        !           922:                WaitForSingleObject (WriteBufferEmptyEvent, INFINITE);
        !           923: 
        !           924:                WriteThreadExitRequested = TRUE;
        !           925:                SetEvent (WriteBufferFullEvent);
        !           926: 
        !           927:                WaitForSingleObject (WriteThreadHandle, INFINITE);
        !           928:        }
        !           929: 
        !           930:        CloseHandle (WriteBufferEmptyEvent);
        !           931:        CloseHandle (WriteBufferFullEvent);
        !           932:        TCfree (WriteThreadBuffer);
        !           933: }
        !           934: 
        !           935: 
1.1.1.14  root      936: BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
                    937: {
                    938:        UINT64_STRUCT unitNo;
                    939:        DWORD bytesWritten;
                    940: 
                    941:        if (*write_buf_cnt == 0)
                    942:                return TRUE;
                    943: 
                    944:        unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
                    945: 
                    946:        EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
                    947: 
1.1.1.16! root      948:        if (WriteThreadRunning)
        !           949:        {
        !           950:                if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED)
        !           951:                        return FALSE;
        !           952:                
        !           953:                if (WriteRequestResult != ERROR_SUCCESS)
        !           954:                {
        !           955:                        SetLastError (WriteRequestResult);
        !           956:                        return FALSE;
        !           957:                }
        !           958: 
        !           959:                memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt);
        !           960:                WriteRequestHandle = dev;
        !           961:                WriteRequestSize = *write_buf_cnt;
        !           962: 
        !           963:                if (!SetEvent (WriteBufferFullEvent))
        !           964:                        return FALSE;
        !           965:        }
        !           966:        else
        !           967:        {
        !           968:                if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
        !           969:                        return FALSE;
        !           970:        }
1.1.1.14  root      971: 
                    972:        *write_buf_cnt = 0;
                    973:        return TRUE;
                    974: }

unix.superglobalmegacorp.com

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