mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-05-17 10:01:31 +00:00
This update introduces a screen protection mechanism that leverages the Windows Display Affinity API to prevent screen capture, screen recording, and inclusion in the Windows 11 Recall feature. By default, all VeraCrypt windows, menus, and tooltips are protected. Users can enable or disable this feature through a new setting available in the application Preferences, as well as in the installer and MSI configurations. This enhances user privacy by mitigating potential leaks of sensitive interface content. Note: Due to a regression in Windows 11 affecting layered windows, ComboBox dropdowns cannot currently be protected by this mechanism.
852 lines
25 KiB
C++
852 lines
25 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-2025 AM Crypto
|
|
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_DESTROY:
|
|
DetachProtectionFromCurrentThread();
|
|
break;
|
|
|
|
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;
|
|
|
|
case WM_DESTROY:
|
|
DetachProtectionFromCurrentThread();
|
|
break;
|
|
}
|
|
|
|
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 ("UNMOUNT_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;
|
|
}
|
|
|