Truecrypt代码Format分析(2)---核心函数TcFormatVolume( )详解(上)

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( )详解(下)
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值