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

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
1.1.1.20! root        6:  the original source code (contained in this file) and all other portions
        !             7:  of this file are Copyright (c) 2003-2009 TrueCrypt Developers Association
        !             8:  and are governed by the TrueCrypt License 2.8 the full text of which is
        !             9:  contained in the file License.txt included in TrueCrypt binary and source
        !            10:  code distribution packages. */
1.1.1.10  root       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:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
                    345:                        bTimeStampValid = FALSE;
                    346:                else
                    347:                        bTimeStampValid = TRUE;
1.1.1.3   root      348:        }
1.1       root      349: 
1.1.1.16  root      350:        KillTimer (volParams->hwndDlg, TIMER_ID_RANDVIEW);
1.1       root      351: 
1.1.1.6   root      352:        /* Volume header */
1.1.1.4   root      353: 
                    354:        // Hidden volume setup
1.1.1.15  root      355:        if (volParams->hiddenVol)
1.1.1.4   root      356:        {
1.1.1.14  root      357:                LARGE_INTEGER headerOffset;
                    358: 
1.1.1.16  root      359:                // Check hidden volume size
1.1.1.15  root      360:                if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
1.1.1.4   root      361:                {               
1.1.1.7   root      362:                        nStatus = ERR_VOL_SIZE_WRONG;
                    363:                        goto error;
1.1.1.4   root      364:                }
                    365: 
                    366:                // Seek to hidden volume header location
1.1.1.14  root      367:                
                    368:                headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
                    369: 
                    370:                if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.4   root      371:                {
1.1.1.14  root      372:                        nStatus = ERR_OS_ERROR;
1.1.1.7   root      373:                        goto error;
1.1.1.4   root      374:                }
                    375:        }
1.1.1.12  root      376:        else if (bInstantRetryOtherFilesys)
                    377:        {
                    378:                // The previous file system format failed and the user wants to try again with a different file system.
                    379:                // The volume header had been written successfully so we need to seek to the byte after the header.
                    380: 
1.1.1.14  root      381:                LARGE_INTEGER offset;
                    382:                offset.QuadPart = TC_VOLUME_DATA_OFFSET;
                    383:                if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
1.1.1.12  root      384:                {
1.1.1.14  root      385:                        nStatus = ERR_OS_ERROR;
1.1.1.12  root      386:                        goto error;
                    387:                }
                    388:        }
1.1.1.4   root      389: 
1.1.1.12  root      390:        if (!bInstantRetryOtherFilesys)
1.1.1.10  root      391:        {
1.1.1.12  root      392:                // Write the volume header
1.1.1.14  root      393:                if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
1.1.1.12  root      394:                {
1.1.1.14  root      395:                        nStatus = ERR_OS_ERROR;
1.1.1.12  root      396:                        goto error;
                    397:                }
1.1.1.4   root      398: 
1.1.1.14  root      399:                // To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
1.1.1.15  root      400:                if (!volParams->hiddenVol)
1.1.1.14  root      401:                {
                    402:                        byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
                    403:                        ZeroMemory (buf, sizeof (buf));
                    404:                        if (_lwrite ((HFILE) dev, buf, sizeof (buf)) == HFILE_ERROR)
                    405:                        {
                    406:                                nStatus = ERR_OS_ERROR;
                    407:                                goto error;
                    408:                        }
                    409:                }
                    410:        }
1.1.1.4   root      411: 
1.1.1.15  root      412:        if (volParams->hiddenVol)
1.1.1.4   root      413:        {
                    414:                // Calculate data area position of hidden volume
1.1.1.14  root      415:                cryptoInfo->hiddenVolumeOffset = dataOffset;
1.1.1.4   root      416: 
                    417:                // Validate the offset
1.1.1.14  root      418:                if (dataOffset % SECTOR_SIZE != 0)
1.1.1.4   root      419:                {
1.1.1.6   root      420:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    421:                        goto error;
1.1.1.4   root      422:                }
                    423: 
1.1.1.15  root      424:                volParams->quickFormat = TRUE;          // To entirely format a hidden volume would be redundant
1.1.1.4   root      425:        }
                    426: 
1.1.1.14  root      427:        /* Data area */
                    428:        startSector = dataOffset / SECTOR_SIZE;
                    429: 
1.1.1.4   root      430:        // Format filesystem
                    431: 
1.1.1.15  root      432:        switch (volParams->fileSystem)
1.1.1.3   root      433:        {
                    434:        case FILESYS_NONE:
1.1.1.10  root      435:        case FILESYS_NTFS:
1.1.1.16  root      436: 
                    437:                if (volParams->bDevice && !StartFormatWriteThread())
                    438:                {
                    439:                        nStatus = ERR_OS_ERROR; 
                    440:                        goto error;
                    441:                }
                    442: 
1.1.1.15  root      443:                nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
1.1.1.16  root      444: 
                    445:                if (volParams->bDevice)
                    446:                        StopFormatWriteThread();
                    447: 
1.1.1.3   root      448:                break;
1.1.1.10  root      449:                
1.1.1.3   root      450:        case FILESYS_FAT:
1.1.1.4   root      451:                if (num_sectors > 0xFFFFffff)
                    452:                {
1.1.1.6   root      453:                        nStatus = ERR_VOL_SIZE_WRONG; 
                    454:                        goto error;
1.1.1.4   root      455:                }
                    456: 
                    457:                // Calculate the fats, root dir etc
                    458:                ft.num_sectors = (unsigned int) (num_sectors);
1.1.1.15  root      459:                ft.cluster_size = volParams->clusterSize;
1.1.1.6   root      460:                memcpy (ft.volume_name, "NO NAME    ", 11);
1.1.1.4   root      461:                GetFatParams (&ft); 
1.1.1.15  root      462:                *(volParams->realClusterSize) = ft.cluster_size * SECTOR_SIZE;
1.1.1.4   root      463: 
1.1.1.16  root      464:                if (volParams->bDevice && !StartFormatWriteThread())
                    465:                {
                    466:                        nStatus = ERR_OS_ERROR; 
                    467:                        goto error;
                    468:                }
                    469: 
1.1.1.15  root      470:                nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
1.1.1.16  root      471: 
                    472:                if (volParams->bDevice)
                    473:                        StopFormatWriteThread();
                    474: 
1.1.1.3   root      475:                break;
1.1.1.13  root      476: 
                    477:        default:
                    478:                nStatus = ERR_PARAMETER_INCORRECT; 
                    479:                goto error;
1.1.1.3   root      480:        }
1.1       root      481: 
1.1.1.15  root      482:        if (nStatus != ERR_SUCCESS)
                    483:                goto error;
                    484: 
1.1.1.14  root      485:        // Write header backup
1.1.1.16  root      486:        offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
1.1.1.14  root      487: 
                    488:        if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
                    489:        {
                    490:                nStatus = ERR_OS_ERROR;
                    491:                goto error;
                    492:        }
                    493: 
1.1.1.16  root      494:        nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.14  root      495:                header,
1.1.1.15  root      496:                volParams->ea,
1.1.1.14  root      497:                FIRST_MODE_OF_OPERATION_ID,
1.1.1.15  root      498:                volParams->password,
                    499:                volParams->pkcs5,
1.1.1.14  root      500:                cryptoInfo->master_keydata,
                    501:                &cryptoInfo,
1.1.1.16  root      502:                dataAreaSize,
                    503:                volParams->hiddenVol ? dataAreaSize : 0,
1.1.1.14  root      504:                dataOffset,
1.1.1.16  root      505:                dataAreaSize,
1.1.1.14  root      506:                0,
1.1.1.15  root      507:                volParams->headerFlags,
1.1.1.14  root      508:                FALSE);
                    509: 
                    510:        if (_lwrite ((HFILE) dev, header, TC_VOLUME_HEADER_EFFECTIVE_SIZE) == HFILE_ERROR)
                    511:        {
                    512:                nStatus = ERR_OS_ERROR;
                    513:                goto error;
                    514:        }
                    515: 
1.1.1.16  root      516:        // Fill reserved header sectors (including the backup header area) with random data
1.1.1.15  root      517:        if (!volParams->hiddenVol)
1.1.1.14  root      518:        {
1.1.1.16  root      519:                nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
1.1.1.14  root      520: 
                    521:                if (nStatus != ERR_SUCCESS)
                    522:                        goto error;
                    523:        }
                    524: 
1.1.1.19  root      525: #ifndef DEBUG
                    526:        if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS)
                    527:                Sleep (500);    // User-friendly GUI
                    528: #endif
                    529: 
1.1.1.10  root      530: error:
                    531:        dwError = GetLastError();
1.1.1.3   root      532: 
                    533:        burn (header, sizeof (header));
                    534:        VirtualUnlock (header, sizeof (header));
1.1       root      535: 
1.1.1.11  root      536:        if (dev != INVALID_HANDLE_VALUE)
1.1.1.4   root      537:        {
1.1.1.15  root      538:                if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
1.1.1.11  root      539:                {
                    540:                        // Remove preallocated part before closing file handle if format failed
                    541:                        if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
                    542:                                SetEndOfFile (dev);
                    543:                }
1.1.1.6   root      544: 
1.1.1.11  root      545:                FlushFileBuffers (dev);
1.1.1.4   root      546: 
1.1.1.11  root      547:                if (bTimeStampValid)
1.1.1.20! root      548:                        SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
1.1.1.11  root      549: 
                    550:                CloseHandle (dev);
                    551:                dev = INVALID_HANDLE_VALUE;
                    552:        }
1.1       root      553: 
1.1.1.6   root      554:        if (nStatus != 0)
1.1.1.3   root      555:        {
1.1.1.10  root      556:                SetLastError(dwError);
1.1.1.12  root      557:                goto fv_end;
1.1.1.10  root      558:        }
1.1.1.6   root      559: 
1.1.1.15  root      560:        if (volParams->fileSystem == FILESYS_NTFS)
1.1.1.10  root      561:        {
                    562:                // Quick-format volume as NTFS
                    563:                int driveNo = GetLastAvailableDrive ();
                    564:                MountOptions mountOptions;
                    565:                int retCode;
1.1.1.3   root      566: 
1.1.1.10  root      567:                ZeroMemory (&mountOptions, sizeof (mountOptions));
1.1.1.5   root      568: 
1.1.1.10  root      569:                if (driveNo == -1)
                    570:                {
1.1.1.15  root      571:                        MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
                    572:                        MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.3   root      573: 
1.1.1.12  root      574:                        nStatus = ERR_NO_FREE_DRIVES;
                    575:                        goto fv_end;
1.1.1.10  root      576:                }
1.1.1.4   root      577: 
1.1.1.10  root      578:                mountOptions.ReadOnly = FALSE;
                    579:                mountOptions.Removable = FALSE;
                    580:                mountOptions.ProtectHiddenVolume = FALSE;
                    581:                mountOptions.PreserveTimestamp = bPreserveTimestamp;
1.1.1.13  root      582:                mountOptions.PartitionInInactiveSysEncScope = FALSE;
1.1.1.14  root      583:                mountOptions.UseBackupHeader = FALSE;
1.1.1.3   root      584: 
1.1.1.15  root      585:                if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
1.1.1.10  root      586:                {
1.1.1.15  root      587:                        MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
                    588:                        MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
1.1.1.12  root      589:                        nStatus = ERR_VOL_MOUNT_FAILED;
                    590:                        goto fv_end;
1.1.1.10  root      591:                }
1.1.1.3   root      592: 
1.1.1.10  root      593:                if (!IsAdmin () && IsUacSupported ())
1.1.1.15  root      594:                        retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
1.1.1.10  root      595:                else
1.1.1.15  root      596:                        retCode = FormatNtfs (driveNo, volParams->clusterSize);
1.1.1.3   root      597: 
1.1.1.10  root      598:                if (retCode != TRUE)
                    599:                {
1.1.1.15  root      600:                        if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
                    601:                                MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      602: 
1.1.1.16  root      603:                        if (dataAreaSize <= TC_MAX_FAT_FS_SIZE)
1.1.1.12  root      604:                        {
                    605:                                if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
                    606:                                {
                    607:                                        // NTFS format failed and the user wants to try FAT format immediately
1.1.1.15  root      608:                                        volParams->fileSystem = FILESYS_FAT;
1.1.1.12  root      609:                                        bInstantRetryOtherFilesys = TRUE;
1.1.1.15  root      610:                                        volParams->quickFormat = TRUE;          // Volume has already been successfully TC-formatted
                    611:                                        volParams->clusterSize = 0;             // Default cluster size
1.1.1.12  root      612:                                        goto begin_format;
                    613:                                }
                    614:                        }
                    615:                        else
                    616:                                Error ("FORMAT_NTFS_FAILED");
                    617: 
                    618:                        nStatus = ERR_DONT_REPORT;
                    619:                        goto fv_end;
1.1.1.3   root      620:                }
1.1.1.10  root      621: 
1.1.1.15  root      622:                if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
                    623:                        MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
1.1.1.3   root      624:        }
                    625: 
1.1.1.12  root      626: fv_end:
1.1.1.17  root      627:        dwError = GetLastError();
1.1.1.12  root      628: 
                    629:        if (dosDev[0])
1.1.1.15  root      630:                RemoveFakeDosName (volParams->volumePath, dosDev);
1.1.1.12  root      631: 
                    632:        crypto_close (cryptoInfo);
                    633: 
1.1.1.17  root      634:        SetLastError (dwError);
1.1       root      635:        return nStatus;
1.1.1.3   root      636: }
1.1       root      637: 
1.1.1.3   root      638: 
1.1.1.8   root      639: int FormatNoFs (unsigned __int64 startSector, __int64 num_sectors, void * dev, PCRYPTO_INFO cryptoInfo, BOOL quickFormat)
1.1.1.3   root      640: {
                    641:        int write_buf_cnt = 0;
1.1.1.17  root      642:        char sector[SECTOR_SIZE], *write_buf;
1.1.1.4   root      643:        unsigned __int64 nSecNo = startSector;
1.1.1.12  root      644:        int retVal = 0;
1.1.1.16  root      645:        DWORD err;
1.1.1.12  root      646:        char temporaryKey[MASTER_KEYDATA_SIZE];
                    647:        char originalK2[MASTER_KEYDATA_SIZE];
1.1.1.4   root      648: 
1.1.1.8   root      649:        LARGE_INTEGER startOffset;
                    650:        LARGE_INTEGER newOffset;
                    651: 
1.1.1.4   root      652:        // Seek to start sector
                    653:        startOffset.QuadPart = startSector * SECTOR_SIZE;
1.1.1.6   root      654:        if (!SetFilePointerEx ((HANDLE) dev, startOffset, &newOffset, FILE_BEGIN)
                    655:                || newOffset.QuadPart != startOffset.QuadPart)
1.1.1.4   root      656:        {
1.1.1.14  root      657:                return ERR_OS_ERROR;
1.1.1.4   root      658:        }
1.1.1.12  root      659: 
1.1.1.19  root      660:        write_buf = (char *)TCalloc (FormatWriteBufferSize);
1.1.1.17  root      661:        if (!write_buf)
                    662:                return ERR_OUTOFMEMORY;
                    663: 
1.1.1.12  root      664:        VirtualLock (temporaryKey, sizeof (temporaryKey));
                    665:        VirtualLock (originalK2, sizeof (originalK2));
1.1.1.3   root      666: 
                    667:        memset (sector, 0, sizeof (sector));
                    668: 
1.1.1.12  root      669:        // Remember the original secondary key (XTS mode) before generating a temporary one
                    670:        memcpy (originalK2, cryptoInfo->k2, sizeof (cryptoInfo->k2));
                    671: 
1.1.1.7   root      672:        /* Fill the rest of the data area with random data */
                    673: 
1.1.1.3   root      674:        if(!quickFormat)
                    675:        {
1.1.1.7   root      676:                /* Generate a random temporary key set to be used for "dummy" encryption that will fill
                    677:                the free disk space (data area) with random data.  This is necessary for plausible
1.1.1.12  root      678:                deniability of hidden volumes. */
1.1.1.6   root      679: 
1.1.1.9   root      680:                // Temporary master key
                    681:                if (!RandgetBytes (temporaryKey, EAGetKeySize (cryptoInfo->ea), FALSE))
                    682:                        goto fail;
1.1.1.12  root      683: 
                    684:                // Temporary secondary key (XTS mode)
                    685:                if (!RandgetBytes (cryptoInfo->k2, sizeof cryptoInfo->k2, FALSE))
1.1.1.9   root      686:                        goto fail;
1.1.1.7   root      687: 
                    688:                retVal = EAInit (cryptoInfo->ea, temporaryKey, cryptoInfo->ks);
1.1.1.12  root      689:                if (retVal != ERR_SUCCESS)
                    690:                        goto fail;
                    691: 
1.1.1.7   root      692:                if (!EAInitMode (cryptoInfo))
                    693:                {
1.1.1.12  root      694:                        retVal = ERR_MODE_INIT_FAILED;
                    695:                        goto fail;
1.1.1.7   root      696:                }
1.1.1.4   root      697: 
1.1.1.3   root      698:                while (num_sectors--)
                    699:                {
1.1.1.12  root      700:                        /* Generate random plaintext. Note that reused plaintext blocks are not a concern here
                    701:                        since XTS mode is designed to hide patterns. Furthermore, patterns in plaintext do 
                    702:                        occur commonly on media in the "real world", so it might actually be a fatal mistake
                    703:                        to try to avoid them completely. */
1.1.1.9   root      704: 
1.1.1.12  root      705: #if RNG_POOL_SIZE < SECTOR_SIZE
                    706: #error RNG_POOL_SIZE < SECTOR_SIZE
1.1.1.7   root      707: #endif
                    708: 
1.1.1.12  root      709:                        if (!RandpeekBytes (sector, SECTOR_SIZE))
1.1.1.9   root      710:                                goto fail;
1.1.1.14  root      711: 
1.1.1.7   root      712:                        // Encrypt the random plaintext and write it to the disk
1.1.1.6   root      713:                        if (WriteSector (dev, sector, write_buf, &write_buf_cnt, &nSecNo,
1.1.1.8   root      714:                                cryptoInfo) == FALSE)
1.1.1.3   root      715:                                goto fail;
                    716:                }
1.1.1.14  root      717: 
                    718:                if (!FlushFormatWriteBuffer (dev, write_buf, &write_buf_cnt, &nSecNo, cryptoInfo))
1.1.1.3   root      719:                        goto fail;
                    720:        }
                    721:        else
                    722:                nSecNo = num_sectors;
                    723: 
                    724:        UpdateProgressBar (nSecNo);
                    725: 
1.1.1.12  root      726:        // Restore the original secondary key (XTS mode) in case NTFS format fails and the user wants to try FAT immediately
                    727:        memcpy (cryptoInfo->k2, originalK2, sizeof (cryptoInfo->k2));
                    728: 
                    729:        // Reinitialize the encryption algorithm and mode in case NTFS format fails and the user wants to try FAT immediately
                    730:        retVal = EAInit (cryptoInfo->ea, cryptoInfo->master_keydata, cryptoInfo->ks);
                    731:        if (retVal != ERR_SUCCESS)
                    732:                goto fail;
                    733:        if (!EAInitMode (cryptoInfo))
                    734:        {
                    735:                retVal = ERR_MODE_INIT_FAILED;
                    736:                goto fail;
                    737:        }
                    738: 
1.1.1.7   root      739:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      740:        burn (originalK2, sizeof(originalK2));
                    741:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    742:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17  root      743:        TCfree (write_buf);
                    744: 
1.1.1.3   root      745:        return 0;
                    746: 
                    747: fail:
1.1.1.16  root      748:        err = GetLastError();
1.1.1.3   root      749: 
1.1.1.7   root      750:        burn (temporaryKey, sizeof(temporaryKey));
1.1.1.12  root      751:        burn (originalK2, sizeof(originalK2));
                    752:        VirtualUnlock (temporaryKey, sizeof (temporaryKey));
                    753:        VirtualUnlock (originalK2, sizeof (originalK2));
1.1.1.17  root      754:        TCfree (write_buf);
1.1.1.16  root      755: 
                    756:        SetLastError (err);
1.1.1.12  root      757:        return (retVal ? retVal : ERR_OS_ERROR);
1.1       root      758: }
1.1.1.3   root      759: 
                    760: 
                    761: volatile BOOLEAN FormatExResult;
                    762: 
                    763: BOOLEAN __stdcall FormatExCallback (int command, DWORD subCommand, PVOID parameter)
                    764: {
                    765:        if (command == FMIFS_DONE)
                    766:                FormatExResult = *(BOOLEAN *) parameter;
                    767:        return TRUE;
                    768: }
                    769: 
                    770: BOOL FormatNtfs (int driveNo, int clusterSize)
                    771: {
1.1.1.19  root      772:        WCHAR dir[8] = { (WCHAR) driveNo + 'A', 0 };
1.1.1.3   root      773:        PFORMATEX FormatEx;
                    774:        HMODULE hModule = LoadLibrary ("fmifs.dll");
1.1.1.10  root      775:        int i;
1.1.1.3   root      776: 
                    777:        if (hModule == NULL)
                    778:                return FALSE;
                    779: 
1.1.1.19  root      780:        if (!(FormatEx = (PFORMATEX) GetProcAddress (GetModuleHandle ("fmifs.dll"), "FormatEx")))
1.1.1.3   root      781:        {
                    782:                FreeLibrary (hModule);
                    783:                return FALSE;
                    784:        }
                    785: 
                    786:        wcscat (dir, L":\\");
                    787: 
                    788:        FormatExResult = FALSE;
                    789: 
1.1.1.12  root      790:        // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS.
1.1.1.10  root      791:        // It often helps to retry several times.
1.1.1.19  root      792:        for (i = 0; i < 50 && FormatExResult != TRUE; i++)
1.1.1.10  root      793:        {
1.1.1.11  root      794:                FormatEx (dir, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * SECTOR_SIZE, FormatExCallback);
1.1.1.10  root      795:        }
1.1.1.3   root      796: 
1.1.1.19  root      797:        // The device may be referenced for some time after FormatEx() returns
                    798:        Sleep (2000);
                    799: 
1.1.1.3   root      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.19  root      816:        if (*write_buf_cnt == FormatWriteBufferSize && !FlushFormatWriteBuffer (dev, write_buf, write_buf_cnt, nSecNo, cryptoInfo))
1.1.1.14  root      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: 
1.1.1.19  root      895:        WriteThreadBuffer = TCalloc (FormatWriteBufferSize);
1.1.1.16  root      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.