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