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