"Fossies" - the Fresh Open Source Software Archive

Member "src/Main/Forms/MainFrame.cpp" (10 Oct 2018, 46553 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 "MainFrame.cpp" see the Fossies "Dox" file reference documentation.

    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 
   15 #ifdef TC_UNIX
   16 #include <fcntl.h>
   17 #include <unistd.h>
   18 #include <sys/stat.h>
   19 #include <sys/types.h>
   20 #endif
   21 
   22 #include "Common/SecurityToken.h"
   23 #include "Main/Main.h"
   24 #include "Main/Resources.h"
   25 #include "Main/Application.h"
   26 #include "Main/GraphicUserInterface.h"
   27 #include "Main/VolumeHistory.h"
   28 #include "Main/Xml.h"
   29 #include "MainFrame.h"
   30 #include "AboutDialog.h"
   31 #include "BenchmarkDialog.h"
   32 #include "ChangePasswordDialog.h"
   33 #include "EncryptionTestDialog.h"
   34 #include "FavoriteVolumesDialog.h"
   35 #include "LegalNoticesDialog.h"
   36 #include "PreferencesDialog.h"
   37 #include "SecurityTokenKeyfilesDialog.h"
   38 #include "VolumeCreationWizard.h"
   39 #include "VolumePropertiesDialog.h"
   40 
   41 namespace VeraCrypt
   42 {
   43     DEFINE_EVENT_TYPE(wxEVT_COMMAND_UPDATE_VOLUME_LIST)
   44     DEFINE_EVENT_TYPE(wxEVT_COMMAND_PREF_UPDATED)
   45     DEFINE_EVENT_TYPE(wxEVT_COMMAND_OPEN_VOLUME_REQUEST)
   46     DEFINE_EVENT_TYPE(wxEVT_COMMAND_SHOW_WARNING)
   47 
   48     MainFrame::MainFrame (wxWindow* parent) : MainFrameBase (parent),
   49         ListItemRightClickEventPending (false),
   50         SelectedItemIndex (-1),
   51         SelectedSlotNumber (0),
   52         ShowRequestFifo (-1)
   53     {
   54         wxBusyCursor busy;
   55 
   56         SetName (Application::GetName());
   57         SetTitle (Application::GetName());
   58         SetIcon (Resources::GetVeraCryptIcon());
   59 
   60 #if defined(TC_UNIX) && !defined(TC_MACOSX)
   61         try
   62         {
   63             string fifoPath = GetShowRequestFifoPath();
   64 
   65             remove (fifoPath.c_str());
   66             throw_sys_if (mkfifo (fifoPath.c_str(), S_IRUSR | S_IWUSR) == -1);
   67 
   68             ShowRequestFifo = open (fifoPath.c_str(), O_RDONLY | O_NONBLOCK);
   69             throw_sys_if (ShowRequestFifo == -1);
   70         }
   71         catch (...)
   72         {
   73 #ifdef DEBUG
   74             throw;
   75 #endif
   76         }
   77 #endif
   78 
   79         InitControls();
   80         InitPreferences();
   81         InitTaskBarIcon();
   82         InitEvents();
   83         InitMessageFilter();
   84 
   85         if (!GetPreferences().SecurityTokenModule.IsEmpty() && !SecurityToken::IsInitialized())
   86         {
   87             try
   88             {
   89                 Gui->InitSecurityTokenLibrary();
   90             }
   91             catch (exception &e)
   92             {
   93                 Gui->ShowError (e);
   94             }
   95         }
   96 
   97         Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrame::OnQuit ) );
   98         Connect( wxID_ANY, wxEVT_COMMAND_UPDATE_VOLUME_LIST, wxCommandEventHandler( MainFrame::OnUpdateVolumeList ) );
   99         Connect( wxID_ANY, wxEVT_COMMAND_PREF_UPDATED, wxCommandEventHandler( MainFrame::OnPreferencesUpdated ) );
  100         Connect( wxID_ANY, wxEVT_COMMAND_OPEN_VOLUME_REQUEST, wxCommandEventHandler( MainFrame::OnOpenVolumeSystemRequest ) );
  101 
  102     }
  103 
  104     MainFrame::~MainFrame ()
  105     {
  106 #if defined(TC_UNIX) && !defined(TC_MACOSX)
  107         if (ShowRequestFifo != -1)
  108         {
  109             try
  110             {
  111                 close (ShowRequestFifo);
  112                 remove (string (GetShowRequestFifoPath()).c_str());
  113             }
  114             catch (...) { }
  115         }
  116 #endif
  117 
  118         Disconnect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainFrame::OnQuit ) );
  119         Disconnect( wxID_ANY, wxEVT_COMMAND_UPDATE_VOLUME_LIST, wxCommandEventHandler( MainFrame::OnUpdateVolumeList ) );
  120         Disconnect( wxID_ANY, wxEVT_COMMAND_PREF_UPDATED, wxCommandEventHandler( MainFrame::OnPreferencesUpdated ) );
  121         Disconnect( wxID_ANY, wxEVT_COMMAND_OPEN_VOLUME_REQUEST, wxCommandEventHandler( MainFrame::OnOpenVolumeSystemRequest ) );
  122         Core->VolumeMountedEvent.Disconnect (this);
  123         Core->VolumeDismountedEvent.Disconnect (this);
  124         Gui->OpenVolumeSystemRequestEvent.Disconnect (this);
  125         Gui->PreferencesUpdatedEvent.Disconnect (this);
  126 
  127         VolumeHistory::DisconnectComboBox (VolumePathComboBox);
  128 
  129 #ifdef TC_WINDOWS
  130         Hotkey::UnregisterList (this, GetPreferences().Hotkeys);
  131 #endif
  132     }
  133 
  134     void MainFrame::AddToFavorites (const VolumeInfoList &volumes)
  135     {
  136         try
  137         {
  138             FavoriteVolumeList newFavorites;
  139 
  140             // Delete duplicates
  141             foreach (shared_ptr <FavoriteVolume> favorite, FavoriteVolume::LoadList())
  142             {
  143                 bool mounted = false;
  144                 foreach_ref (const VolumeInfo &volume, volumes)
  145                 {
  146                     if (volume.Path == favorite->Path)
  147                     {
  148                         mounted = true;
  149                         break;
  150                     }
  151                 }
  152                 if (!mounted)
  153                     newFavorites.push_back (favorite);
  154             }
  155 
  156             size_t newItemCount = 0;
  157             foreach_ref (const VolumeInfo &volume, volumes)
  158             {
  159                 newFavorites.push_back (shared_ptr <FavoriteVolume> (new FavoriteVolume (volume.Path, volume.MountPoint, volume.SlotNumber, volume.Protection == VolumeProtection::ReadOnly, volume.SystemEncryption)));
  160                 ++newItemCount;
  161             }
  162 
  163             OrganizeFavorites (newFavorites, newItemCount);
  164         }
  165         catch (exception &e)
  166         {
  167             Gui->ShowError (e);
  168         }
  169     }
  170 
  171     bool MainFrame::CanExit () const
  172     {
  173         return Gui->IsTheOnlyTopLevelWindow (this);
  174     }
  175 
  176     void MainFrame::ChangePassword (ChangePasswordDialog::Mode::Enum mode)
  177     {
  178         if (!CheckVolumePathNotEmpty ())
  179             return;
  180 
  181         shared_ptr <VolumePath> volumePath = GetSelectedVolumePath();
  182 
  183 #ifdef TC_WINDOWS
  184         if (Core->IsVolumeMounted (*volumePath))
  185         {
  186             Gui->ShowInfo (LangString [mode == ChangePasswordDialog::Mode::ChangePkcs5Prf ? "MOUNTED_NO_PKCS5_PRF_CHANGE" : "MOUNTED_NOPWCHANGE"]);
  187             return;
  188         }
  189 #endif
  190 #ifdef TC_MACOSX
  191         if (Gui->IsInBackgroundMode())
  192             Gui->SetBackgroundMode (false);
  193 #endif
  194         ChangePasswordDialog dialog (this, volumePath, mode);
  195         dialog.ShowModal();
  196     }
  197 
  198     void MainFrame::CheckFilesystem (bool repair)
  199     {
  200         shared_ptr <VolumeInfo> selectedVolume = GetSelectedVolume();
  201         if (selectedVolume)
  202         {
  203             try
  204             {
  205 #ifdef TC_WINDOWS
  206                 string mountPoint = selectedVolume->MountPoint;
  207 
  208                 wstring args = StringFormatter (repair ? L"/C echo {0} & chkdsk {1} /F /X & pause" : L"/C echo {0} & chkdsk {1} & pause",
  209                     StringFormatter (LangString[repair ? "REPAIRING_FS" : "CHECKING_FS"], mountPoint), mountPoint);
  210 
  211                 ShellExecute (static_cast <HWND> (GetHandle()),
  212                     L"runas",
  213                     L"cmd.exe", args.c_str(), nullptr, SW_SHOW);
  214 #else
  215 #   ifdef TC_MACOSX
  216                 Gui->ShowInfo (_("Disk Utility will be launched after you press 'OK'.\n\nPlease select your volume in the Disk Utility window and press 'Verify Disk' or 'Repair Disk' button on the 'First Aid' page."));
  217 #   endif
  218                 Core->CheckFilesystem (selectedVolume, repair);
  219                 UpdateVolumeList();
  220 #endif
  221             }
  222             catch (exception &e)
  223             {
  224                 Gui->ShowError (e);
  225             }
  226         }
  227     }
  228 
  229     bool MainFrame::CheckVolumePathNotEmpty () const
  230     {
  231         if (VolumePathComboBox->GetValue().empty())
  232         {
  233             Gui->ShowInfo ("NO_VOLUME_SELECTED");
  234             return false;
  235         }
  236         return true;
  237     }
  238 
  239     void MainFrame::DismountVolume (shared_ptr <VolumeInfo> volume)
  240     {
  241         try
  242         {
  243             if (!volume)
  244                 volume = GetSelectedVolume();
  245 
  246             if (volume)
  247                 Gui->DismountVolume (volume);
  248         }
  249         catch (exception &e)
  250         {
  251             Gui->ShowError (e);
  252         }
  253     }
  254 
  255     shared_ptr <VolumeInfo> MainFrame::GetSelectedVolume () const
  256     {
  257         return Core->GetMountedVolume (SelectedSlotNumber);
  258     }
  259 
  260     void MainFrame::InitControls ()
  261     {
  262         LogoBitmap->SetBitmap (Resources::GetLogoBitmap());
  263 
  264         list <int> colPermilles;
  265 
  266 #ifndef TC_WINDOWS
  267         SettingsMenu->Remove (HotkeysMenuItem);
  268 #endif
  269 
  270 #ifdef TC_MACOSX
  271         SettingsMenu->Remove (PreferencesMenuItem);
  272         SettingsMenu->AppendSeparator();
  273         SettingsMenu->Append (PreferencesMenuItem);
  274 
  275         LowStaticBoxSizer->Detach (HigherButtonSizer);
  276         VolumeStaticBoxSizer->Detach (VolumeGridBagSizer);
  277         VolumeStaticBoxSizer->Add (VolumeGridBagSizer, 1, wxEXPAND, 0);
  278 
  279         ExitButton->SetLabel (_("Close"));
  280         MountAllDevicesButton->SetLabel (_("Mount All Devices"));
  281 #endif
  282 
  283 #ifdef TC_WINDOWS
  284         SlotListCtrl->InsertColumn (ColumnSlot, LangString["DRIVE"], wxLIST_FORMAT_LEFT, 1);
  285         colPermilles.push_back (75);
  286 #else
  287         SlotListCtrl->InsertColumn (ColumnSlot, _("Slot"), wxLIST_FORMAT_LEFT, 1);
  288         colPermilles.push_back (82);
  289 #endif
  290 
  291         SlotListCtrl->InsertColumn (ColumnPath, LangString["VOLUME"], wxLIST_FORMAT_LEFT, 1);
  292 #ifdef TC_WINDOWS
  293         colPermilles.push_back (487);
  294 #else
  295         colPermilles.push_back (429);
  296 #endif
  297 
  298         SlotListCtrl->InsertColumn (ColumnSize, LangString["SIZE"], wxLIST_FORMAT_RIGHT, 1);
  299 #ifdef TC_WINDOWS
  300         colPermilles.push_back (126);
  301 #else
  302         colPermilles.push_back (130);
  303 #endif
  304 
  305 #ifdef TC_WINDOWS
  306         SlotListCtrl->InsertColumn (ColumnEA, LangString["ENCRYPTION_ALGORITHM_LV"], wxLIST_FORMAT_LEFT, 1);
  307         colPermilles.push_back (233);
  308 #else
  309         SlotListCtrl->InsertColumn (ColumnMountPoint, LangString["MOUNT_POINT"], wxLIST_FORMAT_LEFT, 1);
  310         colPermilles.push_back (259);
  311 #endif
  312 
  313         SlotListCtrl->InsertColumn (ColumnType, LangString["TYPE"], wxLIST_FORMAT_LEFT, 1);
  314         colPermilles.push_back (100);
  315 
  316         wxImageList *imageList = new wxImageList (16, 12, true);
  317         imageList->Add (Resources::GetDriveIconBitmap(), Resources::GetDriveIconMaskBitmap());
  318         SlotListCtrl->AssignImageList (imageList, wxIMAGE_LIST_SMALL);
  319 
  320         SetMinSize (wxSize (-1, -1));
  321 
  322         size_t slotListRowCount = 12;
  323 
  324 #ifndef TC_WINDOWS
  325         int screenHeight = wxSystemSettings::GetMetric (wxSYS_SCREEN_Y);
  326 
  327         if (screenHeight < 480)
  328             slotListRowCount = 1;
  329         else if (screenHeight <= 600)
  330             slotListRowCount = slotListRowCount * screenHeight / 1000;
  331 #endif
  332 
  333         Gui->SetListCtrlHeight (SlotListCtrl, slotListRowCount);
  334 
  335 #ifdef __WXGTK__
  336         wxSize size (-1, (int) ((double) Gui->GetCharHeight (this) * 1.53));
  337         CreateVolumeButton->SetMinSize (size);
  338         VolumePropertiesButton->SetMinSize (size);
  339         WipeCacheButton->SetMinSize (size);
  340         VolumePathComboBox->SetMinSize (size);
  341         SelectFileButton->SetMinSize (size);
  342         SelectDeviceButton->SetMinSize (size);
  343         VolumeToolsButton->SetMinSize (size);
  344         size = wxSize (-1, 38);
  345         VolumeButton->SetMinSize (size);
  346 #endif
  347         Fit();
  348         Layout();
  349         Center();
  350 
  351         VolumePathComboBox->SetMinSize (VolumePathComboBox->GetSize());
  352         VolumePathComboBox->SetMaxSize (VolumePathComboBox->GetSize());
  353 
  354         SetMinSize (GetSize());
  355         SetMaxSize (GetSize());
  356 
  357         Gui->SetListCtrlColumnWidths (SlotListCtrl, colPermilles);
  358 
  359         UpdateVolumeList();
  360         UpdateWipeCacheButton();
  361     }
  362 
  363     void MainFrame::InitEvents ()
  364     {
  365         Core->VolumeMountedEvent.Connect (EventConnector <MainFrame> (this, &MainFrame::OnVolumeMounted));
  366         Core->VolumeDismountedEvent.Connect (EventConnector <MainFrame> (this, &MainFrame::OnVolumeDismounted));
  367         Gui->OpenVolumeSystemRequestEvent.Connect (EventConnector <MainFrame> (this, &MainFrame::OnOpenVolumeSystemRequestEvent));
  368         Gui->PreferencesUpdatedEvent.Connect (EventConnector <MainFrame> (this, &MainFrame::OnPreferencesUpdatedEvent));
  369 
  370         // Drag & drop
  371         class FileDropTarget : public wxFileDropTarget
  372         {
  373         public:
  374             FileDropTarget (MainFrame *frame) : Frame (frame) { }
  375 
  376             wxDragResult OnDragOver (wxCoord x, wxCoord y, wxDragResult def)
  377             {
  378                 wxPoint p;
  379                 wxWindow *w = wxFindWindowAtPointer (p);
  380                 if (w == Frame || wxGetTopLevelParent (w) == Frame)
  381                     return wxDragLink;
  382                 return wxDragNone;
  383             }
  384 
  385             bool OnDropFiles (wxCoord x, wxCoord y, const wxArrayString &filenames)
  386             {
  387                 if (!filenames.empty())
  388                     Frame->SetVolumePath (wstring (filenames.front()));
  389                 return true;
  390             }
  391 
  392             MainFrame *Frame;
  393         };
  394 
  395         SetDropTarget (new FileDropTarget (this));
  396 #ifdef TC_MACOSX
  397         foreach (wxWindow *c, MainPanel->GetChildren())
  398             c->SetDropTarget (new FileDropTarget (this));
  399 #endif
  400 
  401         // Volume history
  402         VolumeHistory::ConnectComboBox (VolumePathComboBox);
  403 
  404 #ifdef TC_WINDOWS
  405         // Hotkeys
  406         Hotkey::RegisterList (this, GetPreferences().Hotkeys);
  407         Connect (wxEVT_HOTKEY, wxKeyEventHandler (MainFrame::OnHotkey));
  408 #endif
  409 
  410         // Timer
  411         class Timer : public wxTimer
  412         {
  413         public:
  414             Timer (MainFrame *frame) : Frame (frame) { }
  415 
  416             void Notify()
  417             {
  418                 Frame->OnTimer();
  419             }
  420 
  421             MainFrame *Frame;
  422         };
  423 
  424         mTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
  425         mTimer->Start (2000);
  426     }
  427 
  428 #ifdef TC_WINDOWS
  429 #include <dbt.h>
  430     static WNDPROC MainFrameWndProc;
  431     static LRESULT CALLBACK MainFrameWndProcFilter (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  432     {
  433         if (message == WM_DEVICECHANGE && !Core->IsDeviceChangeInProgress())
  434         {
  435             MainFrame *frame = dynamic_cast <MainFrame *> (Gui->GetMainFrame());
  436             PDEV_BROADCAST_HDR hdr = (PDEV_BROADCAST_HDR) lParam;
  437 
  438             if (wParam == DBT_DEVICEREMOVECOMPLETE && hdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
  439             {
  440                 PDEV_BROADCAST_VOLUME vol = (PDEV_BROADCAST_VOLUME) lParam;
  441                 for (wchar_t driveNo = 0; driveNo < 26; ++driveNo)
  442                 {
  443                     if (vol->dbcv_unitmask & (1 << driveNo))
  444                         frame->OnDeviceChange (wstring (StringFormatter (L"{0}:\\", wchar_t (L'A' + driveNo))));
  445                 }
  446             }
  447             else
  448             {
  449                 frame->OnDeviceChange ();
  450             }
  451         }
  452 
  453         return CallWindowProc (MainFrameWndProc, hwnd, message, wParam, lParam);
  454     }
  455 #endif
  456 
  457     void MainFrame::InitMessageFilter ()
  458     {
  459 #ifdef TC_WINDOWS
  460         HWND mainFrameHwnd = static_cast <HWND> (GetHandle());
  461         MainFrameWndProc = (WNDPROC) GetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC);
  462         SetWindowLongPtr (mainFrameHwnd, GWL_WNDPROC, (LONG_PTR) MainFrameWndProcFilter);
  463 #endif
  464     }
  465 
  466     void MainFrame::InitPreferences ()
  467     {
  468         try
  469         {
  470             LoadPreferences();
  471 
  472             VolumeSlotNumber lastSelectedSlotNumber = GetPreferences().LastSelectedSlotNumber;
  473             if (Core->IsSlotNumberValid (lastSelectedSlotNumber))
  474             {
  475                 long slotIndex = SlotNumberToItemIndex (lastSelectedSlotNumber);
  476                 if (slotIndex >= 0)
  477                 {
  478                     SlotListCtrl->SetItemState (slotIndex, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
  479                     SlotListCtrl->EnsureVisible (slotIndex);
  480                 }
  481             }
  482 
  483             LoadFavoriteVolumes();
  484             VolumeHistory::Load();
  485 
  486             if (VolumePathComboBox->GetValue().empty() && !VolumeHistory::Get().empty())
  487                 SetVolumePath (VolumeHistory::Get().front());
  488         }
  489         catch (exception &e)
  490         {
  491             Gui->ShowError (e);
  492             Gui->ShowError (_("Error while loading configuration files located in ") + wstring (Application::GetConfigFilePath (L"")));
  493         }
  494     }
  495 
  496     void MainFrame::InitTaskBarIcon ()
  497     {
  498         class TaskBarIcon : public wxTaskBarIcon
  499         {
  500         public:
  501             TaskBarIcon (MainFrame *frame) : Busy (false), Frame (frame)
  502             {
  503                 Connect (wxEVT_TASKBAR_LEFT_DOWN, wxTaskBarIconEventHandler (TaskBarIcon::OnLeftButtonDown));
  504             }
  505 
  506             wxMenu *CreatePopupMenu ()
  507             {
  508                 auto_ptr <wxMenu> popup (new wxMenu);
  509 
  510                 Gui->AppendToMenu (*popup, LangString[Gui->IsInBackgroundMode() ? "SHOW_TC" : "HIDE_TC"], this, wxCommandEventHandler (TaskBarIcon::OnShowHideMenuItemSelected));
  511 
  512                 popup->AppendSeparator();
  513                 Gui->AppendToMenu (*popup, _("Mount All Favorite Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnMountAllFavoritesMenuItemSelected))->Enable (!Busy);
  514                 Gui->AppendToMenu (*popup, _("Dismount All Mounted Volumes"), this, wxCommandEventHandler (TaskBarIcon::OnDismountAllMenuItemSelected))->Enable (!Busy);
  515 
  516                 // Favorite volumes
  517                 if (Gui->GetPreferences().BackgroundTaskMenuMountItemsEnabled && !Frame->FavoriteVolumesMenuMap.empty())
  518                 {
  519                     popup->AppendSeparator();
  520                     typedef pair <int, FavoriteVolume> FavMapPair;
  521                     foreach (FavMapPair fp, Frame->FavoriteVolumesMenuMap)
  522                     {
  523                         Gui->AppendToMenu (*popup, LangString["MOUNT"] + L" " + wstring (fp.second.Path) + (fp.second.MountPoint.IsEmpty() ? L"" : L"  " + wstring (fp.second.MountPoint)),
  524                             this, wxCommandEventHandler (TaskBarIcon::OnFavoriteVolumeMenuItemSelected), fp.first)->Enable (!Busy);
  525                     }
  526                 }
  527 
  528                 // Mounted volumes
  529                 VolumeInfoList mountedVolumes = Core->GetMountedVolumes();
  530                 if (!mountedVolumes.empty())
  531                 {
  532                     if (Gui->GetPreferences().BackgroundTaskMenuOpenItemsEnabled)
  533                     {
  534                         popup->AppendSeparator();
  535                         OpenMap.clear();
  536                         foreach (shared_ptr <VolumeInfo> volume, mountedVolumes)
  537                         {
  538                             if (!volume->MountPoint.IsEmpty())
  539                             {
  540                                 wxString label = LangString["OPEN"] + L" " + wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")";
  541                                 wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnOpenMenuItemSelected));
  542                                 OpenMap[item->GetId()] = volume;
  543                             }
  544                         }
  545                     }
  546 
  547                     if (Gui->GetPreferences().BackgroundTaskMenuDismountItemsEnabled)
  548                     {
  549                         popup->AppendSeparator();
  550                         DismountMap.clear();
  551                         foreach (shared_ptr <VolumeInfo> volume, mountedVolumes)
  552                         {
  553                             wxString label = LangString["DISMOUNT"] + L" ";
  554 
  555                             if (!volume->MountPoint.IsEmpty())
  556                                 label += wstring (volume->MountPoint) + L" (" + wstring (volume->Path) + L")";
  557                             else
  558                                 label += wstring (volume->Path);
  559 
  560                             wxMenuItem *item = Gui->AppendToMenu (*popup, label, this, wxCommandEventHandler (TaskBarIcon::OnDismountMenuItemSelected));
  561                             item->Enable (!Busy);
  562                             DismountMap[item->GetId()] = volume;
  563                         }
  564                     }
  565                 }
  566 
  567                 popup->AppendSeparator();
  568                 Gui->AppendToMenu (*popup, _("Preferences..."), this, wxCommandEventHandler (TaskBarIcon::OnPreferencesMenuItemSelected))->Enable (!Busy);
  569 #ifndef TC_MACOSX
  570                 popup->AppendSeparator();
  571                 Gui->AppendToMenu (*popup, _("Exit"), this, wxCommandEventHandler (TaskBarIcon::OnExitMenuItemSelected))->Enable (!Busy && Frame->CanExit());
  572 #endif
  573                 return popup.release();
  574             }
  575 
  576             void OnDismountAllMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnDismountAllButtonClick (event); Busy = false; }
  577             void OnDismountMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->DismountVolume (DismountMap[event.GetId()]); Busy = false; }
  578             void OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnFavoriteVolumeMenuItemSelected (event); Busy = false; }
  579             void OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->MountAllFavorites (); Busy = false; }
  580 
  581             void OnExitMenuItemSelected (wxCommandEvent& event)
  582             {
  583                 Busy = true;
  584                 if (Core->GetMountedVolumes().empty() || Gui->AskYesNo (LangString ["CONFIRM_EXIT"], false, true))
  585                     Frame->Close (true);
  586                 Busy = false;
  587             }
  588 
  589             void OnLeftButtonDown (wxTaskBarIconEvent& event) { Gui->SetBackgroundMode (false); }
  590             void OnOpenMenuItemSelected (wxCommandEvent& event) { Gui->OpenExplorerWindow (OpenMap[event.GetId()]->MountPoint); }
  591             void OnPreferencesMenuItemSelected (wxCommandEvent& event) { Busy = true; Frame->OnPreferencesMenuItemSelected (event); Busy = false; }
  592             void OnShowHideMenuItemSelected (wxCommandEvent& event) { Gui->SetBackgroundMode (!Gui->IsInBackgroundMode()); }
  593 
  594             bool Busy;
  595             map < int, shared_ptr <VolumeInfo> > DismountMap;
  596             MainFrame *Frame;
  597             map < int, shared_ptr <VolumeInfo> > OpenMap;
  598         };
  599 
  600         mTaskBarIcon.reset (new TaskBarIcon (this));
  601         ShowTaskBarIcon (GetPreferences().BackgroundTaskEnabled);
  602     }
  603 
  604     void MainFrame::LoadFavoriteVolumes ()
  605     {
  606         typedef pair <int, FavoriteVolume> FavMapPair;
  607         foreach (FavMapPair p, FavoriteVolumesMenuMap)
  608         {
  609             FavoritesMenu->Delete (p.first);
  610         }
  611         FavoriteVolumesMenuMap.clear();
  612 
  613         foreach_ref (const FavoriteVolume &favorite, FavoriteVolume::LoadList())
  614         {
  615             wstring label = wstring (favorite.Path);
  616             if (!favorite.MountPoint.IsEmpty())
  617                 label += wstring (L"   ") + wstring (favorite.MountPoint);
  618 
  619             wxMenuItem *item = Gui->AppendToMenu (*FavoritesMenu, label, this, wxCommandEventHandler (MainFrame::OnFavoriteVolumeMenuItemSelected));
  620             FavoriteVolumesMenuMap[item->GetId()] = favorite;
  621         }
  622     }
  623 
  624     void MainFrame::LoadPreferences ()
  625     {
  626         UserPreferences prefs;
  627         prefs.Load();
  628         Gui->SetPreferences (prefs);
  629         NoHistoryCheckBox->SetValue (!prefs.SaveHistory);
  630     }
  631 
  632     void MainFrame::MountAllDevices ()
  633     {
  634         try
  635         {
  636             MountOptions mountOptions (GetPreferences().DefaultMountOptions);
  637             if (CmdLine->ArgTrueCryptMode)
  638             {
  639                 mountOptions.TrueCryptMode = CmdLine->ArgTrueCryptMode;
  640             }
  641             if (CmdLine->ArgHash)
  642             {
  643                 mountOptions.Kdf = Pkcs5Kdf::GetAlgorithm (*CmdLine->ArgHash, mountOptions.TrueCryptMode);
  644             }
  645             if (CmdLine->ArgPim > 0)
  646             {
  647                 mountOptions.Pim = CmdLine->ArgPim;
  648             }
  649 
  650             if (SlotListCtrl->GetSelectedItemCount() == 1)
  651                 mountOptions.SlotNumber = SelectedSlotNumber;
  652 
  653             Gui->MountAllDeviceHostedVolumes (mountOptions);
  654         }
  655         catch (exception &e)
  656         {
  657             Gui->ShowError (e);
  658         }
  659     }
  660 
  661     void MainFrame::MountAllFavorites ()
  662     {
  663         try
  664         {
  665             MountOptions mountOptions (GetPreferences().DefaultMountOptions);
  666             if (CmdLine->ArgTrueCryptMode)
  667             {
  668                 mountOptions.TrueCryptMode = CmdLine->ArgTrueCryptMode;
  669             }
  670             if (CmdLine->ArgHash)
  671             {
  672                 mountOptions.Kdf = Pkcs5Kdf::GetAlgorithm (*CmdLine->ArgHash, mountOptions.TrueCryptMode);
  673             }
  674             if (CmdLine->ArgPim > 0)
  675             {
  676                 mountOptions.Pim = CmdLine->ArgPim;
  677             }
  678 
  679             Gui->MountAllFavoriteVolumes (mountOptions);
  680         }
  681         catch (exception &e)
  682         {
  683             Gui->ShowError (e);
  684         }
  685     }
  686 
  687     void MainFrame::MountVolume ()
  688     {
  689         if (!IsFreeSlotSelected())
  690         {
  691             Gui->ShowWarning (_("Please select a free drive slot from the list."));
  692             return;
  693         }
  694 
  695         if (!CheckVolumePathNotEmpty())
  696             return;
  697 
  698         MountOptions mountOptions (GetPreferences().DefaultMountOptions);
  699         mountOptions.SlotNumber = SelectedSlotNumber;
  700         mountOptions.Path = GetSelectedVolumePath();
  701         if (CmdLine->ArgTrueCryptMode)
  702         {
  703             mountOptions.TrueCryptMode = CmdLine->ArgTrueCryptMode;
  704         }
  705         if (CmdLine->ArgHash)
  706         {
  707             mountOptions.Kdf = Pkcs5Kdf::GetAlgorithm (*CmdLine->ArgHash, mountOptions.TrueCryptMode);
  708         }
  709         if (CmdLine->ArgPim > 0)
  710         {
  711             mountOptions.Pim = CmdLine->ArgPim;
  712         }
  713 
  714         try
  715         {
  716             if (Gui->MountVolume (mountOptions) && GetPreferences().SaveHistory)
  717                 VolumeHistory::Add (*mountOptions.Path);
  718         }
  719         catch (exception &e)
  720         {
  721             Gui->ShowError (e);
  722         }
  723     }
  724 
  725     void MainFrame::OnAboutMenuItemSelected (wxCommandEvent& event)
  726     {
  727 #ifdef TC_MACOSX
  728         if (Gui->IsInBackgroundMode())
  729             Gui->SetBackgroundMode (false);
  730 #endif
  731         AboutDialog dialog (this);
  732         dialog.ShowModal();
  733     }
  734 
  735     void MainFrame::OnActivate (wxActivateEvent& event)
  736     {
  737         Gui->SetActiveFrame (this);
  738 
  739 #ifdef TC_MACOSX
  740         if (event.GetActive() && Gui->IsInBackgroundMode())
  741             Gui->SetBackgroundMode (false);
  742 #endif
  743         event.Skip();
  744     }
  745 
  746     void MainFrame::OnAddAllMountedToFavoritesMenuItemSelected (wxCommandEvent& event)
  747     {
  748         AddToFavorites (MountedVolumes);
  749     }
  750 
  751     void MainFrame::OnAddToFavoritesMenuItemSelected (wxCommandEvent& event)
  752     {
  753         shared_ptr <VolumeInfo> selectedVolume = GetSelectedVolume();
  754         if (selectedVolume)
  755         {
  756             VolumeInfoList volumes;
  757             volumes.push_back (selectedVolume);
  758             AddToFavorites (volumes);
  759         }
  760     }
  761 
  762     void MainFrame::OnBackupVolumeHeadersMenuItemSelected (wxCommandEvent& event)
  763     {
  764         if (!CheckVolumePathNotEmpty ())
  765             return;
  766 
  767         try
  768         {
  769             Gui->BackupVolumeHeaders (GetSelectedVolumePath());
  770         }
  771         catch (exception &e)
  772         {
  773             Gui->ShowError (e);
  774         }
  775     }
  776 
  777     void MainFrame::OnBenchmarkMenuItemSelected (wxCommandEvent& event)
  778     {
  779 #ifdef TC_MACOSX
  780         if (Gui->IsInBackgroundMode())
  781             Gui->SetBackgroundMode (false);
  782 #endif
  783         BenchmarkDialog dialog (this);
  784         dialog.ShowModal();
  785     }
  786 
  787     void MainFrame::OnClearSlotSelectionMenuItemSelected (wxCommandEvent& event)
  788     {
  789         Gui->ClearListCtrlSelection (SlotListCtrl);
  790         UpdateControls();
  791     }
  792 
  793     void MainFrame::OnClose (wxCloseEvent& event)
  794     {
  795         if (GetPreferences().WipeCacheOnClose)
  796             Core->WipePasswordCache();
  797 
  798 #ifdef TC_MACOSX
  799         if (!event.CanVeto() && GetPreferences().DismountOnLogOff)
  800         {
  801             try
  802             {
  803                 Gui->DismountVolumes (Core->GetMountedVolumes(), GetPreferences().ForceAutoDismount, false);
  804             }
  805             catch (...) { }
  806         }
  807 #endif
  808 
  809         if (!Gui->IsTheOnlyTopLevelWindow (this))
  810         {
  811             // Bring first frame to foreground
  812             wxFrame *frame = nullptr;
  813             foreach (wxWindow *window, wxTopLevelWindows)
  814             {
  815                 if (window != this
  816                     && dynamic_cast <wxFrame *> (window)
  817                     && StringConverter::GetTypeName (typeid (*window)).find ("wxTaskBarIcon") == string::npos)
  818                 {
  819                     frame = dynamic_cast <wxFrame *> (window);
  820                     if (window->IsShown())
  821                         break;
  822                 }
  823             }
  824 
  825             if (frame)
  826             {
  827                 frame->Show();
  828                 if (frame->IsIconized())
  829                     frame->Iconize(false);
  830                 frame->Raise();
  831             }
  832         }
  833         else if (event.CanVeto() && GetPreferences().BackgroundTaskEnabled
  834             && (!GetPreferences().CloseBackgroundTaskOnNoVolumes || !MountedVolumes.empty()))
  835         {
  836             // Enter background mode
  837             if (!Gui->IsInBackgroundMode())
  838                 Gui->SetBackgroundMode (true);
  839         }
  840         else
  841         {
  842 #ifdef __WXGTK__
  843             Show();
  844 #endif
  845             SavePreferences();
  846 
  847             Destroy();
  848         }
  849 
  850          // Cancel close - veto is not used to prevent aborting log off procedure on Windows
  851         return;
  852     }
  853 
  854     void MainFrame::OnCloseAllSecurityTokenSessionsMenuItemSelected (wxCommandEvent& event)
  855     {
  856         try
  857         {
  858             {
  859                 wxBusyCursor busy;
  860                 SecurityToken::CloseAllSessions();
  861             }
  862             Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED");
  863         }
  864         catch (exception &e)
  865         {
  866             Gui->ShowError (e);
  867         }
  868     }
  869 
  870     void MainFrame::OnCreateVolumeButtonClick (wxCommandEvent& event)
  871     {
  872         try
  873         {
  874             (new VolumeCreationWizard (nullptr))->Show();
  875         }
  876         catch (exception &e)
  877         {
  878             Gui->ShowError (e);
  879         }
  880     }
  881 
  882     void MainFrame::OnDefaultKeyfilesMenuItemSelected (wxCommandEvent& event)
  883     {
  884 #ifdef TC_MACOSX
  885         if (Gui->IsInBackgroundMode())
  886             Gui->SetBackgroundMode (false);
  887 #endif
  888         PreferencesDialog dialog (this);
  889         dialog.SelectPage (dialog.DefaultKeyfilesPage);
  890         dialog.ShowModal();
  891     }
  892 
  893     void MainFrame::OnDefaultMountParametersMenuItemSelected(wxCommandEvent& event)
  894     {
  895 #ifdef TC_MACOSX
  896         if (Gui->IsInBackgroundMode())
  897             Gui->SetBackgroundMode (false);
  898 #endif
  899         PreferencesDialog dialog (this);
  900         dialog.SelectPage (dialog.DefaultMountOptionsPage);
  901         dialog.ShowModal();
  902     }
  903 
  904     void MainFrame::OnDeviceChange (const DirectoryPath &mountPoint)
  905     {
  906         // Check if any host device has been removed and force dismount of volumes accordingly
  907         VolumeInfoList removedVolumes;
  908         foreach (shared_ptr <VolumeInfo> volume, Core->GetMountedVolumes())
  909         {
  910             // File-hosted volumes
  911             if (!volume->Path.IsDevice() && !mountPoint.IsEmpty())
  912             {
  913                 if (wxString (wstring(volume->Path)).Upper().StartsWith (wstring (mountPoint).c_str()))
  914                 {
  915                     removedVolumes.push_back (volume);
  916                     continue;
  917                 }
  918             }
  919 
  920             // Device-hosted volumes
  921             if (volume->Path.IsDevice() && !Core->IsDevicePresent (volume->Path))
  922                 removedVolumes.push_back (volume);
  923         }
  924 
  925         if (!removedVolumes.empty())
  926             Gui->AutoDismountVolumes (removedVolumes, true);
  927     }
  928 
  929     void MainFrame::OnDismountAllButtonClick (wxCommandEvent& event)
  930     {
  931         Gui->DismountAllVolumes();
  932     }
  933 
  934     void MainFrame::OnEncryptionTestMenuItemSelected (wxCommandEvent& event)
  935     {
  936 #ifdef TC_MACOSX
  937         if (Gui->IsInBackgroundMode())
  938             Gui->SetBackgroundMode (false);
  939 #endif
  940         EncryptionTestDialog dialog (this);
  941         dialog.ShowModal();
  942     }
  943 
  944     void MainFrame::OnExitButtonClick (wxCommandEvent& event)
  945     {
  946         Close();
  947     }
  948 
  949     void MainFrame::OnFavoriteVolumeMenuItemSelected (wxCommandEvent& event)
  950     {
  951         FavoriteVolume favorite = FavoriteVolumesMenuMap[event.GetId()];
  952         if (!favorite.Path.IsEmpty())
  953         {
  954             SetVolumePath (favorite.Path);
  955 
  956             MountOptions mountOptions (GetPreferences().DefaultMountOptions);
  957             if (CmdLine->ArgTrueCryptMode)
  958             {
  959                 mountOptions.TrueCryptMode = CmdLine->ArgTrueCryptMode;
  960             }
  961             if (CmdLine->ArgHash)
  962             {
  963                 mountOptions.Kdf = Pkcs5Kdf::GetAlgorithm (*CmdLine->ArgHash, mountOptions.TrueCryptMode);
  964             }
  965             if (CmdLine->ArgPim > 0)
  966             {
  967                 mountOptions.Pim = CmdLine->ArgPim;
  968             }
  969             favorite.ToMountOptions (mountOptions);
  970 
  971             shared_ptr <VolumeInfo> volume = Gui->MountVolume (mountOptions);
  972             if (volume)
  973                 SlotListCtrl->EnsureVisible (SlotNumberToItemIndex (volume->SlotNumber));
  974         }
  975     }
  976 
  977     void MainFrame::OnHiddenVolumeProtectionTriggered (shared_ptr <VolumeInfo> protectedVolume)
  978     {
  979         Gui->ShowWarningTopMost (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (protectedVolume->Path)));
  980     }
  981 
  982     void MainFrame::OnHotkey (wxKeyEvent& event)
  983     {
  984 #ifdef TC_WINDOWS
  985         switch (event.GetId())
  986         {
  987         case Hotkey::Id::CloseAllSecurityTokenSessions:
  988             try
  989             {
  990                 SecurityToken::CloseAllSessions();
  991                 Gui->ShowInfo ("ALL_TOKEN_SESSIONS_CLOSED");
  992             }
  993             catch (exception &e) { Gui->ShowError (e); }
  994             break;
  995 
  996         case Hotkey::Id::DismountAll:
  997         case Hotkey::Id::DismountAllWipeCache:
  998             {
  999                 if (event.GetId() == Hotkey::Id::DismountAllWipeCache)
 1000                     WipeCache();
 1001 
 1002                 size_t mountedCount = Core->GetMountedVolumes().size();
 1003                 Gui->DismountAllVolumes();
 1004                 size_t newMountedCount = Core->GetMountedVolumes().size();
 1005 
 1006                 if (newMountedCount < mountedCount)
 1007                 {
 1008                     if (newMountedCount == 0 && GetPreferences().DisplayMessageAfterHotkeyDismount)
 1009                         Gui->ShowInfo ("MOUNTED_VOLUMES_DISMOUNTED");
 1010                     else if (GetPreferences().BeepAfterHotkeyMountDismount)
 1011                         MessageBeep((UINT) -1);
 1012                 }
 1013             }
 1014             break;
 1015 
 1016         case Hotkey::Id::ForceDismountAllWipeCache:
 1017         case Hotkey::Id::ForceDismountAllWipeCacheExit:
 1018             {
 1019                 bool mounted = !Core->GetMountedVolumes().empty();
 1020 
 1021                 WipeCache();
 1022                 Gui->DismountAllVolumes (true, true);
 1023 
 1024                 if (mounted && GetPreferences().DisplayMessageAfterHotkeyDismount)
 1025                     Gui->ShowInfo ("VOLUMES_DISMOUNTED_CACHE_WIPED");
 1026                 else if (mounted && GetPreferences().BeepAfterHotkeyMountDismount)
 1027                     MessageBeep((UINT) -1);
 1028 
 1029                 if (event.GetId() == Hotkey::Id::ForceDismountAllWipeCacheExit)
 1030                     Close (true);
 1031             }
 1032             break;
 1033 
 1034         case Hotkey::Id::MountAllDevices:
 1035         case Hotkey::Id::MountAllFavorites:
 1036             {
 1037                 size_t mountedCount = Core->GetMountedVolumes().size();
 1038 
 1039                 if (event.GetId() == Hotkey::Id::MountAllDevices)
 1040                     MountAllDevices();
 1041                 else
 1042                     MountAllFavorites();
 1043 
 1044                 if (Core->GetMountedVolumes().size() > mountedCount && GetPreferences().BeepAfterHotkeyMountDismount)
 1045                     MessageBeep((UINT) -1);
 1046             }
 1047             break;
 1048 
 1049         case Hotkey::Id::ShowHideApplication:
 1050             Gui->SetBackgroundMode (!Gui->IsInBackgroundMode());
 1051             break;
 1052 
 1053         case Hotkey::Id::WipeCache:
 1054             WipeCache();
 1055             Gui->ShowInfo ("PASSWORD_CACHE_WIPED");
 1056             break;
 1057 
 1058         default:
 1059             assert (false);
 1060             break;
 1061         }
 1062 #endif // TC_WINDOWS
 1063     }
 1064 
 1065     void MainFrame::OnHotkeysMenuItemSelected (wxCommandEvent& event)
 1066     {
 1067 #ifdef TC_MACOSX
 1068         if (Gui->IsInBackgroundMode())
 1069             Gui->SetBackgroundMode (false);
 1070 #endif
 1071         PreferencesDialog dialog (this);
 1072         dialog.SelectPage (dialog.HotkeysPage);
 1073         dialog.ShowModal();
 1074     }
 1075 
 1076     void MainFrame::OnLegalNoticesMenuItemSelected (wxCommandEvent& event)
 1077     {
 1078 #ifdef TC_MACOSX
 1079         if (Gui->IsInBackgroundMode())
 1080             Gui->SetBackgroundMode (false);
 1081 #endif
 1082         LegalNoticesDialog dialog (this);
 1083         dialog.ShowModal();
 1084     }
 1085 
 1086     void MainFrame::OnListChanged ()
 1087     {
 1088         OnListItemSelectionChanged();
 1089         UpdateControls();
 1090     }
 1091 
 1092     void MainFrame::OnListItemActivated (wxListEvent& event)
 1093     {
 1094         if (IsMountedSlotSelected())
 1095             OpenSelectedVolume();
 1096         else
 1097             MountVolume();
 1098     }
 1099 
 1100     void MainFrame::OnListItemDeleted (long itemIndex)
 1101     {
 1102         if (SelectedItemIndex > itemIndex)
 1103             --SelectedItemIndex;
 1104     }
 1105 
 1106     void MainFrame::OnListItemDeselected (wxListEvent& event)
 1107     {
 1108         OnListItemSelectionChanged();
 1109     }
 1110 
 1111     void MainFrame::OnListItemInserted (long itemIndex)
 1112     {
 1113         if (SelectedItemIndex >= itemIndex)
 1114             ++SelectedItemIndex;
 1115     }
 1116 
 1117     void MainFrame::OnListItemRightClick (wxListEvent& event)
 1118     {
 1119 #ifdef TC_MACOSX
 1120         if (SelectedItemIndex != event.GetIndex())
 1121         {
 1122             SelectedItemIndex = event.GetIndex();
 1123             OnListItemSelectionChanged();
 1124         }
 1125 
 1126         if (!ListItemRightClickEventPending)
 1127         {
 1128             ListItemRightClickEventPending = true;
 1129             SlotListCtrl->GetEventHandler()->AddPendingEvent (event);
 1130             return;
 1131         }
 1132 
 1133         ListItemRightClickEventPending = false;
 1134 #endif
 1135 
 1136         wxMenu popup;
 1137         if (IsMountedSlotSelected())
 1138         {
 1139             Gui->AppendToMenu (popup, LangString["DISMOUNT"], this, wxCommandEventHandler (MainFrame::OnDismountVolumeMenuItemSelected));
 1140             Gui->AppendToMenu (popup, LangString["OPEN"], this, wxCommandEventHandler (MainFrame::OnOpenVolumeMenuItemSelected));
 1141             Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected));
 1142 
 1143             popup.AppendSeparator();
 1144             Gui->AppendToMenu (popup, _("Add to Favorites..."), this, wxCommandEventHandler (MainFrame::OnAddToFavoritesMenuItemSelected));
 1145 
 1146             popup.AppendSeparator();
 1147             Gui->AppendToMenu (popup, LangString["IDPM_CHECK_FILESYS"], this, wxCommandEventHandler (MainFrame::OnCheckFilesystemMenuItemSelected));
 1148             Gui->AppendToMenu (popup, LangString["IDPM_REPAIR_FILESYS"], this, wxCommandEventHandler (MainFrame::OnRepairFilesystemMenuItemSelected));
 1149 
 1150             popup.AppendSeparator();
 1151             Gui->AppendToMenu (popup, LangString["IDPM_PROPERTIES"], this, wxCommandEventHandler (MainFrame::OnVolumePropertiesButtonClick));
 1152 
 1153             PopupMenu (&popup);
 1154         }
 1155         else if (IsFreeSlotSelected())
 1156         {
 1157             Gui->AppendToMenu (popup, _("Mount Volume"), this, wxCommandEventHandler (MainFrame::OnMountVolumeMenuItemSelected));
 1158 
 1159             popup.AppendSeparator();
 1160 
 1161             Gui->AppendToMenu (popup, LangString["SELECT_FILE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectFileAndMountMenuItemSelected));
 1162             Gui->AppendToMenu (popup, LangString["SELECT_DEVICE_AND_MOUNT"], this, wxCommandEventHandler (MainFrame::OnSelectDeviceAndMountMenuItemSelected));
 1163 
 1164             popup.AppendSeparator();
 1165 
 1166             Gui->AppendToMenu (popup, _("Deselect"), this, wxCommandEventHandler (MainFrame::OnClearSlotSelectionMenuItemSelected));
 1167 
 1168             PopupMenu (&popup);
 1169         }
 1170     }
 1171 
 1172     void MainFrame::OnListItemSelected (wxListEvent& event)
 1173     {
 1174         SelectedItemIndex = event.GetIndex();
 1175         OnListItemSelectionChanged();
 1176     }
 1177 
 1178     void MainFrame::OnListItemSelectionChanged ()
 1179     {
 1180         if (SlotListCtrl->GetSelectedItemCount() < 1)
 1181             SelectedItemIndex = -1;
 1182 
 1183         if (SelectedItemIndex >= 0)
 1184             SelectedSlotNumber = (VolumeSlotNumber) SlotListCtrl->GetItemData (SelectedItemIndex);
 1185         else
 1186             SelectedSlotNumber = 0;
 1187 
 1188         UpdateControls();
 1189     }
 1190 
 1191     void MainFrame::OnManageSecurityTokenKeyfilesMenuItemSelected (wxCommandEvent& event)
 1192     {
 1193         try
 1194         {
 1195 #ifdef TC_MACOSX
 1196             if (Gui->IsInBackgroundMode())
 1197                 Gui->SetBackgroundMode (false);
 1198 #endif
 1199             SecurityTokenKeyfilesDialog dialog (this, false);
 1200             dialog.ShowModal();
 1201         }
 1202         catch (exception &e)
 1203         {
 1204             Gui->ShowError (e);
 1205         }
 1206     }
 1207 
 1208     void MainFrame::OnMountAllDevicesButtonClick (wxCommandEvent& event)
 1209     {
 1210         MountAllDevices();
 1211     }
 1212 
 1213     void MainFrame::OnMountAllFavoritesMenuItemSelected (wxCommandEvent& event)
 1214     {
 1215         MountAllFavorites();
 1216     }
 1217 
 1218     void MainFrame::OnNoHistoryCheckBoxClick (wxCommandEvent& event)
 1219     {
 1220         UserPreferences prefs = GetPreferences();
 1221         prefs.SaveHistory = !event.IsChecked();
 1222         Gui->SetPreferences (prefs);
 1223 
 1224         if (event.IsChecked())
 1225         {
 1226             try
 1227             {
 1228                 VolumeHistory::Clear();
 1229             }
 1230             catch (exception &e) { Gui->ShowError (e); }
 1231         }
 1232     }
 1233 
 1234     void MainFrame::OnOrganizeFavoritesMenuItemSelected (wxCommandEvent& event)
 1235     {
 1236         try
 1237         {
 1238             OrganizeFavorites (FavoriteVolume::LoadList());
 1239         }
 1240         catch (exception &e)
 1241         {
 1242             Gui->ShowError (e);
 1243         }
 1244     }
 1245 
 1246     void MainFrame::OnPreferencesMenuItemSelected (wxCommandEvent& event)
 1247     {
 1248 #ifdef TC_MACOSX
 1249         if (Gui->IsInBackgroundMode())
 1250             Gui->SetBackgroundMode (false);
 1251 #endif
 1252         PreferencesDialog dialog (this);
 1253         dialog.ShowModal();
 1254     }
 1255 
 1256     void MainFrame::OnOpenVolumeSystemRequest (wxCommandEvent& event)
 1257     {
 1258         wstring* eventPath = (wstring*) event.GetClientData();
 1259         SetVolumePath (*eventPath);
 1260         delete eventPath;
 1261     }
 1262 
 1263     void MainFrame::OnOpenVolumeSystemRequestEvent (EventArgs &args)
 1264     {
 1265         wstring* eventPath = new wstring (dynamic_cast <OpenVolumeSystemRequestEventArgs &> (args).mVolumePath);
 1266         wxCommandEvent* pEvent = new wxCommandEvent( wxEVT_COMMAND_OPEN_VOLUME_REQUEST,0);
 1267         pEvent->SetClientData(eventPath);
 1268         wxQueueEvent (this, pEvent);
 1269     }
 1270 
 1271     void MainFrame::OnPreferencesUpdated (wxCommandEvent& event)
 1272     {
 1273         const UserPreferences &prefs = GetPreferences();
 1274 
 1275         NoHistoryCheckBox->SetValue (!prefs.SaveHistory);
 1276 
 1277         ShowTaskBarIcon (prefs.BackgroundTaskEnabled);
 1278         if (Gui->IsInBackgroundMode() && !prefs.BackgroundTaskEnabled)
 1279             Close (true);
 1280 
 1281         SavePreferences();
 1282     }
 1283 
 1284     void MainFrame::OnRestoreVolumeHeaderMenuItemSelected (wxCommandEvent& event)
 1285     {
 1286         if (!CheckVolumePathNotEmpty ())
 1287             return;
 1288 
 1289         try
 1290         {
 1291             Gui->RestoreVolumeHeaders (GetSelectedVolumePath());
 1292         }
 1293         catch (exception &e)
 1294         {
 1295             Gui->ShowError (e);
 1296         }
 1297     }
 1298 
 1299     void MainFrame::OnSecurityTokenPreferencesMenuItemSelected (wxCommandEvent& event)
 1300     {
 1301 #ifdef TC_MACOSX
 1302         if (Gui->IsInBackgroundMode())
 1303             Gui->SetBackgroundMode (false);
 1304 #endif
 1305         PreferencesDialog dialog (this);
 1306         dialog.SelectPage (dialog.SecurityTokensPage);
 1307         dialog.ShowModal();
 1308     }
 1309 
 1310 
 1311     void MainFrame::OnSelectDeviceAndMountMenuItemSelected (wxCommandEvent& event)
 1312     {
 1313         DevicePath path = Gui->SelectDevice (this);
 1314 
 1315         if (!path.IsEmpty())
 1316         {
 1317             SetVolumePath (path);
 1318             OnMountVolumeMenuItemSelected (event);
 1319         }
 1320     }
 1321 
 1322     void MainFrame::OnSelectDeviceButtonClick (wxCommandEvent& event)
 1323     {
 1324         DevicePath path = Gui->SelectDevice (this);
 1325 
 1326         if (!path.IsEmpty())
 1327             SetVolumePath (path);
 1328     }
 1329 
 1330     void MainFrame::OnSelectFileAndMountMenuItemSelected (wxCommandEvent& event)
 1331     {
 1332         FilePath path = Gui->SelectVolumeFile (this);
 1333 
 1334         if (!path.IsEmpty())
 1335         {
 1336             SetVolumePath (path);
 1337             OnMountVolumeMenuItemSelected (event);
 1338         }
 1339     }
 1340 
 1341     void MainFrame::OnSelectFileButtonClick (wxCommandEvent& event)
 1342     {
 1343         FilePath path = Gui->SelectVolumeFile (this);
 1344         if (!path.IsEmpty())
 1345             SetVolumePath (path);
 1346     }
 1347 
 1348     void MainFrame::OnTimer ()
 1349     {
 1350         try
 1351         {
 1352             UpdateVolumeList();
 1353             UpdateWipeCacheButton();
 1354 
 1355             if (GetPreferences().BackgroundTaskEnabled)
 1356             {
 1357                 // Inactivity auto-dismount
 1358                 if (GetPreferences().DismountOnInactivity)
 1359                 {
 1360                     VolumeInfoList inactiveVolumes;
 1361                     wxLongLong currentTime = wxGetLocalTimeMillis().GetValue();
 1362 
 1363                     map <wstring, VolumeActivityMapEntry> newActivityTimeMap;
 1364 
 1365                     foreach (shared_ptr <VolumeInfo> volume, MountedVolumes)
 1366                     {
 1367                         if (VolumeActivityMap.find (volume->Path) != VolumeActivityMap.end()
 1368                             && VolumeActivityMap[volume->Path].SerialInstanceNumber == volume->SerialInstanceNumber)
 1369                         {
 1370                             VolumeActivityMapEntry ae = VolumeActivityMap[volume->Path];
 1371 
 1372                             if (volume->TotalDataRead != ae.TotalDataRead || volume->TotalDataWritten != ae.TotalDataWritten)
 1373                             {
 1374                                 ae.LastActivityTime = currentTime;
 1375                                 ae.TotalDataRead = volume->TotalDataRead;
 1376                                 ae.TotalDataWritten = volume->TotalDataWritten;
 1377                             }
 1378                             else if ((currentTime - ae.LastActivityTime) > GetPreferences().MaxVolumeIdleTime * 1000LL * 60)
 1379                             {
 1380                                 inactiveVolumes.push_back (volume);
 1381                             }
 1382 
 1383                             newActivityTimeMap[volume->Path] = ae;
 1384                         }
 1385                         else
 1386                         {
 1387                             newActivityTimeMap[volume->Path] = VolumeActivityMapEntry (*volume, currentTime);
 1388                         }
 1389                     }
 1390 
 1391                     VolumeActivityMap = newActivityTimeMap;
 1392 
 1393                     if (!inactiveVolumes.empty())
 1394                         Gui->AutoDismountVolumes (inactiveVolumes);
 1395                 }
 1396 
 1397                 // Screen saver auto-dismount
 1398                 if (GetPreferences().DismountOnScreenSaver)
 1399                 {
 1400 #ifdef TC_WINDOWS
 1401                     bool running;
 1402                     if (SystemParametersInfo (SPI_GETSCREENSAVERRUNNING, 0, &running, 0) != 0)
 1403                     {
 1404                         static bool previousState = false;
 1405                         if (running && !previousState)
 1406                         {
 1407                             previousState = true;
 1408                             Gui->OnAutoDismountAllEvent();
 1409                         }
 1410                         else
 1411                         {
 1412                             previousState = running;
 1413                         }
 1414                     }
 1415 #endif
 1416                 }
 1417             }
 1418 
 1419             if (Gui->IsInBackgroundMode())
 1420             {
 1421                 if (!GetPreferences().BackgroundTaskEnabled)
 1422                 {
 1423                     Close (true);
 1424                 }
 1425                 else if (MountedVolumes.empty() && (GetPreferences().CloseBackgroundTaskOnNoVolumes || Core->IsInPortableMode()))
 1426                 {
 1427                     Close (true);
 1428                 }
 1429             }
 1430 
 1431 #if defined(TC_UNIX) && !defined(TC_MACOSX)
 1432             try
 1433             {
 1434                 byte buf[128];
 1435                 if (read (ShowRequestFifo, buf, sizeof (buf)) > 0 && Gui->IsInBackgroundMode())
 1436                     Gui->SetBackgroundMode (false);
 1437             }
 1438             catch (...)
 1439             {
 1440 #ifdef DEBUG
 1441                 throw;
 1442 #endif
 1443             }
 1444 #endif
 1445         }
 1446         catch (exception &e)
 1447         {
 1448             Gui->ShowError (e);
 1449         }
 1450     }
 1451 
 1452     void MainFrame::OnVolumeButtonClick (wxCommandEvent& event)
 1453     {
 1454         if (IsMountedSlotSelected())
 1455             DismountVolume();
 1456         else
 1457             MountVolume();
 1458     }
 1459 
 1460     void MainFrame::OnVolumePropertiesButtonClick (wxCommandEvent& event)
 1461     {
 1462         shared_ptr <VolumeInfo> selectedVolume = GetSelectedVolume();
 1463         if (selectedVolume)
 1464         {
 1465 #ifdef TC_MACOSX
 1466             if (Gui->IsInBackgroundMode())
 1467                 Gui->SetBackgroundMode (false);
 1468 #endif
 1469             VolumePropertiesDialog dialog (this, *selectedVolume);
 1470             dialog.ShowModal();
 1471         }
 1472     }
 1473 
 1474     void MainFrame::OnVolumeToolsButtonClick (wxCommandEvent& event)
 1475     {
 1476         if (!CheckVolumePathNotEmpty())
 1477             return;
 1478 
 1479         wxMenu popup;
 1480 
 1481         Gui->AppendToMenu (popup, _("Change Volume Password..."), this, wxCommandEventHandler (MainFrame::OnChangePasswordMenuItemSelected));
 1482 
 1483         popup.AppendSeparator ();
 1484 
 1485         Gui->AppendToMenu (popup, _("Add/Remove Keyfiles to/from Volume..."), this, wxCommandEventHandler (MainFrame::OnChangeKeyfilesMenuItemSelected));
 1486         Gui->AppendToMenu (popup, _("Remove All Keyfiles from Volume..."), this, wxCommandEventHandler (MainFrame::OnRemoveKeyfilesMenuItemSelected));
 1487 
 1488         popup.AppendSeparator ();
 1489 
 1490         Gui->AppendToMenu (popup, _("Change Header Key Derivation Algorithm..."), this, wxCommandEventHandler (MainFrame::OnChangePkcs5PrfMenuItemSelected));
 1491 
 1492         popup.AppendSeparator ();
 1493 
 1494         Gui->AppendToMenu (popup, _("Backup Volume Header..."), this, wxCommandEventHandler (MainFrame::OnBackupVolumeHeadersMenuItemSelected));
 1495         Gui->AppendToMenu (popup, _("Restore Volume Header..."), this, wxCommandEventHandler (MainFrame::OnRestoreVolumeHeaderMenuItemSelected));
 1496 
 1497         PopupMenu (&popup, VolumeToolsButton->GetPosition().x + 2, VolumeToolsButton->GetPosition().y + 2);
 1498     }
 1499 
 1500     void MainFrame::OnWipeCacheButtonClick (wxCommandEvent& event)
 1501     {
 1502         WipeCache();
 1503         Gui->ShowInfo ("PASSWORD_CACHE_WIPED");
 1504     }
 1505 
 1506     void MainFrame::OpenSelectedVolume () const
 1507     {
 1508         shared_ptr <VolumeInfo> selectedVolume = GetSelectedVolume();
 1509         if (selectedVolume)
 1510         {
 1511             try
 1512             {
 1513                 wxBusyCursor busy;
 1514                 Gui->OpenExplorerWindow (selectedVolume->MountPoint);
 1515             }
 1516             catch (exception &e)
 1517             {
 1518                 Gui->ShowError (e);
 1519             }
 1520         }
 1521     }
 1522 
 1523     void MainFrame::OrganizeFavorites (const FavoriteVolumeList &favorites, size_t newItemCount)
 1524     {
 1525 #ifdef TC_MACOSX
 1526         if (Gui->IsInBackgroundMode())
 1527             Gui->SetBackgroundMode (false);
 1528 #endif
 1529         FavoriteVolumesDialog dialog (this, favorites, newItemCount);
 1530 
 1531         if (dialog.ShowModal() == wxID_OK)
 1532         {
 1533             FavoriteVolume::SaveList (dialog.GetFavorites());
 1534             LoadFavoriteVolumes();
 1535         }
 1536     }
 1537 
 1538     void MainFrame::SavePreferences () const
 1539     {
 1540         try
 1541         {
 1542             UserPreferences prefs = GetPreferences();
 1543             prefs.LastSelectedSlotNumber = SelectedSlotNumber;
 1544             prefs.Save();
 1545 
 1546             VolumeHistory::Save();
 1547         }
 1548         catch (exception &e)
 1549         {
 1550             if (!Core->IsInPortableMode())
 1551                 Gui->ShowError (e);
 1552         }
 1553     }
 1554 
 1555     void MainFrame::ShowTaskBarIcon (bool show)
 1556     {
 1557         if (!show && mTaskBarIcon->IsIconInstalled())
 1558         {
 1559             mTaskBarIcon->RemoveIcon();
 1560         }
 1561         else if (show && !mTaskBarIcon->IsIconInstalled())
 1562         {
 1563 #ifndef TC_MACOSX
 1564             mTaskBarIcon->SetIcon (Resources::GetVeraCryptIcon(), L"VeraCrypt");
 1565 #endif
 1566         }
 1567     }
 1568 
 1569     long MainFrame::SlotNumberToItemIndex (uint32 slotNumber) const
 1570     {
 1571         for (long itemIndex = 0; itemIndex < SlotListCtrl->GetItemCount(); itemIndex++)
 1572         {
 1573             wxListItem item;
 1574             item.SetId (itemIndex);
 1575             if (slotNumber == (uint32) SlotListCtrl->GetItemData (item))
 1576                 return itemIndex;
 1577         }
 1578         return -1;
 1579     }
 1580 
 1581     void MainFrame::UpdateControls ()
 1582     {
 1583         bool mounted = IsMountedSlotSelected();
 1584 
 1585         VolumeButton->SetLabel (mounted ? LangString["DISMOUNT"] : wxString (_("Mount")));
 1586         VolumePropertiesButton->Enable (mounted);
 1587 
 1588         DismountVolumeMenuItem->Enable (mounted);
 1589         MountVolumeMenuItem->Enable (!mounted);
 1590         VolumePropertiesMenuItem->Enable (mounted);
 1591         AddToFavoritesMenuItem->Enable (mounted);
 1592         AddAllMountedToFavoritesMenuItem->Enable (!MountedVolumes.empty());
 1593         UpdateWipeCacheButton();
 1594     }
 1595 
 1596     void MainFrame::UpdateVolumeList ()
 1597     {
 1598         static Mutex mutex;
 1599         ScopeLock lock (mutex);
 1600 
 1601         bool listChanged = false;
 1602 
 1603         MountedVolumes = Core->GetMountedVolumes();
 1604 
 1605         map < VolumeSlotNumber, shared_ptr <VolumeInfo> > mountedVolumesMap;
 1606         foreach (shared_ptr <VolumeInfo> volume, MountedVolumes)
 1607         {
 1608             mountedVolumesMap[volume->SlotNumber] = volume;
 1609         }
 1610 
 1611         VolumeInfoList protectionTriggeredVolumes;
 1612         SlotListCtrl->SetColumnWidth(0, wxLIST_AUTOSIZE);
 1613 
 1614         // Update list
 1615         long prevItemIndex = -1;
 1616         for (VolumeSlotNumber slotNumber = Core->GetFirstSlotNumber(); slotNumber <= Core->GetLastSlotNumber(); ++slotNumber)
 1617         {
 1618             long itemIndex = SlotNumberToItemIndex (slotNumber);
 1619             vector <wstring> fields (SlotListCtrl->GetColumnCount());
 1620 
 1621             if (mountedVolumesMap.find (slotNumber) != mountedVolumesMap.end())
 1622             {
 1623                 shared_ptr <VolumeInfo> volume = mountedVolumesMap[slotNumber];
 1624 
 1625 #ifdef TC_WINDOWS
 1626                 fields[ColumnSlot] = volume->MountPoint;
 1627                 fields[ColumnEA] = volume->EncryptionAlgorithmName;
 1628 #else
 1629                 fields[ColumnSlot] = StringConverter::FromNumber (slotNumber);
 1630                 fields[ColumnMountPoint] = volume->MountPoint;
 1631 #endif
 1632                 fields[ColumnPath] = volume->Path;
 1633                 fields[ColumnSize] = Gui->SizeToString (volume->Size);
 1634                 fields[ColumnType] = Gui->VolumeTypeToString (volume->Type, volume->TrueCryptMode, volume->Protection);
 1635 
 1636                 if (volume->HiddenVolumeProtectionTriggered)
 1637                 {
 1638                     fields[ColumnType] += L"(!)";
 1639                 }
 1640 
 1641                 bool slotUpdated = false;
 1642                 if (itemIndex == -1)
 1643                 {
 1644                     Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) volume->SlotNumber);
 1645                     OnListItemInserted (prevItemIndex);
 1646 
 1647                     listChanged |= true;
 1648                     slotUpdated = true;
 1649                 }
 1650                 else
 1651                 {
 1652                     if (Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields))
 1653                     {
 1654                         listChanged = true;
 1655                         slotUpdated = true;
 1656                     }
 1657                     prevItemIndex = itemIndex;
 1658                 }
 1659 
 1660                 if (slotUpdated && volume->HiddenVolumeProtectionTriggered)
 1661                     protectionTriggeredVolumes.push_back (volume);
 1662             }
 1663             else
 1664             {
 1665 #ifdef TC_WINDOWS
 1666                 fields[ColumnSlot] = Core->SlotNumberToMountPoint (slotNumber);
 1667 #else
 1668                 fields[ColumnSlot] = StringConverter::FromNumber (slotNumber);
 1669 #endif
 1670 
 1671 #ifdef TC_WINDOWS
 1672                 if (Core->IsMountPointAvailable (fields[ColumnSlot]))
 1673 #else
 1674                 if (true)
 1675 #endif
 1676                 {
 1677                     if (itemIndex == -1)
 1678                     {
 1679                         Gui->InsertToListCtrl (SlotListCtrl, ++prevItemIndex, fields, 0, (void *) slotNumber);
 1680                         OnListItemInserted (prevItemIndex);
 1681                         listChanged |= true;
 1682                     }
 1683                     else
 1684                     {
 1685                         listChanged |= Gui->UpdateListCtrlItem (SlotListCtrl, itemIndex, fields);
 1686                         prevItemIndex = itemIndex;
 1687                     }
 1688                 }
 1689                 else if (itemIndex != -1)
 1690                 {
 1691                     SlotListCtrl->DeleteItem (itemIndex);
 1692                     OnListItemDeleted (itemIndex);
 1693                     listChanged = true;
 1694                 }
 1695             }
 1696         }
 1697 
 1698         if (listChanged)
 1699             OnListChanged();
 1700 
 1701         foreach (shared_ptr <VolumeInfo> volume, protectionTriggeredVolumes)
 1702             OnHiddenVolumeProtectionTriggered (volume);
 1703     }
 1704 
 1705     void MainFrame::UpdateWipeCacheButton ()
 1706     {
 1707         bool enabled = WipeCacheButton->IsEnabled();
 1708         bool empty = Core->IsPasswordCacheEmpty();
 1709 
 1710         if (empty && enabled)
 1711         {
 1712             WipeCacheButton->Disable();
 1713             WipeCachedPasswordsMenuItem->Enable (false);
 1714         }
 1715         else if (!empty && !enabled)
 1716         {
 1717             WipeCacheButton->Enable();
 1718             WipeCachedPasswordsMenuItem->Enable();
 1719         }
 1720     }
 1721 
 1722     void MainFrame::WipeCache ()
 1723     {
 1724         Core->WipePasswordCache();
 1725         UpdateWipeCacheButton();
 1726     }
 1727 }