"Fossies" - the Fresh Open Source Software Archive

Member "src/Main/Forms/VolumeCreationWizard.cpp" (10 Oct 2018, 34426 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 "VolumeCreationWizard.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "System.h"
   14 #include "Platform/SystemInfo.h"
   15 #ifdef TC_UNIX
   16 #include <unistd.h>
   17 #include "Platform/Unix/Process.h"
   18 #endif
   19 #include "Core/RandomNumberGenerator.h"
   20 #include "Core/VolumeCreator.h"
   21 #include "Main/Application.h"
   22 #include "Main/GraphicUserInterface.h"
   23 #include "Main/Resources.h"
   24 #include "VolumeCreationWizard.h"
   25 #include "EncryptionOptionsWizardPage.h"
   26 #include "InfoWizardPage.h"
   27 #include "ProgressWizardPage.h"
   28 #include "SingleChoiceWizardPage.h"
   29 #include "VolumeCreationProgressWizardPage.h"
   30 #include "VolumeFormatOptionsWizardPage.h"
   31 #include "VolumeLocationWizardPage.h"
   32 #include "VolumePasswordWizardPage.h"
   33 #include "VolumePimWizardPage.h"
   34 #include "VolumeSizeWizardPage.h"
   35 #include "WaitDialog.h"
   36 
   37 namespace VeraCrypt
   38 {
   39 #ifdef TC_MACOSX
   40 
   41     bool VolumeCreationWizard::ProcessEvent(wxEvent& event)
   42     {
   43         if(GraphicUserInterface::HandlePasswordEntryCustomEvent (event))
   44             return true;
   45         else
   46             return WizardFrame::ProcessEvent(event);
   47     }
   48 #endif
   49 
   50     VolumeCreationWizard::VolumeCreationWizard (wxWindow* parent)
   51         : WizardFrame (parent),
   52         CrossPlatformSupport (true),
   53         DisplayKeyInfo (false),
   54         LargeFilesSupport (false),
   55         QuickFormatEnabled (false),
   56         SelectedFilesystemClusterSize (0),
   57         SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT),
   58         SelectedVolumeHostType (VolumeHostType::File),
   59         SelectedVolumeType (VolumeType::Normal),
   60         Pim (0),
   61         SectorSize (0),
   62         VolumeSize (0)
   63     {
   64         RandomNumberGenerator::Start();
   65 
   66         SetTitle (LangString["INTRO_TITLE"]);
   67         SetImage (Resources::GetVolumeCreationWizardBitmap (Gui->GetCharHeight (this) * 21));
   68         SetMaxStaticTextWidth (55);
   69         
   70 #ifdef TC_MACOSX
   71         GraphicUserInterface::InstallPasswordEntryCustomKeyboardShortcuts (this);
   72 #endif
   73 
   74         SetStep (Step::VolumeHostType);
   75 
   76         class Timer : public wxTimer
   77         {
   78         public:
   79             Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { }
   80 
   81             void Notify()
   82             {
   83                 Wizard->OnRandomPoolUpdateTimer();
   84             }
   85 
   86             VolumeCreationWizard *Wizard;
   87         };
   88 
   89         RandomPoolUpdateTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
   90         RandomPoolUpdateTimer->Start (200);
   91     }
   92 
   93     VolumeCreationWizard::~VolumeCreationWizard ()
   94     {
   95     }
   96 
   97     WizardPage *VolumeCreationWizard::GetPage (WizardStep step)
   98     {
   99         switch (step)
  100         {
  101         case Step::VolumeHostType:
  102             {
  103                 ClearHistory();
  104 
  105                 OuterVolume = false;
  106                 LargeFilesSupport = false;
  107                 QuickFormatEnabled = false;
  108                 Pim = 0;
  109 
  110                 SingleChoiceWizardPage <VolumeHostType::Enum> *page = new SingleChoiceWizardPage <VolumeHostType::Enum> (GetPageParent(), wxEmptyString, true);
  111                 page->SetMinSize (wxSize (Gui->GetCharWidth (this) * 58, Gui->GetCharHeight (this) * 18 + 5));
  112 
  113                 page->SetPageTitle (LangString["INTRO_TITLE"]);
  114 
  115                 page->AddChoice (VolumeHostType::File, LangString["IDC_FILE_CONTAINER"], LangString["IDT_FILE_CONTAINER"], L"introcontainer", LangString["IDC_MORE_INFO_ON_CONTAINERS"]);
  116                 page->AddChoice (VolumeHostType::Device, _("Create a volume within a partition/&drive"), _("Formats and encrypts a non-system partition, entire external or secondary drive, entire USB stick, etc."));
  117 
  118                 page->SetSelection (SelectedVolumeHostType);
  119                 return page;
  120             }
  121 
  122         case Step::VolumeType:
  123             {
  124                 SingleChoiceWizardPage <VolumeType::Enum> *page = new SingleChoiceWizardPage <VolumeType::Enum> (GetPageParent(), wxEmptyString, true);
  125                 page->SetPageTitle (LangString["VOLUME_TYPE_TITLE"]);
  126 
  127                 page->AddChoice (VolumeType::Normal, LangString["IDC_STD_VOL"], LangString["NORMAL_VOLUME_TYPE_HELP"]);
  128                 page->AddChoice (VolumeType::Hidden, LangString["IDC_HIDDEN_VOL"], LangString["HIDDEN_VOLUME_TYPE_HELP"], L"hiddenvolume", LangString["IDC_HIDDEN_VOL_HELP"]);
  129 
  130                 page->SetSelection (SelectedVolumeType);
  131                 return page;
  132             }
  133 
  134         case Step::VolumeLocation:
  135             {
  136                 VolumeLocationWizardPage *page = new VolumeLocationWizardPage (GetPageParent(), SelectedVolumeHostType);
  137                 page->SetPageTitle (LangString["VOLUME_LOCATION"]);
  138 
  139                 if (SelectedVolumeType == VolumeType::Hidden)
  140                     page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP_HIDDEN_HOST_VOL"]);
  141                 else
  142                     page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP" : "DEVICE_HELP_NO_INPLACE"]);
  143 
  144                 page->SetVolumePath (SelectedVolumePath);
  145                 return page;
  146             }
  147 
  148         case Step::EncryptionOptions:
  149             {
  150                 EncryptionOptionsWizardPage *page = new EncryptionOptionsWizardPage (GetPageParent());
  151 
  152                 if (OuterVolume)
  153                     page->SetPageTitle (LangString["CIPHER_HIDVOL_HOST_TITLE"]);
  154                 else if (SelectedVolumeType == VolumeType::Hidden)
  155                     page->SetPageTitle (LangString["CIPHER_HIDVOL_TITLE"]);
  156                 else
  157                     page->SetPageTitle (LangString["CIPHER_TITLE"]);
  158 
  159                 page->SetEncryptionAlgorithm (SelectedEncryptionAlgorithm);
  160                 page->SetHash (SelectedHash);
  161                 return page;
  162             }
  163 
  164         case Step::VolumeSize:
  165             {
  166                 wxString freeSpaceText;
  167                 wxString pageTitle;
  168                 wxString pageText;
  169 
  170                 if (OuterVolume)
  171                 {
  172                     pageTitle = LangString["SIZE_HIDVOL_HOST_TITLE"];
  173                     pageText = LangString["SIZE_HELP_HIDDEN_HOST_VOL"];
  174                 }
  175                 else if (SelectedVolumeType == VolumeType::Hidden)
  176                 {
  177                     pageTitle = LangString["SIZE_HIDVOL_TITLE"];
  178                     pageText = LangString["SIZE_HELP_HIDDEN_VOL"] + L"\n\n" + _("Please note that if your operating system does not allocate files from the beginning of the free space, the maximum possible hidden volume size may be much smaller than the size of the free space on the outer volume. This not a bug in VeraCrypt but a limitation of the operating system.");
  179                     freeSpaceText = StringFormatter (_("Maximum possible hidden volume size for this volume is {0}."), Gui->SizeToString (MaxHiddenVolumeSize));
  180                 }
  181                 else
  182                 {
  183                     pageTitle = LangString["SIZE_TITLE"];
  184                     pageText = LangString["VOLUME_SIZE_HELP"];
  185                 }
  186 
  187                 VolumeSizeWizardPage *page = new VolumeSizeWizardPage (GetPageParent(), SelectedVolumePath, SectorSize, freeSpaceText);
  188 
  189                 page->SetPageTitle (pageTitle);
  190                 page->SetPageText (pageText);
  191 
  192                 if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden)
  193                     page->SetMaxVolumeSize (MaxHiddenVolumeSize);
  194                 else
  195                     page->SetVolumeSize (VolumeSize);
  196 
  197                 if (OuterVolume)
  198                     page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_HOST_SIZE);
  199                 else if (SelectedVolumeType == VolumeType::Hidden)
  200                     page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_SIZE);
  201                 else
  202                     page->SetMinVolumeSize (TC_MIN_VOLUME_SIZE);
  203 
  204                 return page;
  205             }
  206 
  207         case Step::VolumePassword:
  208             {
  209                 VolumePasswordWizardPage *page = new VolumePasswordWizardPage (GetPageParent(), Password, Keyfiles);
  210                 page->EnableUsePim (); // force displaying "Use PIM"
  211                 page->SetPimSelected (Pim > 0);
  212 
  213                 if (OuterVolume)
  214                     page->SetPageTitle (LangString["PASSWORD_HIDVOL_HOST_TITLE"]);
  215                 else if (SelectedVolumeType == VolumeType::Hidden)
  216                     page->SetPageTitle (LangString["PASSWORD_HIDVOL_TITLE"]);
  217                 else
  218                     page->SetPageTitle (LangString["PASSWORD_TITLE"]);
  219 
  220                 page->SetPageText (LangString[OuterVolume ? "PASSWORD_HIDDENVOL_HOST_HELP" : "PASSWORD_HELP"]);
  221                 return page;
  222             }
  223 
  224         case Step::VolumePim:
  225             {
  226                 VolumePimWizardPage *page = new VolumePimWizardPage (GetPageParent());
  227 
  228                 if (OuterVolume)
  229                     page->SetPageTitle (LangString["PIM_HIDVOL_HOST_TITLE"]);
  230                 else if (SelectedVolumeType == VolumeType::Hidden)
  231                     page->SetPageTitle (LangString["PIM_HIDVOL_TITLE"]);
  232                 else
  233                     page->SetPageTitle (LangString["PIM_TITLE"]);
  234 
  235                 page->SetPageText (LangString["PIM_HELP"]);
  236                 page->SetVolumePim (Pim);
  237                 return page;
  238             }
  239 
  240         case Step::LargeFilesSupport:
  241             {
  242                 SingleChoiceWizardPage <bool> *page = new SingleChoiceWizardPage <bool> (GetPageParent(), wxEmptyString, true);
  243                 page->SetPageTitle (LangString["FILESYS_PAGE_TITLE"]);
  244 
  245                 page->AddChoice (false, _("I will not store files larger than 4 GB on the volume"),
  246                     _("Choose this option if you do not need to store files larger than 4 GB (4,294,967,296 bytes) on the volume."));
  247 
  248                 page->AddChoice (true, _("I will store files larger than 4 GB on the volume"),
  249                     _("Choose this option if you need to store files larger than 4 GB (4,294,967,296 bytes) on the volume."));
  250 
  251                 page->SetSelection (LargeFilesSupport);
  252                 return page;
  253             }
  254 
  255         case Step::FormatOptions:
  256             {
  257                 VolumeFormatOptionsWizardPage *page = new VolumeFormatOptionsWizardPage (GetPageParent(), VolumeSize, SectorSize,
  258                     SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden), OuterVolume, LargeFilesSupport);
  259 
  260                 page->SetPageTitle (_("Format Options"));
  261                 page->SetFilesystemType (SelectedFilesystemType);
  262 
  263                 if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden)
  264                     QuickFormatEnabled = true;
  265                 page->SetQuickFormat (QuickFormatEnabled);
  266 
  267                 return page;
  268             }
  269 
  270         case Step::CrossPlatformSupport:
  271             {
  272                 SingleChoiceWizardPage <bool> *page = new SingleChoiceWizardPage <bool> (GetPageParent(), wxEmptyString, true);
  273                 page->SetPageTitle (_("Cross-Platform Support"));
  274 
  275                 page->AddChoice (true, _("I will mount the volume on other platforms"),
  276                     _("Choose this option if you need to use the volume on other platforms."));
  277 
  278                 page->AddChoice (false, StringFormatter (_("I will mount the volume only on {0}"), SystemInfo::GetPlatformName()),
  279                     _("Choose this option if you do not need to use the volume on other platforms."));
  280 
  281                 page->SetSelection (CrossPlatformSupport);
  282                 return page;
  283             }
  284 
  285         case Step::CreationProgress:
  286             {
  287                 VolumeCreationProgressWizardPage *page = new VolumeCreationProgressWizardPage (GetPageParent(), DisplayKeyInfo);
  288 
  289                 if (OuterVolume)
  290                     page->SetPageTitle (LangString["FORMAT_HIDVOL_HOST_TITLE"]);
  291                 else if (SelectedVolumeType == VolumeType::Hidden)
  292                     page->SetPageTitle (LangString["FORMAT_HIDVOL_TITLE"]);
  293                 else
  294                     page->SetPageTitle (LangString["FORMAT_TITLE"]);
  295 
  296                 page->SetPageText (LangString["FORMAT_HELP"]);
  297                 page->AbortEvent.Connect (EventConnector <VolumeCreationWizard> (this, &VolumeCreationWizard::OnAbortButtonClick));
  298                 page->SetNextButtonText (LangString["FORMAT"]);
  299                 return page;
  300             }
  301 
  302         case Step::VolumeCreatedInfo:
  303             {
  304                 InfoWizardPage *page = new InfoWizardPage (GetPageParent());
  305                 page->SetPageTitle (LangString["FORMAT_FINISHED_TITLE"]);
  306                 page->SetPageText (LangString["FORMAT_FINISHED_HELP"]);
  307 
  308                 SetCancelButtonText (_("Exit"));
  309                 return page;
  310             }
  311 
  312         case Step::OuterVolumeContents:
  313             {
  314                 ClearHistory();
  315 
  316                 MountOptions mountOptions;
  317                 mountOptions.Keyfiles = Keyfiles;
  318                 mountOptions.Password = Password;
  319                 mountOptions.Pim = Pim;
  320                 mountOptions.Path = make_shared <VolumePath> (SelectedVolumePath);
  321 
  322                 try
  323                 {
  324                     wxBusyCursor busy;
  325                     Gui->SetActiveFrame (this);
  326                     MountedOuterVolume = Core->MountVolume (mountOptions);
  327                 }
  328                 catch (exception &e)
  329                 {
  330                     Gui->SetActiveFrame (this);
  331                     Gui->ShowError (e);
  332 
  333                     Close();
  334                     return new InfoWizardPage (GetPageParent());
  335                 }
  336 
  337                 struct OpenOuterVolumeFunctor : public Functor
  338                 {
  339                     OpenOuterVolumeFunctor (const DirectoryPath &outerVolumeMountPoint) : OuterVolumeMountPoint (outerVolumeMountPoint) { }
  340 
  341                     virtual void operator() ()
  342                     {
  343                         Gui->OpenExplorerWindow (OuterVolumeMountPoint);
  344                     }
  345 
  346                     DirectoryPath OuterVolumeMountPoint;
  347                 };
  348 
  349                 InfoWizardPage *page = new InfoWizardPage (GetPageParent(), _("Open Outer Volume"),
  350                     shared_ptr <Functor> (new OpenOuterVolumeFunctor (MountedOuterVolume->MountPoint)));
  351 
  352                 page->SetPageTitle (LangString["HIDVOL_HOST_FILLING_TITLE"]);
  353 
  354                 page->SetPageText (StringFormatter (
  355                     _("Outer volume has been successfully created and mounted as '{0}'. To this volume you should now copy some sensitive-looking files that you actually do NOT want to hide. The files will be there for anyone forcing you to disclose your password. You will reveal only the password for this outer volume, not for the hidden one. The files that you really care about will be stored in the hidden volume, which will be created later on. When you finish copying, click Next. Do not dismount the volume.\n\nNote: After you click Next, the outer volume will be analyzed to determine the size of uninterrupted area of free space whose end is aligned with the end of the volume. This area will accommodate the hidden volume, so it will limit its maximum possible size. The procedure ensures no data on the outer volume are overwritten by the hidden volume."),
  356                     wstring (MountedOuterVolume->MountPoint)));
  357 
  358                 return page;
  359             }
  360 
  361         case Step::HiddenVolume:
  362             {
  363                 ClearHistory();
  364                 OuterVolume = false;
  365                 LargeFilesSupport = false;
  366                 Pim = 0;
  367 
  368                 InfoWizardPage *page = new InfoWizardPage (GetPageParent());
  369                 page->SetPageTitle (LangString["HIDVOL_PRE_CIPHER_TITLE"]);
  370                 page->SetPageText (LangString["HIDVOL_PRE_CIPHER_HELP"]);
  371 
  372                 return page;
  373             }
  374 
  375         default:
  376             throw ParameterIncorrect (SRC_POS);
  377         }
  378     }
  379 
  380     void VolumeCreationWizard::OnAbortButtonClick (EventArgs &args)
  381     {
  382         AbortRequested = true;
  383     }
  384 
  385     void VolumeCreationWizard::OnMouseMotion (wxMouseEvent& event)
  386     {
  387         event.Skip();
  388         if (!IsWorkInProgress() && RandomNumberGenerator::IsRunning())
  389         {
  390             RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&event), sizeof (event)));
  391 
  392             long coord = event.GetX();
  393             RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&coord), sizeof (coord)));
  394             coord = event.GetY();
  395             RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&coord), sizeof (coord)));
  396 
  397             VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
  398             if (page)
  399             {
  400                 page->IncrementEntropyProgress ();
  401             }
  402         }
  403     }
  404 
  405     void VolumeCreationWizard::OnProgressTimer ()
  406     {
  407         if (!IsWorkInProgress())
  408             return;
  409 
  410         if (AbortRequested && !AbortConfirmationPending)
  411         {
  412             AbortConfirmationPending = true;
  413             if (Gui->AskYesNo (LangString ["FORMAT_ABORT"], true))
  414             {
  415                 if (IsWorkInProgress() && Creator.get() != nullptr)
  416                 {
  417                     CreationAborted = true;
  418                     Creator->Abort();
  419                 }
  420             }
  421             AbortRequested = false;
  422             AbortConfirmationPending = false;
  423         }
  424 
  425         VolumeCreator::ProgressInfo progress = Creator->GetProgressInfo();
  426 
  427         VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
  428         page->SetProgressValue (progress.SizeDone);
  429 
  430         if (!progress.CreationInProgress && !AbortConfirmationPending)
  431         {
  432             SetWorkInProgress (false);
  433             OnVolumeCreatorFinished ();
  434         }
  435     }
  436 
  437     void VolumeCreationWizard::OnRandomPoolUpdateTimer ()
  438     {
  439         if (!IsWorkInProgress())
  440         {
  441             wxLongLong time = wxGetLocalTimeMillis();
  442             RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&time), sizeof (time)));
  443         }
  444     }
  445 
  446     void VolumeCreationWizard::OnVolumeCreatorFinished ()
  447     {
  448         VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
  449 
  450         ProgressTimer.reset();
  451         page->SetProgressState (false);
  452 
  453         Gui->EndInteractiveBusyState (this);
  454         SetWorkInProgress (false);
  455         UpdateControls();
  456 
  457         try
  458         {
  459             if (!CreationAborted)
  460             {
  461                 Creator->CheckResult();
  462 
  463 #ifdef TC_UNIX
  464                 // Format non-FAT filesystem
  465                 const char *fsFormatter = nullptr;
  466 
  467                 switch (SelectedFilesystemType)
  468                 {
  469 #if defined (TC_LINUX)
  470                 case VolumeCreationOptions::FilesystemType::Ext2:       fsFormatter = "mkfs.ext2"; break;
  471                 case VolumeCreationOptions::FilesystemType::Ext3:       fsFormatter = "mkfs.ext3"; break;
  472                 case VolumeCreationOptions::FilesystemType::Ext4:       fsFormatter = "mkfs.ext4"; break;
  473                 case VolumeCreationOptions::FilesystemType::NTFS:       fsFormatter = "mkfs.ntfs"; break;
  474                 case VolumeCreationOptions::FilesystemType::exFAT:      fsFormatter = "mkfs.exfat"; break;
  475 #elif defined (TC_MACOSX)
  476                 case VolumeCreationOptions::FilesystemType::MacOsExt:   fsFormatter = "newfs_hfs"; break;
  477                 case VolumeCreationOptions::FilesystemType::exFAT:      fsFormatter = "newfs_exfat"; break;
  478 #elif defined (TC_FREEBSD) || defined (TC_SOLARIS)
  479                 case VolumeCreationOptions::FilesystemType::UFS:        fsFormatter = "newfs" ; break;
  480 #endif
  481                 default: break;
  482                 }
  483 
  484                 if (fsFormatter)
  485                 {
  486                     wxBusyCursor busy;
  487 
  488                     MountOptions mountOptions (Gui->GetPreferences().DefaultMountOptions);
  489                     mountOptions.Path = make_shared <VolumePath> (SelectedVolumePath);
  490                     mountOptions.NoFilesystem = true;
  491                     mountOptions.Protection = VolumeProtection::None;
  492                     mountOptions.Password = Password;
  493                     mountOptions.Pim = Pim;
  494                     mountOptions.Keyfiles = Keyfiles;
  495                     mountOptions.Kdf = Kdf;
  496                     mountOptions.TrueCryptMode = false;
  497 
  498                     shared_ptr <VolumeInfo> volume = Core->MountVolume (mountOptions);
  499                     finally_do_arg (shared_ptr <VolumeInfo>, volume, { Core->DismountVolume (finally_arg, true); });
  500 
  501                     Thread::Sleep (2000);   // Try to prevent race conditions caused by OS
  502 
  503                     // Temporarily take ownership of the device if the user is not an administrator
  504                     UserId origDeviceOwner ((uid_t) -1);
  505 
  506                     DevicePath virtualDevice = volume->VirtualDevice;
  507 #ifdef TC_MACOSX
  508                     string virtualDeviceStr = virtualDevice;
  509                     if (virtualDeviceStr.find ("/dev/rdisk") != 0)
  510                         virtualDevice = "/dev/r" + virtualDeviceStr.substr (5);
  511 #endif
  512                     try
  513                     {
  514                         File file;
  515                         file.Open (virtualDevice, File::OpenReadWrite);
  516                     }
  517                     catch (...)
  518                     {
  519                         if (!Core->HasAdminPrivileges())
  520                         {
  521                             origDeviceOwner = virtualDevice.GetOwner();
  522                             Core->SetFileOwner (virtualDevice, UserId (getuid()));
  523                         }
  524                     }
  525 
  526                     finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner,
  527                     {
  528                         if (finally_arg2.SystemId != (uid_t) -1)
  529                             Core->SetFileOwner (finally_arg, finally_arg2);
  530                     });
  531 
  532                     // Create filesystem
  533                     list <string> args;
  534 
  535                     if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::MacOsExt && VolumeSize >= 10 * BYTES_PER_MB)
  536                         args.push_back ("-J");
  537 
  538                     // Perform a quick NTFS formatting
  539                     if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::NTFS)
  540                         args.push_back ("-f");
  541 
  542                     args.push_back (string (virtualDevice));
  543 
  544                     Process::Execute (fsFormatter, args);
  545                 }
  546 #endif // TC_UNIX
  547 
  548                 if (OuterVolume)
  549                 {
  550                     SetStep (Step::OuterVolumeContents);
  551                 }
  552                 else
  553                 {
  554                     Gui->ShowInfo (SelectedVolumeType == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO");
  555                     SetStep (Step::VolumeCreatedInfo);
  556                 }
  557 
  558                 return;
  559             }
  560         }
  561         catch (exception &e)
  562         {
  563             Gui->ShowError (e);
  564         }
  565 
  566         page->SetProgressValue (0);
  567         if (SelectedVolumeType == VolumeType::Normal && !SelectedVolumePath.IsDevice())
  568         {
  569             try
  570             {
  571                 FilePath (wstring (SelectedVolumePath)).Delete();
  572             }
  573             catch (...) { }
  574         }
  575     }
  576 
  577     WizardFrame::WizardStep VolumeCreationWizard::ProcessPageChangeRequest (bool forward)
  578     {
  579         switch (GetCurrentStep())
  580         {
  581         case Step::VolumeHostType:
  582             {
  583                 SingleChoiceWizardPage <VolumeHostType::Enum> *page = dynamic_cast <SingleChoiceWizardPage <VolumeHostType::Enum> *> (GetCurrentPage());
  584 
  585                 try
  586                 {
  587                     SelectedVolumeHostType = page->GetSelection();
  588                 }
  589                 catch (NoItemSelected &)
  590                 {
  591                     return GetCurrentStep();
  592                 }
  593 
  594                 return Step::VolumeType;
  595             }
  596 
  597         case Step::VolumeType:
  598             {
  599                 SingleChoiceWizardPage <VolumeType::Enum> *page = dynamic_cast <SingleChoiceWizardPage <VolumeType::Enum> *> (GetCurrentPage());
  600 
  601                 try
  602                 {
  603                     SelectedVolumeType = page->GetSelection();
  604                 }
  605                 catch (NoItemSelected &)
  606                 {
  607                     return GetCurrentStep();
  608                 }
  609 
  610                 if (SelectedVolumeType == VolumeType::Hidden)
  611                     OuterVolume = true;
  612 
  613                 return Step::VolumeLocation;
  614             }
  615 
  616         case Step::VolumeLocation:
  617             {
  618                 VolumeLocationWizardPage *page = dynamic_cast <VolumeLocationWizardPage *> (GetCurrentPage());
  619                 SelectedVolumePath = page->GetVolumePath();
  620                 VolumeSize = 0;
  621 
  622                 if (forward)
  623                 {
  624                     if (Core->IsVolumeMounted (SelectedVolumePath))
  625                     {
  626                         Gui->ShowInfo ("DISMOUNT_FIRST");
  627                         return GetCurrentStep();
  628                     }
  629 
  630                     if (SelectedVolumePath.IsDevice())
  631                     {
  632                         if (!DeviceWarningConfirmed && !Gui->AskYesNo (LangString["FORMAT_DEVICE_FOR_ADVANCED_ONLY"]))
  633                             return GetCurrentStep();
  634 
  635                         DeviceWarningConfirmed = true;
  636 
  637                         foreach_ref (const HostDevice &drive, Core->GetHostDevices())
  638                         {
  639                             if (drive.Path == SelectedVolumePath && !drive.Partitions.empty())
  640                             {
  641                                 foreach_ref (const HostDevice &partition, drive.Partitions)
  642                                 {
  643                                     if (partition.MountPoint == "/")
  644                                     {
  645                                         Gui->ShowError (_("Error: You are trying to encrypt a system drive.\n\nVeraCrypt can encrypt a system drive only under Windows."));
  646                                         return GetCurrentStep();
  647                                     }
  648                                 }
  649 
  650                                 Gui->ShowError ("DEVICE_PARTITIONS_ERR");
  651                                 return GetCurrentStep();
  652                             }
  653                         }
  654 
  655                         try
  656                         {
  657                             SectorSize = Core->GetDeviceSectorSize (SelectedVolumePath);
  658                             VolumeSize = Core->GetDeviceSize (SelectedVolumePath);
  659                         }
  660                         catch (UserAbort&)
  661                         {
  662                             return Step::VolumeLocation;
  663                         }
  664                         catch (exception &e)
  665                         {
  666                             Gui->ShowError (e);
  667                             Gui->ShowError ("CANNOT_CALC_SPACE");
  668                             return GetCurrentStep();
  669                         }
  670 
  671                         DirectoryPath mountPoint;
  672                         try
  673                         {
  674                             mountPoint = Core->GetDeviceMountPoint (SelectedVolumePath);
  675 
  676                             if (!mountPoint.IsEmpty())
  677                             {
  678                                 if (mountPoint == "/")
  679                                 {
  680                                     Gui->ShowError (_("Error: You are trying to encrypt a system partition.\n\nVeraCrypt can encrypt system partitions only under Windows."));
  681                                     return GetCurrentStep();
  682                                 }
  683 
  684                                 if (!Gui->AskYesNo (StringFormatter (_("WARNING: Formatting of the device will destroy all data on filesystem '{0}'.\n\nDo you want to continue?"), wstring (mountPoint)), false, true))
  685                                     return GetCurrentStep();
  686 
  687                                 try
  688                                 {
  689                                     Core->DismountFilesystem (mountPoint, true);
  690                                 }
  691                                 catch (exception &e)
  692                                 {
  693                                     Gui->ShowError (e);
  694                                     Gui->ShowError (StringFormatter (_("The filesystem of the selected device is currently mounted. Please dismount '{0}' before proceeding."), wstring (mountPoint)));
  695                                     return GetCurrentStep();
  696                                 }
  697                             }
  698                         }
  699                         catch (...) { }
  700                     }
  701                     else
  702                         SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
  703                 }
  704 
  705                 return Step::EncryptionOptions;
  706             }
  707 
  708         case Step::EncryptionOptions:
  709             {
  710                 EncryptionOptionsWizardPage *page = dynamic_cast <EncryptionOptionsWizardPage *> (GetCurrentPage());
  711                 SelectedEncryptionAlgorithm = page->GetEncryptionAlgorithm ();
  712                 SelectedHash = page->GetHash ();
  713 
  714                 if (forward)
  715                     RandomNumberGenerator::SetHash (SelectedHash);
  716 
  717                 if (SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden))
  718                     return Step::VolumePassword;
  719                 else
  720                     return Step::VolumeSize;
  721             }
  722 
  723         case Step::VolumeSize:
  724             {
  725                 VolumeSizeWizardPage *page = dynamic_cast <VolumeSizeWizardPage *> (GetCurrentPage());
  726 
  727                 try
  728                 {
  729                     VolumeSize = page->GetVolumeSize();
  730                 }
  731                 catch (Exception &e)
  732                 {
  733                     if (forward)
  734                     {
  735                         Gui->ShowError (e);
  736                         return GetCurrentStep();
  737                     }
  738                 }
  739 
  740                 if (forward
  741                     && !OuterVolume && SelectedVolumeType == VolumeType::Hidden
  742                     && (double) VolumeSize / MaxHiddenVolumeSize > 0.85)
  743                 {
  744                     if (!Gui->AskYesNo (LangString["FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME"]))
  745                         return GetCurrentStep();
  746                 }
  747 
  748                 if (forward
  749                     && SelectedVolumeHostType == VolumeHostType::File
  750                     && VolumeSize > 4 * BYTES_PER_GB
  751                     && (OuterVolume || SelectedVolumeType != VolumeType::Hidden)
  752                     && !Core->FilesystemSupportsLargeFiles (SelectedVolumePath))
  753                 {
  754                     Gui->ShowWarning (LangString["VOLUME_TOO_LARGE_FOR_FAT32"]);
  755                 }
  756 
  757                 return Step::VolumePassword;
  758             }
  759 
  760         case Step::VolumePassword:
  761             {
  762                 VolumePasswordWizardPage *page = dynamic_cast <VolumePasswordWizardPage *> (GetCurrentPage());
  763                 try
  764                 {
  765                     Password = page->GetPassword();
  766                 }
  767                 catch (PasswordException& e)
  768                 {
  769                     Gui->ShowWarning (e);
  770                     return GetCurrentStep();
  771                 }
  772 
  773                 Kdf = page->GetPkcs5Kdf();
  774                 Keyfiles = page->GetKeyfiles();
  775 
  776                 if (forward && Password && !Password->IsEmpty())
  777                 {
  778                     if (Password->Size() < VolumePassword::WarningSizeThreshold)
  779                     {
  780                         if (!Gui->AskYesNo (LangString["PASSWORD_LENGTH_WARNING"], false, true))
  781                         {
  782                             return GetCurrentStep();
  783                         }
  784                     }
  785                 }
  786 
  787                 if (page->IsPimSelected ())
  788                     return Step::VolumePim;
  789                 else
  790                 {
  791                     // Clear PIM
  792                     Pim = 0;
  793 
  794                     // Skip PIM
  795                     if (forward && OuterVolume)
  796                     {
  797                         // Use FAT to prevent problems with free space
  798                         QuickFormatEnabled = false;
  799                         SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT;
  800                         return Step::CreationProgress;
  801                     }
  802 
  803                     if (VolumeSize > 4 * BYTES_PER_GB)
  804                     {
  805                         if (VolumeSize <= TC_MAX_FAT_SECTOR_COUNT * SectorSize)
  806                             return Step::LargeFilesSupport;
  807                         else
  808                             SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
  809                     }
  810 
  811                     return Step::FormatOptions;
  812                 }
  813             }
  814 
  815         case Step::VolumePim:
  816             {
  817                 VolumePimWizardPage *page = dynamic_cast <VolumePimWizardPage *> (GetCurrentPage());
  818                 Pim = page->GetVolumePim();
  819 
  820                 if (forward && Password && !Password->IsEmpty())
  821                 {
  822                     if (-1 == Pim)
  823                     {
  824                         // PIM invalid: don't go anywhere
  825                         Gui->ShowError ("PIM_TOO_BIG");
  826                         return GetCurrentStep();
  827                     }
  828 
  829                     if (Password->Size() < VolumePassword::WarningSizeThreshold)
  830                     {
  831                         if (Pim > 0 && Pim < 485)
  832                         {
  833                             Gui->ShowError ("PIM_REQUIRE_LONG_PASSWORD");
  834                             return GetCurrentStep();
  835                         }
  836                     }
  837                     else if (Pim > 0 && Pim < 485)
  838                     {
  839                         if (!Gui->AskYesNo (LangString["PIM_SMALL_WARNING"], false, true))
  840                         {
  841                             return GetCurrentStep();
  842                         }
  843                     }
  844                 }
  845 
  846 
  847                 if (forward && OuterVolume)
  848                 {
  849                     // Use FAT to prevent problems with free space
  850                     QuickFormatEnabled = false;
  851                     SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT;
  852                     return Step::CreationProgress;
  853                 }
  854 
  855                 if (VolumeSize > 4 * BYTES_PER_GB)
  856                 {
  857                     if (VolumeSize <= TC_MAX_FAT_SECTOR_COUNT * SectorSize)
  858                         return Step::LargeFilesSupport;
  859                     else
  860                         SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
  861                 }
  862 
  863                 return Step::FormatOptions;
  864             }
  865 
  866         case Step::LargeFilesSupport:
  867             {
  868                 SingleChoiceWizardPage <bool> *page = dynamic_cast <SingleChoiceWizardPage <bool> *> (GetCurrentPage());
  869 
  870                 try
  871                 {
  872                     LargeFilesSupport = page->GetSelection();
  873                 }
  874                 catch (NoItemSelected &)
  875                 {
  876                     return GetCurrentStep();
  877                 }
  878 
  879                 if (LargeFilesSupport)
  880                     SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
  881                 else
  882                     SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT;
  883 
  884                 return Step::FormatOptions;
  885             }
  886 
  887         case Step::FormatOptions:
  888             {
  889                 VolumeFormatOptionsWizardPage *page = dynamic_cast <VolumeFormatOptionsWizardPage *> (GetCurrentPage());
  890                 SelectedFilesystemType = page->GetFilesystemType();
  891                 QuickFormatEnabled = page->IsQuickFormatEnabled();
  892 
  893                 if (SelectedFilesystemType != VolumeCreationOptions::FilesystemType::None
  894                     && SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT)
  895                     return Step::CrossPlatformSupport;
  896 
  897                 return Step::CreationProgress;
  898             }
  899 
  900         case Step::CrossPlatformSupport:
  901             {
  902                 SingleChoiceWizardPage <bool> *page = dynamic_cast <SingleChoiceWizardPage <bool> *> (GetCurrentPage());
  903 
  904                 try
  905                 {
  906                     CrossPlatformSupport = page->GetSelection();
  907                 }
  908                 catch (NoItemSelected &)
  909                 {
  910                     return GetCurrentStep();
  911                 }
  912 
  913                 if (forward && CrossPlatformSupport)
  914                     Gui->ShowWarning (StringFormatter (_("Please note that the volume will not be formatted with a FAT filesystem and, therefore, you may be required to install additional filesystem drivers on platforms other than {0}, which will enable you to mount the volume."), SystemInfo::GetPlatformName()));
  915 
  916                 return Step::CreationProgress;
  917             }
  918 
  919         case Step::CreationProgress:
  920             {
  921                 VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
  922 
  923                 DisplayKeyInfo = page->IsKeyInfoDisplayed();
  924 
  925                 if (forward)
  926                 {
  927                     if (SelectedVolumeType != VolumeType::Hidden || OuterVolume)
  928                     {
  929                         if (OuterVolume && VolumeSize > TC_MAX_FAT_SECTOR_COUNT * SectorSize)
  930                         {
  931                             uint64 limit = TC_MAX_FAT_SECTOR_COUNT * SectorSize / BYTES_PER_TB;
  932                             wstring err = StringFormatter (_("Error: The hidden volume to be created is larger than {0} TB ({1} GB).\n\nPossible solutions:\n- Create a container/partition smaller than {0} TB.\n"), limit, limit * 1024);
  933 
  934                             if (SectorSize < 4096)
  935                             {
  936                                 err += _("- Use a drive with 4096-byte sectors to be able to create partition/device-hosted hidden volumes up to 16 TB in size");
  937 #if defined (TC_LINUX)
  938                                 err += _(".\n");
  939 #else
  940                                 err += _(" (not supported by components available on this platform).\n");
  941 #endif
  942                             }
  943 
  944                             Gui->ShowError (err);
  945                             return GetCurrentStep();
  946                         }
  947 
  948                         if (SelectedVolumePath.IsDevice())
  949                         {
  950                             wxString confirmMsg = LangString["OVERWRITEPROMPT_DEVICE"];
  951 
  952                             if (!Gui->AskYesNo (wxString::Format (confirmMsg, wxString (_("DEVICE")).c_str(), wstring (SelectedVolumePath).c_str(), L""), false, true))
  953                                 return GetCurrentStep();
  954                         }
  955                         else if (FilesystemPath (wstring (SelectedVolumePath)).IsFile())
  956                         {
  957                             wxString confirmMsg = LangString["OVERWRITEPROMPT"];
  958 
  959                             if (!Gui->AskYesNo (wxString::Format (confirmMsg, wstring (SelectedVolumePath).c_str()), false, true))
  960                                 return GetCurrentStep();
  961                         }
  962                     }
  963 
  964                     AbortRequested = false;
  965                     AbortConfirmationPending = false;
  966                     CreationAborted = false;
  967                     SetWorkInProgress (true);
  968                     UpdateControls();
  969 
  970                     Gui->BeginInteractiveBusyState (this);
  971 
  972                     try
  973                     {
  974                         make_shared_auto (VolumeCreationOptions, options);
  975 
  976                         options->Filesystem = SelectedFilesystemType;
  977                         options->FilesystemClusterSize = SelectedFilesystemClusterSize;
  978                         options->SectorSize = SectorSize;
  979                         options->EA = SelectedEncryptionAlgorithm;
  980                         options->Password = Password;
  981                         options->Pim = Pim;
  982                         options->Keyfiles = Keyfiles;
  983                         options->Path = SelectedVolumePath;
  984                         options->Quick = QuickFormatEnabled;
  985                         options->Size = VolumeSize;
  986                         options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType;
  987                         options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash, false);
  988 
  989                         Creator.reset (new VolumeCreator);
  990                         VolumeCreatorThreadRoutine routine(options, Creator);
  991                         Gui->ExecuteWaitThreadRoutine (this, &routine);
  992 
  993                         page->SetKeyInfo (Creator->GetKeyInfo());
  994 
  995                         class Timer : public wxTimer
  996                         {
  997                         public:
  998                             Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { }
  999 
 1000                             void Notify()
 1001                             {
 1002                                 Wizard->OnProgressTimer();
 1003                             }
 1004 
 1005                             VolumeCreationWizard *Wizard;
 1006                         };
 1007 
 1008                         page->SetProgressRange (options->Size);
 1009                         page->SetProgressState (true);
 1010                         ProgressTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
 1011                         ProgressTimer->Start (50);
 1012                     }
 1013                     catch (Exception &e)
 1014                     {
 1015                         CreationAborted = true;
 1016                         OnVolumeCreatorFinished();
 1017                         Gui->ShowError (e);
 1018                     }
 1019                 }
 1020 
 1021                 return GetCurrentStep();
 1022             }
 1023 
 1024         case Step::VolumeCreatedInfo:
 1025             Creator.reset();
 1026             SetCancelButtonText (L"");
 1027 
 1028             return Step::VolumeHostType;
 1029 
 1030         case Step::OuterVolumeContents:
 1031             try
 1032             {
 1033                 // Determine maximum size of the hidden volume. Scan cluster table offline as a live filesystem test would
 1034                 // require using FUSE and loop device which cannot be used for devices with sectors larger than 512.
 1035 
 1036                 wxBusyCursor busy;
 1037                 MaxHiddenVolumeSize = 0;
 1038 
 1039                 Gui->SetActiveFrame (this);
 1040 
 1041                 if (MountedOuterVolume)
 1042                 {
 1043                     Core->DismountVolume (MountedOuterVolume);
 1044                     MountedOuterVolume.reset();
 1045                 }
 1046 
 1047 #ifdef TC_UNIX
 1048                 // Temporarily take ownership of a device if the user is not an administrator
 1049                 UserId origDeviceOwner ((uid_t) -1);
 1050 
 1051                 if (!Core->HasAdminPrivileges() && SelectedVolumePath.IsDevice())
 1052                 {
 1053                     origDeviceOwner = FilesystemPath (wstring (SelectedVolumePath)).GetOwner();
 1054                     Core->SetFileOwner (SelectedVolumePath, UserId (getuid()));
 1055                 }
 1056 
 1057                 finally_do_arg2 (FilesystemPath, SelectedVolumePath, UserId, origDeviceOwner,
 1058                 {
 1059                     if (finally_arg2.SystemId != (uid_t) -1)
 1060                         Core->SetFileOwner (finally_arg, finally_arg2);
 1061                 });
 1062 #endif
 1063 
 1064                 shared_ptr <Volume> outerVolume = Core->OpenVolume (make_shared <VolumePath> (SelectedVolumePath), true, Password, Pim, Kdf, false, Keyfiles, VolumeProtection::ReadOnly);
 1065                 MaxHiddenVolumeSize = Core->GetMaxHiddenVolumeSize (outerVolume);
 1066 
 1067                 // Add a reserve (in case the user mounts the outer volume and creates new files
 1068                 // on it by accident or OS writes some new data behind his or her back, such as
 1069                 // System Restore etc.)
 1070 
 1071                 uint64 reservedSize = outerVolume->GetSize() / 200;
 1072                 if (reservedSize > 10 * BYTES_PER_MB)
 1073                     reservedSize = 10 * BYTES_PER_MB;
 1074 
 1075                 if (MaxHiddenVolumeSize < reservedSize)
 1076                     MaxHiddenVolumeSize = 0;
 1077                 else
 1078                     MaxHiddenVolumeSize -= reservedSize;
 1079 
 1080                 MaxHiddenVolumeSize -= MaxHiddenVolumeSize % outerVolume->GetSectorSize();      // Must be a multiple of the sector size
 1081             }
 1082             catch (exception &e)
 1083             {
 1084                 Gui->SetActiveFrame (this);
 1085                 Gui->ShowError (e);
 1086                 return GetCurrentStep();
 1087             }
 1088 
 1089             return Step::HiddenVolume;
 1090 
 1091         case Step::HiddenVolume:
 1092             return Step::EncryptionOptions;
 1093 
 1094         default:
 1095             throw ParameterIncorrect (SRC_POS);
 1096         }
 1097     }
 1098 
 1099     void VolumeCreationWizard::UpdateControls ()
 1100     {
 1101         VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
 1102         if (page)
 1103         {
 1104             page->EnableAbort (IsWorkInProgress());
 1105         }
 1106     }
 1107 
 1108     bool VolumeCreationWizard::DeviceWarningConfirmed;
 1109 }