TCFormatVolume()函数位于\Common\Format.c文件中.
int TCFormatVolume (volatile FORMAT_VOL_PARAMETERS *volParams)
{
// 定义变量
int nStatus;
PCRYPTO_INFO cryptoInfo = NULL;
HANDLE dev = INVALID_HANDLE_VALUE;
DWORD dwError;
char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
unsigned __int64 num_sectors, startSector;
fatparams ft;
FILETIME ftCreationTime;
FILETIME ftLastWriteTime;
FILETIME ftLastAccessTime;
BOOL bTimeStampValid = FALSE;
BOOL bInstantRetryOtherFilesys = FALSE;
char dosDev[TC_MAX_PATH] = { 0 };
char devName[MAX_PATH] = { 0 };
int driveLetter = -1;
WCHAR deviceName[MAX_PATH];
uint64 dataOffset, dataAreaSize;
LARGE_INTEGER offset;
BOOL bFailedRequiredDASD = FALSE;
FormatSectorSize = volParams->sectorSize;
// 判断FormatSectorSize是否符合,format_sector规范
if (FormatSectorSize < TC_MIN_VOLUME_SECTOR_SIZE
|| FormatSectorSize > TC_MAX_VOLUME_SECTOR_SIZE
|| FormatSectorSize % ENCRYPTION_DATA_UNIT_SIZE != 0)
{
Error ("SECTOR_SIZE_UNSUPPORTED");
return ERR_DONT_REPORT;
}
//下面确定 dataOffset
if(volParams->hiddenVol)
{
//如果为hiddenVol
dataOffset = volParams->hiddenVolHostSize - TC_VOLUME_HEADER_GROUP_SIZE - volParams->size;
}
else
{
//否则为非hiddenVol
//....
dataOffset = TC_VOLUME_DATA_OFFSET;
}
// 获得Volume数据区的大小,用以确定sector的数目
dataAreaSize = GetVolumeDataAreaSize (volParams->hiddenVol, volParams->size);
num_sector = dataAreaSize / FormatSectorSize;
// 如果加密的是一个分区卷
if(volParams->bDevice)
{
strcpy ((char *)deviceName, volParams->volumePath);
ToUNICODE ((char *)deviceName);
//获取DriverLetter
driveLetter = GetDiskDeviceDriveLetter (deviceName);
}
VirtualLock (header, sizeof (header));
// Creates a volume header in memory
// 该函数的详细分析见下文,主要是创建一个与加密信息相关的volume header
nStatus =CreateVolumeHeaderInMemory(FALSE,
header,
volParams->ea,
FIRST_MODE_OF_OPERATION_ID,
volParams->password,
volParams->pkcs5,
NULL,
&cryptoInfo,
dataAreaSize,
volParams->hiddenVol ? dataAreaSize : 0,
dataOffset,
dataAreaSize,
0,
volParams->headerFlags,
FormatSectorSize,
FALSE);
if (nStatus != 0)
{
burn (header, sizeof (header));
VirtualUnlock (header, sizeof (header));
return nStatus;
}
// 下面进行format操作
begin_format:
//如果加密的是一个分区卷
if(volParams->bDevice)
{
DWORD dwResult;
int nPass;
//
// FakeDosNameForDevice()函数内部调用DefineDosDevice().
// 传递DDD_RAW_TARGET_PATH,假装将path string 转化为 device name,通过返回值
// 来判断是否真能转换.
// bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile);
if(FakeDosNameForDevice(volParams->volumePath,dosDev,devName,FALSE) != 0 )
{
return ERR_OS_ERROR;
}
// IsDeviceMounted()函数内部调用DeviceIoControl,通过向驱动发送IOCLT_CODE,
// 即FSCTL_IS_VOLUME_MOUNTED,来判断Device是否已经Mounted了.
if (IsDeviceMounted (devName))
{
// 如果该Device已经被Mounted了,那么则调用DismountDrive()函数.
// 向驱动发送FSCTL_DISMOUNT_VOLUME,对Device进行Dismount.
if ((dev = DismountDrive (devName, volParams->volumePath)) == INVALID_HANDLE_VALUE)
{
Error ("FORMAT_CANT_DISMOUNT_FILESYS");
nStatus = ERR_DONT_REPORT;
goto error;
}
/* Gain "raw" access to the partition (it contains a live filesystem and the filesystem driver
would otherwise prevent us from writing to hidden sectors). */
// 获得该分区的"raw" access
if (!DeviceIoControl (dev,
FSCTL_ALLOW_EXTENDED_DASD_IO,
NULL,
0,
NULL,
0,
&dwResult,
NULL))
{
// 如果获取失败,则设置bFailedRequiredDASD为TRUE
bFailedRequiredDASD = TRUE;
}
}
//下面 else if {...}针对是对WIN_VISTA的讨论,
//因为VISTA在一个没被格式化且没有分配驱动盘符之前,是不允许对该磁盘的Sector overwritting的.
//解决这个难题的话,所以就只能临时分配一个盘符给这个分区.
else if (IsOSAtLeast (WIN_VISTA) && driveLetter == -1)
{
// Windows Vista doesn't allow overwriting sectors belonging to an unformatted partition
// to which no drive letter has been assigned under the system. This problem can be worked
// around by assigning a drive letter to the partition temporarily.
char szDriveLetter[] = { 'A', ':', 0 };
char rootPath[] = { 'A', ':', '\\', 0 };
char uniqVolName[MAX_PATH+1] = { 0 };
int tmpDriveLetter = -1;
BOOL bResult = FALSE;
tmpDriveLetter = GetFirstAvailableDrive ();
if (tmpDriveLetter != -1)
{
rootPath[0] += (char) tmpDriveLetter;
szDriveLetter[0] += (char) tmpDriveLetter;
if (DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter, volParams->volumePath))
{
bResult = GetVolumeNameForVolumeMountPoint (rootPath, uniqVolName, MAX_PATH);
DefineDosDevice (DDD_RAW_TARGET_PATH|DDD_REMOVE_DEFINITION|DDD_EXACT_MATCH_ON_REMOVE,
szDriveLetter,
volParams->volumePath);
if (bResult
&& SetVolumeMountPoint (rootPath, uniqVolName))
{
// The drive letter can be removed now
DeleteVolumeMountPoint (rootPath);
}
}
}
}
// For extra safety, we will try to gain "raw" access to the partition. Note that this should actually be
// redundant because if the filesystem was mounted, we already tried to obtain DASD above. If we failed,
// bFailedRequiredDASD was set to TRUE and therefore we will perform pseudo "quick format" below. However,
// for extra safety, in case IsDeviceMounted() failed to detect a live filesystem, we will blindly
// send FSCTL_ALLOW_EXTENDED_DASD_IO (possibly for a second time) without checking the result.
// 上面的英文意思说是为了安全起见,所以要发送FSCTL_ALLOW_EXTENDED_DASD_IO这个操作码,second_time...
DeviceIoControl (dev,
FSCTL_ALLOW_EXTENDED_DASD_IO,
NULL,
0,
NULL,
0,
&dwResult,
NULL);
}
// If DASD is needed but we failed to obtain it, perform open - 'quick format' - close - open
// so that the filesystem driver does not prevent us from formatting hidden sectors.
//上面的意思说的是,如果我们获得DASD失败,执行 open - 'quick format'-close -open
// 然后文件系统就不会阻止我们进行格式化隐藏扇区的操作了....
for (nPass = (bFailedRequiredDASD ? 0 : 1); nPass < 2; nPass++)
{
int retryCount;
retryCount = 0;
// Try exclusive access mode first
// Note that when exclusive access is denied, it is worth retrying (usually succeeds after a few tries).
// 进行独占模式的访问尝试,如果最高模式被禁止了,那么值得进行retry...
while (dev == INVALID_HANDLE_VALUE && retryCount++ < EXCL_ACCESS_MAX_AUTO_RETRIES)
{
dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (retryCount > 1)
Sleep (EXCL_ACCESS_AUTO_RETRY_DELAY);
}
if (dev == INVALID_HANDLE_VALUE)
{
// Exclusive access denied -- retry in shared mode
// 如果独占模式访问被禁止,那么尝试一下 share_mode
dev = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (dev != INVALID_HANDLE_VALUE)
{
if (IDNO == MessageBoxW (volParams->hwndDlg, GetString ("DEVICE_IN_USE_FORMAT"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2))
{
nStatus = ERR_DONT_REPORT;
goto error;
}
}
else
{
handleWin32Error (volParams->hwndDlg);
Error ("CANT_ACCESS_VOL");
nStatus = ERR_DONT_REPORT;
goto error;
}
}
if (volParams->hiddenVol || bInstantRetryOtherFilesys)
break; // The following "quick format" operation would damage the outer volume
if (nPass == 0)
{
char buf [2 * TC_MAX_VOLUME_SECTOR_SIZE];
DWORD bw;
// Perform pseudo "quick format" so that the filesystem driver does not prevent us from
// formatting hidden sectors
// 执行"快速格式化",快速格式化实际就是抹去FAT表,也就是往FAT表中填0.
memset (buf, 0, sizeof (buf));
if (!WriteFile (dev, buf, sizeof (buf), &bw, NULL))
{
nStatus = ERR_OS_ERROR;
goto error;
}
// The FlushFileBuffers function flushes the buffers of the specified file and causes all buffered data to be written to the file.
FlushFileBuffers (dev);
CloseHandle (dev);
dev = INVALID_HANDLE_VALUE;
}
}
// 如果 VOLUME 已经 MOUNTED了,那么执行FORMAT操作的时候会失败的.
if (DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL))
{
Error ("FORMAT_CANT_DISMOUNT_FILESYS");
nStatus = ERR_DONT_REPORT;
goto error;
}
}// 对与分区加密的讨论就结束了,下面是 file_container 的讨论.
else
{
//file_container 部分参见下篇Truecrypt代码Format分析(2)---核心函数TcFormatVolume( )详解(下)
}
}