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

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

unix.superglobalmegacorp.com

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