mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-11 11:08:02 -06:00
845 lines
24 KiB
C++
845 lines
24 KiB
C++
/*
|
|
Legal Notice: Some portions of the source code contained in this file were
|
|
derived from the source code of TrueCrypt 7.1a, which is
|
|
Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
|
|
governed by the TrueCrypt License 3.0, also from the source code of
|
|
Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
|
|
and which is governed by the 'License Agreement for Encryption for the Masses'
|
|
and also from the source code of extcv, which is Copyright (c) 2009-2010 Kih-Oskh
|
|
or Copyright (c) 2012-2013 Josef Schneider <josef@netpage.dk>
|
|
|
|
Modifications and additions to the original source code (contained in this file)
|
|
and all other portions of this file are Copyright (c) 2013-2017 IDRIX
|
|
and are governed by the Apache License 2.0 the full text of which is
|
|
contained in the file License.txt included in VeraCrypt binary and source
|
|
code distribution packages. */
|
|
|
|
#include "Tcdefs.h"
|
|
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include <dbt.h>
|
|
#include <fcntl.h>
|
|
#include <io.h>
|
|
#include <sys/stat.h>
|
|
#include <windowsx.h>
|
|
#include <stdio.h>
|
|
|
|
#include "Apidrvr.h"
|
|
#include "Volumes.h"
|
|
#include "Crypto.h"
|
|
#include "Dlgcode.h"
|
|
#include "Language.h"
|
|
#include "Pkcs5.h"
|
|
#include "Random.h"
|
|
// #include "../Mount/Mount.h"
|
|
|
|
#include "../Common/Dictionary.h"
|
|
#include "../Common/Common.h"
|
|
#include "../Common/Resource.h"
|
|
#include "../Common/SecurityToken.h"
|
|
#include "../Common/Progress.h"
|
|
|
|
#include "ExpandVolume.h"
|
|
#include "Resource.h"
|
|
|
|
// TO DO: display sector sizes different than 512 bytes
|
|
#define SECTOR_SIZE_MSG 512
|
|
|
|
#define TIMER_ID_RANDVIEW 0xff
|
|
#define TIMER_INTERVAL_RANDVIEW 50
|
|
|
|
BOOL bSeManageVolumeNameSet = FALSE;
|
|
|
|
// see definition of enum EV_FileSystem
|
|
const wchar_t * szFileSystemStr[4] = {L"RAW",L"FAT",L"NTFS",L"EXFAT"};
|
|
|
|
// prototypes for internal functions
|
|
BOOL CALLBACK ExpandVolSizeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
namespace VeraCryptExpander
|
|
{
|
|
/* defined in WinMain.c, referenced by ExpandVolumeWizard() */
|
|
int ExtcvAskVolumePassword (HWND hwndDlg, const wchar_t* fileName, Password *password, int *pkcs5, int *pim, char *titleStringId, BOOL enableMountOptions);
|
|
}
|
|
|
|
|
|
int GetSpaceString(wchar_t *dest, size_t cbDest, uint64 size, BOOL bDevice)
|
|
{
|
|
const wchar_t * szFmtBytes = L"%.0lf %s";
|
|
const wchar_t * szFmtOther = L"%.2lf %s";
|
|
const wchar_t * SuffixStr[] = {GetString("BYTE"), GetString("KB"), GetString("MB"), GetString("GB"), GetString("TB")};
|
|
const uint64 Muliplier[] = {1, BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
|
|
const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
|
|
int i;
|
|
|
|
for (i=1; i<=nMaxSuffix && size>Muliplier[i]; i++) ;
|
|
|
|
--i;
|
|
|
|
if (bDevice) {
|
|
wchar_t szTemp[512];
|
|
|
|
if (StringCbPrintfW(szTemp, sizeof(szTemp),i?szFmtOther:szFmtBytes, size/(double)Muliplier[i], SuffixStr[i]) < 0 )
|
|
return -1;
|
|
|
|
return StringCbPrintfW(dest, cbDest, L"%I64u sectors (%s)", size/SECTOR_SIZE_MSG , szTemp);
|
|
}
|
|
|
|
return StringCbPrintfW(dest, cbDest,i?szFmtOther:szFmtBytes, size/(double)Muliplier[i], SuffixStr[i]);
|
|
}
|
|
|
|
void SetCurrentVolSize(HWND hwndDlg, uint64 size)
|
|
{
|
|
const uint64 Muliplier[] = {BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
|
|
const int IdRadioBtn[] = {IDC_KB, IDC_MB, IDC_GB, IDC_TB};
|
|
const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
|
|
int i;
|
|
wchar_t szTemp[256];
|
|
|
|
for (i=1; i<=nMaxSuffix && size>Muliplier[i]; i++) ;
|
|
|
|
--i;
|
|
|
|
SendDlgItemMessage (hwndDlg, IdRadioBtn[i], BM_SETCHECK, BST_CHECKED, 0);
|
|
StringCbPrintfW(szTemp,sizeof(szTemp),L"%I64u",size/Muliplier[i]);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTemp);
|
|
}
|
|
|
|
uint64 GetSizeBoxMultiplier(HWND hwndDlg)
|
|
{
|
|
const uint64 Muliplier[] = {BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
|
|
const int IdRadioBtn[] = {IDC_KB, IDC_MB, IDC_GB, IDC_TB};
|
|
const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
|
|
int i;
|
|
|
|
for (i=nMaxSuffix; i>0 && !IsButtonChecked (GetDlgItem (hwndDlg, IdRadioBtn[i])); --i) ;
|
|
|
|
return Muliplier[i];
|
|
}
|
|
|
|
void HandleQuickExpanddCheckBox (HWND hwndDlg)
|
|
{
|
|
if (IsButtonChecked (GetDlgItem (hwndDlg, IDC_INIT_NEWSPACE)))
|
|
{
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKEXPAND), FALSE);
|
|
SendDlgItemMessage (hwndDlg, IDC_QUICKEXPAND, BM_SETCHECK, BST_UNCHECKED, 0);
|
|
}
|
|
else
|
|
{
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_QUICKEXPAND), TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL CALLBACK ExpandVolSizeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static EXPAND_VOL_THREAD_PARAMS *pVolExpandParam;
|
|
|
|
WORD lw = LOWORD (wParam);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
wchar_t szTemp[4096];
|
|
|
|
pVolExpandParam = (EXPAND_VOL_THREAD_PARAMS*)lParam;
|
|
|
|
LocalizeDialog (hwndDlg, NULL);
|
|
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), !pVolExpandParam->bIsDevice);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_KB), !pVolExpandParam->bIsDevice);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_MB), !pVolExpandParam->bIsDevice);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_GB), !pVolExpandParam->bIsDevice);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_TB), !pVolExpandParam->bIsDevice);
|
|
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_INIT_NEWSPACE),
|
|
!(pVolExpandParam->bIsLegacy && pVolExpandParam->bIsDevice));
|
|
SendDlgItemMessage (hwndDlg, IDC_INIT_NEWSPACE, BM_SETCHECK,
|
|
pVolExpandParam->bInitFreeSpace ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
|
|
if (!pVolExpandParam->bIsDevice)
|
|
SetCurrentVolSize(hwndDlg,pVolExpandParam->oldSize);
|
|
|
|
SendMessage (GetDlgItem (hwndDlg, IDC_BOX_HELP), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE);
|
|
|
|
GetSpaceString(szTemp,sizeof(szTemp),pVolExpandParam->oldSize,pVolExpandParam->bIsDevice);
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_OLDSIZE), szTemp);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NAME), pVolExpandParam->szVolumeName);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_FILE_SYSTEM), szFileSystemStr[pVolExpandParam->FileSystem]);
|
|
|
|
if (pVolExpandParam->bIsDevice)
|
|
{
|
|
GetSpaceString(szTemp,sizeof(szTemp),pVolExpandParam->newSize,TRUE);
|
|
}
|
|
else
|
|
{
|
|
wchar_t szHostFreeStr[256];
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDT_NEW_SIZE), L"");
|
|
GetSpaceString(szHostFreeStr,sizeof(szHostFreeStr),pVolExpandParam->hostSizeFree,FALSE);
|
|
StringCbPrintfW (szTemp,sizeof(szTemp),GetString("EXPANDER_FREE_SPACE"), szHostFreeStr);
|
|
|
|
if (!pVolExpandParam->bDisableQuickExpand)
|
|
{
|
|
ShowWindow (GetDlgItem (hwndDlg, IDC_QUICKEXPAND), SW_SHOW);
|
|
HandleQuickExpanddCheckBox (hwndDlg);
|
|
}
|
|
}
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NEWSIZE), szTemp);
|
|
|
|
// set help text
|
|
if (pVolExpandParam->bIsDevice)
|
|
{
|
|
StringCbPrintfW (szTemp,sizeof(szTemp),GetString("EXPANDER_HELP_DEVICE"));
|
|
if (pVolExpandParam->bIsLegacy)
|
|
StringCbCatW(szTemp,sizeof(szTemp),L" Note: filling the new space with random data is not supported for legacy volumes.");
|
|
}
|
|
else
|
|
{
|
|
StringCbPrintfW (szTemp, sizeof(szTemp),GetString("EXPANDER_HELP_FILE"),TC_MINVAL_FS_EXPAND/1024);
|
|
}
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_BOX_HELP), szTemp);
|
|
|
|
}
|
|
return 0;
|
|
|
|
|
|
case WM_COMMAND:
|
|
if (lw == IDCANCEL)
|
|
{
|
|
EndDialog (hwndDlg, lw);
|
|
return 1;
|
|
}
|
|
|
|
if (lw == IDC_CONTINUE)
|
|
{
|
|
wchar_t szTemp[4096];
|
|
|
|
pVolExpandParam->bInitFreeSpace = IsButtonChecked (GetDlgItem (hwndDlg, IDC_INIT_NEWSPACE));
|
|
pVolExpandParam->bQuickExpand = IsButtonChecked (GetDlgItem (hwndDlg, IDC_QUICKEXPAND));
|
|
if (!pVolExpandParam->bIsDevice) // for devices new size is set by calling function
|
|
{
|
|
GetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTemp, ARRAYSIZE (szTemp));
|
|
pVolExpandParam->newSize = _wtoi64(szTemp) * GetSizeBoxMultiplier(hwndDlg);
|
|
}
|
|
|
|
EndDialog (hwndDlg, lw);
|
|
return 1;
|
|
}
|
|
|
|
if (lw == IDC_INIT_NEWSPACE && !pVolExpandParam->bDisableQuickExpand)
|
|
{
|
|
HandleQuickExpanddCheckBox (hwndDlg);
|
|
return 1;
|
|
}
|
|
|
|
if (lw == IDC_QUICKEXPAND && IsButtonChecked (GetDlgItem (hwndDlg, IDC_QUICKEXPAND)))
|
|
{
|
|
// If quick expand selected, then we warn about security issue
|
|
if (MessageBoxW (hwndDlg, GetString ("QUICK_EXPAND_WARNING"),
|
|
lpszTitle, YES_NO|MB_ICONWARNING|MB_DEFBUTTON2) == IDNO)
|
|
{
|
|
SendDlgItemMessage (hwndDlg, IDC_QUICKEXPAND, BM_SETCHECK, BST_UNCHECKED, 0);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
extern "C" void AddProgressDlgStatus(HWND hwndDlg, const wchar_t* szText)
|
|
{
|
|
HWND hwndCtrl;
|
|
|
|
hwndCtrl = GetDlgItem (hwndDlg,IDC_BOX_STATUS);
|
|
SendMessage(hwndCtrl,EM_REPLACESEL,FALSE,(LPARAM)szText);
|
|
SendMessage(hwndCtrl,EM_SCROLLCARET,0,0);
|
|
}
|
|
|
|
|
|
extern "C" void SetProgressDlgStatus(HWND hwndDlg, const wchar_t* szText)
|
|
{
|
|
HWND hwndCtrl;
|
|
|
|
hwndCtrl = GetDlgItem (hwndDlg,IDC_BOX_STATUS);
|
|
SendMessage(hwndCtrl,EM_SETSEL,0,-1);
|
|
SendMessage(hwndCtrl,EM_REPLACESEL,FALSE,(LPARAM)szText);
|
|
SendMessage(hwndCtrl,EM_SCROLLCARET,0,0);
|
|
}
|
|
|
|
|
|
BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
static EXPAND_VOL_THREAD_PARAMS *pProgressDlgParam;
|
|
static BOOL bVolTransformStarted = FALSE;
|
|
static BOOL showRandPool = TRUE;
|
|
static unsigned char randPool[16];
|
|
static unsigned char maskRandPool [16];
|
|
static BOOL bUseMask = FALSE;
|
|
static DWORD mouseEntropyGathered = 0xFFFFFFFF;
|
|
static DWORD mouseEventsInitialCount = 0;
|
|
/* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */
|
|
static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8;
|
|
static HWND hEntropyBar = NULL;
|
|
|
|
WORD lw = LOWORD (wParam);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
wchar_t szOldHostSize[512], szNewHostSize[512];
|
|
HCRYPTPROV hRngProv;
|
|
|
|
pProgressDlgParam = (EXPAND_VOL_THREAD_PARAMS*)lParam;
|
|
bVolTransformStarted = FALSE;
|
|
showRandPool = FALSE;
|
|
|
|
hCurPage = hwndDlg;
|
|
nPbar = IDC_PROGRESS_BAR;
|
|
|
|
VirtualLock (randPool, sizeof(randPool));
|
|
VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered));
|
|
VirtualLock (maskRandPool, sizeof(maskRandPool));
|
|
|
|
LocalizeDialog (hwndDlg, NULL);
|
|
|
|
mouseEntropyGathered = 0xFFFFFFFF;
|
|
mouseEventsInitialCount = 0;
|
|
bUseMask = FALSE;
|
|
if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
|
{
|
|
if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool))
|
|
bUseMask = TRUE;
|
|
CryptReleaseContext (hRngProv, 0);
|
|
}
|
|
|
|
GetSpaceString(szOldHostSize,sizeof(szOldHostSize),pProgressDlgParam->oldSize,pProgressDlgParam->bIsDevice);
|
|
GetSpaceString(szNewHostSize,sizeof(szNewHostSize),pProgressDlgParam->newSize,pProgressDlgParam->bIsDevice);
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_OLDSIZE), szOldHostSize);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NEWSIZE), szNewHostSize);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NAME), pProgressDlgParam->szVolumeName);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_FILE_SYSTEM), szFileSystemStr[pProgressDlgParam->FileSystem]);
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_INITSPACE), pProgressDlgParam->bInitFreeSpace?GetString("UISTR_YES"):GetString("UISTR_NO"));
|
|
|
|
SendMessage (GetDlgItem (hwndDlg, IDC_BOX_STATUS), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE);
|
|
|
|
SendMessage (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE);
|
|
|
|
// set status text
|
|
if ( !pProgressDlgParam->bInitFreeSpace && pProgressDlgParam->bIsLegacy )
|
|
{
|
|
showRandPool = FALSE;
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), FALSE);
|
|
SetDlgItemText(hwndDlg, IDC_BOX_STATUS, GetString("EXPANDER_STATUS_TEXT_LEGACY"));
|
|
}
|
|
else
|
|
{
|
|
SetDlgItemText(hwndDlg, IDC_BOX_STATUS, GetString("EXPANDER_STATUS_TEXT"));
|
|
}
|
|
|
|
SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, BST_UNCHECKED, 0);
|
|
hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR);
|
|
SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel);
|
|
SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0);
|
|
SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL);
|
|
}
|
|
return 0;
|
|
case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED:
|
|
{
|
|
int nStatus = (int)lParam;
|
|
|
|
NormalCursor ();
|
|
if (nStatus != 0)
|
|
{
|
|
if ( nStatus != ERR_USER_ABORT )
|
|
AddProgressDlgStatus (hwndDlg, GetString("EXPANDER_FINISH_ERROR"));
|
|
else
|
|
AddProgressDlgStatus (hwndDlg, GetString("EXPANDER_FINISH_ABORT"));
|
|
}
|
|
else
|
|
{
|
|
AddProgressDlgStatus (hwndDlg, GetString("EXPANDER_FINISH_OK"));
|
|
}
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_CONTINUE), GetString("EXIT"));
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_CONTINUE), TRUE);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE);
|
|
}
|
|
return 1;
|
|
|
|
case WM_TIMER:
|
|
|
|
switch (wParam)
|
|
{
|
|
case TIMER_ID_RANDVIEW:
|
|
{
|
|
wchar_t szRndPool[64] = {0};
|
|
DWORD mouseEventsCounter;
|
|
|
|
RandpeekBytes (hwndDlg, randPool, sizeof (randPool),&mouseEventsCounter);
|
|
|
|
ProcessEntropyEstimate (hEntropyBar, &mouseEventsInitialCount, mouseEventsCounter, maxEntropyLevel, &mouseEntropyGathered);
|
|
|
|
if (showRandPool)
|
|
StringCbPrintfW (szRndPool, sizeof(szRndPool), L"%08X%08X%08X%08X",
|
|
*((DWORD*) (randPool + 12)), *((DWORD*) (randPool + 8)), *((DWORD*) (randPool + 4)), *((DWORD*) (randPool)));
|
|
else if (bUseMask)
|
|
{
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
wchar_t tmp2[3];
|
|
unsigned char tmpByte = randPool[i] ^ maskRandPool[i];
|
|
tmp2[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*');
|
|
tmp2[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*');
|
|
tmp2[2] = 0;
|
|
StringCbCatW (szRndPool, sizeof(szRndPool), tmp2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wmemset (szRndPool, L'*', 32);
|
|
}
|
|
|
|
SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), szRndPool);
|
|
|
|
burn (randPool, sizeof(randPool));
|
|
burn (szRndPool, sizeof(szRndPool));
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
case WM_COMMAND:
|
|
if (lw == IDC_DISPLAY_POOL_CONTENTS)
|
|
{
|
|
showRandPool = IsButtonChecked (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS));
|
|
return 1;
|
|
}
|
|
if (lw == IDCANCEL)
|
|
{
|
|
if (bVolTransformStarted)
|
|
{
|
|
if (MessageBoxW (hwndDlg, GetString("EXPANDER_CANCEL_WARNING"), lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
|
|
return 1;
|
|
|
|
// tell the volume transform thread to terminate
|
|
bVolTransformThreadCancel = TRUE;
|
|
}
|
|
NormalCursor ();
|
|
EndDialog (hwndDlg, lw);
|
|
return 1;
|
|
}
|
|
|
|
if (lw == IDC_CONTINUE)
|
|
{
|
|
if (bVolTransformStarted)
|
|
{
|
|
// TransformThreadFunction finished -> OK button is now exit
|
|
NormalCursor ();
|
|
EndDialog (hwndDlg, lw);
|
|
}
|
|
else
|
|
{
|
|
showRandPool = FALSE;
|
|
KillTimer (hwndDlg, TIMER_ID_RANDVIEW);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE);
|
|
EnableWindow (GetDlgItem (hwndDlg, IDC_CONTINUE), FALSE);
|
|
SetProgressDlgStatus (hwndDlg, GetString("EXPANDER_STARTING_STATUS"));
|
|
bVolTransformStarted = TRUE;
|
|
pProgressDlgParam->hwndDlg = hwndDlg;
|
|
if ( _beginthread (volTransformThreadFunction, 0, pProgressDlgParam) == -1L )
|
|
{
|
|
handleError (hwndDlg, ERR_OS_ERROR, SRC_POS);
|
|
EndDialog (hwndDlg, lw);
|
|
}
|
|
WaitCursor();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_NCDESTROY:
|
|
burn (randPool, sizeof (randPool));
|
|
burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount));
|
|
burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered));
|
|
burn (maskRandPool, sizeof(maskRandPool));
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
typedef struct
|
|
{
|
|
OpenVolumeContext *context;
|
|
const wchar_t *volumePath;
|
|
Password *password;
|
|
int pkcs5_prf;
|
|
int pim;
|
|
BOOL write;
|
|
BOOL preserveTimestamps;
|
|
BOOL useBackupHeader;
|
|
int* nStatus;
|
|
} OpenVolumeThreadParam;
|
|
|
|
void CALLBACK OpenVolumeWaitThreadProc(void* pArg, HWND hwndDlg)
|
|
{
|
|
OpenVolumeThreadParam* pThreadParam = (OpenVolumeThreadParam*) pArg;
|
|
|
|
*(pThreadParam)->nStatus = OpenVolume(pThreadParam->context, pThreadParam->volumePath, pThreadParam->password, pThreadParam->pkcs5_prf,
|
|
pThreadParam->pim, pThreadParam->write, pThreadParam->preserveTimestamps, pThreadParam->useBackupHeader);
|
|
}
|
|
|
|
/*
|
|
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, wchar_t *lpszVolume)
|
|
{
|
|
int nStatus = ERR_OS_ERROR;
|
|
wchar_t szTmp[4096];
|
|
Password VolumePassword;
|
|
int VolumePkcs5 = 0, VolumePim = -1;
|
|
uint64 hostSize, volSize, hostSizeFree, maxSizeFS;
|
|
BOOL bIsDevice, bIsLegacy;
|
|
DWORD dwError;
|
|
int driveNo;
|
|
enum EV_FileSystem volFSType;
|
|
wchar_t rootPath[] = L"A:\\";
|
|
|
|
switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE))
|
|
{
|
|
case 1:
|
|
case 2:
|
|
MessageBoxW (hwndDlg, GetString("EXPANDER_SYSTEM_VOLUME_ERROR"), lpszTitle, MB_OK|MB_ICONEXCLAMATION);
|
|
goto ret;
|
|
}
|
|
|
|
EnableElevatedCursorChange (hwndDlg);
|
|
WaitCursor();
|
|
|
|
if (IsMountedVolume (lpszVolume))
|
|
{
|
|
Warning ("DISMOUNT_FIRST", hwndDlg);
|
|
goto ret;
|
|
}
|
|
|
|
if (Randinit() != ERR_SUCCESS) {
|
|
if (CryptoAPILastError == ERROR_SUCCESS)
|
|
nStatus = ERR_RAND_INIT_FAILED;
|
|
else
|
|
nStatus = ERR_CAPI_INIT_FAILED;
|
|
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, GetString("EXPANDER_HIDDEN_VOLUME_ERROR"), 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;
|
|
|
|
if (!VeraCryptExpander::ExtcvAskVolumePassword (hwndDlg, lpszVolume, &VolumePassword, &VolumePkcs5, &VolumePim, "ENTER_NORMAL_VOL_PASSWORD", FALSE))
|
|
{
|
|
goto ret;
|
|
}
|
|
|
|
EnableElevatedCursorChange (hwndDlg);
|
|
WaitCursor();
|
|
|
|
if (KeyFilesEnable && FirstKeyFile)
|
|
KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile, lpszVolume);
|
|
|
|
|
|
OpenVolumeThreadParam threadParam;
|
|
threadParam.context = &expandVol;
|
|
threadParam.volumePath = lpszVolume;
|
|
threadParam.password = &VolumePassword;
|
|
threadParam.pkcs5_prf = VolumePkcs5;
|
|
threadParam.pim = VolumePim;
|
|
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, SRC_POS);
|
|
}
|
|
|
|
WaitCursor();
|
|
|
|
// auto mount the volume to check the file system type
|
|
nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, &VolumePassword, VolumePkcs5, VolumePim);
|
|
|
|
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, GetString("EXPANDER_NO_FREE_SPACE"), 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, GetString("EXPANDER_WARNING_FILE_CONTAINER_JUNK"), 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, GetString("EXPANDER_WARNING_FAT"),
|
|
lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
|
|
goto ret;
|
|
break;
|
|
case EV_FS_TYPE_EXFAT:
|
|
if (MessageBoxW (hwndDlg, GetString("EXPANDER_WARNING_EXFAT"),
|
|
lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
|
|
goto ret;
|
|
break;
|
|
default:
|
|
if (MessageBoxW (hwndDlg, GetString("EXPANDER_WARNING_UNKNOWN_FS"),
|
|
lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
|
|
goto ret;
|
|
}
|
|
|
|
EXPAND_VOL_THREAD_PARAMS VolExpandParam;
|
|
|
|
VolExpandParam.bInitFreeSpace = (bIsLegacy && bIsDevice) ? FALSE:TRUE;
|
|
VolExpandParam.bQuickExpand = FALSE;
|
|
VolExpandParam.bDisableQuickExpand = bIsDevice;
|
|
VolExpandParam.szVolumeName = lpszVolume;
|
|
VolExpandParam.FileSystem = volFSType;
|
|
VolExpandParam.pVolumePassword = &VolumePassword;
|
|
VolExpandParam.VolumePkcs5 = VolumePkcs5;
|
|
VolExpandParam.VolumePim = VolumePim;
|
|
VolExpandParam.bIsDevice = bIsDevice;
|
|
VolExpandParam.bIsLegacy = bIsLegacy;
|
|
VolExpandParam.oldSize = bIsDevice ? volSize : hostSize;
|
|
VolExpandParam.newSize = hostSize;
|
|
VolExpandParam.hostSizeFree = hostSizeFree;
|
|
|
|
// disable Quick Expand if the file is sparse or compressed
|
|
if (!bIsDevice)
|
|
{
|
|
DWORD dwFileAttrib = GetFileAttributesW (lpszVolume);
|
|
if (INVALID_FILE_ATTRIBUTES != dwFileAttrib)
|
|
{
|
|
if (dwFileAttrib & (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_SPARSE_FILE))
|
|
VolExpandParam.bDisableQuickExpand = TRUE;
|
|
}
|
|
}
|
|
|
|
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) && ((hostSize == volSize) || (newVolumeSize != hostSize) || ((hostSize - volSize) < TC_MINVAL_FS_EXPAND)))
|
|
{
|
|
StringCbPrintfW(szTmp,sizeof(szTmp),GetString("EXPANDER_ERROR_VOLUME_SIZE_TOO_SMALL"),TC_MINVAL_FS_EXPAND/BYTES_PER_KB);
|
|
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
continue;
|
|
}
|
|
|
|
if ( newVolumeSize - hostSize > hostSizeFree )
|
|
{
|
|
StringCbPrintfW(szTmp,sizeof(szTmp), GetString("EXPANDER_ERROR_VOLUME_SIZE_TOO_LARGE"));
|
|
MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
continue;
|
|
}
|
|
|
|
if ( newVolumeSize>maxSizeFS )
|
|
{
|
|
StringCbPrintfW(szTmp,sizeof(szTmp), GetString("EXPANDER_ERROR_MAX_FILE_SIZE_EXCEEDED"),maxSizeFS/BYTES_PER_MB);
|
|
MessageBoxW (hwndDlg, L"!\n",lpszTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
continue;
|
|
}
|
|
|
|
if (VolExpandParam.bQuickExpand && !bSeManageVolumeNameSet)
|
|
{
|
|
if (!SetPrivilege (SE_MANAGE_VOLUME_NAME, TRUE))
|
|
{
|
|
MessageBoxW (hwndDlg, GetString("EXPANDER_ERROR_QUICKEXPAND_PRIVILEGES"),lpszTitle, MB_OK | MB_ICONEXCLAMATION );
|
|
VolExpandParam.bQuickExpand = FALSE;
|
|
continue;
|
|
}
|
|
|
|
bSeManageVolumeNameSet = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( newVolumeSize > TC_MAX_VOLUME_SIZE )
|
|
{
|
|
// note: current limit TC_MAX_VOLUME_SIZE is 1 PetaByte
|
|
StringCbPrintfW(szTmp,sizeof(szTmp), GetString("EXPANDER_ERROR_MAX_VC_VOLUME_SIZE_EXCEEDED"),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, SRC_POS);
|
|
|
|
burn (&VolumePassword, sizeof (VolumePassword));
|
|
|
|
RestoreDefaultKeyFilesParam();
|
|
RandStop (FALSE);
|
|
NormalCursor();
|
|
|
|
return;
|
|
}
|
|
|