1202 lines
34 KiB
C++
1202 lines
34 KiB
C++
/*
|
|
Derived from source code of TrueCrypt 7.1a, which is
|
|
Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
|
|
by the TrueCrypt License 3.0.
|
|
|
|
Modifications and additions to the original source code (contained in this file)
|
|
and all other portions of this file are Copyright (c) 2013-2017 IDRIX
|
|
and are governed by the Apache License 2.0 the full text of which is
|
|
contained in the file License.txt included in VeraCrypt binary and source
|
|
code distribution packages.
|
|
*/
|
|
|
|
#include "System.h"
|
|
#include "Platform/SystemInfo.h"
|
|
#ifdef TC_UNIX
|
|
#include <unistd.h>
|
|
#include <sys/statvfs.h> // header for statvfs
|
|
#include "Platform/Unix/Process.h"
|
|
#endif
|
|
#include "Core/RandomNumberGenerator.h"
|
|
#include "Core/VolumeCreator.h"
|
|
#include "Main/Application.h"
|
|
#include "Main/GraphicUserInterface.h"
|
|
#include "Main/Resources.h"
|
|
#include "VolumeCreationWizard.h"
|
|
#include "EncryptionOptionsWizardPage.h"
|
|
#include "InfoWizardPage.h"
|
|
#include "ProgressWizardPage.h"
|
|
#include "SingleChoiceWizardPage.h"
|
|
#include "VolumeCreationProgressWizardPage.h"
|
|
#include "VolumeFormatOptionsWizardPage.h"
|
|
#include "VolumeLocationWizardPage.h"
|
|
#include "VolumePasswordWizardPage.h"
|
|
#include "VolumePimWizardPage.h"
|
|
#include "VolumeSizeWizardPage.h"
|
|
#include "WaitDialog.h"
|
|
|
|
namespace VeraCrypt
|
|
{
|
|
#ifdef TC_MACOSX
|
|
|
|
bool VolumeCreationWizard::ProcessEvent(wxEvent& event)
|
|
{
|
|
if(GraphicUserInterface::HandlePasswordEntryCustomEvent (event))
|
|
return true;
|
|
else
|
|
return WizardFrame::ProcessEvent(event);
|
|
}
|
|
#endif
|
|
|
|
VolumeCreationWizard::VolumeCreationWizard (wxWindow* parent)
|
|
: WizardFrame (parent),
|
|
CrossPlatformSupport (true),
|
|
DisplayKeyInfo (false),
|
|
LargeFilesSupport (false),
|
|
QuickFormatEnabled (false),
|
|
SelectedFilesystemClusterSize (0),
|
|
SelectedFilesystemType (VolumeCreationOptions::FilesystemType::FAT),
|
|
SelectedVolumeHostType (VolumeHostType::File),
|
|
SelectedVolumeType (VolumeType::Normal),
|
|
Pim (0),
|
|
OuterPim (0),
|
|
SectorSize (0),
|
|
VolumeSize (0)
|
|
{
|
|
RandomNumberGenerator::Start();
|
|
|
|
SetTitle (LangString["INTRO_TITLE"]);
|
|
SetImage (Resources::GetVolumeCreationWizardBitmap (Gui->GetCharHeight (this) * 21));
|
|
SetMaxStaticTextWidth (55);
|
|
|
|
#ifdef TC_MACOSX
|
|
GraphicUserInterface::InstallPasswordEntryCustomKeyboardShortcuts (this);
|
|
#endif
|
|
|
|
SetStep (Step::VolumeHostType);
|
|
|
|
class Timer : public wxTimer
|
|
{
|
|
public:
|
|
Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { }
|
|
|
|
void Notify()
|
|
{
|
|
Wizard->OnRandomPoolUpdateTimer();
|
|
}
|
|
|
|
VolumeCreationWizard *Wizard;
|
|
};
|
|
|
|
RandomPoolUpdateTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
|
|
RandomPoolUpdateTimer->Start (200);
|
|
}
|
|
|
|
VolumeCreationWizard::~VolumeCreationWizard ()
|
|
{
|
|
burn (&Pim, sizeof (Pim));
|
|
burn (&OuterPim, sizeof (OuterPim));
|
|
}
|
|
|
|
WizardPage *VolumeCreationWizard::GetPage (WizardStep step)
|
|
{
|
|
switch (step)
|
|
{
|
|
case Step::VolumeHostType:
|
|
{
|
|
ClearHistory();
|
|
|
|
OuterVolume = false;
|
|
LargeFilesSupport = false;
|
|
QuickFormatEnabled = false;
|
|
Pim = 0;
|
|
|
|
SingleChoiceWizardPage <VolumeHostType::Enum> *page = new SingleChoiceWizardPage <VolumeHostType::Enum> (GetPageParent(), wxEmptyString, true);
|
|
page->SetMinSize (wxSize (Gui->GetCharWidth (this) * 58, Gui->GetCharHeight (this) * 18 + 5));
|
|
|
|
page->SetPageTitle (LangString["INTRO_TITLE"]);
|
|
|
|
page->AddChoice (VolumeHostType::File, LangString["IDC_FILE_CONTAINER"], LangString["IDT_FILE_CONTAINER"], L"introcontainer", LangString["IDC_MORE_INFO_ON_CONTAINERS"]);
|
|
page->AddChoice (VolumeHostType::Device, LangString["IDC_NONSYS_DEVICE"], LangString["IDT_NON_SYS_DEVICE"]);
|
|
|
|
page->SetSelection (SelectedVolumeHostType);
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumeType:
|
|
{
|
|
SingleChoiceWizardPage <VolumeType::Enum> *page = new SingleChoiceWizardPage <VolumeType::Enum> (GetPageParent(), wxEmptyString, true);
|
|
page->SetPageTitle (LangString["VOLUME_TYPE_TITLE"]);
|
|
|
|
page->AddChoice (VolumeType::Normal, LangString["IDC_STD_VOL"], LangString["NORMAL_VOLUME_TYPE_HELP"]);
|
|
page->AddChoice (VolumeType::Hidden, LangString["IDC_HIDDEN_VOL"], LangString["HIDDEN_VOLUME_TYPE_HELP"], L"hiddenvolume", LangString["IDC_HIDDEN_VOL_HELP"]);
|
|
|
|
page->SetSelection (SelectedVolumeType);
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumeLocation:
|
|
{
|
|
VolumeLocationWizardPage *page = new VolumeLocationWizardPage (GetPageParent(), SelectedVolumeHostType);
|
|
page->SetPageTitle (LangString["LOCATION"]);
|
|
|
|
if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP_HIDDEN_HOST_VOL" : "DEVICE_HELP_HIDDEN_HOST_VOL"]);
|
|
else
|
|
page->SetPageText (LangString[SelectedVolumeHostType == VolumeHostType::File ? "FILE_HELP" : "DEVICE_HELP_NO_INPLACE"]);
|
|
|
|
page->SetVolumePath (SelectedVolumePath);
|
|
return page;
|
|
}
|
|
|
|
case Step::EncryptionOptions:
|
|
{
|
|
EncryptionOptionsWizardPage *page = new EncryptionOptionsWizardPage (GetPageParent());
|
|
|
|
if (OuterVolume)
|
|
page->SetPageTitle (LangString["CIPHER_HIDVOL_HOST_TITLE"]);
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetPageTitle (LangString["CIPHER_HIDVOL_TITLE"]);
|
|
else
|
|
page->SetPageTitle (LangString["CIPHER_TITLE"]);
|
|
|
|
page->SetEncryptionAlgorithm (SelectedEncryptionAlgorithm);
|
|
page->SetHash (SelectedHash);
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumeSize:
|
|
{
|
|
wxString freeSpaceText;
|
|
wxString pageTitle;
|
|
wxString pageText;
|
|
|
|
if (OuterVolume)
|
|
{
|
|
pageTitle = LangString["SIZE_HIDVOL_HOST_TITLE"];
|
|
pageText = LangString["SIZE_HELP_HIDDEN_HOST_VOL"];
|
|
}
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
{
|
|
pageTitle = LangString["SIZE_HIDVOL_TITLE"];
|
|
pageText = LangString["SIZE_HELP_HIDDEN_VOL"] + L"\n\n" + LangString["LINUX_DYNAMIC_NOTICE"];
|
|
freeSpaceText = StringFormatter (LangString["LINUX_MAX_HIDDEN_SIZE"], Gui->SizeToString (MaxHiddenVolumeSize));
|
|
}
|
|
else
|
|
{
|
|
pageTitle = LangString["SIZE_TITLE"];
|
|
pageText = LangString["VOLUME_SIZE_HELP"];
|
|
}
|
|
|
|
VolumeSizeWizardPage *page = new VolumeSizeWizardPage (GetPageParent(), SelectedVolumePath, SectorSize, freeSpaceText);
|
|
|
|
page->SetPageTitle (pageTitle);
|
|
page->SetPageText (pageText);
|
|
|
|
if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetMaxVolumeSize (MaxHiddenVolumeSize);
|
|
else
|
|
page->SetVolumeSize (VolumeSize);
|
|
|
|
if (OuterVolume)
|
|
page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_HOST_SIZE);
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetMinVolumeSize (TC_MIN_HIDDEN_VOLUME_SIZE);
|
|
else
|
|
page->SetMinVolumeSize (TC_MIN_VOLUME_SIZE);
|
|
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumePassword:
|
|
{
|
|
VolumePasswordWizardPage *page = new VolumePasswordWizardPage (GetPageParent(), Password, Keyfiles);
|
|
page->EnableUsePim (); // force displaying "Use PIM"
|
|
page->SetPimSelected (Pim > 0);
|
|
|
|
if (OuterVolume)
|
|
page->SetPageTitle (LangString["PASSWORD_HIDVOL_HOST_TITLE"]);
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetPageTitle (LangString["PASSWORD_HIDVOL_TITLE"]);
|
|
else
|
|
page->SetPageTitle (LangString["PASSWORD_TITLE"]);
|
|
|
|
page->SetPageText (LangString[OuterVolume ? "PASSWORD_HIDDENVOL_HOST_HELP" : "PASSWORD_HELP"]);
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumePim:
|
|
{
|
|
VolumePimWizardPage *page = new VolumePimWizardPage (GetPageParent());
|
|
|
|
if (OuterVolume)
|
|
page->SetPageTitle (LangString["PIM_HIDVOL_HOST_TITLE"]);
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetPageTitle (LangString["PIM_HIDVOL_TITLE"]);
|
|
else
|
|
page->SetPageTitle (LangString["PIM_TITLE"]);
|
|
|
|
page->SetPageText (LangString["PIM_HELP"]);
|
|
page->SetVolumePim (Pim);
|
|
return page;
|
|
}
|
|
|
|
case Step::LargeFilesSupport:
|
|
{
|
|
SingleChoiceWizardPage <bool> *page = new SingleChoiceWizardPage <bool> (GetPageParent(), wxEmptyString, true);
|
|
page->SetPageTitle (LangString["FILESYS_PAGE_TITLE"]);
|
|
|
|
page->AddChoice (true, LangString["UISTR_YES"],LangString["FILESYS_PAGE_HELP_QUESTION"]);
|
|
|
|
page->AddChoice (false, LangString["UISTR_NO"],LangString["FILESYS_PAGE_HELP_EXPLANATION"]);
|
|
|
|
page->SetSelection (LargeFilesSupport);
|
|
return page;
|
|
}
|
|
|
|
case Step::FormatOptions:
|
|
{
|
|
shared_ptr <VolumeLayout> layout ((OuterVolume || SelectedVolumeType != VolumeType::Hidden)? (VolumeLayout*) new VolumeLayoutV2Normal() : (VolumeLayout*) new VolumeLayoutV2Hidden());
|
|
uint64 filesystemSize = layout->GetMaxDataSize (VolumeSize);
|
|
|
|
VolumeFormatOptionsWizardPage *page = new VolumeFormatOptionsWizardPage (GetPageParent(), filesystemSize, SectorSize,
|
|
SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden), OuterVolume, LargeFilesSupport);
|
|
|
|
page->SetPageTitle (LangString["FORMAT_TITLE"]);
|
|
page->SetFilesystemType (SelectedFilesystemType);
|
|
|
|
if (!OuterVolume && SelectedVolumeType == VolumeType::Hidden)
|
|
QuickFormatEnabled = true;
|
|
page->SetQuickFormat (QuickFormatEnabled);
|
|
|
|
return page;
|
|
}
|
|
|
|
case Step::CrossPlatformSupport:
|
|
{
|
|
SingleChoiceWizardPage <bool> *page = new SingleChoiceWizardPage <bool> (GetPageParent(), wxEmptyString, true);
|
|
page->SetPageTitle ( LangString["LINUX_CROSS_SUPPORT"]);
|
|
|
|
page->AddChoice (true, LangString["LINUX_CROSS_SUPPORT_OTHER"], LangString["LINUX_CROSS_SUPPORT_OTHER_HELP"]);
|
|
|
|
page->AddChoice (false, StringFormatter ( LangString["LINUX_CROSS_SUPPORT_ONLY"], SystemInfo::GetPlatformName()),
|
|
LangString["LINUX_CROSS_SUPPORT_ONLY_HELP"]);
|
|
|
|
page->SetSelection (CrossPlatformSupport);
|
|
return page;
|
|
}
|
|
|
|
case Step::CreationProgress:
|
|
{
|
|
VolumeCreationProgressWizardPage *page = new VolumeCreationProgressWizardPage (GetPageParent(), DisplayKeyInfo);
|
|
|
|
if (OuterVolume)
|
|
page->SetPageTitle (LangString["FORMAT_HIDVOL_HOST_TITLE"]);
|
|
else if (SelectedVolumeType == VolumeType::Hidden)
|
|
page->SetPageTitle (LangString["FORMAT_HIDVOL_TITLE"]);
|
|
else
|
|
page->SetPageTitle (LangString["FORMAT_TITLE"]);
|
|
|
|
page->SetPageText (LangString["FORMAT_HELP"]);
|
|
page->AbortEvent.Connect (EventConnector <VolumeCreationWizard> (this, &VolumeCreationWizard::OnAbortButtonClick));
|
|
page->SetNextButtonText (LangString["FORMAT"]);
|
|
return page;
|
|
}
|
|
|
|
case Step::VolumeCreatedInfo:
|
|
{
|
|
InfoWizardPage *page = new InfoWizardPage (GetPageParent());
|
|
page->SetPageTitle (LangString["FORMAT_FINISHED_TITLE"]);
|
|
page->SetPageText (LangString["FORMAT_FINISHED_HELP"]);
|
|
|
|
SetCancelButtonText (LangString["IDC_EXIT"]);
|
|
return page;
|
|
}
|
|
|
|
case Step::OuterVolumeContents:
|
|
{
|
|
ClearHistory();
|
|
|
|
MountOptions mountOptions;
|
|
mountOptions.Keyfiles = Keyfiles;
|
|
mountOptions.Password = Password;
|
|
mountOptions.Pim = Pim;
|
|
mountOptions.Path = make_shared <VolumePath> (SelectedVolumePath);
|
|
|
|
try
|
|
{
|
|
wxBusyCursor busy;
|
|
Gui->SetActiveFrame (this);
|
|
MountedOuterVolume = Core->MountVolume (mountOptions);
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
Gui->SetActiveFrame (this);
|
|
Gui->ShowError (e);
|
|
|
|
Close();
|
|
return new InfoWizardPage (GetPageParent());
|
|
}
|
|
|
|
struct OpenOuterVolumeFunctor : public Functor
|
|
{
|
|
OpenOuterVolumeFunctor (const DirectoryPath &outerVolumeMountPoint) : OuterVolumeMountPoint (outerVolumeMountPoint) { }
|
|
|
|
virtual void operator() ()
|
|
{
|
|
Gui->OpenExplorerWindow (OuterVolumeMountPoint);
|
|
}
|
|
|
|
DirectoryPath OuterVolumeMountPoint;
|
|
};
|
|
|
|
InfoWizardPage *page = new InfoWizardPage (GetPageParent(), LangString["LINUX_OPEN_OUTER_VOL"],
|
|
shared_ptr <Functor> (new OpenOuterVolumeFunctor (MountedOuterVolume->MountPoint)));
|
|
|
|
page->SetPageTitle (LangString["HIDVOL_HOST_FILLING_TITLE"]);
|
|
|
|
page->SetPageText (StringFormatter (LangString["LINUX_OUTER_VOL_IS_MOUNTED"],
|
|
wstring (MountedOuterVolume->MountPoint)));
|
|
|
|
return page;
|
|
}
|
|
|
|
case Step::HiddenVolume:
|
|
{
|
|
ClearHistory();
|
|
OuterVolume = false;
|
|
LargeFilesSupport = false;
|
|
Pim = 0;
|
|
|
|
InfoWizardPage *page = new InfoWizardPage (GetPageParent());
|
|
page->SetPageTitle (LangString["HIDVOL_PRE_CIPHER_TITLE"]);
|
|
page->SetPageText (LangString["HIDVOL_PRE_CIPHER_HELP"]);
|
|
|
|
return page;
|
|
}
|
|
|
|
default:
|
|
throw ParameterIncorrect (SRC_POS);
|
|
}
|
|
}
|
|
|
|
void VolumeCreationWizard::OnAbortButtonClick (EventArgs &args)
|
|
{
|
|
AbortRequested = true;
|
|
}
|
|
|
|
void VolumeCreationWizard::OnMouseMotion (wxMouseEvent& event)
|
|
{
|
|
event.Skip();
|
|
if (!IsWorkInProgress() && RandomNumberGenerator::IsRunning())
|
|
{
|
|
RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&event), sizeof (event)));
|
|
|
|
long coord = event.GetX();
|
|
RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&coord), sizeof (coord)));
|
|
coord = event.GetY();
|
|
RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&coord), sizeof (coord)));
|
|
|
|
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
|
|
if (page)
|
|
{
|
|
page->IncrementEntropyProgress ();
|
|
}
|
|
}
|
|
}
|
|
|
|
void VolumeCreationWizard::OnProgressTimer ()
|
|
{
|
|
if (!IsWorkInProgress())
|
|
return;
|
|
|
|
if (AbortRequested && !AbortConfirmationPending)
|
|
{
|
|
AbortConfirmationPending = true;
|
|
if (Gui->AskYesNo (LangString ["FORMAT_ABORT"], true))
|
|
{
|
|
if (IsWorkInProgress() && Creator.get() != nullptr)
|
|
{
|
|
CreationAborted = true;
|
|
Creator->Abort();
|
|
}
|
|
}
|
|
AbortRequested = false;
|
|
AbortConfirmationPending = false;
|
|
}
|
|
|
|
VolumeCreator::ProgressInfo progress = Creator->GetProgressInfo();
|
|
|
|
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
|
|
page->SetProgressValue (progress.SizeDone);
|
|
|
|
if (!progress.CreationInProgress && !AbortConfirmationPending)
|
|
{
|
|
SetWorkInProgress (false);
|
|
OnVolumeCreatorFinished ();
|
|
}
|
|
}
|
|
|
|
void VolumeCreationWizard::OnRandomPoolUpdateTimer ()
|
|
{
|
|
if (!IsWorkInProgress())
|
|
{
|
|
wxLongLong time = wxGetLocalTimeMillis();
|
|
RandomNumberGenerator::AddToPool (ConstBufferPtr (reinterpret_cast <byte *> (&time), sizeof (time)));
|
|
}
|
|
}
|
|
|
|
void VolumeCreationWizard::OnVolumeCreatorFinished ()
|
|
{
|
|
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
|
|
|
|
ProgressTimer.reset();
|
|
page->SetProgressState (false);
|
|
|
|
Gui->EndInteractiveBusyState (this);
|
|
SetWorkInProgress (false);
|
|
UpdateControls();
|
|
|
|
try
|
|
{
|
|
if (!CreationAborted)
|
|
{
|
|
Creator->CheckResult();
|
|
|
|
#ifdef TC_UNIX
|
|
// Format non-FAT filesystem
|
|
const char *fsFormatter = VolumeCreationOptions::FilesystemType::GetFsFormatter (SelectedFilesystemType);
|
|
|
|
if (fsFormatter)
|
|
{
|
|
wxBusyCursor busy;
|
|
|
|
MountOptions mountOptions (Gui->GetPreferences().DefaultMountOptions);
|
|
mountOptions.Path = make_shared <VolumePath> (SelectedVolumePath);
|
|
mountOptions.NoFilesystem = true;
|
|
mountOptions.Protection = VolumeProtection::None;
|
|
mountOptions.Password = Password;
|
|
mountOptions.Pim = Pim;
|
|
mountOptions.Keyfiles = Keyfiles;
|
|
mountOptions.Kdf = Kdf;
|
|
mountOptions.TrueCryptMode = false;
|
|
|
|
shared_ptr <VolumeInfo> volume = Core->MountVolume (mountOptions);
|
|
finally_do_arg (shared_ptr <VolumeInfo>, volume, { Core->DismountVolume (finally_arg, true); });
|
|
|
|
shared_ptr <VolumeLayout> layout((volume->Type == VolumeType::Normal)? (VolumeLayout*) new VolumeLayoutV2Normal() : (VolumeLayout*) new VolumeLayoutV2Hidden());
|
|
uint64 filesystemSize = layout->GetMaxDataSize (VolumeSize);
|
|
|
|
Thread::Sleep (2000); // Try to prevent race conditions caused by OS
|
|
|
|
// Temporarily take ownership of the device if the user is not an administrator
|
|
UserId origDeviceOwner ((uid_t) -1);
|
|
|
|
DevicePath virtualDevice = volume->VirtualDevice;
|
|
#ifdef TC_MACOSX
|
|
string virtualDeviceStr = virtualDevice;
|
|
if (virtualDeviceStr.find ("/dev/rdisk") != 0)
|
|
virtualDevice = "/dev/r" + virtualDeviceStr.substr (5);
|
|
#endif
|
|
try
|
|
{
|
|
File file;
|
|
file.Open (virtualDevice, File::OpenReadWrite);
|
|
}
|
|
catch (...)
|
|
{
|
|
if (!Core->HasAdminPrivileges())
|
|
{
|
|
origDeviceOwner = virtualDevice.GetOwner();
|
|
Core->SetFileOwner (virtualDevice, UserId (getuid()));
|
|
}
|
|
}
|
|
|
|
finally_do_arg2 (FilesystemPath, virtualDevice, UserId, origDeviceOwner,
|
|
{
|
|
if (finally_arg2.SystemId != (uid_t) -1)
|
|
Core->SetFileOwner (finally_arg, finally_arg2);
|
|
});
|
|
|
|
// Create filesystem
|
|
list <string> args;
|
|
|
|
if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::MacOsExt && VolumeSize >= 10 * BYTES_PER_MB)
|
|
args.push_back ("-J");
|
|
|
|
// Perform a quick NTFS formatting
|
|
if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::NTFS)
|
|
args.push_back ("-f");
|
|
|
|
if (SelectedFilesystemType == VolumeCreationOptions::FilesystemType::Btrfs)
|
|
{
|
|
args.push_back ("-f");
|
|
if (filesystemSize < VC_MIN_LARGE_BTRFS_VOLUME_SIZE)
|
|
{
|
|
// use mixed mode for small BTRFS volumes
|
|
args.push_back ("-M");
|
|
}
|
|
}
|
|
|
|
args.push_back (string (virtualDevice));
|
|
|
|
Process::Execute (fsFormatter, args);
|
|
}
|
|
#endif // TC_UNIX
|
|
|
|
if (OuterVolume)
|
|
{
|
|
SetStep (Step::OuterVolumeContents);
|
|
}
|
|
else
|
|
{
|
|
Gui->ShowInfo (SelectedVolumeType == VolumeType::Hidden ? "HIDVOL_FORMAT_FINISHED_HELP" : "FORMAT_FINISHED_INFO");
|
|
SetStep (Step::VolumeCreatedInfo);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
Gui->ShowError (e);
|
|
}
|
|
|
|
page->SetProgressValue (0);
|
|
if (SelectedVolumeType == VolumeType::Normal && !SelectedVolumePath.IsDevice())
|
|
{
|
|
try
|
|
{
|
|
FilePath (wstring (SelectedVolumePath)).Delete();
|
|
}
|
|
catch (...) { }
|
|
}
|
|
}
|
|
|
|
WizardFrame::WizardStep VolumeCreationWizard::ProcessPageChangeRequest (bool forward)
|
|
{
|
|
switch (GetCurrentStep())
|
|
{
|
|
case Step::VolumeHostType:
|
|
{
|
|
SingleChoiceWizardPage <VolumeHostType::Enum> *page = dynamic_cast <SingleChoiceWizardPage <VolumeHostType::Enum> *> (GetCurrentPage());
|
|
|
|
try
|
|
{
|
|
SelectedVolumeHostType = page->GetSelection();
|
|
}
|
|
catch (NoItemSelected &)
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
return Step::VolumeType;
|
|
}
|
|
|
|
case Step::VolumeType:
|
|
{
|
|
SingleChoiceWizardPage <VolumeType::Enum> *page = dynamic_cast <SingleChoiceWizardPage <VolumeType::Enum> *> (GetCurrentPage());
|
|
|
|
try
|
|
{
|
|
SelectedVolumeType = page->GetSelection();
|
|
}
|
|
catch (NoItemSelected &)
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (SelectedVolumeType == VolumeType::Hidden)
|
|
OuterVolume = true;
|
|
|
|
return Step::VolumeLocation;
|
|
}
|
|
|
|
case Step::VolumeLocation:
|
|
{
|
|
VolumeLocationWizardPage *page = dynamic_cast <VolumeLocationWizardPage *> (GetCurrentPage());
|
|
SelectedVolumePath = page->GetVolumePath();
|
|
VolumeSize = 0;
|
|
|
|
if (forward)
|
|
{
|
|
if (Core->IsVolumeMounted (SelectedVolumePath))
|
|
{
|
|
Gui->ShowInfo ("DISMOUNT_FIRST");
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (SelectedVolumePath.IsDevice())
|
|
{
|
|
if (!DeviceWarningConfirmed && !Gui->AskYesNo (LangString["FORMAT_DEVICE_FOR_ADVANCED_ONLY"]))
|
|
return GetCurrentStep();
|
|
|
|
DeviceWarningConfirmed = true;
|
|
|
|
foreach_ref (const HostDevice &drive, Core->GetHostDevices())
|
|
{
|
|
if (drive.Path == SelectedVolumePath && !drive.Partitions.empty())
|
|
{
|
|
foreach_ref (const HostDevice &partition, drive.Partitions)
|
|
{
|
|
if (partition.MountPoint == "/")
|
|
{
|
|
Gui->ShowError (LangString["LINUX_ERROR_TRY_ENCRYPT_SYSTEM_DRIVE"]);
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
|
|
Gui->ShowError ("DEVICE_PARTITIONS_ERR");
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
SectorSize = Core->GetDeviceSectorSize (SelectedVolumePath);
|
|
VolumeSize = Core->GetDeviceSize (SelectedVolumePath);
|
|
}
|
|
catch (UserAbort&)
|
|
{
|
|
return Step::VolumeLocation;
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
Gui->ShowError (e);
|
|
Gui->ShowError ("CANNOT_CALC_SPACE");
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
DirectoryPath mountPoint;
|
|
try
|
|
{
|
|
mountPoint = Core->GetDeviceMountPoint (SelectedVolumePath);
|
|
|
|
if (!mountPoint.IsEmpty())
|
|
{
|
|
if (mountPoint == "/")
|
|
{
|
|
Gui->ShowError (LangString["LINUX_ERROR_TRY_ENCRYPT_SYSTEM_PARTITION"]);
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (!Gui->AskYesNo (StringFormatter (LangString["LINUX_WARNING_FORMAT_DESTROY_FS"], wstring (mountPoint)), false, true))
|
|
return GetCurrentStep();
|
|
|
|
try
|
|
{
|
|
Core->DismountFilesystem (mountPoint, true);
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
Gui->ShowError (e);
|
|
Gui->ShowError (StringFormatter (LangString["LINUX_MOUNTET_HINT"], wstring (mountPoint)));
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
catch (...) { }
|
|
}
|
|
else
|
|
SectorSize = TC_SECTOR_SIZE_FILE_HOSTED_VOLUME;
|
|
}
|
|
|
|
return Step::EncryptionOptions;
|
|
}
|
|
|
|
case Step::EncryptionOptions:
|
|
{
|
|
EncryptionOptionsWizardPage *page = dynamic_cast <EncryptionOptionsWizardPage *> (GetCurrentPage());
|
|
SelectedEncryptionAlgorithm = page->GetEncryptionAlgorithm ();
|
|
SelectedHash = page->GetHash ();
|
|
|
|
if (forward)
|
|
RandomNumberGenerator::SetHash (SelectedHash);
|
|
|
|
if (SelectedVolumePath.IsDevice() && (OuterVolume || SelectedVolumeType != VolumeType::Hidden))
|
|
return Step::VolumePassword;
|
|
else
|
|
return Step::VolumeSize;
|
|
}
|
|
|
|
case Step::VolumeSize:
|
|
{
|
|
VolumeSizeWizardPage *page = dynamic_cast <VolumeSizeWizardPage *> (GetCurrentPage());
|
|
|
|
try
|
|
{
|
|
VolumeSize = page->GetVolumeSize();
|
|
}
|
|
catch (Exception &e)
|
|
{
|
|
if (forward)
|
|
{
|
|
Gui->ShowError (e);
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
|
|
if (forward
|
|
&& !OuterVolume && SelectedVolumeType == VolumeType::Hidden
|
|
&& (double) VolumeSize / MaxHiddenVolumeSize > 0.85)
|
|
{
|
|
if (!Gui->AskYesNo (LangString["FREE_SPACE_FOR_WRITING_TO_OUTER_VOLUME"]))
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (forward
|
|
&& SelectedVolumeHostType == VolumeHostType::File
|
|
&& VolumeSize > 4 * BYTES_PER_GB
|
|
&& (OuterVolume || SelectedVolumeType != VolumeType::Hidden)
|
|
&& !Core->FilesystemSupportsLargeFiles (SelectedVolumePath))
|
|
{
|
|
Gui->ShowWarning (LangString["VOLUME_TOO_LARGE_FOR_FAT32"]);
|
|
}
|
|
|
|
return Step::VolumePassword;
|
|
}
|
|
|
|
case Step::VolumePassword:
|
|
{
|
|
VolumePasswordWizardPage *page = dynamic_cast <VolumePasswordWizardPage *> (GetCurrentPage());
|
|
try
|
|
{
|
|
Password = page->GetPassword();
|
|
}
|
|
catch (PasswordException& e)
|
|
{
|
|
Gui->ShowWarning (e);
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
Kdf = page->GetPkcs5Kdf();
|
|
Keyfiles = page->GetKeyfiles();
|
|
|
|
if (forward && Password && !Password->IsEmpty())
|
|
{
|
|
if (Password->Size() < VolumePassword::WarningSizeThreshold)
|
|
{
|
|
if (!Gui->AskYesNo (LangString["PASSWORD_LENGTH_WARNING"], false, true))
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (page->IsPimSelected ())
|
|
return Step::VolumePim;
|
|
else
|
|
{
|
|
// Clear PIM
|
|
Pim = 0;
|
|
|
|
if (forward && !OuterVolume && SelectedVolumeType == VolumeType::Hidden)
|
|
{
|
|
shared_ptr <VolumePassword> hiddenPassword;
|
|
try
|
|
{
|
|
hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled);
|
|
}
|
|
catch (...)
|
|
{
|
|
hiddenPassword = Password;
|
|
}
|
|
|
|
// check if Outer and Hidden passwords are the same
|
|
if ( (hiddenPassword && !hiddenPassword->IsEmpty() && OuterPassword && !OuterPassword->IsEmpty() && (*(OuterPassword.get()) == *(hiddenPassword.get())))
|
|
||
|
|
((!hiddenPassword || hiddenPassword->IsEmpty()) && (!OuterPassword || OuterPassword->IsEmpty()))
|
|
)
|
|
{
|
|
//check if they have also the same PIM
|
|
if (OuterPim == Pim)
|
|
{
|
|
Gui->ShowError (LangString["LINUX_HIDDEN_PASS_NO_DIFF"]);
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (VolumeSize > 4 * BYTES_PER_GB)
|
|
{
|
|
if (VolumeSize <= TC_MAX_FAT_SECTOR_COUNT * SectorSize)
|
|
return Step::LargeFilesSupport;
|
|
else
|
|
SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
|
|
}
|
|
|
|
return Step::FormatOptions;
|
|
}
|
|
}
|
|
|
|
case Step::VolumePim:
|
|
{
|
|
VolumePimWizardPage *page = dynamic_cast <VolumePimWizardPage *> (GetCurrentPage());
|
|
Pim = page->GetVolumePim();
|
|
|
|
if (-1 == Pim)
|
|
{
|
|
// PIM invalid: don't go anywhere
|
|
Gui->ShowError ("PIM_TOO_BIG");
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (forward && !OuterVolume && SelectedVolumeType == VolumeType::Hidden)
|
|
{
|
|
shared_ptr <VolumePassword> hiddenPassword;
|
|
try
|
|
{
|
|
hiddenPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled);
|
|
}
|
|
catch (...)
|
|
{
|
|
hiddenPassword = Password;
|
|
}
|
|
|
|
// check if Outer and Hidden passwords are the same
|
|
if ( (hiddenPassword && !hiddenPassword->IsEmpty() && OuterPassword && !OuterPassword->IsEmpty() && (*(OuterPassword.get()) == *(hiddenPassword.get())))
|
|
||
|
|
((!hiddenPassword || hiddenPassword->IsEmpty()) && (!OuterPassword || OuterPassword->IsEmpty()))
|
|
)
|
|
{
|
|
//check if they have also the same PIM
|
|
if (OuterPim == Pim)
|
|
{
|
|
Gui->ShowError (LangString["LINUX_HIDDEN_PASS_NO_DIFF"]);
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (forward && Password && !Password->IsEmpty())
|
|
{
|
|
if (Password->Size() < VolumePassword::WarningSizeThreshold)
|
|
{
|
|
if (Pim > 0 && Pim < 485)
|
|
{
|
|
Gui->ShowError ("PIM_REQUIRE_LONG_PASSWORD");
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
else if (Pim > 0 && Pim < 485)
|
|
{
|
|
if (!Gui->AskYesNo (LangString["PIM_SMALL_WARNING"], false, true))
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (VolumeSize > 4 * BYTES_PER_GB)
|
|
{
|
|
if (VolumeSize <= TC_MAX_FAT_SECTOR_COUNT * SectorSize)
|
|
return Step::LargeFilesSupport;
|
|
else
|
|
SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
|
|
}
|
|
|
|
return Step::FormatOptions;
|
|
}
|
|
|
|
case Step::LargeFilesSupport:
|
|
{
|
|
SingleChoiceWizardPage <bool> *page = dynamic_cast <SingleChoiceWizardPage <bool> *> (GetCurrentPage());
|
|
|
|
try
|
|
{
|
|
LargeFilesSupport = page->GetSelection();
|
|
}
|
|
catch (NoItemSelected &)
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (LargeFilesSupport)
|
|
SelectedFilesystemType = VolumeCreationOptions::FilesystemType::GetPlatformNative();
|
|
else
|
|
SelectedFilesystemType = VolumeCreationOptions::FilesystemType::FAT;
|
|
|
|
return Step::FormatOptions;
|
|
}
|
|
|
|
case Step::FormatOptions:
|
|
{
|
|
VolumeFormatOptionsWizardPage *page = dynamic_cast <VolumeFormatOptionsWizardPage *> (GetCurrentPage());
|
|
|
|
if (forward && OuterVolume)
|
|
{
|
|
if (page->GetFilesystemType() != VolumeCreationOptions::FilesystemType::FAT)
|
|
{
|
|
if (!Gui->AskYesNo (LangString["LINUX_CONFIRM_INNER_VOLUME_CALC"], false, true))
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
}
|
|
|
|
SelectedFilesystemType = page->GetFilesystemType();
|
|
QuickFormatEnabled = page->IsQuickFormatEnabled();
|
|
|
|
if (SelectedFilesystemType != VolumeCreationOptions::FilesystemType::None
|
|
&& SelectedFilesystemType != VolumeCreationOptions::FilesystemType::FAT)
|
|
return Step::CrossPlatformSupport;
|
|
|
|
return Step::CreationProgress;
|
|
}
|
|
|
|
case Step::CrossPlatformSupport:
|
|
{
|
|
SingleChoiceWizardPage <bool> *page = dynamic_cast <SingleChoiceWizardPage <bool> *> (GetCurrentPage());
|
|
|
|
try
|
|
{
|
|
CrossPlatformSupport = page->GetSelection();
|
|
}
|
|
catch (NoItemSelected &)
|
|
{
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (forward && CrossPlatformSupport)
|
|
Gui->ShowWarning (StringFormatter (LangString["LINUX_NOT_FAT_HINT"], SystemInfo::GetPlatformName()));
|
|
|
|
return Step::CreationProgress;
|
|
}
|
|
|
|
case Step::CreationProgress:
|
|
{
|
|
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
|
|
|
|
DisplayKeyInfo = page->IsKeyInfoDisplayed();
|
|
|
|
if (forward)
|
|
{
|
|
if (SelectedVolumeType != VolumeType::Hidden || OuterVolume)
|
|
{
|
|
if (OuterVolume && VolumeSize > TC_MAX_FAT_SECTOR_COUNT * SectorSize)
|
|
{
|
|
uint64 limit = TC_MAX_FAT_SECTOR_COUNT * SectorSize / BYTES_PER_TB;
|
|
wstring err = StringFormatter (LangString["LINUX_ERROR_SIZE_HIDDEN_VOL"], limit, limit * 1024);
|
|
|
|
if (SectorSize < 4096)
|
|
{
|
|
err += LangString["LINUX_MAX_SIZE_HINT"];
|
|
#if defined (TC_LINUX)
|
|
err += LangString["LINUX_DOT_LF"];
|
|
#else
|
|
err += LangString["LINUX_NOT_SUPPORTED"];
|
|
#endif
|
|
}
|
|
|
|
Gui->ShowError (err);
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
if (SelectedVolumePath.IsDevice())
|
|
{
|
|
wxString confirmMsg = LangString["OVERWRITEPROMPT_DEVICE"];
|
|
|
|
if (!Gui->AskYesNo (wxString::Format (confirmMsg, wxString (LangString["DEVICE"]).c_str(), wstring (SelectedVolumePath).c_str(), L""), false, true))
|
|
return GetCurrentStep();
|
|
}
|
|
else if (FilesystemPath (wstring (SelectedVolumePath)).IsFile())
|
|
{
|
|
wxString confirmMsg = LangString["OVERWRITEPROMPT"];
|
|
|
|
if (!Gui->AskYesNo (wxString::Format (confirmMsg, wstring (SelectedVolumePath).c_str()), false, true))
|
|
return GetCurrentStep();
|
|
}
|
|
}
|
|
|
|
AbortRequested = false;
|
|
AbortConfirmationPending = false;
|
|
CreationAborted = false;
|
|
SetWorkInProgress (true);
|
|
UpdateControls();
|
|
|
|
Gui->BeginInteractiveBusyState (this);
|
|
|
|
try
|
|
{
|
|
make_shared_auto (VolumeCreationOptions, options);
|
|
|
|
options->Filesystem = SelectedFilesystemType;
|
|
options->FilesystemClusterSize = SelectedFilesystemClusterSize;
|
|
options->SectorSize = SectorSize;
|
|
options->EA = SelectedEncryptionAlgorithm;
|
|
options->Password = Password;
|
|
options->Pim = Pim;
|
|
options->Keyfiles = Keyfiles;
|
|
options->Path = SelectedVolumePath;
|
|
options->Quick = QuickFormatEnabled;
|
|
options->Size = VolumeSize;
|
|
options->Type = OuterVolume ? VolumeType::Normal : SelectedVolumeType;
|
|
options->VolumeHeaderKdf = Pkcs5Kdf::GetAlgorithm (*SelectedHash, false);
|
|
options->EMVSupportEnabled = Gui->GetPreferences().EMVSupportEnabled;
|
|
|
|
|
|
Creator.reset (new VolumeCreator);
|
|
VolumeCreatorThreadRoutine routine(options, Creator);
|
|
Gui->ExecuteWaitThreadRoutine (this, &routine);
|
|
|
|
page->SetKeyInfo (Creator->GetKeyInfo());
|
|
|
|
class Timer : public wxTimer
|
|
{
|
|
public:
|
|
Timer (VolumeCreationWizard *wizard) : Wizard (wizard) { }
|
|
|
|
void Notify()
|
|
{
|
|
Wizard->OnProgressTimer();
|
|
}
|
|
|
|
VolumeCreationWizard *Wizard;
|
|
};
|
|
|
|
page->SetProgressRange (options->Size);
|
|
page->SetProgressState (true);
|
|
ProgressTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
|
|
ProgressTimer->Start (50);
|
|
}
|
|
catch (Exception &e)
|
|
{
|
|
CreationAborted = true;
|
|
OnVolumeCreatorFinished();
|
|
Gui->ShowError (e);
|
|
}
|
|
}
|
|
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
case Step::VolumeCreatedInfo:
|
|
Creator.reset();
|
|
SetCancelButtonText (L"");
|
|
|
|
// clear saved credentials
|
|
Password.reset();
|
|
OuterPassword.reset();
|
|
burn (&Pim, sizeof (Pim));
|
|
burn (&OuterPim, sizeof (OuterPim));
|
|
|
|
return Step::VolumeHostType;
|
|
|
|
case Step::OuterVolumeContents:
|
|
try
|
|
{
|
|
// Determine maximum size of the hidden volume. Scan cluster table offline as a live filesystem test would
|
|
// require using FUSE and loop device which cannot be used for devices with sectors larger than 512.
|
|
|
|
wxBusyCursor busy;
|
|
bool outerVolumeAvailableSpaceValid = false;
|
|
uint64 outerVolumeAvailableSpace = 0;
|
|
MaxHiddenVolumeSize = 0;
|
|
|
|
Gui->SetActiveFrame (this);
|
|
|
|
if (MountedOuterVolume)
|
|
{
|
|
#ifdef TC_UNIX
|
|
const DirectoryPath &outerVolumeMountPoint = MountedOuterVolume->MountPoint;
|
|
struct statvfs stat;
|
|
if (statvfs(((string)outerVolumeMountPoint).c_str(), &stat) == 0)
|
|
{
|
|
outerVolumeAvailableSpace = (uint64) stat.f_bsize * (uint64) stat.f_bavail;
|
|
outerVolumeAvailableSpaceValid = true;
|
|
}
|
|
#endif
|
|
Core->DismountVolume (MountedOuterVolume);
|
|
MountedOuterVolume.reset();
|
|
}
|
|
|
|
#ifdef TC_UNIX
|
|
// Temporarily take ownership of a device if the user is not an administrator
|
|
UserId origDeviceOwner ((uid_t) -1);
|
|
|
|
if (!Core->HasAdminPrivileges() && SelectedVolumePath.IsDevice())
|
|
{
|
|
origDeviceOwner = FilesystemPath (wstring (SelectedVolumePath)).GetOwner();
|
|
Core->SetFileOwner (SelectedVolumePath, UserId (getuid()));
|
|
}
|
|
|
|
finally_do_arg2 (FilesystemPath, SelectedVolumePath, UserId, origDeviceOwner,
|
|
{
|
|
if (finally_arg2.SystemId != (uid_t) -1)
|
|
Core->SetFileOwner (finally_arg, finally_arg2);
|
|
});
|
|
#endif
|
|
|
|
shared_ptr <Volume> outerVolume = Core->OpenVolume (make_shared <VolumePath> (SelectedVolumePath), true, Password, Pim, Kdf, false, Keyfiles, VolumeProtection::ReadOnly);
|
|
try
|
|
{
|
|
MaxHiddenVolumeSize = Core->GetMaxHiddenVolumeSize (outerVolume);
|
|
}
|
|
catch (ParameterIncorrect& )
|
|
{
|
|
// Outer volume not using FAT
|
|
// estimate maximum hidden volume size as 80% of available size of outer volume
|
|
if (outerVolumeAvailableSpaceValid)
|
|
{
|
|
MaxHiddenVolumeSize =(4ULL * outerVolumeAvailableSpace) / 5ULL;
|
|
}
|
|
else
|
|
throw;
|
|
}
|
|
|
|
// Add a reserve (in case the user mounts the outer volume and creates new files
|
|
// on it by accident or OS writes some new data behind his or her back, such as
|
|
// System Restore etc.)
|
|
|
|
uint64 reservedSize = outerVolume->GetSize() / 200;
|
|
if (reservedSize > 10 * BYTES_PER_MB)
|
|
reservedSize = 10 * BYTES_PER_MB;
|
|
|
|
if (MaxHiddenVolumeSize < reservedSize)
|
|
MaxHiddenVolumeSize = 0;
|
|
else
|
|
MaxHiddenVolumeSize -= reservedSize;
|
|
|
|
MaxHiddenVolumeSize -= MaxHiddenVolumeSize % outerVolume->GetSectorSize(); // Must be a multiple of the sector size
|
|
|
|
// remember Outer password and keyfiles in order to be able to compare it with those of Hidden volume
|
|
try
|
|
{
|
|
OuterPassword = Keyfile::ApplyListToPassword (Keyfiles, Password, Gui->GetPreferences().EMVSupportEnabled);
|
|
}
|
|
catch (...)
|
|
{
|
|
OuterPassword = Password;
|
|
}
|
|
|
|
OuterPim = Pim;
|
|
}
|
|
catch (exception &e)
|
|
{
|
|
Gui->SetActiveFrame (this);
|
|
Gui->ShowError (e);
|
|
return GetCurrentStep();
|
|
}
|
|
|
|
return Step::HiddenVolume;
|
|
|
|
case Step::HiddenVolume:
|
|
return Step::EncryptionOptions;
|
|
|
|
default:
|
|
throw ParameterIncorrect (SRC_POS);
|
|
}
|
|
}
|
|
|
|
void VolumeCreationWizard::UpdateControls ()
|
|
{
|
|
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
|
|
if (page)
|
|
{
|
|
page->EnableAbort (IsWorkInProgress());
|
|
}
|
|
}
|
|
|
|
bool VolumeCreationWizard::DeviceWarningConfirmed;
|
|
}
|