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

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.18! root        8:  by the TrueCrypt License 2.7 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:                }
1.1.1.17  root      174:                else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
1.1.1.10  root      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:
1.1.1.17  root      630:        dwError = GetLastError();
1.1.1.12  root      631: 
                    632:        if (dosDev[0])
1.1.1.15  root      633:                RemoveFakeDosName (volParams->volumePath, dosDev);
1.1.1.12  root      634: 
                    635:        crypto_close (cryptoInfo);
                    636: 
1.1.1.17  root      637:        SetLastError (dwError);
1.1       root      638:        return nStatus;
1.1.1.3   root      639: }
1.1       root      640: 
1.1.1.3   root      641: 
1.1.1.8   root      642: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3   root      643: {
                    644:        int write_buf_cnt = 0;
1.1.1.17  root      645:        char sector[SECTOR_SIZE], *write_buf;
1.1.1.4   root      646:        unsigned __int64 nSecNo = startSector;
1.1.1.12  root      647:        int retVal = 0;
1.1.1.16  root      648:        DWORD err;
1.1.1.12  root      649:        char temporaryKey[MASTER_KEYDATA_SIZE];
                    650:        char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4   root      651: 
1.1.1.8   root      652:        LARGE_INTEGER startOffset;
                    653:        LARGE_INTEGER newOffset;
                    654: 
1.1.1.4   root      655:        // Seek to start sector
                    656:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6   root      657:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    658:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      659:        {
1.1.1.14  root      660:                return ERR_OS_ERROR;
1.1.1.4   root      661:        }
1.1.1.12  root      662: 
1.1.1.17  root      663:        write_buf = (char *)TCalloc (WRITE_BUF_SIZE);
                    664:        if (!write_buf)
                    665:                return ERR_OUTOFMEMORY;
                    666: 
1.1.1.12  root      667:        VirtualLock (temporaryKey, sizeof (temporaryKey));
                    668:        VirtualLock (originalK2, sizeof (originalK2));
1.1.1.3   root      669: 
                    670:        memset (sector, 0, sizeof (sector));
                    671: 
1.1.1.12  root      672:        // Remember the original secondary key (XTS mode) before generating a temporary one
                    673:        memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
                    674: 
1.1.1.7   root      675:        /* Fill the rest of the data area with random data */
                    676: 
1.1.1.3   root      677:        if(!quickFormat)
                    678:        {
1.1.1.7   root      679:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    680:                the free disk space (data area) with random data.  This is necessary for plausible
1.1.1.12  root      681:                deniability of hidden volumes. */
1.1.1.6   root      682: 
1.1.1.9   root      683:                // Temporary master key
                    684:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    685:                        goto fail;
1.1.1.12  root      686: 
                    687:                // Temporary secondary key (XTS mode)
                    688:                if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9   root      689:                        goto fail;
1.1.1.7   root      690: 
                    691:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12  root      692:                if (retVal != ERR_SUCCESS)
                    693:                        goto fail;
                    694: 
1.1.1.7   root      695:                if (!EAInitMode (cryptoInfo))
                    696:                {
1.1.1.12  root      697:                        retVal = ERR_MODE_INIT_FAILED;
                    698:                        goto fail;
1.1.1.7   root      699:                }
1.1.1.4   root      700: 
1.1.1.3   root      701:                while (num_sectors--)
                    702:                {
1.1.1.12  root      703:                        /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
                    704:                        since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do 
                    705:                        occur commonly on media in the "real world", so it might actually be a fatal mistake
                    706:                        to try to avoid them completely. */
1.1.1.9   root      707: 
1.1.1.12  root      708: #if RNG_POOL_SIZE < SECTOR_SIZE
                    709: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7   root      710: #endif
                    711: 
1.1.1.12  root      712:                        if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9   root      713:                                goto fail;
1.1.1.14  root      714: 
1.1.1.7   root      715:                        // Encrypt the random plaintext and write it to the disk
1.1.1.6   root      716:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      717:                                cryptoInfo) == FALSE)
1.1.1.3   root      718:                                goto fail;
                    719:                }
1.1.1.14  root      720: 
                    721:                if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1.1.3   root      722:                        goto fail;
                    723:        }
                    724:        else
                    725:                nSecNo = num_sectors;
                    726: 
                    727:        UpdateProgressBar (nSecNo);
                    728: 
1.1.1.12  root      729:        // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
                    730:        memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
                    731: 
                    732:        // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
                    733:        retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
                    734:        if (retVal != ERR_SUCCESS)
                    735:                goto fail;
                    736:        if (!EAInitMode (cryptoInfo))
                    737:        {
                    738:                retVal = ERR_MODE_INIT_FAILED;
                    739:                goto fail;
                    740:        }
                    741: 
1.1.1.7   root      742:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      743:        burn (originalK2, sizeof(originalK2));
                    744:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    745:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17  root      746:        TCfree (write_buf);
                    747: 
1.1.1.3   root      748:        return 0;
                    749: 
                    750: fail:
1.1.1.16  root      751:        err = GetLastError();
1.1.1.3   root      752: 
1.1.1.7   root      753:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      754:        burn (originalK2, sizeof(originalK2));
                    755:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    756:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17  root      757:        TCfree (write_buf);
1.1.1.16  root      758: 
                    759:        SetLastError (err);
1.1.1.12  root      760:        return (retVal ? retVal : ERR_OS_ERROR);
1.1       root      761: }
1.1.1.3   root      762: 
                    763: 
                    764: volatile BOOLEAN FormatExResult;
                    765: 
                    766: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    767: {
                    768:        if (command == FMIFS_DONE)
                    769:                FormatExResult = *(BOOLEAN *) parameter;
                    770:        return TRUE;
                    771: }
                    772: 
                    773: BOOL FormatNtfs (int driveNo, int clusterSize)
                    774: {
                    775:        WCHAR dir[8] = { driveNo + 'A', 0 };
                    776:        PFORMATEX FormatEx;
                    777:        HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10  root      778:        int i;
1.1.1.3   root      779: 
                    780:        if (hModule == NULL)
                    781:                return FALSE;
                    782: 
                    783:        if (!(FormatEx = (void *) GetProcAddress (GetModuleHandle("fmifs.dll"), "FormatEx")))
                    784:        {
                    785:                FreeLibrary (hModule);
                    786:                return FALSE;
                    787:        }
                    788: 
                    789:        wcscat (dir, L":\\");
                    790: 
                    791:        FormatExResult = FALSE;
                    792: 
1.1.1.12  root      793:        // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10  root      794:        // It often helps to retry several times.
                    795:        for (i = 0; i < 10 && FormatExResult != TRUE; i++)
                    796:        {
1.1.1.11  root      797:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10  root      798:        }
1.1.1.3   root      799: 
                    800:        FreeLibrary (hModule);
                    801:        return FormatExResult;
                    802: }
                    803: 
1.1.1.8   root      804: 
1.1.1.12  root      805: BOOL WriteSector (void *dev, char *sector,
1.1.1.3   root      806:             char *write_buf, int *write_buf_cnt,
1.1.1.8   root      807:             __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
1.1.1.3   root      808: {
1.1.1.8   root      809:        static __int32 updateTime = 0;
1.1.1.4   root      810: 
1.1.1.12  root      811:        (*nSecNo)++;
1.1.1.4   root      812: 
1.1.1.3   root      813:        memcpy (write_buf + *write_buf_cnt, sector, SECTOR_SIZE);
                    814:        (*write_buf_cnt) += SECTOR_SIZE;
                    815: 
1.1.1.14  root      816:        if (*write_buf_cnt == WRITE_BUF_SIZE && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
                    817:                return FALSE;
1.1.1.6   root      818:        
                    819:        if (GetTickCount () - updateTime > 25)
1.1.1.3   root      820:        {
1.1.1.6   root      821:                if (UpdateProgressBar (*nSecNo))
1.1.1.3   root      822:                        return FALSE;
1.1.1.6   root      823: 
                    824:                updateTime = GetTickCount ();
1.1.1.3   root      825:        }
                    826: 
                    827:        return TRUE;
                    828: 
                    829: }
1.1.1.14  root      830: 
                    831: 
1.1.1.16  root      832: static volatile BOOL WriteThreadRunning;
                    833: static volatile BOOL WriteThreadExitRequested;
                    834: static HANDLE WriteThreadHandle;
                    835: 
                    836: static byte *WriteThreadBuffer;
                    837: static HANDLE WriteBufferEmptyEvent;
                    838: static HANDLE WriteBufferFullEvent;
                    839: 
                    840: static volatile HANDLE WriteRequestHandle;
                    841: static volatile int WriteRequestSize; 
                    842: static volatile DWORD WriteRequestResult;
                    843: 
                    844: 
                    845: static void __cdecl FormatWriteThreadProc (void *arg)
                    846: {
                    847:        DWORD bytesWritten;
                    848: 
                    849:        SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
                    850: 
                    851:        while (!WriteThreadExitRequested)
                    852:        {
                    853:                if (WaitForSingleObject (WriteBufferFullEvent, INFINITE) == WAIT_FAILED)
                    854:                {
                    855:                        handleWin32Error (NULL);
                    856:                        break;
                    857:                }
                    858: 
                    859:                if (WriteThreadExitRequested)
                    860:                        break;
                    861: 
                    862:                if (!WriteFile (WriteRequestHandle, WriteThreadBuffer, WriteRequestSize, &bytesWritten, NULL))
                    863:                        WriteRequestResult = GetLastError();
                    864:                else            
                    865:                        WriteRequestResult = ERROR_SUCCESS;
                    866: 
                    867:                if (!SetEvent (WriteBufferEmptyEvent))
                    868:                {
                    869:                        handleWin32Error (NULL);
                    870:                        break;
                    871:                }
                    872:        }
                    873: 
                    874:        WriteThreadRunning = FALSE;
                    875:        _endthread();
                    876: }
                    877: 
                    878: 
                    879: static BOOL StartFormatWriteThread ()
                    880: {
                    881:        DWORD sysErr;
                    882: 
                    883:        WriteBufferEmptyEvent = NULL;
                    884:        WriteBufferFullEvent = NULL;
                    885:        WriteThreadBuffer = NULL;
                    886: 
                    887:        WriteBufferEmptyEvent = CreateEvent (NULL, FALSE, TRUE, NULL);
                    888:        if (!WriteBufferEmptyEvent)
                    889:                goto err;
                    890: 
                    891:        WriteBufferFullEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
                    892:        if (!WriteBufferFullEvent)
                    893:                goto err;
                    894: 
                    895:        WriteThreadBuffer = TCalloc (WRITE_BUF_SIZE);
                    896:        if (!WriteThreadBuffer)
                    897:        {
                    898:                SetLastError (ERROR_OUTOFMEMORY);
                    899:                goto err;
                    900:        }
                    901: 
                    902:        WriteThreadExitRequested = FALSE;
                    903:        WriteRequestResult = ERROR_SUCCESS;
                    904: 
                    905:        WriteThreadHandle = (HANDLE) _beginthread (FormatWriteThreadProc, 0, NULL);
                    906:        if ((uintptr_t) WriteThreadHandle == -1L)
                    907:                goto err;
                    908: 
                    909:        WriteThreadRunning = TRUE;
                    910:        return TRUE;
                    911: 
                    912: err:
                    913:        sysErr = GetLastError();
                    914: 
                    915:        if (WriteBufferEmptyEvent)
                    916:                CloseHandle (WriteBufferEmptyEvent);
                    917:        if (WriteBufferFullEvent)
                    918:                CloseHandle (WriteBufferFullEvent);
                    919:        if (WriteThreadBuffer)
                    920:                TCfree (WriteThreadBuffer);
                    921: 
                    922:        SetLastError (sysErr);
                    923:        return FALSE;
                    924: }
                    925: 
                    926: 
                    927: static void StopFormatWriteThread ()
                    928: {
                    929:        if (WriteThreadRunning)
                    930:        {
                    931:                WaitForSingleObject (WriteBufferEmptyEvent, INFINITE);
                    932: 
                    933:                WriteThreadExitRequested = TRUE;
                    934:                SetEvent (WriteBufferFullEvent);
                    935: 
                    936:                WaitForSingleObject (WriteThreadHandle, INFINITE);
                    937:        }
                    938: 
                    939:        CloseHandle (WriteBufferEmptyEvent);
                    940:        CloseHandle (WriteBufferFullEvent);
                    941:        TCfree (WriteThreadBuffer);
                    942: }
                    943: 
                    944: 
1.1.1.14  root      945: BOOL FlushFormatWriteBuffer (void *dev, char *write_buf, int *write_buf_cnt, __int64 *nSecNo, PCRYPTO_INFO cryptoInfo)
                    946: {
                    947:        UINT64_STRUCT unitNo;
                    948:        DWORD bytesWritten;
                    949: 
                    950:        if (*write_buf_cnt == 0)
                    951:                return TRUE;
                    952: 
                    953:        unitNo.Value = (*nSecNo - *write_buf_cnt / SECTOR_SIZE) * SECTOR_SIZE / ENCRYPTION_DATA_UNIT_SIZE;
                    954: 
                    955:        EncryptDataUnits (write_buf, &unitNo, *write_buf_cnt / ENCRYPTION_DATA_UNIT_SIZE, cryptoInfo);
                    956: 
1.1.1.16  root      957:        if (WriteThreadRunning)
                    958:        {
                    959:                if (WaitForSingleObject (WriteBufferEmptyEvent, INFINITE) == WAIT_FAILED)
                    960:                        return FALSE;
                    961:                
                    962:                if (WriteRequestResult != ERROR_SUCCESS)
                    963:                {
1.1.1.17  root      964:                        SetEvent (WriteBufferEmptyEvent);
1.1.1.16  root      965:                        SetLastError (WriteRequestResult);
                    966:                        return FALSE;
                    967:                }
                    968: 
                    969:                memcpy (WriteThreadBuffer, write_buf, *write_buf_cnt);
                    970:                WriteRequestHandle = dev;
                    971:                WriteRequestSize = *write_buf_cnt;
                    972: 
                    973:                if (!SetEvent (WriteBufferFullEvent))
                    974:                        return FALSE;
                    975:        }
                    976:        else
                    977:        {
                    978:                if (!WriteFile ((HANDLE) dev, write_buf, *write_buf_cnt, &bytesWritten, NULL))
                    979:                        return FALSE;
                    980:        }
1.1.1.14  root      981: 
                    982:        *write_buf_cnt = 0;
                    983:        return TRUE;
                    984: }

unix.superglobalmegacorp.com

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