"Fossies" - the Fresh Open Source Software Archive

Member "src/ExpandVolume/DlgExpandVolume.cpp" (10 Oct 2018, 24107 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "DlgExpandVolume.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses'
    8  and also from the source code of extcv, which is Copyright (c) 2009-2010 Kih-Oskh
    9  or Copyright (c) 2012-2013 Josef Schneider <josef@netpage.dk>
   10 
   11  Modifications and additions to the original source code (contained in this file)
   12  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   13  and are governed by the Apache License 2.0 the full text of which is
   14  contained in the file License.txt included in VeraCrypt binary and source
   15  code distribution packages. */
   16 
   17 #include "Tcdefs.h"
   18 
   19 #include <time.h>
   20 #include <math.h>
   21 #include <dbt.h>
   22 #include <fcntl.h>
   23 #include <io.h>
   24 #include <sys/stat.h>
   25 #include <windowsx.h>
   26 #include <stdio.h>
   27 
   28 #include "Apidrvr.h"
   29 #include "Volumes.h"
   30 #include "Crypto.h"
   31 #include "Dlgcode.h"
   32 #include "Language.h"
   33 #include "Pkcs5.h"
   34 #include "Random.h"
   35 // #include "../Mount/Mount.h"
   36 
   37 #include "../Common/Dictionary.h"
   38 #include "../Common/Common.h"
   39 #include "../Common/Resource.h"
   40 #include "../Common/SecurityToken.h"
   41 #include "../Common/Progress.h"
   42 
   43 #include "ExpandVolume.h"
   44 #include "Resource.h"
   45 
   46 // TO DO: display sector sizes different than 512 bytes
   47 #define SECTOR_SIZE_MSG                     512
   48 
   49 #define TIMER_ID_RANDVIEW                               0xff
   50 #define TIMER_INTERVAL_RANDVIEW                         50
   51 
   52 // see definition of enum EV_FileSystem
   53 const wchar_t * szFileSystemStr[4] = {L"RAW",L"FAT",L"NTFS",L"EXFAT"};
   54 
   55 // prototypes for internal functions
   56 BOOL CALLBACK ExpandVolSizeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
   57 BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
   58 
   59 namespace VeraCryptExpander
   60 {
   61 /* defined in WinMain.c, referenced by ExpandVolumeWizard() */
   62 int ExtcvAskVolumePassword (HWND hwndDlg, const wchar_t* fileName, Password *password, int *pkcs5, int *pim, BOOL* truecryptMode, char *titleStringId, BOOL enableMountOptions);
   63 }
   64 
   65 
   66 int GetSpaceString(wchar_t *dest, size_t cbDest, uint64 size, BOOL bDevice)
   67 {
   68     const wchar_t * szFmtBytes = L"%.0lf %s";
   69     const wchar_t * szFmtOther = L"%.2lf %s";
   70     const wchar_t * SuffixStr[] = {L"Byte", L"KB", L"MB", L"GB", L"TB"};
   71     const uint64 Muliplier[] = {1, BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
   72     const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
   73     int i;
   74 
   75     for (i=1; i<=nMaxSuffix && size>Muliplier[i]; i++) ;
   76 
   77     --i;
   78 
   79     if (bDevice) {
   80         wchar_t szTemp[512];
   81 
   82         if (StringCbPrintfW(szTemp, sizeof(szTemp),i?szFmtOther:szFmtBytes, size/(double)Muliplier[i], SuffixStr[i]) < 0 )
   83             return -1;
   84 
   85         return StringCbPrintfW(dest, cbDest, L"%I64u sectors (%s)", size/SECTOR_SIZE_MSG , szTemp);
   86     }
   87 
   88     return StringCbPrintfW(dest, cbDest,i?szFmtOther:szFmtBytes, size/(double)Muliplier[i], SuffixStr[i]);
   89 }
   90 
   91 void SetCurrentVolSize(HWND hwndDlg, uint64 size)
   92 {
   93     const uint64 Muliplier[] = {BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
   94     const int IdRadioBtn[] = {IDC_KB, IDC_MB, IDC_GB, IDC_TB};
   95     const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
   96     int i;
   97     wchar_t szTemp[256];
   98 
   99     for (i=1; i<=nMaxSuffix && size>Muliplier[i]; i++) ;
  100 
  101     --i;
  102 
  103     SendDlgItemMessage (hwndDlg, IdRadioBtn[i], BM_SETCHECK, BST_CHECKED, 0);
  104     StringCbPrintfW(szTemp,sizeof(szTemp),L"%I64u",size/Muliplier[i]);
  105     SetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTemp);
  106 }
  107 
  108 uint64 GetSizeBoxMultiplier(HWND hwndDlg)
  109 {
  110     const uint64 Muliplier[] = {BYTES_PER_KB, BYTES_PER_MB, BYTES_PER_GB, BYTES_PER_TB};
  111     const int IdRadioBtn[] = {IDC_KB, IDC_MB, IDC_GB, IDC_TB};
  112     const int nMaxSuffix = sizeof(Muliplier)/sizeof(uint64) - 1;
  113     int i;
  114 
  115     for (i=nMaxSuffix; i>0 && !IsButtonChecked (GetDlgItem (hwndDlg, IdRadioBtn[i])); --i) ;
  116 
  117     return Muliplier[i];
  118 }
  119 
  120 BOOL CALLBACK ExpandVolSizeDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  121 {
  122     static EXPAND_VOL_THREAD_PARAMS *pVolExpandParam;
  123 
  124     WORD lw = LOWORD (wParam);
  125 
  126     switch (msg)
  127     {
  128     case WM_INITDIALOG:
  129         {
  130             wchar_t szTemp[4096];
  131 
  132             pVolExpandParam = (EXPAND_VOL_THREAD_PARAMS*)lParam;
  133 
  134             EnableWindow (GetDlgItem (hwndDlg, IDC_SIZEBOX), !pVolExpandParam->bIsDevice);
  135             EnableWindow (GetDlgItem (hwndDlg, IDC_KB), !pVolExpandParam->bIsDevice);
  136             EnableWindow (GetDlgItem (hwndDlg, IDC_MB), !pVolExpandParam->bIsDevice);
  137             EnableWindow (GetDlgItem (hwndDlg, IDC_GB), !pVolExpandParam->bIsDevice);
  138             EnableWindow (GetDlgItem (hwndDlg, IDC_TB), !pVolExpandParam->bIsDevice);
  139 
  140             EnableWindow (GetDlgItem (hwndDlg, IDC_INIT_NEWSPACE),
  141                 !(pVolExpandParam->bIsLegacy && pVolExpandParam->bIsDevice));
  142             SendDlgItemMessage (hwndDlg, IDC_INIT_NEWSPACE, BM_SETCHECK,
  143                 pVolExpandParam->bInitFreeSpace ? BST_CHECKED : BST_UNCHECKED, 0);
  144 
  145             if (!pVolExpandParam->bIsDevice)
  146                 SetCurrentVolSize(hwndDlg,pVolExpandParam->oldSize);
  147 
  148             SendMessage (GetDlgItem (hwndDlg, IDC_BOX_HELP), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE);
  149 
  150             GetSpaceString(szTemp,sizeof(szTemp),pVolExpandParam->oldSize,pVolExpandParam->bIsDevice);
  151 
  152             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_OLDSIZE), szTemp);
  153             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NAME), pVolExpandParam->szVolumeName);
  154             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_FILE_SYSTEM), szFileSystemStr[pVolExpandParam->FileSystem]);
  155 
  156             if (pVolExpandParam->bIsDevice)
  157             {
  158                 GetSpaceString(szTemp,sizeof(szTemp),pVolExpandParam->newSize,TRUE);
  159             }
  160             else
  161             {
  162                 wchar_t szHostFreeStr[256];
  163 
  164                 SetWindowText (GetDlgItem (hwndDlg, IDT_NEW_SIZE), L"");
  165                 GetSpaceString(szHostFreeStr,sizeof(szHostFreeStr),pVolExpandParam->hostSizeFree,FALSE);
  166                 StringCbPrintfW (szTemp,sizeof(szTemp),L"%s available on host drive", szHostFreeStr);
  167             }
  168 
  169             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NEWSIZE), szTemp);
  170 
  171             // set help text
  172             if (pVolExpandParam->bIsDevice)
  173             {
  174                 StringCbPrintfW (szTemp,sizeof(szTemp),L"This is a device-based VeraCrypt volume.\n\nThe new volume size will be choosen automatically as the size of the host device.");
  175                 if (pVolExpandParam->bIsLegacy)
  176                     StringCbCatW(szTemp,sizeof(szTemp),L" Note: filling the new space with random data is not supported for legacy volumes.");
  177             }
  178             else
  179             {
  180                 StringCbPrintfW (szTemp, sizeof(szTemp),L"Please specify the new size of the VeraCrypt volume (must be at least %I64u KB larger than the current size).",TC_MINVAL_FS_EXPAND/1024);
  181             }
  182             SetWindowText (GetDlgItem (hwndDlg, IDC_BOX_HELP), szTemp);
  183 
  184         }
  185         return 0;
  186 
  187 
  188     case WM_COMMAND:
  189         if (lw == IDCANCEL)
  190         {
  191             EndDialog (hwndDlg, lw);
  192             return 1;
  193         }
  194 
  195         if (lw == IDOK)
  196         {
  197             wchar_t szTemp[4096];
  198 
  199             pVolExpandParam->bInitFreeSpace = IsButtonChecked (GetDlgItem (hwndDlg, IDC_INIT_NEWSPACE));
  200             if (!pVolExpandParam->bIsDevice) // for devices new size is set by calling function
  201             {
  202                 GetWindowText (GetDlgItem (hwndDlg, IDC_SIZEBOX), szTemp, ARRAYSIZE (szTemp));
  203                 pVolExpandParam->newSize = _wtoi64(szTemp) * GetSizeBoxMultiplier(hwndDlg);
  204             }
  205 
  206             EndDialog (hwndDlg, lw);
  207             return 1;
  208         }
  209 
  210         return 0;
  211     }
  212 
  213     return 0;
  214 }
  215 
  216 
  217 extern "C" void AddProgressDlgStatus(HWND hwndDlg, const wchar_t* szText)
  218 {
  219     HWND hwndCtrl;
  220 
  221     hwndCtrl = GetDlgItem (hwndDlg,IDC_BOX_STATUS);
  222     SendMessage(hwndCtrl,EM_REPLACESEL,FALSE,(LPARAM)szText);
  223     SendMessage(hwndCtrl,EM_SCROLLCARET,0,0);
  224 }
  225 
  226 
  227 extern "C" void SetProgressDlgStatus(HWND hwndDlg, const wchar_t* szText)
  228 {
  229     HWND hwndCtrl;
  230 
  231     hwndCtrl = GetDlgItem (hwndDlg,IDC_BOX_STATUS);
  232     SendMessage(hwndCtrl,EM_SETSEL,0,-1);
  233     SendMessage(hwndCtrl,EM_REPLACESEL,FALSE,(LPARAM)szText);
  234     SendMessage(hwndCtrl,EM_SCROLLCARET,0,0);
  235 }
  236 
  237 
  238 BOOL CALLBACK ExpandVolProgressDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  239 {
  240     static EXPAND_VOL_THREAD_PARAMS *pProgressDlgParam;
  241     static BOOL bVolTransformStarted = FALSE;
  242     static BOOL showRandPool = TRUE;
  243     static unsigned char randPool[16];
  244     static unsigned char maskRandPool [16];
  245     static BOOL bUseMask = FALSE;
  246     static DWORD mouseEntropyGathered = 0xFFFFFFFF;
  247     static DWORD mouseEventsInitialCount = 0;
  248     /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */
  249     static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8;
  250     static HWND hEntropyBar = NULL;
  251 
  252     WORD lw = LOWORD (wParam);
  253 
  254     switch (msg)
  255     {
  256     case WM_INITDIALOG:
  257         {
  258             wchar_t szOldHostSize[512], szNewHostSize[512];
  259             HCRYPTPROV hRngProv;
  260 
  261             pProgressDlgParam = (EXPAND_VOL_THREAD_PARAMS*)lParam;
  262             bVolTransformStarted = FALSE;
  263             showRandPool = FALSE;
  264 
  265             hCurPage = hwndDlg;
  266             nPbar = IDC_PROGRESS_BAR;
  267 
  268             VirtualLock (randPool, sizeof(randPool));
  269             VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered));
  270             VirtualLock (maskRandPool, sizeof(maskRandPool));
  271 
  272             mouseEntropyGathered = 0xFFFFFFFF;
  273             mouseEventsInitialCount = 0;
  274             bUseMask = FALSE;
  275             if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
  276             {
  277                 if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool))
  278                     bUseMask = TRUE;
  279                 CryptReleaseContext (hRngProv, 0);
  280             }
  281 
  282             GetSpaceString(szOldHostSize,sizeof(szOldHostSize),pProgressDlgParam->oldSize,pProgressDlgParam->bIsDevice);
  283             GetSpaceString(szNewHostSize,sizeof(szNewHostSize),pProgressDlgParam->newSize,pProgressDlgParam->bIsDevice);
  284 
  285             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_OLDSIZE), szOldHostSize);
  286             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NEWSIZE), szNewHostSize);
  287             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_NAME), pProgressDlgParam->szVolumeName);
  288             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_FILE_SYSTEM), szFileSystemStr[pProgressDlgParam->FileSystem]);
  289             SetWindowText (GetDlgItem (hwndDlg, IDC_EXPAND_VOLUME_INITSPACE), pProgressDlgParam->bInitFreeSpace?L"Yes":L"No");
  290 
  291             SendMessage (GetDlgItem (hwndDlg, IDC_BOX_STATUS), WM_SETFONT, (WPARAM) hBoldFont, (LPARAM) TRUE);
  292 
  293             SendMessage (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE);
  294 
  295             // set status text
  296             if ( !pProgressDlgParam->bInitFreeSpace && pProgressDlgParam->bIsLegacy )
  297             {
  298                 showRandPool = FALSE;
  299                 EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE);
  300                 EnableWindow (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), FALSE);
  301                 SetDlgItemText(hwndDlg, IDC_BOX_STATUS, L"Click 'Continue' to expand the volume.");
  302             }
  303             else
  304             {
  305                 SetDlgItemText(hwndDlg, IDC_BOX_STATUS, L"IMPORTANT: Move your mouse as randomly as possible within this window. The longer you move it, the better. This significantly increases the cryptographic strength of the encryption keys. Then click 'Continue' to expand the volume.");
  306             }
  307 
  308             SendMessage (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), BM_SETCHECK, BST_UNCHECKED, 0);
  309             hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR);
  310             SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel);
  311             SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0);
  312             SetTimer (hwndDlg, TIMER_ID_RANDVIEW, TIMER_INTERVAL_RANDVIEW, NULL);
  313         }
  314         return 0;
  315     case TC_APPMSG_VOL_TRANSFORM_THREAD_ENDED:
  316         {
  317             int nStatus = (int)lParam;
  318 
  319             NormalCursor ();
  320             if (nStatus != 0)
  321             {
  322                 if ( nStatus != ERR_USER_ABORT )
  323                     AddProgressDlgStatus (hwndDlg, L"Error: volume expansion failed.");
  324                 else
  325                     AddProgressDlgStatus (hwndDlg, L"Error: operation aborted by user.");
  326             }
  327             else
  328             {
  329                 AddProgressDlgStatus (hwndDlg, L"Finished. Volume successfully expanded.");
  330             }
  331 
  332             SetWindowText (GetDlgItem (hwndDlg, IDOK), L"Exit");
  333             EnableWindow (GetDlgItem (hwndDlg, IDOK), TRUE);
  334             EnableWindow (GetDlgItem (hwndDlg, IDCANCEL), FALSE);
  335         }
  336         return 1;
  337 
  338     case WM_TIMER:
  339 
  340         switch (wParam)
  341         {
  342         case TIMER_ID_RANDVIEW:
  343             {
  344                 wchar_t szRndPool[64] = {0};
  345                 DWORD mouseEventsCounter;
  346 
  347                 RandpeekBytes (hwndDlg, randPool, sizeof (randPool),&mouseEventsCounter);
  348 
  349                 ProcessEntropyEstimate (hEntropyBar, &mouseEventsInitialCount, mouseEventsCounter, maxEntropyLevel, &mouseEntropyGathered);
  350 
  351                 if (showRandPool)
  352                     StringCbPrintfW (szRndPool, sizeof(szRndPool), L"%08X%08X%08X%08X",
  353                         *((DWORD*) (randPool + 12)), *((DWORD*) (randPool + 8)), *((DWORD*) (randPool + 4)), *((DWORD*) (randPool)));
  354                 else if (bUseMask)
  355                 {
  356                     for (int i = 0; i < 16; i++)
  357                     {
  358                         wchar_t tmp2[3];
  359                         unsigned char tmpByte = randPool[i] ^ maskRandPool[i];
  360                         tmp2[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*');
  361                         tmp2[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*');
  362                         tmp2[2] = 0;
  363                         StringCbCatW (szRndPool, sizeof(szRndPool), tmp2);
  364                     }
  365                 }
  366                 else
  367                 {
  368                     wmemset (szRndPool, L'*', 32);
  369                 }
  370 
  371                 SetWindowText (GetDlgItem (hwndDlg, IDC_RANDOM_BYTES), szRndPool);
  372 
  373                 burn (randPool, sizeof(randPool));
  374                 burn (szRndPool, sizeof(szRndPool));
  375             }
  376             return 1;
  377         }
  378         return 0;
  379 
  380     case WM_COMMAND:
  381         if (lw == IDC_DISPLAY_POOL_CONTENTS)
  382         {
  383             showRandPool = IsButtonChecked (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS));
  384             return 1;
  385         }
  386         if (lw == IDCANCEL)
  387         {
  388             if (bVolTransformStarted)
  389             {
  390                 if (MessageBoxW (hwndDlg, L"Warning: Volume expansion is in progress!\n\nStopping now may result in a damaged volume.\n\nDo you really want to cancel?", lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
  391                     return 1;
  392 
  393                 // tell the volume transform thread to terminate
  394                 bVolTransformThreadCancel = TRUE;
  395             }
  396             EndDialog (hwndDlg, lw);
  397             return 1;
  398         }
  399 
  400         if (lw == IDOK)
  401         {
  402             if (bVolTransformStarted)
  403             {
  404                 // TransformThreadFunction finished -> OK button is now exit
  405                 EndDialog (hwndDlg, lw);
  406             }
  407             else
  408             {
  409                 showRandPool = FALSE;
  410                 KillTimer (hwndDlg, TIMER_ID_RANDVIEW);
  411                 EnableWindow (GetDlgItem (hwndDlg, IDC_DISPLAY_POOL_CONTENTS), FALSE);
  412                 EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE);
  413                 SetProgressDlgStatus (hwndDlg, L"Starting volume expansion ...\r\n");
  414                 bVolTransformStarted = TRUE;
  415                 pProgressDlgParam->hwndDlg = hwndDlg;
  416                 if ( _beginthread (volTransformThreadFunction, 0, pProgressDlgParam) == -1L )
  417                 {
  418                     handleError (hwndDlg, ERR_OS_ERROR, SRC_POS);
  419                     EndDialog (hwndDlg, lw);
  420                 }
  421                 WaitCursor();
  422             }
  423             return 1;
  424         }
  425 
  426         return 0;
  427 
  428     case WM_NCDESTROY:
  429         burn (randPool, sizeof (randPool));
  430         burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount));
  431         burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered));
  432         burn (maskRandPool, sizeof(maskRandPool));
  433         return 0;
  434     }
  435 
  436     return 0;
  437 }
  438 
  439 
  440 typedef struct
  441 {
  442     OpenVolumeContext *context;
  443     const wchar_t *volumePath;
  444     Password *password;
  445     int pkcs5_prf;
  446     int pim;
  447     BOOL truecryptMode;
  448     BOOL write;
  449     BOOL preserveTimestamps;
  450     BOOL useBackupHeader;
  451     int* nStatus;
  452 } OpenVolumeThreadParam;
  453 
  454 void CALLBACK OpenVolumeWaitThreadProc(void* pArg, HWND hwndDlg)
  455 {
  456     OpenVolumeThreadParam* pThreadParam = (OpenVolumeThreadParam*) pArg;
  457 
  458     *(pThreadParam)->nStatus = OpenVolume(pThreadParam->context, pThreadParam->volumePath, pThreadParam->password, pThreadParam->pkcs5_prf,
  459         pThreadParam->pim, pThreadParam->truecryptMode, pThreadParam->write, pThreadParam->preserveTimestamps, pThreadParam->useBackupHeader);
  460 }
  461 
  462 /*
  463     ExpandVolumeWizard
  464 
  465     Expands a trucrypt volume (wizard for user interface)
  466 
  467     Parameters:
  468 
  469         hwndDlg : HWND
  470             [in] handle to parent window (if any)
  471 
  472         szVolume : char *
  473             [in] Pointer to a string with the volume name (e.g. '\Device\Harddisk0\Partition1' or 'C:\topsecret.tc')
  474 
  475     Return value:
  476 
  477         none
  478 
  479 */
  480 void ExpandVolumeWizard (HWND hwndDlg, wchar_t *lpszVolume)
  481 {
  482     int nStatus = ERR_OS_ERROR;
  483     wchar_t szTmp[4096];
  484     Password VolumePassword;
  485     int VolumePkcs5 = 0, VolumePim = -1;
  486     uint64 hostSize, volSize, hostSizeFree, maxSizeFS;
  487     BOOL bIsDevice, bIsLegacy;
  488     DWORD dwError;
  489     int driveNo;
  490     enum EV_FileSystem volFSType;
  491     wchar_t rootPath[] = L"A:\\";
  492 
  493     switch (IsSystemDevicePath (lpszVolume, hwndDlg, TRUE))
  494     {
  495     case 1:
  496     case 2:
  497         MessageBoxW (hwndDlg, L"A VeraCrypt system volume can't be expanded.", lpszTitle, MB_OK|MB_ICONEXCLAMATION);
  498         goto ret;
  499     }
  500 
  501     EnableElevatedCursorChange (hwndDlg);
  502     WaitCursor();
  503 
  504     if (IsMountedVolume (lpszVolume))
  505     {
  506         Warning ("DISMOUNT_FIRST", hwndDlg);
  507         goto ret;
  508     }
  509 
  510     if (Randinit() != ERR_SUCCESS) {
  511         if (CryptoAPILastError == ERROR_SUCCESS)
  512             nStatus = ERR_RAND_INIT_FAILED;
  513         else
  514             nStatus = ERR_CAPI_INIT_FAILED;
  515         goto error;
  516     }
  517 
  518     NormalCursor();
  519 
  520     // Ask the user if there is a hidden volume
  521     char *volTypeChoices[] = {0, "DOES_VOLUME_CONTAIN_HIDDEN", "VOLUME_CONTAINS_HIDDEN", "VOLUME_DOES_NOT_CONTAIN_HIDDEN", "IDCANCEL", 0};
  522     switch (AskMultiChoice ((void **) volTypeChoices, FALSE, hwndDlg))
  523     {
  524     case 1:
  525         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);
  526         goto ret;
  527 
  528     case 2:
  529         break;
  530 
  531     default:
  532         nStatus = ERR_SUCCESS;
  533         goto ret;
  534     }
  535 
  536     WaitCursor();
  537 
  538     nStatus = QueryVolumeInfo(hwndDlg,lpszVolume,&hostSizeFree,&maxSizeFS);
  539 
  540     if (nStatus!=ERR_SUCCESS)
  541     {
  542         nStatus = ERR_OS_ERROR;
  543         goto error;
  544     }
  545 
  546     NormalCursor();
  547 
  548     while (TRUE)
  549     {
  550         OpenVolumeContext expandVol;
  551         BOOL truecryptMode = FALSE;
  552 
  553         if (!VeraCryptExpander::ExtcvAskVolumePassword (hwndDlg, lpszVolume, &VolumePassword, &VolumePkcs5, &VolumePim, &truecryptMode, "ENTER_NORMAL_VOL_PASSWORD", FALSE))
  554         {
  555             goto ret;
  556         }
  557 
  558         EnableElevatedCursorChange (hwndDlg);
  559         WaitCursor();
  560 
  561         if (KeyFilesEnable && FirstKeyFile)
  562             KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile, lpszVolume);
  563 
  564         WaitCursor ();
  565 
  566         OpenVolumeThreadParam threadParam;
  567         threadParam.context = &expandVol;
  568         threadParam.volumePath = lpszVolume;
  569         threadParam.password = &VolumePassword;
  570         threadParam.pkcs5_prf = VolumePkcs5;
  571         threadParam.pim = VolumePim;
  572         threadParam.truecryptMode = FALSE;
  573         threadParam.write = FALSE;
  574         threadParam.preserveTimestamps = bPreserveTimestamp;
  575         threadParam.useBackupHeader = FALSE;
  576         threadParam.nStatus = &nStatus;
  577 
  578         ShowWaitDialog (hwndDlg, TRUE, OpenVolumeWaitThreadProc, &threadParam);
  579 
  580         NormalCursor ();
  581 
  582         dwError = GetLastError();
  583 
  584         if (nStatus == ERR_SUCCESS)
  585         {
  586             bIsDevice = expandVol.IsDevice;
  587             bIsLegacy = expandVol.CryptoInfo->LegacyVolume;
  588             hostSize = expandVol.HostSize;
  589             VolumePkcs5 = expandVol.CryptoInfo->pkcs5;
  590             if ( bIsLegacy )
  591             {
  592                 if ( bIsDevice )
  593                     volSize = 0; // updated later
  594                 else
  595                     volSize = hostSize;
  596             }
  597             else
  598             {
  599                 volSize = GetVolumeSizeByDataAreaSize (expandVol.CryptoInfo->VolumeSize.Value, bIsLegacy);
  600             }
  601             CloseVolume (&expandVol);
  602             break;
  603         }
  604         else if (nStatus != ERR_PASSWORD_WRONG)
  605         {
  606             SetLastError (dwError);
  607             goto error;
  608         }
  609 
  610         NormalCursor();
  611 
  612         handleError (hwndDlg, nStatus, SRC_POS);
  613     }
  614 
  615     WaitCursor();
  616 
  617     // auto mount the volume to check the file system type
  618     nStatus=MountVolTemp(hwndDlg, lpszVolume, &driveNo, &VolumePassword, VolumePkcs5, VolumePim);
  619 
  620     if (nStatus != ERR_SUCCESS)
  621         goto error;
  622 
  623     rootPath[0] += driveNo;
  624 
  625     if ( !GetFileSystemType(rootPath,&volFSType) )
  626         volFSType = EV_FS_TYPE_RAW;
  627 
  628     if ( bIsLegacy && bIsDevice && volFSType == EV_FS_TYPE_NTFS )
  629     {
  630         uint64 NumberOfSectors;
  631         DWORD BytesPerSector;
  632 
  633         if ( !GetNtfsNumberOfSectors(rootPath, &NumberOfSectors, &BytesPerSector) )
  634             nStatus = ERR_OS_ERROR;
  635 
  636         // NTFS reported size does not include boot sector copy at volume end
  637         volSize = ( NumberOfSectors + 1 ) * BytesPerSector;
  638     }
  639 
  640     UnmountVolume (hwndDlg, driveNo, TRUE);
  641 
  642     NormalCursor();
  643 
  644     if (nStatus != ERR_SUCCESS)
  645         goto error;
  646 
  647     if ( bIsDevice && bIsLegacy && volFSType != EV_FS_TYPE_NTFS )
  648     {
  649         MessageBoxW (hwndDlg,
  650             L"Expanding a device hosted legacy volume with no NTFS file system\n"
  651             L"is unsupported.\n"
  652             L"Note that expanding the VeraCrypt volume itself is not neccessary\n"
  653             L"for legacy volumes.\n",
  654             lpszTitle, MB_OK|MB_ICONEXCLAMATION);
  655         goto ret;
  656     }
  657 
  658     // check if there is enough free space on host device/drive to expand the volume
  659     if ( (bIsDevice && hostSize < volSize + TC_MINVAL_FS_EXPAND) || (!bIsDevice && hostSizeFree < TC_MINVAL_FS_EXPAND) )
  660     {
  661         MessageBoxW (hwndDlg, L"Not enough free space to expand the volume", lpszTitle, MB_OK|MB_ICONEXCLAMATION);
  662         goto ret;
  663     }
  664 
  665     if (!bIsDevice && hostSize != volSize ) {
  666         // there is some junk data at the end of the volume
  667         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)
  668             goto ret;
  669     }
  670 
  671     switch (volFSType)
  672     {
  673     case EV_FS_TYPE_NTFS:
  674         break;
  675     case EV_FS_TYPE_FAT:
  676         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?",
  677             lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
  678             goto ret;
  679         break;
  680     case EV_FS_TYPE_EXFAT:
  681         if (MessageBoxW (hwndDlg,L"Warning: The VeraCrypt volume contains an exFAT file system!\n\nOnly the VeraCrypt volume itself will be expanded, but not the file system.\n\nDo you want to continue?",
  682             lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
  683             goto ret;
  684         break;
  685     default:
  686         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?",
  687             lpszTitle, YES_NO|MB_ICONQUESTION|MB_DEFBUTTON2) == IDNO)
  688             goto ret;
  689     }
  690 
  691     EXPAND_VOL_THREAD_PARAMS VolExpandParam;
  692 
  693     VolExpandParam.bInitFreeSpace = (bIsLegacy && bIsDevice) ? FALSE:TRUE;
  694     VolExpandParam.szVolumeName = lpszVolume;
  695     VolExpandParam.FileSystem = volFSType;
  696     VolExpandParam.pVolumePassword = &VolumePassword;
  697     VolExpandParam.VolumePkcs5 = VolumePkcs5;
  698     VolExpandParam.VolumePim = VolumePim;
  699     VolExpandParam.bIsDevice = bIsDevice;
  700     VolExpandParam.bIsLegacy = bIsLegacy;
  701     VolExpandParam.oldSize = bIsDevice ? volSize : hostSize;
  702     VolExpandParam.newSize = hostSize;
  703     VolExpandParam.hostSizeFree = hostSizeFree;
  704 
  705     while (1)
  706     {
  707         uint64 newVolumeSize;
  708 
  709         if (IDCANCEL == DialogBoxParamW (hInst,
  710             MAKEINTRESOURCEW (IDD_SIZE_DIALOG), hwndDlg,
  711             (DLGPROC) ExpandVolSizeDlgProc, (LPARAM) &VolExpandParam))
  712         {
  713             goto ret;
  714         }
  715 
  716         newVolumeSize = VolExpandParam.newSize;
  717 
  718         if ( !bIsDevice )
  719         {
  720             if ( newVolumeSize < hostSize + TC_MINVAL_FS_EXPAND)
  721             {
  722                 StringCbPrintfW(szTmp,sizeof(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);
  723                 MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
  724                 continue;
  725             }
  726 
  727             if ( newVolumeSize - hostSize > hostSizeFree )
  728             {
  729                 StringCbPrintfW(szTmp,sizeof(szTmp),L"New volume size too large, not enough space on host drive.");
  730                 MessageBoxW (hwndDlg, szTmp, lpszTitle, MB_OK | MB_ICONEXCLAMATION );
  731                 continue;
  732             }
  733 
  734             if ( newVolumeSize>maxSizeFS )
  735             {
  736                 StringCbPrintfW(szTmp,sizeof(szTmp),L"Maximum file size of %I64u MB on host drive exceeded.",maxSizeFS/BYTES_PER_MB);
  737                 MessageBoxW (hwndDlg, L"!\n",lpszTitle, MB_OK | MB_ICONEXCLAMATION );
  738                 continue;
  739             }
  740         }
  741 
  742         if ( newVolumeSize > TC_MAX_VOLUME_SIZE )
  743         {
  744             // note: current limit TC_MAX_VOLUME_SIZE is 1 PetaByte
  745             StringCbPrintfW(szTmp,sizeof(szTmp),L"Maximum VeraCrypt volume size of %I64u TB exceeded!\n",TC_MAX_VOLUME_SIZE/BYTES_PER_TB);
  746             MessageBoxW (hwndDlg, szTmp,lpszTitle, MB_OK | MB_ICONEXCLAMATION );
  747             if (bIsDevice)
  748                 break; // TODO: ask to limit volume size to TC_MAX_VOLUME_SIZE
  749             continue;
  750         }
  751 
  752         break;
  753     }
  754 
  755     VolExpandParam.oldSize = volSize;
  756 
  757     // start progress dialog
  758     DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_EXPAND_PROGRESS_DLG), hwndDlg,
  759         (DLGPROC) ExpandVolProgressDlgProc, (LPARAM) &VolExpandParam );
  760 
  761 ret:
  762     nStatus = ERR_SUCCESS;
  763 
  764 error:
  765 
  766     if (nStatus != 0)
  767         handleError (hwndDlg, nStatus, SRC_POS);
  768 
  769     burn (&VolumePassword, sizeof (VolumePassword));
  770 
  771     RestoreDefaultKeyFilesParam();
  772     RandStop (FALSE);
  773     NormalCursor();
  774 
  775     return;
  776 }
  777