Beispiel #1
0
BOOL EjectVolume( TCHAR cDriveLetter, BOOL reload )
{
   HANDLE hVolume;

   BOOL fRemoveSafely = FALSE;
   BOOL fAutoEject = FALSE;

   // Open the volume.
   hVolume = OpenVolume(cDriveLetter);
   if (hVolume == INVALID_HANDLE_VALUE)
       return FALSE;

   // Lock and dismount the volume.
   if (LockVolume(hVolume) && DismountVolume(hVolume)) {
       fRemoveSafely = TRUE;

       // Set prevent removal to false and eject the volume.
       if (PreventRemovalOfVolume(hVolume, FALSE) &&
           AutoEjectVolume(hVolume,reload))
           fAutoEject = TRUE;
   }

   // Close the volume so other processes can use the drive.
   if (!CloseVolume(hVolume))
       return FALSE;

   /*
	 if (fAutoEject)
       printf("Media in Drive %c has been ejected safely.\n", cDriveLetter);
   else {
       if (fRemoveSafely)
           printf("Media in Drive %c can be safely removed.\n", cDriveLetter);
   }
	 */

   return TRUE;
}
/*
	ExpandVolumeWizard

	Expands a trucrypt volume (wizard for user interface)

	Parameters:

		hwndDlg : HWND
			[in] handle to parent window (if any)

		szVolume : char *
			[in] Pointer to a string with the volume name (e.g. '\Device\Harddisk0\Partition1' or 'C:\topsecret.tc')

	Return value:

		none

*/
void ExpandVolumeWizard (HWND hwndDlg, char *lpszVolume)
{
	int nStatus = ERR_OS_ERROR;
	wchar_t szTmp[4096];
	Password VolumePassword;
	int VolumePkcs5 = 0;
	uint64 hostSize, volSize, hostSizeFree, maxSizeFS;
	BOOL bIsDevice, bIsLegacy;
	DWORD dwError;
	int driveNo;
	enum EV_FileSystem volFSType;
	char rootPath[] = "A:\\";

	switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE))
	{
	case 1:
	case 2:
		MessageBoxW (hwndDlg, L"A VeraCrypt system volume can't be expanded.", lpszTitle, MB_OK|MB_ICONEXCLAMATION);
		goto ret;
	}

	EnableElevatedCursorChange (hwndDlg);
	WaitCursor();

	if (IsMountedVolume (lpszVolume))
	{
		Warning ("DISMOUNT_FIRST", hwndDlg);
		goto ret;
	}

	if (Randinit() != ERR_SUCCESS) {
		nStatus = ERR_PARAMETER_INCORRECT;
		goto error;
	}

	NormalCursor();

	// Ask the user if there is a hidden volume
	char *volTypeChoices[] = {0, "DOES_VOLUME_CONTAIN_HIDDEN", "VOLUME_CONTAINS_HIDDEN", "VOLUME_DOES_NOT_CONTAIN_HIDDEN", "IDCANCEL", 0};
	switch (AskMultiChoice ((void **) volTypeChoices, FALSE, hwndDlg))
	{
	case 1:
		MessageBoxW (hwndDlg, L"An outer volume containing a hidden volume can't be expanded, because this destroys the hidden volume.", lpszTitle, MB_OK|MB_ICONEXCLAMATION);
		goto ret;

	case 2:
		break;

	default:
		nStatus = ERR_SUCCESS;
		goto ret;
	}

	WaitCursor();

	nStatus = QueryVolumeInfo(hwndDlg,lpszVolume,&hostSizeFree,&maxSizeFS);

	if (nStatus!=ERR_SUCCESS)
	{
		nStatus = ERR_OS_ERROR;
		goto error;
	}

	NormalCursor();

	while (TRUE)
	{
		OpenVolumeContext expandVol;
		BOOL truecryptMode = FALSE;

		if (!VeraCryptExpander::ExtcvAskVolumePassword (hwndDlg, &VolumePassword, &VolumePkcs5, &truecryptMode, "ENTER_NORMAL_VOL_PASSWORD", FALSE))
		{
			goto ret;
		}

		EnableElevatedCursorChange (hwndDlg);
		WaitCursor();

		if (KeyFilesEnable && FirstKeyFile)
			KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile);

		WaitCursor ();

		OpenVolumeThreadParam threadParam;
		threadParam.context = &expandVol;
		threadParam.volumePath = lpszVolume;
		threadParam.password = &VolumePassword;
		threadParam.pkcs5_prf = VolumePkcs5;
		threadParam.truecryptMode = FALSE;
		threadParam.write = FALSE;
		threadParam.preserveTimestamps = bPreserveTimestamp;
		threadParam.useBackupHeader = FALSE;
		threadParam.nStatus = &nStatus;

		ShowWaitDialog (hwndDlg, TRUE, OpenVolumeWaitThreadProc, &threadParam);

		NormalCursor ();

		dwError = GetLastError();

		if (nStatus == ERR_SUCCESS)
		{
			bIsDevice = expandVol.IsDevice;
			bIsLegacy = expandVol.CryptoInfo->LegacyVolume;
			hostSize = expandVol.HostSize;			
			VolumePkcs5 = expandVol.CryptoInfo->pkcs5;
			if ( bIsLegacy )
			{
				if ( bIsDevice ) 
					volSize = 0; // updated later
				else
					volSize = hostSize;
			}
			else
			{
				volSize = GetVolumeSizeByDataAreaSize (expandVol.CryptoInfo->VolumeSize.Value, bIsLegacy);
			}
			CloseVolume (&expandVol);
			break;
		}
		else if (nStatus != ERR_PASSWORD_WRONG)
		{
			SetLastError (dwError);
			goto error;
		}

		NormalCursor();

		handleError (hwndDlg, nStatus);
	}

	WaitCursor();

	// auto mount the volume to check the file system type
	nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, &VolumePassword, VolumePkcs5);

	if (nStatus != ERR_SUCCESS)
		goto error;

	rootPath[0] += driveNo;

	if ( !GetFileSystemType(rootPath,&volFSType) )
		volFSType = EV_FS_TYPE_RAW;

	if ( bIsLegacy && bIsDevice && volFSType == EV_FS_TYPE_NTFS )
	{
		uint64 NumberOfSectors;
		DWORD BytesPerSector;
		
		if ( !GetNtfsNumberOfSectors(rootPath, &NumberOfSectors, &BytesPerSector) )
			nStatus = ERR_OS_ERROR;

		// NTFS reported size does not include boot sector copy at volume end
		volSize = ( NumberOfSectors + 1 ) * BytesPerSector;
	}

	UnmountVolume (hwndDlg, driveNo, TRUE);

	NormalCursor();

	if (nStatus != ERR_SUCCESS)
		goto error;

	if ( bIsDevice && bIsLegacy && volFSType != EV_FS_TYPE_NTFS )
	{
		MessageBoxW (hwndDlg,
			L"Expanding a device hosted legacy volume with no NTFS file system\n"
			L"is unsupported.\n"
			L"Note that expanding the VeraCrypt volume itself is not neccessary\n"
			L"for legacy volumes.\n",
			lpszTitle, MB_OK|MB_ICONEXCLAMATION);
		goto ret;
	}

	// check if there is enough free space on host device/drive to expand the volume
	if ( (bIsDevice && hostSize < volSize + TC_MINVAL_FS_EXPAND) || (!bIsDevice && hostSizeFree < TC_MINVAL_FS_EXPAND) )
	{
		MessageBoxW (hwndDlg, L"Not enough free space to expand the volume", lpszTitle, MB_OK|MB_ICONEXCLAMATION);
		goto ret;
	}

	if (!bIsDevice && hostSize != volSize ) {
		// there is some junk data at the end of the volume
		if (MessageBoxW (hwndDlg, L"Warning: The container file is larger than the VeraCrypt volume area. The data after the VeraCrypt volume area will be overwritten.\n\nDo you want to continue?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
			goto ret;
	}

	switch (volFSType)
	{
	case EV_FS_TYPE_NTFS:
		break;
	case EV_FS_TYPE_FAT:
		if (MessageBoxW (hwndDlg,L"Warning: The VeraCrypt volume contains a FAT file system!\n\nOnly the VeraCrypt volume itself will be expanded, but not the file system.\n\nDo you want to continue?",
			lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
			goto ret;
		break;
	default:
		if (MessageBoxW (hwndDlg,L"Warning: The VeraCrypt volume contains an unknown or no file system!\n\nOnly the VeraCrypt volume itself will be expanded, the file system remains unchanged.\n\nDo you want to continue?",
			lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
			goto ret;
	}

	EXPAND_VOL_THREAD_PARAMS VolExpandParam;

	VolExpandParam.bInitFreeSpace = (bIsLegacy && bIsDevice) ? FALSE:TRUE;
	VolExpandParam.szVolumeName = lpszVolume;
	VolExpandParam.FileSystem = volFSType;
	VolExpandParam.pVolumePassword = &VolumePassword;
	VolExpandParam.VolumePkcs5 = VolumePkcs5;
	VolExpandParam.bIsDevice = bIsDevice;
	VolExpandParam.bIsLegacy = bIsLegacy;
	VolExpandParam.oldSize = bIsDevice ? volSize : hostSize;
	VolExpandParam.newSize = hostSize;
	VolExpandParam.hostSizeFree = hostSizeFree;

	while (1)
	{
		uint64 newVolumeSize;

		if (IDCANCEL == DialogBoxParamW (hInst,
			MAKEINTRESOURCEW (IDD_SIZE_DIALOG), hwndDlg,
			(DLGPROC) ExpandVolSizeDlgProc, (LPARAM) &VolExpandParam))
		{
			goto ret;
		}

		newVolumeSize = VolExpandParam.newSize;

		if ( !bIsDevice )
		{
			if ( newVolumeSize < hostSize + TC_MINVAL_FS_EXPAND)
			{
				swprintf(szTmp,L"New volume size too small, must be at least %I64u kB larger than the current size.",TC_MINVAL_FS_EXPAND/BYTES_PER_KB);
				MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
				continue;
			}

			if ( newVolumeSize - hostSize > hostSizeFree )
			{
				swprintf(szTmp,L"New volume size too large, not enough space on host drive.");
				MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
				continue;
			}

			if ( newVolumeSize>maxSizeFS )
			{
				swprintf(szTmp,L"Maximum file size of %I64u MB on host drive exceeded.",maxSizeFS/BYTES_PER_MB);
				MessageBoxW (hwndDlg, L"!\n",lpszTitle, MB_OK | MB_ICONEXCLAMATION );
				continue;
			}
		}

		if ( newVolumeSize > TC_MAX_VOLUME_SIZE )
		{
			// note: current limit TC_MAX_VOLUME_SIZE is 1 PetaByte
			swprintf(szTmp,L"Maximum VeraCrypt volume size of %I64u TB exceeded!\n",TC_MAX_VOLUME_SIZE/BYTES_PER_TB);
			MessageBoxW (hwndDlg, szTmp,lpszTitle, MB_OK | MB_ICONEXCLAMATION );
			if (bIsDevice)
				break; // TODO: ask to limit volume size to TC_MAX_VOLUME_SIZE
			continue;
		}

		break;
	}

	VolExpandParam.oldSize = volSize;

	// start progress dialog
	DialogBoxParamW (hInst,	MAKEINTRESOURCEW (IDD_EXPAND_PROGRESS_DLG), hwndDlg,
		(DLGPROC) ExpandVolProgressDlgProc, (LPARAM) &VolExpandParam );

ret:
	nStatus = ERR_SUCCESS;

error:

	if (nStatus != 0)
		handleError (hwndDlg, nStatus);

	burn (&VolumePassword, sizeof (VolumePassword));

	RestoreDefaultKeyFilesParam();
	RandStop (FALSE);
	NormalCursor();

	return;
}