// 这是if..else 的下半部分.
else
{
/* File-hosted volume */
// 根据volParams->volumePath,创建文件
dev = CreateFile (volParams->volumePath, GENERIC_READ | GENERIC_WRITE,
(volParams->hiddenVol || bInstantRetryOtherFilesys) ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : 0,
NULL, (volParams->hiddenVol || bInstantRetryOtherFilesys) ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL);
if (dev == INVALID_HANDLE_VALUE)
{
nStatus = ERR_OS_ERROR;
goto error;
}
// DisableFileCompression()函数内部调用DeviceIoControl(),
// 发送IOCTL_CODE,FSCTL_GET_COMPRESSION和FSCTL_SET_COMPRESSION
// 来设置dev的COMPRESSION信息.和稀疏文件的压缩性相关? 可以参见驱动分析...
DisableFileCompression (dev);
// 如果为非hiddenVol则...
if (!volParams->hiddenVol && !bInstantRetryOtherFilesys)
{
LARGE_INTEGER volumeSize;
volumeSize.QuadPart = dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
if (volParams->sparseFileSwitch && volParams->quickFormat)
{
// Create as sparse file container
// 创建一个 稀疏(sparse) file container..
// 在这里解释下 sparse file指的是文件中出现大量的0数据,这些数据对我们用处不大,但是却占用我们的空间
// 因此自从Windows 3.51对此进行了优化,那些无用的0字节被用一定的算法压缩起来,使得这些0字节不再占用那么多空间
// 在你声明一个很大的文件为稀疏文件的时候(如 100GB),这个文件实际并不需要占用那么大空间,因为里面大多是无用的0数据
// 那么,NTFS对稀疏文件的压缩算法可以释放这些无用的0字节算是对磁盘空间效率的优化,但是FAT32并不支持稀疏文件.
DWORD tmp;
if (!DeviceIoControl (dev, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &tmp, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
// Preallocate the file
// 预分配文件大小...
if (!SetFilePointerEx (dev, volumeSize, NULL, FILE_BEGIN)
|| !SetEndOfFile (dev)
|| SetFilePointer (dev, 0, NULL, FILE_BEGIN) != 0)
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
}// File-hosted volume *end
// 如果是 hiddenVol并且非 Device的话,获得与FileTime相关的信息
if (volParams->hiddenVol && !volParams->bDevice && bPreserveTimestamp)
{
if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
bTimeStampValid = FALSE;
else
bTimeStampValid = TRUE;
}
/* Volume header */
// Hidden volume setup
// Hidden Volume 的安装和设置
if(volParams->hiddenVol)
{
LARGE_INTEGER headerOffset;
// Check hidden volume size
// 检查 hidden volume的大小
if (volParams->hiddenVolHostSize < TC_MIN_HIDDEN_VOLUME_HOST_SIZE || volParams->hiddenVolHostSize > TC_MAX_HIDDEN_VOLUME_HOST_SIZE)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
// Seek to hidden volume header location
// 用SetFilePointerEx()定位 hidden volume header的位置
headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
}
// 如果没有尝试其他的Filesystem则...
if (!bInstantRetryOtherFilesys)
{
// Write the volume header
// 往volume中写如header信息,该header是在前面调用CreateVolumeHeaderInMemory()函数,初始化好的.
if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, (byte *)header))
{
nStatus = ERR_OS_ERROR;
goto error;
}
// To prevent fragmentation, write zeroes to reserved header sectors which are going to be filled with random data
// 为了防止磁盘的碎片化,往剩余的header sectors 中填0.
if (!volParams->bDevice && !volParams->hiddenVol)
{
byte buf[TC_VOLUME_HEADER_GROUP_SIZE - TC_VOLUME_HEADER_EFFECTIVE_SIZE];
DWORD bytesWritten;
ZeroMemory (buf, sizeof (buf));
if (!WriteFile (dev, buf, sizeof (buf), &bytesWritten, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
if (bytesWritten != sizeof (buf))
{
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
}
}
// 如果是 hidden Volume
if (volParams->hiddenVol)
{
// Calculate data area position of hidden volume
// 计算获得 数据区 在 hidden volume的 位置
cryptoInfo->hiddenVolumeOffset = dataOffset;
// Validate the offset
// 检测这offset 是否有效
if (dataOffset % FormatSectorSize != 0)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
volParams->quickFormat = TRUE; // To entirely format a hidden volume would be redundant
}
/* Data area */
// 获得数据区的起始扇区,即startSector.
startSector = dataOffset / FormatSectorSize;
// Format filesystem
// 格式化成相应的文件系统,NONE/NTFS/FAT
switch (volParams->fileSystem)
{
case FILESYS_NONE:
case FILESYS_NTFS:
// StartFormatWriteThread()函数内部另外创建了一个线程,然后调用线程函数FormatWriteThreadProc()
// FormatWriteThreadProc()设置当前的线程的优先级为HIGHEST,然后尝试往该dev中写入数据,即WriteThreadBuffer,\
// 而WriteThreadBuffer = (byte *) TCalloc (FormatWriteBufferSize);
if (volParams->bDevice && !StartFormatWriteThread())
{
nStatus = ERR_OS_ERROR;
goto error;
}
// FormatNoFs()这个函数看的我有点吐血了,里面有很多关于加密算法的初始化操作,分析不过来
// 不过主要的格式化操作,由内部的WriteSector()和FlushFormatWriteBuffer()完成.
nStatus = FormatNoFs (startSector, num_sectors, dev, cryptoInfo, volParams->quickFormat);
if (volParams->bDevice)
StopFormatWriteThread();
break;
case FILESYS_FAT:
if (num_sectors > 0xFFFFffff)
{
nStatus = ERR_VOL_SIZE_WRONG;
goto error;
}
// Calculate the fats, root dir etc
/*
typedef struct fatparams_t
{
char volume_name[11];
byte volume_id[4];
unsigned int num_sectors; // total number of sectors
int cluster_count; // number of clusters
int size_root_dir; // size of the root directory in bytes
int size_fat; // size of FAT
int fats;
int media;
int cluster_size;
int fat_length;
uint16 dir_entries;
uint16 sector_size;
int hidden;
__int16 reserved;
uint16 sectors;
unsigned int total_sect;
uint16 heads;
uint16 secs_track;
} fatparams;
*/
// 上面的结构体 与 FAT相关,下面的操作就是初始化fat结构的成员变量.
ft.num_sectors = (unsigned int) (num_sectors);
#if TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
#error TC_MAX_VOLUME_SECTOR_SIZE > 0xFFFF
#endif
ft.sector_size = (uint16) FormatSectorSize;
ft.cluster_size = volParams->clusterSize;
memcpy (ft.volume_name, "NO NAME ", 11);
GetFatParams (&ft);
*(volParams->realClusterSize) = ft.cluster_size * FormatSectorSize;
if (volParams->bDevice && !StartFormatWriteThread())
{
nStatus = ERR_OS_ERROR;
goto error;
}
// 执行FormatFat()函数,进行FS的格式化操作.
nStatus = FormatFat (startSector, &ft, (void *) dev, cryptoInfo, volParams->quickFormat);
if (volParams->bDevice)
StopFormatWriteThread();
break;
default:
nStatus = ERR_PARAMETER_INCORRECT;
goto error;
}
// Write header backup
// 写入header的备份
offset.QuadPart = volParams->hiddenVol ? volParams->hiddenVolHostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET : dataAreaSize + TC_VOLUME_HEADER_GROUP_SIZE;
if (!SetFilePointerEx ((HANDLE) dev, offset, NULL, FILE_BEGIN))
{
nStatus = ERR_OS_ERROR;
goto error;
}
nStatus = CreateVolumeHeaderInMemory (FALSE,
header,
volParams->ea,
FIRST_MODE_OF_OPERATION_ID,
volParams->password,
volParams->pkcs5,
(char *)cryptoInfo->master_keydata,
&cryptoInfo,
dataAreaSize,
volParams->hiddenVol ? dataAreaSize : 0,
dataOffset,
dataAreaSize,
0,
volParams->headerFlags,
FormatSectorSize,
FALSE);
if (!WriteEffectiveVolumeHeader (volParams->bDevice, dev, (byte *)header))
{
nStatus = ERR_OS_ERROR;
goto error;
}
// Fill reserved header sectors (including the backup header area) with random data
// 用随机数据填充剩余的header sectors
if (!volParams->hiddenVol)
{
nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, dataAreaSize, FALSE, FALSE);
if (nStatus != ERR_SUCCESS)
goto error;
}
#ifndef DEBUG
if (volParams->quickFormat && volParams->fileSystem != FILESYS_NTFS)
Sleep (500); // User-friendly GUI
#endif
// 这部分有点懒了...凑合着看吧...
error:
dwError = GetLastError();
burn (header, sizeof (header));
VirtualUnlock (header, sizeof (header));
// 如果dev不为无效的HANDLE
if (dev != INVALID_HANDLE_VALUE)
{
// 如果不是Device或者也不是hidden Volume 那么就移除 先前预先分配的 磁盘空间
if (!volParams->bDevice && !volParams->hiddenVol && nStatus != 0)
{
// Remove preallocated part before closing file handle if format failed
// 如果格式化失败了...
if (SetFilePointer (dev, 0, NULL, FILE_BEGIN) == 0)
SetEndOfFile (dev);
}
FlushFileBuffers (dev);
if (bTimeStampValid)
SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
CloseHandle (dev);
dev = INVALID_HANDLE_VALUE;
}
if (nStatus != 0)
{
SetLastError(dwError);
goto fv_end;
}
// 如果要求被格式化成 NTFS
if (volParams->fileSystem == FILESYS_NTFS)
{
// Quick-format volume as NTFS
int driveNo = GetLastAvailableDrive ();
MountOptions mountOptions;
int retCode;
ZeroMemory (&mountOptions, sizeof (mountOptions));
if (driveNo == -1)
{
MessageBoxW (volParams->hwndDlg, GetString ("NO_FREE_DRIVES"), lpszTitle, ICON_HAND);
MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
nStatus = ERR_NO_FREE_DRIVES;
goto fv_end;
}
mountOptions.ReadOnly = FALSE;
mountOptions.Removable = FALSE;
mountOptions.ProtectHiddenVolume = FALSE;
mountOptions.PreserveTimestamp = bPreserveTimestamp;
mountOptions.PartitionInInactiveSysEncScope = FALSE;
mountOptions.UseBackupHeader = FALSE;
if (MountVolume (volParams->hwndDlg, driveNo, volParams->volumePath, volParams->password, FALSE, TRUE, &mountOptions, FALSE, TRUE) < 1)
{
MessageBoxW (volParams->hwndDlg, GetString ("CANT_MOUNT_VOLUME"), lpszTitle, ICON_HAND);
MessageBoxW (volParams->hwndDlg, GetString ("FORMAT_NTFS_STOP"), lpszTitle, ICON_HAND);
nStatus = ERR_VOL_MOUNT_FAILED;
goto fv_end;
}
if (!IsAdmin () && IsUacSupported ())
retCode = UacFormatNtfs (volParams->hwndDlg, driveNo, volParams->clusterSize);
else
retCode = FormatNtfs (driveNo, volParams->clusterSize);
if (retCode != TRUE)
{
if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
if (dataAreaSize <= TC_MAX_FAT_SECTOR_COUNT * FormatSectorSize)
{
if (AskErrYesNo ("FORMAT_NTFS_FAILED_ASK_FAT") == IDYES)
{
// NTFS format failed and the user wants to try FAT format immediately
volParams->fileSystem = FILESYS_FAT;
bInstantRetryOtherFilesys = TRUE;
volParams->quickFormat = TRUE; // Volume has already been successfully TC-formatted
volParams->clusterSize = 0; // Default cluster size
goto begin_format;
}
}
else
Error ("FORMAT_NTFS_FAILED");
nStatus = ERR_DONT_REPORT;
goto fv_end;
}
if (!UnmountVolume (volParams->hwndDlg, driveNo, FALSE))
MessageBoxW (volParams->hwndDlg, GetString ("CANT_DISMOUNT_VOLUME"), lpszTitle, ICON_HAND);
}
fv_end:
dwError = GetLastError();
if (dosDev[0])
RemoveFakeDosName (volParams->volumePath, dosDev);
crypto_close (cryptoInfo);
SetLastError (dwError);
return nStatus;
}