"Fossies" - the Fresh Open Source Software Archive

Member "src/Main/UserInterface.cpp" (10 Oct 2018, 57022 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 "UserInterface.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 <set>
   15 #include <typeinfo>
   16 #include <wx/apptrait.h>
   17 #include <wx/cmdline.h>
   18 #include "Crypto/cpu.h"
   19 #include "Platform/PlatformTest.h"
   20 #ifdef TC_UNIX
   21 #include <errno.h>
   22 #include "Platform/Unix/Process.h"
   23 #endif
   24 #include "Platform/SystemInfo.h"
   25 #include "Platform/SystemException.h"
   26 #include "Common/SecurityToken.h"
   27 #include "Volume/EncryptionTest.h"
   28 #include "Application.h"
   29 #include "FavoriteVolume.h"
   30 #include "UserInterface.h"
   31 
   32 namespace VeraCrypt
   33 {
   34     UserInterface::UserInterface ()
   35     {
   36     }
   37 
   38     UserInterface::~UserInterface ()
   39     {
   40         Core->WarningEvent.Disconnect (this);
   41         Core->VolumeMountedEvent.Disconnect (this);
   42 
   43         try
   44         {
   45             if (SecurityToken::IsInitialized())
   46                 SecurityToken::CloseLibrary();
   47         }
   48         catch (...) { }
   49     }
   50 
   51     void UserInterface::CheckRequirementsForMountingVolume () const
   52     {
   53 #ifdef TC_LINUX
   54         if (!Preferences.NonInteractive)
   55         {
   56             if (!SystemInfo::IsVersionAtLeast (2, 6, 24))
   57                 ShowWarning (_("Your system uses an old version of the Linux kernel.\n\nDue to a bug in the Linux kernel, your system may stop responding when writing data to a VeraCrypt volume. This problem can be solved by upgrading the kernel to version 2.6.24 or later."));
   58         }
   59 #endif // TC_LINUX
   60     }
   61 
   62     void UserInterface::CloseExplorerWindows (shared_ptr <VolumeInfo> mountedVolume) const
   63     {
   64 #ifdef TC_WINDOWS
   65         struct Args
   66         {
   67             HWND ExplorerWindow;
   68             string DriveRootPath;
   69         };
   70 
   71         struct Enumerator
   72         {
   73             static BOOL CALLBACK ChildWindows (HWND hwnd, LPARAM argsLP)
   74             {
   75                 Args *args = reinterpret_cast <Args *> (argsLP);
   76 
   77                 char s[4096];
   78                 SendMessageA (hwnd, WM_GETTEXT, sizeof (s), (LPARAM) s);
   79 
   80                 if (strstr (s, args->DriveRootPath.c_str()) != NULL)
   81                 {
   82                     PostMessage (args->ExplorerWindow, WM_CLOSE, 0, 0);
   83                     return FALSE;
   84                 }
   85 
   86                 return TRUE;
   87             }
   88 
   89             static BOOL CALLBACK TopLevelWindows (HWND hwnd, LPARAM argsLP)
   90             {
   91                 Args *args = reinterpret_cast <Args *> (argsLP);
   92 
   93                 char s[4096];
   94                 GetClassNameA (hwnd, s, sizeof s);
   95                 if (strcmp (s, "CabinetWClass") == 0)
   96                 {
   97                     GetWindowTextA (hwnd, s, sizeof s);
   98                     if (strstr (s, args->DriveRootPath.c_str()) != NULL)
   99                     {
  100                         PostMessage (hwnd, WM_CLOSE, 0, 0);
  101                         return TRUE;
  102                     }
  103 
  104                     args->ExplorerWindow = hwnd;
  105                     EnumChildWindows (hwnd, ChildWindows, argsLP);
  106                 }
  107 
  108                 return TRUE;
  109             }
  110         };
  111 
  112         Args args;
  113 
  114         string mountPoint = mountedVolume->MountPoint;
  115         if (mountPoint.size() < 2 || mountPoint[1] != ':')
  116             return;
  117 
  118         args.DriveRootPath = string() + mountPoint[0] + string (":\\");
  119 
  120         EnumWindows (Enumerator::TopLevelWindows, (LPARAM) &args);
  121 #endif
  122     }
  123 
  124     void UserInterface::DismountAllVolumes (bool ignoreOpenFiles, bool interactive) const
  125     {
  126         try
  127         {
  128             VolumeInfoList mountedVolumes = Core->GetMountedVolumes();
  129 
  130             if (mountedVolumes.size() < 1)
  131                 ShowInfo (LangString["NO_VOLUMES_MOUNTED"]);
  132 
  133             BusyScope busy (this);
  134             DismountVolumes (mountedVolumes, ignoreOpenFiles, interactive);
  135         }
  136         catch (exception &e)
  137         {
  138             ShowError (e);
  139         }
  140     }
  141 
  142     void UserInterface::DismountVolume (shared_ptr <VolumeInfo> volume, bool ignoreOpenFiles, bool interactive) const
  143     {
  144         VolumeInfoList volumes;
  145         volumes.push_back (volume);
  146 
  147         DismountVolumes (volumes, ignoreOpenFiles, interactive);
  148     }
  149 
  150     void UserInterface::DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles, bool interactive) const
  151     {
  152         BusyScope busy (this);
  153 
  154         volumes.sort (VolumeInfo::FirstVolumeMountedAfterSecond);
  155 
  156         wxString message;
  157         bool twoPassMode = volumes.size() > 1;
  158         bool volumesInUse = false;
  159         bool firstPass = true;
  160 
  161 #ifdef TC_WINDOWS
  162         if (Preferences.CloseExplorerWindowsOnDismount)
  163         {
  164             foreach (shared_ptr <VolumeInfo> volume, volumes)
  165                 CloseExplorerWindows (volume);
  166         }
  167 #endif
  168         while (!volumes.empty())
  169         {
  170             VolumeInfoList volumesLeft;
  171             foreach (shared_ptr <VolumeInfo> volume, volumes)
  172             {
  173                 try
  174                 {
  175                     BusyScope busy (this);
  176                     volume = Core->DismountVolume (volume, ignoreOpenFiles);
  177                 }
  178                 catch (MountedVolumeInUse&)
  179                 {
  180                     if (!firstPass)
  181                         throw;
  182 
  183                     if (twoPassMode || !interactive)
  184                     {
  185                         volumesInUse = true;
  186                         volumesLeft.push_back (volume);
  187                         continue;
  188                     }
  189                     else
  190                     {
  191                         if (AskYesNo (StringFormatter (LangString["UNMOUNT_LOCK_FAILED"], wstring (volume->Path)), true, true))
  192                         {
  193                             BusyScope busy (this);
  194                             volume = Core->DismountVolume (volume, true);
  195                         }
  196                         else
  197                             throw UserAbort (SRC_POS);
  198                     }
  199                 }
  200                 catch (...)
  201                 {
  202                     if (twoPassMode && firstPass)
  203                         volumesLeft.push_back (volume);
  204                     else
  205                         throw;
  206                 }
  207 
  208                 if (volume->HiddenVolumeProtectionTriggered)
  209                     ShowWarning (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (volume->Path)));
  210 
  211                 if (Preferences.Verbose)
  212                 {
  213                     if (!message.IsEmpty())
  214                         message += L'\n';
  215                     message += StringFormatter (_("Volume \"{0}\" has been dismounted."), wstring (volume->Path));
  216                 }
  217             }
  218 
  219             if (twoPassMode && firstPass)
  220             {
  221                 volumes = volumesLeft;
  222 
  223                 if (volumesInUse && interactive)
  224                 {
  225                     if (AskYesNo (LangString["UNMOUNTALL_LOCK_FAILED"], true, true))
  226                         ignoreOpenFiles = true;
  227                     else
  228                         throw UserAbort (SRC_POS);
  229                 }
  230             }
  231             else
  232                 break;
  233 
  234             firstPass = false;
  235         }
  236 
  237         if (Preferences.Verbose && !message.IsEmpty())
  238             ShowInfo (message);
  239     }
  240 
  241     void UserInterface::DisplayVolumeProperties (const VolumeInfoList &volumes) const
  242     {
  243         if (volumes.size() < 1)
  244             throw_err (LangString["NO_VOLUMES_MOUNTED"]);
  245 
  246         wxString prop;
  247 
  248         foreach_ref (const VolumeInfo &volume, volumes)
  249         {
  250             prop << _("Slot") << L": " << StringConverter::FromNumber (volume.SlotNumber) << L'\n';
  251             prop << LangString["VOLUME"] << L": " << wstring (volume.Path) << L'\n';
  252 #ifndef TC_WINDOWS
  253             prop << LangString["VIRTUAL_DEVICE"] << L": " << wstring (volume.VirtualDevice) << L'\n';
  254 #endif
  255             prop << LangString["MOUNT_POINT"] << L": " << wstring (volume.MountPoint) << L'\n';
  256             prop << LangString["SIZE"] << L": " << SizeToString (volume.Size) << L'\n';
  257             prop << LangString["TYPE"] << L": " << VolumeTypeToString (volume.Type, volume.TrueCryptMode, volume.Protection) << L'\n';
  258 
  259             prop << LangString["READ_ONLY"] << L": " << LangString [volume.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"] << L'\n';
  260 
  261             wxString protection;
  262             if (volume.Type == VolumeType::Hidden)
  263                 protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"];
  264             else if (volume.HiddenVolumeProtectionTriggered)
  265                 protection = LangString["HID_VOL_DAMAGE_PREVENTED"];
  266             else
  267                 protection = LangString [volume.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"];
  268 
  269             prop << LangString["HIDDEN_VOL_PROTECTION"] << L": " << protection << L'\n';
  270             prop << LangString["ENCRYPTION_ALGORITHM"] << L": " << volume.EncryptionAlgorithmName << L'\n';
  271             prop << LangString["KEY_SIZE"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n';
  272 
  273             if (volume.EncryptionModeName == L"XTS")
  274                 prop << LangString["SECONDARY_KEY_SIZE_XTS"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n';;
  275 
  276             wstringstream blockSize;
  277             blockSize << volume.EncryptionAlgorithmBlockSize * 8;
  278             if (volume.EncryptionAlgorithmBlockSize != volume.EncryptionAlgorithmMinBlockSize)
  279                 blockSize << L"/" << volume.EncryptionAlgorithmMinBlockSize * 8;
  280 
  281             prop << LangString["BLOCK_SIZE"] << L": " << blockSize.str() + L" " + LangString ["BITS"] << L'\n';
  282             prop << LangString["MODE_OF_OPERATION"] << L": " << volume.EncryptionModeName << L'\n';
  283             prop << LangString["PKCS5_PRF"] << L": " << volume.Pkcs5PrfName << L'\n';
  284 
  285             prop << LangString["VOLUME_FORMAT_VERSION"] << L": " << (volume.MinRequiredProgramVersion < 0x10b ? 1 : 2) << L'\n';
  286             prop << LangString["BACKUP_HEADER"] << L": " << LangString[volume.MinRequiredProgramVersion >= 0x10b ? "UISTR_YES" : "UISTR_NO"] << L'\n';
  287 
  288 #ifdef TC_LINUX
  289             if (string (volume.VirtualDevice).find ("/dev/mapper/veracrypt") != 0)
  290             {
  291 #endif
  292             prop << LangString["TOTAL_DATA_READ"] << L": " << SizeToString (volume.TotalDataRead) << L'\n';
  293             prop << LangString["TOTAL_DATA_WRITTEN"] << L": " << SizeToString (volume.TotalDataWritten) << L'\n';
  294 #ifdef TC_LINUX
  295             }
  296 #endif
  297 
  298             prop << L'\n';
  299         }
  300 
  301         ShowString (prop);
  302     }
  303 
  304     wxString UserInterface::ExceptionToMessage (const exception &ex)
  305     {
  306         wxString message;
  307 
  308         const Exception *e = dynamic_cast <const Exception *> (&ex);
  309         if (e)
  310         {
  311             message = ExceptionToString (*e);
  312 
  313             // System exception
  314             const SystemException *sysEx = dynamic_cast <const SystemException *> (&ex);
  315             if (sysEx)
  316             {
  317                 if (!message.IsEmpty())
  318                 {
  319                     message += L"\n\n";
  320                 }
  321 
  322                 message += wxString (sysEx->SystemText()).Trim (true);
  323             }
  324 
  325             if (!message.IsEmpty())
  326             {
  327                 // Subject
  328                 if (!e->GetSubject().empty())
  329                 {
  330                     message = message.Trim (true);
  331 
  332                     if (message.EndsWith (L"."))
  333                         message.Truncate (message.size() - 1);
  334 
  335                     if (!message.EndsWith (L":"))
  336                         message << L":\n";
  337                     else
  338                         message << L"\n";
  339 
  340                     message << e->GetSubject();
  341                 }
  342 
  343 #ifdef TC_UNIX
  344                 if (sysEx && sysEx->GetErrorCode() == EIO)
  345                     message << L"\n\n" << LangString["ERR_HARDWARE_ERROR"];
  346 #endif
  347 
  348                 if (sysEx && sysEx->what())
  349                     message << L"\n\n" << StringConverter::ToWide (sysEx->what());
  350 
  351                 return message;
  352             }
  353         }
  354 
  355         // bad_alloc
  356         const bad_alloc *outOfMemory = dynamic_cast <const bad_alloc *> (&ex);
  357         if (outOfMemory)
  358             return _("Out of memory.");
  359 
  360         // Unresolved exceptions
  361         string typeName (StringConverter::GetTypeName (typeid (ex)));
  362         size_t pos = typeName.find ("VeraCrypt::");
  363         if (pos != string::npos)
  364         {
  365             return StringConverter::ToWide (typeName.substr (pos + string ("VeraCrypt::").size()))
  366                 + L" at " + StringConverter::ToWide (ex.what());
  367         }
  368 
  369         return StringConverter::ToWide (typeName) + L" at " + StringConverter::ToWide (ex.what());
  370     }
  371 
  372     wxString UserInterface::ExceptionToString (const Exception &ex)
  373     {
  374         // Error messages
  375         const ErrorMessage *errMsgEx = dynamic_cast <const ErrorMessage *> (&ex);
  376         if (errMsgEx)
  377             return wstring (*errMsgEx).c_str();
  378 
  379         // ExecutedProcessFailed
  380         const ExecutedProcessFailed *execEx = dynamic_cast <const ExecutedProcessFailed *> (&ex);
  381         if (execEx)
  382         {
  383             wstring errOutput;
  384 
  385             // ElevationFailed
  386             if (dynamic_cast <const ElevationFailed*> (&ex))
  387                 errOutput += wxString (_("Failed to obtain administrator privileges")) + (StringConverter::Trim (execEx->GetErrorOutput()).empty() ? L". " : L": ");
  388 
  389             errOutput += StringConverter::ToWide (execEx->GetErrorOutput());
  390 
  391             if (errOutput.empty())
  392                 return errOutput + StringFormatter (_("Command \"{0}\" returned error {1}."), execEx->GetCommand(), execEx->GetExitCode());
  393 
  394             return wxString (errOutput).Trim (true);
  395         }
  396 
  397         // PasswordIncorrect
  398         if (dynamic_cast <const PasswordException *> (&ex))
  399         {
  400             wxString message = ExceptionTypeToString (typeid (ex));
  401 
  402 #ifndef TC_NO_GUI
  403             if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic && wxGetKeyState (WXK_CAPITAL))
  404                 message += wxString (L"\n\n") + LangString["CAPSLOCK_ON"];
  405 #endif
  406             if (Keyfile::WasHiddenFilePresentInKeyfilePath())
  407             {
  408 #ifdef TC_UNIX
  409                 message += _("\n\nWarning: Hidden files are present in a keyfile path. If you need to use them as keyfiles, remove the leading dot from their filenames. Hidden files are visible only if enabled in system options.");
  410 #else
  411                 message += LangString["HIDDEN_FILES_PRESENT_IN_KEYFILE_PATH"];
  412 #endif
  413             }
  414 
  415             return message;
  416         }
  417 
  418         // PKCS#11 Exception
  419         if (dynamic_cast <const Pkcs11Exception *> (&ex))
  420         {
  421             string errorString = string (dynamic_cast <const Pkcs11Exception &> (ex));
  422 
  423             if (LangString.Exists (errorString))
  424                 return LangString[errorString];
  425 
  426             if (errorString.find ("CKR_") == 0)
  427             {
  428                 errorString = errorString.substr (4);
  429                 for (size_t i = 0; i < errorString.size(); ++i)
  430                 {
  431                     if (errorString[i] == '_')
  432                         errorString[i] = ' ';
  433                 }
  434             }
  435 
  436             return LangString["SECURITY_TOKEN_ERROR"] + L":\n\n" + StringConverter::ToWide (errorString);
  437         }
  438 
  439         // Other library exceptions
  440         return ExceptionTypeToString (typeid (ex));
  441     }
  442 
  443     wxString UserInterface::ExceptionTypeToString (const std::type_info &ex)
  444     {
  445 #define EX2MSG(exception, message) do { if (ex == typeid (exception)) return (message); } while (false)
  446         EX2MSG (DriveLetterUnavailable,             LangString["DRIVE_LETTER_UNAVAILABLE"]);
  447         EX2MSG (EncryptedSystemRequired,            _("This operation must be performed only when the system hosted on the volume is running."));
  448         EX2MSG (ExternalException,                  LangString["EXCEPTION_OCCURRED"]);
  449         EX2MSG (InsufficientData,                   _("Not enough data available."));
  450         EX2MSG (InvalidSecurityTokenKeyfilePath,    LangString["INVALID_TOKEN_KEYFILE_PATH"]);
  451         EX2MSG (HigherVersionRequired,              LangString["NEW_VERSION_REQUIRED"]);
  452         EX2MSG (KernelCryptoServiceTestFailed,      _("Kernel cryptographic service test failed. The cryptographic service of your kernel most likely does not support volumes larger than 2 TB.\n\nPossible solutions:\n- Upgrade the Linux kernel to version 2.6.33 or later.\n- Disable use of the kernel cryptographic services (Settings > Preferences > System Integration) or use 'nokernelcrypto' mount option on the command line."));
  453         EX2MSG (KeyfilePathEmpty,                   LangString["ERR_KEYFILE_PATH_EMPTY"]);
  454         EX2MSG (LoopDeviceSetupFailed,              _("Failed to set up a loop device."));
  455         EX2MSG (MissingArgument,                    _("A required argument is missing."));
  456         EX2MSG (MissingVolumeData,                  _("Volume data missing."));
  457         EX2MSG (MountPointRequired,                 _("Mount point required."));
  458         EX2MSG (MountPointUnavailable,              _("Mount point is already in use."));
  459         EX2MSG (NoDriveLetterAvailable,             LangString["NO_FREE_DRIVES"]);
  460         EX2MSG (PasswordEmpty,                      _("No password or keyfile specified."));
  461         EX2MSG (PasswordIncorrect,                  LangString["PASSWORD_WRONG"]);
  462         EX2MSG (PasswordKeyfilesIncorrect,          LangString["PASSWORD_OR_KEYFILE_WRONG"]);
  463         EX2MSG (PasswordOrKeyboardLayoutIncorrect,  LangString["PASSWORD_OR_KEYFILE_WRONG"] + _("\n\nNote that pre-boot authentication passwords need to be typed in the pre-boot environment where non-US keyboard layouts are not available. Therefore, pre-boot authentication passwords must always be typed using the standard US keyboard layout (otherwise, the password will be typed incorrectly in most cases). However, note that you do NOT need a real US keyboard; you just need to change the keyboard layout in your operating system."));
  464         EX2MSG (PasswordOrMountOptionsIncorrect,    LangString["PASSWORD_OR_KEYFILE_OR_MODE_WRONG"] + _("\n\nNote: If you are attempting to mount a partition located on an encrypted system drive without pre-boot authentication or to mount the encrypted system partition of an operating system that is not running, you can do so by selecting 'Options >' > 'Mount partition using system encryption'."));
  465         EX2MSG (PasswordTooLong,                    StringFormatter (_("Password is longer than {0} characters."), (int) VolumePassword::MaxSize));
  466         EX2MSG (PasswordUTF8TooLong,                LangString["PASSWORD_UTF8_TOO_LONG"]);
  467         EX2MSG (PasswordUTF8Invalid,                LangString["PASSWORD_UTF8_INVALID"]);
  468         EX2MSG (PartitionDeviceRequired,            _("Partition device required."));
  469         EX2MSG (ProtectionPasswordIncorrect,        _("Incorrect password to the protected hidden volume or the hidden volume does not exist."));
  470         EX2MSG (ProtectionPasswordKeyfilesIncorrect,_("Incorrect keyfile(s) and/or password to the protected hidden volume or the hidden volume does not exist."));
  471         EX2MSG (RootDeviceUnavailable,              LangString["NODRIVER"]);
  472         EX2MSG (SecurityTokenKeyfileAlreadyExists,  LangString["TOKEN_KEYFILE_ALREADY_EXISTS"]);
  473         EX2MSG (SecurityTokenKeyfileNotFound,       LangString["TOKEN_KEYFILE_NOT_FOUND"]);
  474         EX2MSG (SecurityTokenLibraryNotInitialized, LangString["PKCS11_MODULE_INIT_FAILED"]);
  475         EX2MSG (StringConversionFailed,             _("Invalid characters encountered."));
  476         EX2MSG (StringFormatterException,           _("Error while parsing formatted string."));
  477         EX2MSG (TemporaryDirectoryFailure,          _("Failed to create a file or directory in a temporary directory.\n\nPlease make sure that the temporary directory exists, its security permissions allow you to access it, and there is sufficient disk space."));
  478         EX2MSG (UnportablePassword,                 LangString["UNSUPPORTED_CHARS_IN_PWD"]);
  479 
  480 #if defined (TC_LINUX)
  481         EX2MSG (UnsupportedSectorSize,              LangString["SECTOR_SIZE_UNSUPPORTED"]);
  482         EX2MSG (UnsupportedSectorSizeHiddenVolumeProtection, _("Error: The drive uses a sector size other than 512 bytes.\n\nDue to limitations of components available on your platform, outer volumes hosted on the drive cannot be mounted using hidden volume protection.\n\nPossible solutions:\n- Use a drive with 512-byte sectors.\n- Create a file-hosted volume (container) on the drive.\n- Backup the contents of the hidden volume and then update the outer volume."));
  483         EX2MSG (UnsupportedSectorSizeNoKernelCrypto, _("Error: The drive uses a sector size other than 512 bytes.\n\nDue to limitations of components available on your platform, partition/device-hosted volumes on the drive can only be mounted using kernel cryptographic services.\n\nPossible solutions:\n- Enable use of the kernel cryptographic services (Preferences > System Integration).\n- Use a drive with 512-byte sectors.\n- Create a file-hosted volume (container) on the drive."));
  484 #else
  485         EX2MSG (UnsupportedSectorSize,              _("Error: The drive uses a sector size other than 512 bytes.\n\nDue to limitations of components available on your platform, partition/device-hosted volumes cannot be created/used on the drive.\n\nPossible solutions:\n- Create a file-hosted volume (container) on the drive.\n- Use a drive with 512-byte sectors.\n- Use VeraCrypt on another platform."));
  486 #endif
  487 
  488         EX2MSG (VolumeAlreadyMounted,               LangString["VOL_ALREADY_MOUNTED"]);
  489         EX2MSG (VolumeEncryptionNotCompleted,       LangString["ERR_ENCRYPTION_NOT_COMPLETED"]);
  490         EX2MSG (VolumeHostInUse,                    _("The host file/device is already in use."));
  491         EX2MSG (VolumeSlotUnavailable,              _("Volume slot unavailable."));
  492         EX2MSG (UnsupportedAlgoInTrueCryptMode,     LangString["ALGO_NOT_SUPPORTED_FOR_TRUECRYPT_MODE"]);
  493         EX2MSG (UnsupportedTrueCryptFormat,         LangString["UNSUPPORTED_TRUECRYPT_FORMAT"]);
  494 
  495 #ifdef TC_MACOSX
  496         EX2MSG (HigherFuseVersionRequired,          _("VeraCrypt requires OSXFUSE 2.5 or above."));
  497 #endif
  498 
  499 #undef EX2MSG
  500         return L"";
  501     }
  502 
  503     void UserInterface::Init ()
  504     {
  505         SetAppName (Application::GetName());
  506         SetClassName (Application::GetName());
  507 
  508 #ifdef CRYPTOPP_CPUID_AVAILABLE
  509         DetectX86Features ();
  510 #endif
  511         LangString.Init();
  512         Core->Init();
  513 
  514         CmdLine.reset (new CommandLineInterface (argc, argv, InterfaceType));
  515         SetPreferences (CmdLine->Preferences);
  516 
  517         Core->SetApplicationExecutablePath (Application::GetExecutablePath());
  518 
  519         if (!Preferences.NonInteractive)
  520         {
  521             Core->SetAdminPasswordCallback (GetAdminPasswordRequestHandler());
  522         }
  523         else
  524         {
  525             struct AdminPasswordRequestHandler : public GetStringFunctor
  526             {
  527                 virtual void operator() (string &str)
  528                 {
  529                     throw ElevationFailed (SRC_POS, "sudo", 1, "");
  530                 }
  531             };
  532 
  533             Core->SetAdminPasswordCallback (shared_ptr <GetStringFunctor> (new AdminPasswordRequestHandler));
  534         }
  535 
  536         Core->WarningEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnWarning));
  537         Core->VolumeMountedEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnVolumeMounted));
  538 
  539         if (!CmdLine->Preferences.SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized())
  540         {
  541             try
  542             {
  543                 InitSecurityTokenLibrary();
  544             }
  545             catch (exception &e)
  546             {
  547                 if (Preferences.NonInteractive)
  548                     throw;
  549 
  550                 ShowError (e);
  551             }
  552         }
  553     }
  554 
  555     void UserInterface::ListMountedVolumes (const VolumeInfoList &volumes) const
  556     {
  557         if (volumes.size() < 1)
  558             throw_err (LangString["NO_VOLUMES_MOUNTED"]);
  559 
  560         wxString message;
  561 
  562         foreach_ref (const VolumeInfo &volume, volumes)
  563         {
  564             message << volume.SlotNumber << L": " << StringConverter::QuoteSpaces (volume.Path);
  565 
  566             if (!volume.VirtualDevice.IsEmpty())
  567                 message << L' ' << wstring (volume.VirtualDevice);
  568             else
  569                 message << L" - ";
  570 
  571             if (!volume.MountPoint.IsEmpty())
  572                 message << L' ' << StringConverter::QuoteSpaces (volume.MountPoint);
  573             else
  574                 message << L" - ";
  575 
  576             message << L'\n';
  577         }
  578 
  579         ShowString (message);
  580     }
  581 
  582     VolumeInfoList UserInterface::MountAllDeviceHostedVolumes (MountOptions &options) const
  583     {
  584         BusyScope busy (this);
  585 
  586         VolumeInfoList newMountedVolumes;
  587 
  588         if (!options.MountPoint)
  589             options.MountPoint.reset (new DirectoryPath);
  590 
  591         Core->CoalesceSlotNumberAndMountPoint (options);
  592 
  593         bool sharedAccessAllowed = options.SharedAccessAllowed;
  594         bool someVolumesShared = false;
  595 
  596         HostDeviceList devices;
  597         foreach (shared_ptr <HostDevice> device, Core->GetHostDevices (true))
  598         {
  599             if (device->Partitions.empty())
  600                 devices.push_back (device);
  601             else
  602             {
  603                 foreach (shared_ptr <HostDevice> partition, device->Partitions)
  604                     devices.push_back (partition);
  605             }
  606         }
  607 
  608         set <wstring> mountedVolumes;
  609         foreach_ref (const VolumeInfo &v, Core->GetMountedVolumes())
  610             mountedVolumes.insert (v.Path);
  611 
  612         bool protectedVolumeMounted = false;
  613         bool legacyVolumeMounted = false;
  614 
  615         foreach_ref (const HostDevice &device, devices)
  616         {
  617             if (mountedVolumes.find (wstring (device.Path)) != mountedVolumes.end())
  618                 continue;
  619 
  620             Yield();
  621             options.SlotNumber = Core->GetFirstFreeSlotNumber (options.SlotNumber);
  622             options.MountPoint.reset (new DirectoryPath);
  623             options.Path.reset (new VolumePath (device.Path));
  624 
  625             try
  626             {
  627                 try
  628                 {
  629                     options.SharedAccessAllowed = sharedAccessAllowed;
  630                     newMountedVolumes.push_back (Core->MountVolume (options));
  631                 }
  632                 catch (VolumeHostInUse&)
  633                 {
  634                     if (!sharedAccessAllowed)
  635                     {
  636                         try
  637                         {
  638                             options.SharedAccessAllowed = true;
  639                             newMountedVolumes.push_back (Core->MountVolume (options));
  640                             someVolumesShared = true;
  641                         }
  642                         catch (VolumeHostInUse&)
  643                         {
  644                             continue;
  645                         }
  646                     }
  647                     else
  648                         continue;
  649                 }
  650 
  651                 if (newMountedVolumes.back()->Protection == VolumeProtection::HiddenVolumeReadOnly)
  652                     protectedVolumeMounted = true;
  653 
  654                 if (newMountedVolumes.back()->EncryptionAlgorithmMinBlockSize == 8)
  655                     legacyVolumeMounted = true;
  656             }
  657             catch (DriverError&) { }
  658             catch (MissingVolumeData&) { }
  659             catch (PasswordException&) { }
  660             catch (SystemException&) { }
  661             catch (ExecutedProcessFailed&) { }
  662         }
  663 
  664         if (newMountedVolumes.empty())
  665         {
  666             ShowWarning (LangString [options.Keyfiles && !options.Keyfiles->empty() ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"]);
  667         }
  668         else
  669         {
  670             if (someVolumesShared)
  671                 ShowWarning ("DEVICE_IN_USE_INFO");
  672 
  673             if (legacyVolumeMounted)
  674                 ShowWarning ("WARN_64_BIT_BLOCK_CIPHER");
  675 
  676             if (protectedVolumeMounted)
  677                 ShowInfo (LangString[newMountedVolumes.size() > 1 ? "HIDVOL_PROT_WARN_AFTER_MOUNT_PLURAL" : "HIDVOL_PROT_WARN_AFTER_MOUNT"]);
  678         }
  679 
  680         if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount)
  681             SecurityToken::CloseAllSessions();
  682 
  683         return newMountedVolumes;
  684     }
  685 
  686     VolumeInfoList UserInterface::MountAllFavoriteVolumes (MountOptions &options)
  687     {
  688         BusyScope busy (this);
  689 
  690         VolumeInfoList newMountedVolumes;
  691         foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList())
  692         {
  693             shared_ptr <VolumeInfo> mountedVolume = Core->GetMountedVolume (favorite.Path);
  694             if (mountedVolume)
  695             {
  696                 if (mountedVolume->MountPoint != favorite.MountPoint)
  697                     ShowInfo (StringFormatter (LangString["VOLUME_ALREADY_MOUNTED"], wstring (favorite.Path)));
  698                 continue;
  699             }
  700 
  701             favorite.ToMountOptions (options);
  702 
  703             if (Preferences.NonInteractive)
  704             {
  705                 BusyScope busy (this);
  706                 newMountedVolumes.push_back (Core->MountVolume (options));
  707             }
  708             else
  709             {
  710                 try
  711                 {
  712                     BusyScope busy (this);
  713                     newMountedVolumes.push_back (Core->MountVolume (options));
  714                 }
  715                 catch (...)
  716                 {
  717                     UserPreferences prefs = GetPreferences();
  718                     if (prefs.CloseSecurityTokenSessionsAfterMount)
  719                         Preferences.CloseSecurityTokenSessionsAfterMount = false;
  720 
  721                     shared_ptr <VolumeInfo> volume = MountVolume (options);
  722 
  723                     if (prefs.CloseSecurityTokenSessionsAfterMount)
  724                         Preferences.CloseSecurityTokenSessionsAfterMount = true;
  725 
  726                     if (!volume)
  727                         break;
  728                     newMountedVolumes.push_back (volume);
  729                 }
  730             }
  731         }
  732 
  733         if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount)
  734             SecurityToken::CloseAllSessions();
  735 
  736         return newMountedVolumes;
  737     }
  738 
  739     shared_ptr <VolumeInfo> UserInterface::MountVolume (MountOptions &options) const
  740     {
  741         shared_ptr <VolumeInfo> volume;
  742 
  743         try
  744         {
  745             volume = MountVolumeThread (options);
  746 
  747         }
  748         catch (VolumeHostInUse&)
  749         {
  750             if (options.SharedAccessAllowed)
  751                 throw_err (LangString["FILE_IN_USE_FAILED"]);
  752 
  753             if (!AskYesNo (StringFormatter (LangString["VOLUME_HOST_IN_USE"], wstring (*options.Path)), false, true))
  754                 throw UserAbort (SRC_POS);
  755 
  756             try
  757             {
  758                 options.SharedAccessAllowed = true;
  759                 volume = Core->MountVolume (options);
  760             }
  761             catch (VolumeHostInUse&)
  762             {
  763                 throw_err (LangString["FILE_IN_USE_FAILED"]);
  764             }
  765         }
  766 
  767         if (volume->EncryptionAlgorithmMinBlockSize == 8)
  768             ShowWarning ("WARN_64_BIT_BLOCK_CIPHER");
  769 
  770         if (VolumeHasUnrecommendedExtension (*options.Path))
  771             ShowWarning ("EXE_FILE_EXTENSION_MOUNT_WARNING");
  772 
  773         if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
  774             ShowInfo ("HIDVOL_PROT_WARN_AFTER_MOUNT");
  775 
  776         if (GetPreferences().CloseSecurityTokenSessionsAfterMount)
  777             SecurityToken::CloseAllSessions();
  778 
  779         return volume;
  780     }
  781 
  782     void UserInterface::OnUnhandledException ()
  783     {
  784         try
  785         {
  786             throw;
  787         }
  788         catch (UserAbort&)
  789         {
  790         }
  791         catch (exception &e)
  792         {
  793             ShowError (e);
  794         }
  795         catch (...)
  796         {
  797             ShowError (_("Unknown exception occurred."));
  798         }
  799 
  800         Yield();
  801         Application::SetExitCode (1);
  802     }
  803 
  804     void UserInterface::OnVolumeMounted (EventArgs &args)
  805     {
  806         shared_ptr <VolumeInfo> mountedVolume = (dynamic_cast <VolumeEventArgs &> (args)).mVolume;
  807 
  808         if (Preferences.OpenExplorerWindowAfterMount && !mountedVolume->MountPoint.IsEmpty())
  809             OpenExplorerWindow (mountedVolume->MountPoint);
  810     }
  811 
  812     void UserInterface::OnWarning (EventArgs &args)
  813     {
  814         ExceptionEventArgs &e = dynamic_cast <ExceptionEventArgs &> (args);
  815         ShowWarning (e.mException);
  816     }
  817 
  818     void UserInterface::OpenExplorerWindow (const DirectoryPath &path)
  819     {
  820         if (path.IsEmpty())
  821             return;
  822 
  823         list <string> args;
  824 
  825 #ifdef TC_WINDOWS
  826 
  827         wstring p (Directory::AppendSeparator (path));
  828         SHFILEINFO fInfo;
  829         SHGetFileInfo (p.c_str(), 0, &fInfo, sizeof (fInfo), 0); // Force explorer to discover the drive
  830         ShellExecute (GetTopWindow() ? static_cast <HWND> (GetTopWindow()->GetHandle()) : nullptr, L"open", p.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
  831 
  832 #elif defined (TC_MACOSX)
  833 
  834         args.push_back (string (path));
  835         try
  836         {
  837             Process::Execute ("open", args);
  838         }
  839         catch (exception &e) { ShowError (e); }
  840 
  841 #else
  842         // MIME handler for directory seems to be unavailable through wxWidgets
  843         wxString desktop = GetTraits()->GetDesktopEnvironment();
  844         bool xdgOpenPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/xdg-open")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/xdg-open"));
  845         bool nautilusPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/nautilus")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/nautilus"));
  846 
  847         if (desktop == L"GNOME" || (desktop.empty() && !xdgOpenPresent && nautilusPresent))
  848         {
  849             // args.push_back ("--no-default-window"); // This option causes nautilus not to launch under FreeBSD 11
  850             args.push_back ("--no-desktop");
  851             args.push_back (string (path));
  852             try
  853             {
  854                 Process::Execute ("nautilus", args, 2000);
  855             }
  856             catch (TimeOut&) { }
  857             catch (exception &e) { ShowError (e); }
  858         }
  859         else if (desktop == L"KDE")
  860         {
  861             try
  862             {
  863                 args.push_back (string (path));
  864                 Process::Execute ("dolphin", args, 2000);
  865             }
  866             catch (TimeOut&) { }
  867             catch (exception&)
  868             {
  869                 args.clear();
  870                 args.push_back ("openURL");
  871                 args.push_back (string (path));
  872                 try
  873                 {
  874                     Process::Execute ("kfmclient", args, 2000);
  875                 }
  876                 catch (TimeOut&) { }
  877                 catch (exception &e) { ShowError (e); }
  878             }
  879         }
  880         else if (xdgOpenPresent)
  881         {
  882             // Fallback on the standard xdg-open command
  883             // which is not always available by default
  884             args.push_back (string (path));
  885             try
  886             {
  887                 Process::Execute ("xdg-open", args, 2000);
  888             }
  889             catch (TimeOut&) { }
  890             catch (exception &e) { ShowError (e); }
  891         }
  892         else
  893         {
  894             ShowWarning (wxT("Unable to find a file manager to open the mounted volume"));
  895         }
  896 #endif
  897     }
  898 
  899     bool UserInterface::ProcessCommandLine ()
  900     {
  901         CommandLineInterface &cmdLine = *CmdLine;
  902 
  903         if (cmdLine.ArgCommand == CommandId::None)
  904             return false;
  905 
  906         if (Preferences.UseStandardInput)
  907         {
  908             wstring pwdInput;
  909             getline(wcin, pwdInput);
  910 
  911             cmdLine.ArgPassword = ToUTF8Password ( pwdInput.c_str (), pwdInput.size ());
  912         }
  913 
  914         switch (cmdLine.ArgCommand)
  915         {
  916         case CommandId::AutoMountDevices:
  917         case CommandId::AutoMountFavorites:
  918         case CommandId::AutoMountDevicesFavorites:
  919         case CommandId::MountVolume:
  920             {
  921                 cmdLine.ArgMountOptions.Path = cmdLine.ArgVolumePath;
  922                 cmdLine.ArgMountOptions.MountPoint = cmdLine.ArgMountPoint;
  923                 cmdLine.ArgMountOptions.Password = cmdLine.ArgPassword;
  924                 cmdLine.ArgMountOptions.Pim = cmdLine.ArgPim;
  925                 cmdLine.ArgMountOptions.Keyfiles = cmdLine.ArgKeyfiles;
  926                 cmdLine.ArgMountOptions.SharedAccessAllowed = cmdLine.ArgForce;
  927                 cmdLine.ArgMountOptions.TrueCryptMode = cmdLine.ArgTrueCryptMode;
  928                 if (cmdLine.ArgHash)
  929                 {
  930                     cmdLine.ArgMountOptions.Kdf = Pkcs5Kdf::GetAlgorithm (*cmdLine.ArgHash, cmdLine.ArgTrueCryptMode);
  931                 }
  932 
  933 
  934                 VolumeInfoList mountedVolumes;
  935                 switch (cmdLine.ArgCommand)
  936                 {
  937                 case CommandId::AutoMountDevices:
  938                 case CommandId::AutoMountFavorites:
  939                 case CommandId::AutoMountDevicesFavorites:
  940                     {
  941                         if (cmdLine.ArgCommand == CommandId::AutoMountDevices || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites)
  942                         {
  943                             if (Preferences.NonInteractive)
  944                                 mountedVolumes = UserInterface::MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions);
  945                             else
  946                                 mountedVolumes = MountAllDeviceHostedVolumes (cmdLine.ArgMountOptions);
  947                         }
  948 
  949                         if (cmdLine.ArgCommand == CommandId::AutoMountFavorites || cmdLine.ArgCommand == CommandId::AutoMountDevicesFavorites)
  950                         {
  951                             foreach (shared_ptr <VolumeInfo> v, MountAllFavoriteVolumes(cmdLine.ArgMountOptions))
  952                                 mountedVolumes.push_back (v);
  953                         }
  954                     }
  955                     break;
  956 
  957 
  958                     break;
  959 
  960                 case CommandId::MountVolume:
  961                     if (Preferences.OpenExplorerWindowAfterMount)
  962                     {
  963                         // Open explorer window for an already mounted volume
  964                         shared_ptr <VolumeInfo> mountedVolume = Core->GetMountedVolume (*cmdLine.ArgMountOptions.Path);
  965                         if (mountedVolume && !mountedVolume->MountPoint.IsEmpty())
  966                         {
  967                             OpenExplorerWindow (mountedVolume->MountPoint);
  968                             break;
  969                         }
  970                     }
  971 
  972                     if (Preferences.NonInteractive)
  973                     {
  974                         // Volume path
  975                         if (!cmdLine.ArgMountOptions.Path)
  976                             throw MissingArgument (SRC_POS);
  977 
  978                         mountedVolumes.push_back (Core->MountVolume (cmdLine.ArgMountOptions));
  979                     }
  980                     else
  981                     {
  982                         shared_ptr <VolumeInfo> volume = MountVolume (cmdLine.ArgMountOptions);
  983                         if (!volume)
  984                         {
  985                             Application::SetExitCode (1);
  986                             throw UserAbort (SRC_POS);
  987                         }
  988                         mountedVolumes.push_back (volume);
  989                     }
  990                     break;
  991 
  992                 default:
  993                     throw ParameterIncorrect (SRC_POS);
  994                 }
  995 
  996                 if (Preferences.Verbose && !mountedVolumes.empty())
  997                 {
  998                     wxString message;
  999                     foreach_ref (const VolumeInfo &volume, mountedVolumes)
 1000                     {
 1001                         if (!message.IsEmpty())
 1002                             message += L'\n';
 1003                         message += StringFormatter (_("Volume \"{0}\" has been mounted."), wstring (volume.Path));
 1004                     }
 1005                     ShowInfo (message);
 1006                 }
 1007             }
 1008             return true;
 1009 
 1010         case CommandId::BackupHeaders:
 1011             BackupVolumeHeaders (cmdLine.ArgVolumePath);
 1012             return true;
 1013 
 1014         case CommandId::ChangePassword:
 1015             ChangePassword (cmdLine.ArgVolumePath, cmdLine.ArgPassword, cmdLine.ArgPim, cmdLine.ArgHash, cmdLine.ArgTrueCryptMode, cmdLine.ArgKeyfiles, cmdLine.ArgNewPassword, cmdLine.ArgNewPim, cmdLine.ArgNewKeyfiles, cmdLine.ArgNewHash);
 1016             return true;
 1017 
 1018         case CommandId::CreateKeyfile:
 1019             CreateKeyfile (cmdLine.ArgFilePath);
 1020             return true;
 1021 
 1022         case CommandId::CreateVolume:
 1023             {
 1024                 make_shared_auto (VolumeCreationOptions, options);
 1025 
 1026                 if (cmdLine.ArgHash)
 1027                 {
 1028                     options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*cmdLine.ArgHash, false);
 1029                     RandomNumberGenerator::SetHash (cmdLine.ArgHash);
 1030                 }
 1031 
 1032                 options->EA = cmdLine.ArgEncryptionAlgorithm;
 1033                 options->Filesystem = cmdLine.ArgFilesystem;
 1034                 options->Keyfiles = cmdLine.ArgKeyfiles;
 1035                 options->Password = cmdLine.ArgPassword;
 1036                 options->Pim = cmdLine.ArgPim;
 1037                 options->Quick = cmdLine.ArgQuick;
 1038                 options->Size = cmdLine.ArgSize;
 1039                 options->Type = cmdLine.ArgVolumeType;
 1040 
 1041                 if (cmdLine.ArgVolumePath)
 1042                     options->Path = VolumePath (*cmdLine.ArgVolumePath);
 1043 
 1044                 CreateVolume (options);
 1045                 return true;
 1046             }
 1047 
 1048         case CommandId::DeleteSecurityTokenKeyfiles:
 1049             DeleteSecurityTokenKeyfiles();
 1050             return true;
 1051 
 1052         case CommandId::DismountVolumes:
 1053             DismountVolumes (cmdLine.ArgVolumes, cmdLine.ArgForce, !Preferences.NonInteractive);
 1054             return true;
 1055 
 1056         case CommandId::DisplayVersion:
 1057             ShowString (Application::GetName() + L" " + StringConverter::ToWide (Version::String()) + L"\n");
 1058             return true;
 1059 
 1060         case CommandId::DisplayVolumeProperties:
 1061             DisplayVolumeProperties (cmdLine.ArgVolumes);
 1062             return true;
 1063 
 1064         case CommandId::Help:
 1065             {
 1066                 wstring helpText = StringConverter::ToWide (
 1067                     "Synopsis:\n"
 1068                     "\n"
 1069                     "veracrypt [OPTIONS] COMMAND\n"
 1070                     "veracrypt [OPTIONS] VOLUME_PATH [MOUNT_DIRECTORY]\n"
 1071                     "\n"
 1072                     "\n"
 1073                     "Commands:\n"
 1074                     "\n"
 1075                     "--auto-mount=devices|favorites\n"
 1076                     " Auto mount device-hosted or favorite volumes.\n"
 1077                     "\n"
 1078                     "--backup-headers[=VOLUME_PATH]\n"
 1079                     " Backup volume headers to a file. All required options are requested from the\n"
 1080                     " user.\n"
 1081                     "\n"
 1082                     "-c, --create[=VOLUME_PATH]\n"
 1083                     " Create a new volume. Most options are requested from the user if not specified\n"
 1084                     " on command line. See also options --encryption, -k, --filesystem, --hash, -p,\n"
 1085                     " --random-source, --quick, --size, --volume-type. Note that passing some of the\n"
 1086                     " options may affect security of the volume (see option -p for more information).\n"
 1087                     "\n"
 1088                     " Inexperienced users should use the graphical user interface to create a hidden\n"
 1089                     " volume. When using the text user interface, the following procedure must be\n"
 1090                     " followed to create a hidden volume:\n"
 1091                     "  1) Create an outer volume with no filesystem.\n"
 1092                     "  2) Create a hidden volume within the outer volume.\n"
 1093                     "  3) Mount the outer volume using hidden volume protection.\n"
 1094                     "  4) Create a filesystem on the virtual device of the outer volume.\n"
 1095                     "  5) Mount the new filesystem and fill it with data.\n"
 1096                     "  6) Dismount the outer volume.\n"
 1097                     "  If at any step the hidden volume protection is triggered, start again from 1).\n"
 1098                     "\n"
 1099                     "--create-keyfile[=FILE_PATH]\n"
 1100                     " Create a new keyfile containing pseudo-random data.\n"
 1101                     "\n"
 1102                     "-C, --change[=VOLUME_PATH]\n"
 1103                     " Change a password and/or keyfile(s) of a volume. Most options are requested\n"
 1104                     " from the user if not specified on command line. PKCS-5 PRF HMAC hash\n"
 1105                     " algorithm can be changed with option --hash. See also options -k,\n"
 1106                     " --new-keyfiles, --new-password, -p, --random-source.\n"
 1107                     "\n"
 1108                     "-d, --dismount[=MOUNTED_VOLUME]\n"
 1109                     " Dismount a mounted volume. If MOUNTED_VOLUME is not specified, all\n"
 1110                     " volumes are dismounted. See below for description of MOUNTED_VOLUME.\n"
 1111                     "\n"
 1112                     "--delete-token-keyfiles\n"
 1113                     " Delete keyfiles from security tokens. See also command --list-token-keyfiles.\n"
 1114                     "\n"
 1115                     "--export-token-keyfile\n"
 1116                     " Export a keyfile from a security token. See also command --list-token-keyfiles.\n"
 1117                     "\n"
 1118                     "--import-token-keyfiles\n"
 1119                     " Import keyfiles to a security token. See also option --token-lib.\n"
 1120                     "\n"
 1121                     "-l, --list[=MOUNTED_VOLUME]\n"
 1122                     " Display a list of mounted volumes. If MOUNTED_VOLUME is not specified, all\n"
 1123                     " volumes are listed. By default, the list contains only volume path, virtual\n"
 1124                     " device, and mount point. A more detailed list can be enabled by verbose\n"
 1125                     " output option (-v). See below for description of MOUNTED_VOLUME.\n"
 1126                     "\n"
 1127                     "--list-token-keyfiles\n"
 1128                     " Display a list of all available security token keyfiles. See also command\n"
 1129                     " --import-token-keyfiles.\n"
 1130                     "\n"
 1131                     "--mount[=VOLUME_PATH]\n"
 1132                     " Mount a volume. Volume path and other options are requested from the user\n"
 1133                     " if not specified on command line.\n"
 1134                     "\n"
 1135                     "--restore-headers[=VOLUME_PATH]\n"
 1136                     " Restore volume headers from the embedded or an external backup. All required\n"
 1137                     " options are requested from the user.\n"
 1138                     "\n"
 1139                     "--save-preferences\n"
 1140                     " Save user preferences.\n"
 1141                     "\n"
 1142                     "--test\n"
 1143                     " Test internal algorithms used in the process of encryption and decryption.\n"
 1144                     "\n"
 1145                     "--version\n"
 1146                     " Display program version.\n"
 1147                     "\n"
 1148                     "--volume-properties[=MOUNTED_VOLUME]\n"
 1149                     " Display properties of a mounted volume. See below for description of\n"
 1150                     " MOUNTED_VOLUME.\n"
 1151                     "\n"
 1152                     "MOUNTED_VOLUME:\n"
 1153                     " Specifies a mounted volume. One of the following forms can be used:\n"
 1154                     " 1) Path to the encrypted VeraCrypt volume.\n"
 1155                     " 2) Mount directory of the volume's filesystem (if mounted).\n"
 1156                     " 3) Slot number of the mounted volume (requires --slot).\n"
 1157                     "\n"
 1158                     "\n"
 1159                     "Options:\n"
 1160                     "\n"
 1161                     "--display-password\n"
 1162                     " Display password characters while typing.\n"
 1163                     "\n"
 1164                     "--encryption=ENCRYPTION_ALGORITHM\n"
 1165                     " Use specified encryption algorithm when creating a new volume.\n"
 1166                     "\n"
 1167                     "--filesystem=TYPE\n"
 1168                     " Filesystem type to mount. The TYPE argument is passed to mount(8) command\n"
 1169                     " with option -t. Default type is 'auto'. When creating a new volume, this\n"
 1170                     " option specifies the filesystem to be created on the new volume.\n"
 1171                     " Filesystem type 'none' disables mounting or creating a filesystem.\n"
 1172                     "\n"
 1173                     "--force\n"
 1174                     " Force mounting of a volume in use, dismounting of a volume in use, or\n"
 1175                     " overwriting a file. Note that this option has no effect on some platforms.\n"
 1176                     "\n"
 1177                     "--fs-options=OPTIONS\n"
 1178                     " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n"
 1179                     " command with option -o when a filesystem on a VeraCrypt volume is mounted.\n"
 1180                     " This option is not available on some platforms.\n"
 1181                     "\n"
 1182                     "--hash=HASH\n"
 1183                     " Use specified hash algorithm when creating a new volume or changing password\n"
 1184                     " and/or keyfiles. This option also specifies the mixing PRF of the random\n"
 1185                     " number generator.\n"
 1186                     "\n"
 1187                     "-k, --keyfiles=KEYFILE1[,KEYFILE2,KEYFILE3,...]\n"
 1188                     " Use specified keyfiles when mounting a volume or when changing password\n"
 1189                     " and/or keyfiles. When a directory is specified, all files inside it will be\n"
 1190                     " used (non-recursively). Multiple keyfiles must be separated by comma.\n"
 1191                     " Use double comma (,,) to specify a comma contained in keyfile's name.\n"
 1192                     " Keyfile stored on a security token must be specified as\n"
 1193                     " token://slot/SLOT_NUMBER/file/FILENAME. An empty keyfile (-k \"\") disables\n"
 1194                     " interactive requests for keyfiles. See also options --import-token-keyfiles,\n"
 1195                     " --list-token-keyfiles, --new-keyfiles, --protection-keyfiles.\n"
 1196                     "\n"
 1197                     "--load-preferences\n"
 1198                     " Load user preferences.\n"
 1199                     "\n"
 1200                     "-m, --mount-options=OPTION1[,OPTION2,OPTION3,...]\n"
 1201                     " Specifies comma-separated mount options for a VeraCrypt volume:\n"
 1202                     "  headerbak: Use backup headers when mounting a volume.\n"
 1203                     "  nokernelcrypto: Do not use kernel cryptographic services.\n"
 1204                     "  readonly|ro: Mount volume as read-only.\n"
 1205                     "  system: Mount partition using system encryption.\n"
 1206                     "  timestamp|ts: Do not restore host-file modification timestamp when a volume\n"
 1207                     "   is dismounted (note that the operating system under certain circumstances\n"
 1208                     "   does not alter host-file timestamps, which may be mistakenly interpreted\n"
 1209                     "   to mean that this option does not work).\n"
 1210                     " See also option --fs-options.\n"
 1211                     "\n"
 1212                     "--new-keyfiles=KEYFILE1[,KEYFILE2,KEYFILE3,...]\n"
 1213                     " Add specified keyfiles to a volume. This option can only be used with command\n"
 1214                     " -C.\n"
 1215                     "\n"
 1216                     "--new-password=PASSWORD\n"
 1217                     " Specifies a new password. This option can only be used with command -C.\n"
 1218                     "\n"
 1219                     "--new-pim=PIM\n"
 1220                     " Specifies a new PIM. This option can only be used with command -C.\n"
 1221                     "\n"
 1222                     "-p, --password=PASSWORD\n"
 1223                     " Use specified password to mount/open a volume. An empty password can also be\n"
 1224                     " specified (-p \"\"). Note that passing a password on the command line is\n"
 1225                     " potentially insecure as the password may be visible in the process list\n"
 1226                     " (see ps(1)) and/or stored in a command history file or system logs.\n"
 1227                     "\n"
 1228                     "--pim=PIM\n"
 1229                     " Use specified PIM to mount/open a volume. Note that passing a PIM on the \n"
 1230                     " command line is potentially insecure as the PIM may be visible in the process \n"
 1231                     " list (see ps(1)) and/or stored in a command history file or system logs.\n"
 1232                     "\n"
 1233                     "--protect-hidden=yes|no\n"
 1234                     " Write-protect a hidden volume when mounting an outer volume. Before mounting\n"
 1235                     " the outer volume, the user will be prompted for a password to open the hidden\n"
 1236                     " volume. The size and position of the hidden volume is then determined and the\n"
 1237                     " outer volume is mounted with all sectors belonging to the hidden volume\n"
 1238                     " protected against write operations. When a write to the protected area is\n"
 1239                     " prevented, the whole volume is switched to read-only mode. Verbose list\n"
 1240                     " (-v -l) can be used to query the state of the hidden volume protection.\n"
 1241                     " Warning message is displayed when a volume switched to read-only is being\n"
 1242                     " dismounted.\n"
 1243                     "\n"
 1244                     "--protection-keyfiles=KEYFILE1[,KEYFILE2,KEYFILE3,...]\n"
 1245                     " Use specified keyfiles to open a hidden volume to be protected. This option\n"
 1246                     " may be used only when mounting an outer volume with hidden volume protected.\n"
 1247                     " See also options -k and --protect-hidden.\n"
 1248                     "\n"
 1249                     "--protection-password=PASSWORD\n"
 1250                     " Use specified password to open a hidden volume to be protected. This option\n"
 1251                     " may be used only when mounting an outer volume with hidden volume protected.\n"
 1252                     " See also options -p and --protect-hidden.\n"
 1253                     "\n"
 1254                     "--quick\n"
 1255                     " Do not encrypt free space when creating a device-hosted volume. This option\n"
 1256                     " must not be used when creating an outer volume.\n"
 1257                     "\n"
 1258                     "--random-source=FILE\n"
 1259                     " Use FILE as a source of random data (e.g., when creating a volume) instead\n"
 1260                     " of requiring the user to type random characters.\n"
 1261                     "\n"
 1262                     "--slot=SLOT\n"
 1263                     " Use specified slot number when mounting, dismounting, or listing a volume.\n"
 1264                     "\n"
 1265                     "--size=SIZE[K|M|G|T]\n"
 1266                     " Use specified size when creating a new volume. If no suffix is indicated,\n"
 1267                     " then SIZE is interpreted in bytes. Suffixes K, M, G or T can be used to\n"
 1268                     " indicate a value in KB, MB, GB or TB respectively.\n"
 1269                     "\n"
 1270                     "-t, --text\n"
 1271                     " Use text user interface. Graphical user interface is used by default if\n"
 1272                     " available. This option must be specified as the first argument.\n"
 1273                     "\n"
 1274                     "-tc, --truecrypt\n"
 1275                     " Enable TrueCrypt compatibility mode to enable mounting volumes created\n"
 1276                     " by TrueCrypt 6.x or 7.x. This option must be specified as the first\n"
 1277                     " argument, or immediately after --text.\n"
 1278                     "\n"
 1279                     "--token-lib=LIB_PATH\n"
 1280                     " Use specified PKCS #11 security token library.\n"
 1281                     "\n"
 1282                     "--volume-type=TYPE\n"
 1283                     " Use specified volume type when creating a new volume. TYPE can be 'normal'\n"
 1284                     " or 'hidden'. See option -c for more information on creating hidden volumes.\n"
 1285                     "\n"
 1286                     "-v, --verbose\n"
 1287                     " Enable verbose output.\n"
 1288                     "\n"
 1289                     "\n"
 1290                     "IMPORTANT:\n"
 1291                     "\n"
 1292                     "If you want to use VeraCrypt, you must follow the security requirements and\n"
 1293                     "security precautions listed in chapter 'Security Requirements and Precautions'\n"
 1294                     "in the VeraCrypt documentation (file 'VeraCrypt User Guide.pdf').\n"
 1295                     "\n"
 1296                     "\nExamples:\n\n"
 1297                     "Create a new volume:\n"
 1298                     "veracrypt -t -c\n"
 1299                     "\n"
 1300                     "Mount a volume:\n"
 1301                     "veracrypt volume.hc /media/veracrypt1\n"
 1302                     "\n"
 1303                     "Mount a volume as read-only, using keyfiles:\n"
 1304                     "veracrypt -m ro -k keyfile1,keyfile2 volume.hc\n"
 1305                     "\n"
 1306                     "Mount a volume without mounting its filesystem:\n"
 1307                     "veracrypt --filesystem=none volume.hc\n"
 1308                     "\n"
 1309                     "Mount a volume prompting only for its password:\n"
 1310                     "veracrypt -t -k \"\" --protect-hidden=no volume.hc /media/veracrypt1\n"
 1311                     "\n"
 1312                     "Dismount a volume:\n"
 1313                     "veracrypt -d volume.hc\n"
 1314                     "\n"
 1315                     "Dismount all mounted volumes:\n"
 1316                     "veracrypt -d\n"
 1317                 );
 1318 
 1319 #ifndef TC_NO_GUI
 1320                 if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic)
 1321                 {
 1322                     wxDialog dialog (nullptr, wxID_ANY, _("VeraCrypt Command Line Help"), wxDefaultPosition);
 1323 
 1324                     wxTextCtrl *textCtrl = new wxTextCtrl (&dialog, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
 1325                     textCtrl->SetFont (wxFont (wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, L"Courier"));
 1326                     textCtrl->SetValue (helpText);
 1327 
 1328                     int fontWidth, fontHeight;
 1329                     textCtrl->GetTextExtent (L"A", &fontWidth, &fontHeight);
 1330                     dialog.SetSize (wxSize (fontWidth * 85, fontHeight * 29));
 1331 
 1332                     wxBoxSizer *sizer = new wxBoxSizer (wxVERTICAL);
 1333                     sizer->Add (textCtrl, 1, wxALL | wxEXPAND, 5);
 1334                     sizer->Add (new wxButton (&dialog, wxID_OK, _("OK")), 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5);
 1335 
 1336                     dialog.SetSizer (sizer);
 1337                     dialog.Layout();
 1338                     dialog.ShowModal();
 1339                 }
 1340                 else
 1341 #endif // !TC_NO_GUI
 1342                 {
 1343                     ShowString (L"\n\n");
 1344                     ShowString (helpText);
 1345                 }
 1346             }
 1347             return true;
 1348 
 1349         case CommandId::ExportSecurityTokenKeyfile:
 1350             ExportSecurityTokenKeyfile();
 1351             return true;
 1352 
 1353         case CommandId::ImportSecurityTokenKeyfiles:
 1354             ImportSecurityTokenKeyfiles();
 1355             return true;
 1356 
 1357         case CommandId::ListSecurityTokenKeyfiles:
 1358             ListSecurityTokenKeyfiles();
 1359             return true;
 1360 
 1361         case CommandId::ListVolumes:
 1362             if (Preferences.Verbose)
 1363                 DisplayVolumeProperties (cmdLine.ArgVolumes);
 1364             else
 1365                 ListMountedVolumes (cmdLine.ArgVolumes);
 1366             return true;
 1367 
 1368         case CommandId::RestoreHeaders:
 1369             RestoreVolumeHeaders (cmdLine.ArgVolumePath);
 1370             return true;
 1371 
 1372         case CommandId::SavePreferences:
 1373             Preferences.Save();
 1374             return true;
 1375 
 1376         case CommandId::Test:
 1377             Test();
 1378             return true;
 1379 
 1380         default:
 1381             throw ParameterIncorrect (SRC_POS);
 1382         }
 1383 
 1384         return false;
 1385     }
 1386 
 1387     void UserInterface::SetPreferences (const UserPreferences &preferences)
 1388     {
 1389         Preferences = preferences;
 1390 
 1391         Cipher::EnableHwSupport (!preferences.DefaultMountOptions.NoHardwareCrypto);
 1392 
 1393         PreferencesUpdatedEvent.Raise();
 1394     }
 1395 
 1396     void UserInterface::ShowError (const exception &ex) const
 1397     {
 1398         if (!dynamic_cast <const UserAbort*> (&ex))
 1399             DoShowError (ExceptionToMessage (ex));
 1400     }
 1401 
 1402     wxString UserInterface::SizeToString (uint64 size) const
 1403     {
 1404         wstringstream s;
 1405         if (size > 1024ULL*1024*1024*1024*1024*99)
 1406             s << size/1024/1024/1024/1024/1024 << L" " << LangString["PB"].c_str();
 1407         else if (size > 1024ULL*1024*1024*1024*1024)
 1408             return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024/1024), LangString["PB"].c_str());
 1409         else if (size > 1024ULL*1024*1024*1024*99)
 1410             s << size/1024/1024/1024/1024 << L" " << LangString["TB"].c_str();
 1411         else if (size > 1024ULL*1024*1024*1024)
 1412             return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024/1024), LangString["TB"].c_str());
 1413         else if (size > 1024ULL*1024*1024*99)
 1414             s << size/1024/1024/1024 << L" " << LangString["GB"].c_str();
 1415         else if (size > 1024ULL*1024*1024)
 1416             return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024/1024), LangString["GB"].c_str());
 1417         else if (size > 1024ULL*1024*99)
 1418             s << size/1024/1024 << L" " << LangString["MB"].c_str();
 1419         else if (size > 1024ULL*1024)
 1420             return wxString::Format (L"%.1f %s", (double)(size/1024.0/1024), LangString["MB"].c_str());
 1421         else if (size > 1024ULL)
 1422             s << size/1024 << L" " << LangString["KB"].c_str();
 1423         else
 1424             s << size << L" " << LangString["BYTE"].c_str();
 1425 
 1426         return s.str();
 1427     }
 1428 
 1429     wxString UserInterface::SpeedToString (uint64 speed) const
 1430     {
 1431         wstringstream s;
 1432 
 1433         if (speed > 1024ULL*1024*1024*1024*1024*99)
 1434             s << speed/1024/1024/1024/1024/1024 << L" " << LangString["PB_PER_SEC"].c_str();
 1435         else if (speed > 1024ULL*1024*1024*1024*1024)
 1436             return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024/1024), LangString["PB_PER_SEC"].c_str());
 1437         else if (speed > 1024ULL*1024*1024*1024*99)
 1438             s << speed/1024/1024/1024/1024 << L" " << LangString["TB_PER_SEC"].c_str();
 1439         else if (speed > 1024ULL*1024*1024*1024)
 1440             return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024/1024), LangString["TB_PER_SEC"].c_str());
 1441         else if (speed > 1024ULL*1024*1024*99)
 1442             s << speed/1024/1024/1024 << L" " << LangString["GB_PER_SEC"].c_str();
 1443         else if (speed > 1024ULL*1024*999)
 1444             return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024/1024), LangString["GB_PER_SEC"].c_str());
 1445         else if (speed > 1024ULL*1024*9)
 1446             s << speed/1024/1024 << L" " << LangString["MB_PER_SEC"].c_str();
 1447         else if (speed > 1024ULL*999)
 1448             return wxString::Format (L"%.1f %s", (double)(speed/1024.0/1024), LangString["MB_PER_SEC"].c_str());
 1449         else if (speed > 1024ULL)
 1450             s << speed/1024 << L" " << LangString["KB_PER_SEC"].c_str();
 1451         else
 1452             s << speed << L" " << LangString["B_PER_SEC"].c_str();
 1453 
 1454         return s.str();
 1455     }
 1456 
 1457     void UserInterface::Test () const
 1458     {
 1459         if (!PlatformTest::TestAll())
 1460             throw TestFailed (SRC_POS);
 1461 
 1462         EncryptionTest::TestAll();
 1463 
 1464         // StringFormatter
 1465         if (StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10) != L"10 9 8 7 6 5 4 3 2 1 {0}")
 1466             throw TestFailed (SRC_POS);
 1467         try
 1468         {
 1469             StringFormatter (L"{0} {1}", 1);
 1470             throw TestFailed (SRC_POS);
 1471         }
 1472         catch (StringFormatterException&) { }
 1473 
 1474         try
 1475         {
 1476             StringFormatter (L"{0} {1} {1}", 1, 2, 3);
 1477             throw TestFailed (SRC_POS);
 1478         }
 1479         catch (StringFormatterException&) { }
 1480 
 1481         try
 1482         {
 1483             StringFormatter (L"{0} 1}", 1, 2);
 1484             throw TestFailed (SRC_POS);
 1485         }
 1486         catch (StringFormatterException&) { }
 1487 
 1488         try
 1489         {
 1490             StringFormatter (L"{0} {1", 1, 2);
 1491             throw TestFailed (SRC_POS);
 1492         }
 1493         catch (StringFormatterException&) { }
 1494 
 1495         ShowInfo ("TESTS_PASSED");
 1496     }
 1497 
 1498     wxString UserInterface::TimeSpanToString (uint64 seconds) const
 1499     {
 1500         wstringstream s;
 1501 
 1502         if (seconds >= 60 * 60 * 24 * 2)
 1503             s << seconds / (60 * 24 * 60) << L" " << LangString["DAYS"].c_str();
 1504         else if (seconds >= 120 * 60)
 1505             s << seconds / (60 * 60) << L" " << LangString["HOURS"].c_str();
 1506         else if (seconds >= 120)
 1507             s << seconds / 60 << L" " << LangString["MINUTES"].c_str();
 1508         else
 1509             s << seconds << L" " << LangString["SECONDS"].c_str();
 1510 
 1511         return s.str();
 1512     }
 1513 
 1514     bool UserInterface::VolumeHasUnrecommendedExtension (const VolumePath &path) const
 1515     {
 1516         wxString ext = wxFileName (wxString (wstring (path)).Lower()).GetExt();
 1517         return ext.IsSameAs (L"exe") || ext.IsSameAs (L"sys") || ext.IsSameAs (L"dll");
 1518     }
 1519 
 1520     wxString UserInterface::VolumeTimeToString (VolumeTime volumeTime) const
 1521     {
 1522         wxString dateStr = VolumeTimeToDateTime (volumeTime).Format();
 1523 
 1524 #ifdef TC_WINDOWS
 1525 
 1526         FILETIME ft;
 1527         *(unsigned __int64 *)(&ft) = volumeTime;
 1528         SYSTEMTIME st;
 1529         FileTimeToSystemTime (&ft, &st);
 1530 
 1531         wchar_t wstr[1024];
 1532         if (GetDateFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr)) != 0)
 1533         {
 1534             dateStr = wstr;
 1535             GetTimeFormat (LOCALE_USER_DEFAULT, 0, &st, 0, wstr, array_capacity (wstr));
 1536             dateStr += wxString (L" ") + wstr;
 1537         }
 1538 #endif
 1539         return dateStr;
 1540     }
 1541 
 1542     wxString UserInterface::VolumeTypeToString (VolumeType::Enum type, bool truecryptMode, VolumeProtection::Enum protection) const
 1543     {
 1544         wxString sResult;
 1545         switch (type)
 1546         {
 1547         case VolumeType::Normal:
 1548             sResult = LangString[protection == VolumeProtection::HiddenVolumeReadOnly ? "OUTER" : "NORMAL"];
 1549             break;
 1550 
 1551         case VolumeType::Hidden:
 1552             sResult = LangString["HIDDEN"];
 1553             break;
 1554 
 1555         default:
 1556             sResult = L"?";
 1557             break;
 1558         }
 1559 
 1560         if (truecryptMode)
 1561             sResult = wxT("TrueCrypt-") + sResult;
 1562         return sResult;
 1563     }
 1564 
 1565     #define VC_CONVERT_EXCEPTION(NAME) if (dynamic_cast<NAME*> (ex)) throw (NAME&) *ex;
 1566 
 1567     void UserInterface::ThrowException (Exception* ex)
 1568     {
 1569         VC_CONVERT_EXCEPTION (PasswordIncorrect);
 1570         VC_CONVERT_EXCEPTION (PasswordKeyfilesIncorrect);
 1571         VC_CONVERT_EXCEPTION (PasswordOrKeyboardLayoutIncorrect);
 1572         VC_CONVERT_EXCEPTION (PasswordOrMountOptionsIncorrect);
 1573         VC_CONVERT_EXCEPTION (ProtectionPasswordIncorrect);
 1574         VC_CONVERT_EXCEPTION (ProtectionPasswordKeyfilesIncorrect);
 1575         VC_CONVERT_EXCEPTION (PasswordEmpty);
 1576         VC_CONVERT_EXCEPTION (PasswordTooLong);
 1577         VC_CONVERT_EXCEPTION (PasswordUTF8TooLong);
 1578         VC_CONVERT_EXCEPTION (PasswordUTF8Invalid);
 1579         VC_CONVERT_EXCEPTION (UnportablePassword);
 1580         VC_CONVERT_EXCEPTION (ElevationFailed);
 1581         VC_CONVERT_EXCEPTION (RootDeviceUnavailable);
 1582         VC_CONVERT_EXCEPTION (DriveLetterUnavailable);
 1583         VC_CONVERT_EXCEPTION (DriverError);
 1584         VC_CONVERT_EXCEPTION (EncryptedSystemRequired);
 1585         VC_CONVERT_EXCEPTION (HigherFuseVersionRequired);
 1586         VC_CONVERT_EXCEPTION (KernelCryptoServiceTestFailed);
 1587         VC_CONVERT_EXCEPTION (LoopDeviceSetupFailed);
 1588         VC_CONVERT_EXCEPTION (MountPointRequired);
 1589         VC_CONVERT_EXCEPTION (MountPointUnavailable);
 1590         VC_CONVERT_EXCEPTION (NoDriveLetterAvailable);
 1591         VC_CONVERT_EXCEPTION (TemporaryDirectoryFailure);
 1592         VC_CONVERT_EXCEPTION (UnsupportedSectorSizeHiddenVolumeProtection);
 1593         VC_CONVERT_EXCEPTION (UnsupportedSectorSizeNoKernelCrypto);
 1594         VC_CONVERT_EXCEPTION (VolumeAlreadyMounted);
 1595         VC_CONVERT_EXCEPTION (VolumeSlotUnavailable);
 1596         VC_CONVERT_EXCEPTION (UserInterfaceException);
 1597         VC_CONVERT_EXCEPTION (MissingArgument);
 1598         VC_CONVERT_EXCEPTION (NoItemSelected);
 1599         VC_CONVERT_EXCEPTION (StringFormatterException);
 1600         VC_CONVERT_EXCEPTION (ExecutedProcessFailed);
 1601         VC_CONVERT_EXCEPTION (AlreadyInitialized);
 1602         VC_CONVERT_EXCEPTION (AssertionFailed);
 1603         VC_CONVERT_EXCEPTION (ExternalException);
 1604         VC_CONVERT_EXCEPTION (InsufficientData);
 1605         VC_CONVERT_EXCEPTION (NotApplicable);
 1606         VC_CONVERT_EXCEPTION (NotImplemented);
 1607         VC_CONVERT_EXCEPTION (NotInitialized);
 1608         VC_CONVERT_EXCEPTION (ParameterIncorrect);
 1609         VC_CONVERT_EXCEPTION (ParameterTooLarge);
 1610         VC_CONVERT_EXCEPTION (PartitionDeviceRequired);
 1611         VC_CONVERT_EXCEPTION (StringConversionFailed);
 1612         VC_CONVERT_EXCEPTION (TestFailed);
 1613         VC_CONVERT_EXCEPTION (TimeOut);
 1614         VC_CONVERT_EXCEPTION (UnknownException);
 1615         VC_CONVERT_EXCEPTION (UserAbort)
 1616         VC_CONVERT_EXCEPTION (CipherInitError);
 1617         VC_CONVERT_EXCEPTION (WeakKeyDetected);
 1618         VC_CONVERT_EXCEPTION (HigherVersionRequired);
 1619         VC_CONVERT_EXCEPTION (KeyfilePathEmpty);
 1620         VC_CONVERT_EXCEPTION (MissingVolumeData);
 1621         VC_CONVERT_EXCEPTION (MountedVolumeInUse);
 1622         VC_CONVERT_EXCEPTION (UnsupportedSectorSize);
 1623         VC_CONVERT_EXCEPTION (VolumeEncryptionNotCompleted);
 1624         VC_CONVERT_EXCEPTION (VolumeHostInUse);
 1625         VC_CONVERT_EXCEPTION (VolumeProtected);
 1626         VC_CONVERT_EXCEPTION (VolumeReadOnly);
 1627         VC_CONVERT_EXCEPTION (Pkcs11Exception);
 1628         VC_CONVERT_EXCEPTION (InvalidSecurityTokenKeyfilePath);
 1629         VC_CONVERT_EXCEPTION (SecurityTokenLibraryNotInitialized);
 1630         VC_CONVERT_EXCEPTION (SecurityTokenKeyfileAlreadyExists);
 1631         VC_CONVERT_EXCEPTION (SecurityTokenKeyfileNotFound);
 1632         VC_CONVERT_EXCEPTION (UnsupportedAlgoInTrueCryptMode);
 1633         VC_CONVERT_EXCEPTION (UnsupportedTrueCryptFormat);
 1634         VC_CONVERT_EXCEPTION (SystemException);
 1635         VC_CONVERT_EXCEPTION (CipherException);
 1636         VC_CONVERT_EXCEPTION (VolumeException);
 1637         VC_CONVERT_EXCEPTION (PasswordException);
 1638         throw *ex;
 1639     }
 1640 }