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

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

unix.superglobalmegacorp.com

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