summaryrefslogtreecommitdiff
path: root/Mount/Favorites.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Mount/Favorites.cpp')
-rw-r--r--Mount/Favorites.cpp867
1 files changed, 867 insertions, 0 deletions
diff --git a/Mount/Favorites.cpp b/Mount/Favorites.cpp
new file mode 100644
index 0000000..492eaac
--- /dev/null
+++ b/Mount/Favorites.cpp
@@ -0,0 +1,867 @@
+/*
+ Copyright (c) 2010 TrueCrypt Developers Association. All rights reserved.
+
+ Governed by the TrueCrypt License 3.0 the full text of which is contained in
+ the file License.txt included in TrueCrypt binary and source code distribution
+ packages.
+*/
+
+#include "Tcdefs.h"
+#include "Platform/Finally.h"
+#include "Platform/ForEach.h"
+#include "BootEncryption.h"
+#include "Dlgcode.h"
+#include "Language.h"
+#include "Mount.h"
+#include "Resource.h"
+#include "Xml.h"
+#include "Favorites.h"
+
+using namespace std;
+
+namespace TrueCrypt
+{
+ vector <FavoriteVolume> FavoriteVolumes;
+ vector <FavoriteVolume> SystemFavoriteVolumes;
+ list <FavoriteVolume> FavoritesOnArrivalMountRequired;
+ list <FavoriteVolume> FavoritesMountedOnArrivalStillConnected;
+ HMENU FavoriteVolumesMenu;
+
+
+ BOOL AddMountedVolumeToFavorites (HWND hwndDlg, int driveNo, bool systemFavorites)
+ {
+ VOLUME_PROPERTIES_STRUCT prop;
+ DWORD bytesReturned;
+
+ memset (&prop, 0, sizeof (prop));
+ prop.driveNo = driveNo;
+
+ if (!DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &bytesReturned, NULL))
+ {
+ handleWin32Error (hwndDlg);
+ return FALSE;
+ }
+
+ FavoriteVolume favorite;
+ favorite.MountPoint = "X:\\";
+ favorite.MountPoint[0] = (char) (prop.driveNo + 'A');
+
+ favorite.Path = WideToSingleString ((wchar_t *) prop.wszVolume);
+ if (favorite.Path.find ("\\??\\") == 0)
+ favorite.Path = favorite.Path.substr (4);
+
+ if (IsVolumeDeviceHosted (favorite.Path.c_str()))
+ {
+ // Get GUID path
+ string volumeDevPath = favorite.Path;
+
+ wchar_t resolvedVolumeDevPath[TC_MAX_PATH];
+ if (ResolveSymbolicLink (SingleStringToWide (volumeDevPath).c_str(), resolvedVolumeDevPath))
+ volumeDevPath = WideToSingleString (resolvedVolumeDevPath);
+
+ char volumeName[TC_MAX_PATH];
+ HANDLE find = FindFirstVolume (volumeName, sizeof (volumeName));
+
+ if (find != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ char findVolumeDevPath[TC_MAX_PATH];
+ string vn = volumeName;
+
+ if (QueryDosDevice (vn.substr (4, vn.size() - 5).c_str(), findVolumeDevPath, sizeof (findVolumeDevPath)) != 0
+ && volumeDevPath == findVolumeDevPath)
+ {
+ favorite.VolumePathId = volumeName;
+ break;
+ }
+
+ } while (FindNextVolume (find, volumeName, sizeof (volumeName)));
+
+ FindVolumeClose (find);
+ }
+ }
+
+ favorite.ReadOnly = prop.readOnly ? true : false;
+ favorite.Removable = prop.removable ? true : false;
+ favorite.SystemEncryption = prop.partitionInInactiveSysEncScope ? true : false;
+ favorite.OpenExplorerWindow = (bExplore == TRUE);
+
+ if (favorite.VolumePathId.empty()
+ && IsVolumeDeviceHosted (favorite.Path.c_str())
+ && favorite.Path.find ("\\\\?\\Volume{") != 0)
+ {
+ Warning (favorite.Path.find ("\\Partition0") == string::npos ? "FAVORITE_ADD_PARTITION_TYPE_WARNING" : "FAVORITE_ADD_DRIVE_DEV_WARNING");
+ }
+
+ return OrganizeFavoriteVolumes (hwndDlg, systemFavorites, favorite);
+ }
+
+
+ static BOOL CALLBACK FavoriteVolumesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ /* This dialog is used both for System Favorites and non-system Favorites.
+
+ The following options have different meaning in System Favorites mode:
+
+ IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT => MOUNT_SYSTEM_FAVORITES_ON_BOOT
+ IDC_FAVORITE_DISABLE_HOTKEY => DISABLE_NONADMIN_SYS_FAVORITES_ACCESS
+
+ */
+
+ WORD lw = LOWORD (wParam);
+ static bool SystemFavoritesMode;
+ static vector <FavoriteVolume> Favorites;
+ static int SelectedItem;
+ static HWND FavoriteListControl;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ try
+ {
+ FavoriteListControl = GetDlgItem (hwndDlg, IDC_FAVORITE_VOLUMES_LIST);
+
+ FavoriteVolumesDlgProcArguments *args = (FavoriteVolumesDlgProcArguments *) lParam;
+ SystemFavoritesMode = args->SystemFavorites;
+
+ LocalizeDialog (hwndDlg, SystemFavoritesMode ? "SYSTEM_FAVORITES_DLG_TITLE" : "IDD_FAVORITE_VOLUMES");
+
+ if (SystemFavoritesMode)
+ {
+ RECT rec;
+
+ BootEncryptionStatus bootEncStatus = BootEncryption (hwndDlg).GetStatus();
+
+ if (!bootEncStatus.DriveMounted)
+ throw ErrorException ("SYS_FAVORITES_REQUIRE_PBA");
+
+ ShowWindow (GetDlgItem(hwndDlg, IDC_FAVORITE_MOUNT_ON_LOGON), SW_HIDE);
+ ShowWindow (GetDlgItem(hwndDlg, IDC_FAVORITE_MOUNT_ON_ARRIVAL), SW_HIDE);
+
+ // MOUNT_SYSTEM_FAVORITES_ON_BOOT
+
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT), GetString ("MOUNT_SYSTEM_FAVORITES_ON_BOOT"));
+
+ // DISABLE_NONADMIN_SYS_FAVORITES_ACCESS
+
+ SetWindowTextW (GetDlgItem (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY), GetString ("DISABLE_NONADMIN_SYS_FAVORITES_ACCESS"));
+
+ // Group box
+
+ GetClientRect (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), &rec);
+
+ SetWindowPos (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), 0, 0, 0,
+ rec.right,
+ rec.bottom - CompensateYDPI (90),
+ SWP_NOMOVE | SWP_NOZORDER);
+
+ InvalidateRect (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), NULL, TRUE);
+ }
+ else
+ {
+ ShowWindow (GetDlgItem(hwndDlg, IDC_FAV_VOL_OPTIONS_GLOBAL_SETTINGS_BOX), SW_HIDE);
+ }
+
+ Favorites.clear();
+
+ LVCOLUMNW column;
+ SendMessageW (FavoriteListControl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
+
+ memset (&column, 0, sizeof (column));
+ column.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;
+ column.pszText = GetString ("DRIVE");
+ column.cx = CompensateXDPI (38);
+ column.fmt = LVCFMT_CENTER;
+ SendMessageW (FavoriteListControl, LVM_INSERTCOLUMNW, 1, (LPARAM) &column);
+
+ ++column.iSubItem;
+ column.fmt = LVCFMT_LEFT;
+ column.pszText = GetString ("LABEL");
+ column.cx = CompensateXDPI (160);
+ SendMessageW (FavoriteListControl, LVM_INSERTCOLUMNW, 2, (LPARAM) &column);
+
+ ++column.iSubItem;
+ column.fmt = LVCFMT_LEFT;
+ column.pszText = GetString ("VOLUME");
+ column.cx = CompensateXDPI (330);
+ SendMessageW (FavoriteListControl, LVM_INSERTCOLUMNW, 3, (LPARAM) &column);
+
+ SetControls (hwndDlg, FavoriteVolume(), SystemFavoritesMode, false);
+
+ if (SystemFavoritesMode)
+ LoadFavoriteVolumes (Favorites, true);
+ else
+ Favorites = FavoriteVolumes;
+
+ if (args->AddFavoriteVolume)
+ Favorites.push_back (args->NewFavoriteVolume);
+
+ FillListControl (FavoriteListControl, Favorites);
+
+ SelectedItem = -1;
+
+ if (args->AddFavoriteVolume)
+ {
+ ListView_SetItemState (FavoriteListControl, Favorites.size() - 1, LVIS_SELECTED, LVIS_SELECTED);
+ ListView_EnsureVisible (FavoriteListControl, Favorites.size() - 1, FALSE);
+ }
+
+ if (SystemFavoritesMode)
+ SetDlgItemTextW (hwndDlg, IDC_FAVORITES_HELP_LINK, GetString ("SYS_FAVORITES_HELP_LINK"));
+
+ ToHyperlink (hwndDlg, IDC_FAVORITES_HELP_LINK);
+ }
+ catch (Exception &e)
+ {
+ e.Show (hwndDlg);
+ EndDialog (hwndDlg, IDCLOSE);
+ }
+ }
+ return 1;
+
+ case WM_COMMAND:
+
+ switch (lw)
+ {
+ case IDOK:
+
+ /* Global System Favorites settings */
+
+ if (SystemFavoritesMode)
+ {
+ BootEncryption BootEncObj (NULL);
+
+ if (BootEncObj.GetStatus().DriveMounted)
+ {
+ try
+ {
+ uint32 reqConfig = IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT) ? TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES : 0;
+ if (reqConfig != (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES))
+ BootEncObj.RegisterSystemFavoritesService (reqConfig ? TRUE : FALSE);
+
+ SetDriverConfigurationFlag (TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS, IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY));
+ }
+ catch (Exception &e)
+ {
+ e.Show (hwndDlg);
+ }
+ }
+ }
+
+ /* (System) Favorites list */
+
+ if (SelectedItem != -1 && !Favorites.empty())
+ SetFavoriteVolume (hwndDlg, Favorites[SelectedItem], SystemFavoritesMode);
+
+ if (SaveFavoriteVolumes (Favorites, SystemFavoritesMode))
+ {
+ if (!SystemFavoritesMode)
+ {
+ bMountFavoritesOnLogon = FALSE;
+
+ foreach (const FavoriteVolume &favorite, Favorites)
+ {
+ if (favorite.MountOnLogOn)
+ {
+ bMountFavoritesOnLogon = TRUE;
+ break;
+ }
+ }
+
+ if (!bEnableBkgTask || bCloseBkgTaskWhenNoVolumes || IsNonInstallMode())
+ {
+ foreach (const FavoriteVolume favorite, Favorites)
+ {
+ if (favorite.MountOnArrival)
+ {
+ Warning ("FAVORITE_ARRIVAL_MOUNT_BACKGROUND_TASK_ERR");
+ break;
+ }
+ }
+ }
+
+ FavoriteVolumes = Favorites;
+
+ ManageStartupSeq();
+ SaveSettings (hwndDlg);
+ }
+ else
+ SystemFavoriteVolumes = Favorites;
+
+ OnFavoriteVolumesUpdated();
+ LoadDriveLetters (GetDlgItem (MainDlg, IDC_DRIVELIST), 0);
+
+ EndDialog (hwndDlg, IDOK);
+ }
+
+ return 1;
+
+ case IDCANCEL:
+ EndDialog (hwndDlg, IDCLOSE);
+ return 1;
+
+ case IDC_FAVORITE_MOVE_DOWN:
+ if (SelectedItem != -1 && Favorites.size() > (size_t) SelectedItem + 1)
+ {
+ swap (Favorites[SelectedItem], Favorites[SelectedItem + 1]);
+
+ FillListControl (FavoriteListControl, Favorites);
+ ++SelectedItem;
+ ListView_SetItemState (FavoriteListControl, SelectedItem, LVIS_SELECTED, LVIS_SELECTED);
+ ListView_EnsureVisible (FavoriteListControl, SelectedItem, FALSE);
+ }
+ return 1;
+
+ case IDC_FAVORITE_MOVE_UP:
+ if (SelectedItem > 0)
+ {
+ swap (Favorites[SelectedItem], Favorites[SelectedItem - 1]);
+
+ FillListControl (FavoriteListControl, Favorites);
+ --SelectedItem;
+ ListView_SetItemState (FavoriteListControl, SelectedItem, LVIS_SELECTED, LVIS_SELECTED);
+ ListView_EnsureVisible (FavoriteListControl, SelectedItem, FALSE);
+ }
+ return 1;
+
+ case IDC_FAVORITE_REMOVE:
+ if (SelectedItem != -1)
+ {
+ Favorites.erase (Favorites.begin() + SelectedItem);
+ FillListControl (GetDlgItem (hwndDlg, IDC_FAVORITE_VOLUMES_LIST), Favorites);
+ SetControls (hwndDlg, FavoriteVolume(), SystemFavoritesMode, false);
+ SelectedItem = -1;
+ }
+ return 1;
+
+
+ case IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT: // Note that this option means "MOUNT_SYSTEM_FAVORITES_ON_BOOT" when SystemFavoritesMode is true
+ if (SystemFavoritesMode)
+ {
+ // MOUNT_SYSTEM_FAVORITES_ON_BOOT
+
+ if (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT))
+ {
+ WarningDirect ((wstring (GetString ("SYS_FAVORITES_KEYBOARD_WARNING")) + L"\n\n" + GetString ("BOOT_PASSWORD_CACHE_KEYBOARD_WARNING")).c_str());
+
+ if (!IsServerOS() && !IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY))
+ Info ("SYS_FAVORITES_ADMIN_ONLY_INFO");
+ }
+ }
+ return 1;
+
+ case IDC_FAVORITE_DISABLE_HOTKEY: // Note that this option means "DISABLE_NONADMIN_SYS_FAVORITES_ACCESS" when SystemFavoritesMode is true
+ if (SystemFavoritesMode)
+ {
+ // DISABLE_NONADMIN_SYS_FAVORITES_ACCESS
+
+ if (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY))
+ WarningDirect ((wstring (GetString ("SYS_FAVORITES_ADMIN_ONLY_WARNING")) + L"\n\n" + GetString ("SETTING_REQUIRES_REBOOT")).c_str());
+ else
+ Warning ("SETTING_REQUIRES_REBOOT");
+ }
+ return 1;
+
+ case IDC_FAVORITES_HELP_LINK:
+ Applink (SystemFavoritesMode ? "sysfavorites" : "favorites", TRUE, "");
+ return 1;
+ }
+
+ return 0;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
+ {
+ static bool reentry = false;
+ if (reentry)
+ break;
+
+ reentry = true;
+
+ if (SelectedItem != -1)
+ {
+ SetFavoriteVolume (hwndDlg, Favorites[SelectedItem], SystemFavoritesMode);
+ FillListControlSubItems (FavoriteListControl, SelectedItem, Favorites[SelectedItem]);
+ }
+
+ SelectedItem = ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_FAVORITE_VOLUMES_LIST), -1, LVIS_SELECTED);
+
+ if (SelectedItem != -1)
+ SetControls (hwndDlg, Favorites[SelectedItem], SystemFavoritesMode);
+ else
+ SetControls (hwndDlg, FavoriteVolume(), SystemFavoritesMode, false);
+
+ reentry = false;
+ return 1;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog (hwndDlg, IDCLOSE);
+ return 1;
+ }
+
+ return 0;
+ }
+
+
+ static void FillFavoriteVolumesMenu ()
+ {
+ while (DeleteMenu (FavoriteVolumesMenu, 7, MF_BYPOSITION)) { }
+
+ if (FavoriteVolumes.empty())
+ return;
+
+ AppendMenu (FavoriteVolumesMenu, MF_SEPARATOR, 0, NULL);
+
+ int i = 0;
+ foreach (const FavoriteVolume &favorite, FavoriteVolumes)
+ {
+ UINT flags = MF_STRING;
+
+ if (favorite.DisconnectedDevice)
+ flags |= MF_GRAYED;
+
+ wstring menuText = SingleStringToWide (favorite.Path);
+ if (favorite.DisconnectedDevice)
+ menuText = favorite.Label.empty() ? wstring (L"(") + GetString ("FAVORITE_DISCONNECTED_DEV") + L")" : L"";
+
+ if (!favorite.Label.empty())
+ {
+ if (favorite.DisconnectedDevice)
+ menuText = favorite.Label + L" " + menuText;
+ else
+ menuText = favorite.Label;
+ }
+
+ AppendMenuW (FavoriteVolumesMenu, flags, TC_FAVORITE_MENU_CMD_ID_OFFSET + i++,
+ (menuText + L"\t" + SingleStringToWide (favorite.MountPoint).substr (0, 2)).c_str());
+ }
+ }
+
+
+ static void FillListControl (HWND favoriteListControl, vector <FavoriteVolume> &favorites)
+ {
+ SendMessage (favoriteListControl, LVM_DELETEALLITEMS, 0, 0);
+
+ int line = 0;
+ foreach (const FavoriteVolume favorite, favorites)
+ {
+ ListItemAdd (favoriteListControl, line, (char *) favorite.MountPoint.substr (0, 2).c_str());
+ FillListControlSubItems (favoriteListControl, line++, favorite);
+ }
+ }
+
+
+ static void FillListControlSubItems (HWND FavoriteListControl, int line, const FavoriteVolume &favorite)
+ {
+ ListSubItemSetW (FavoriteListControl, line, 1, (wchar_t *) favorite.Label.c_str());
+
+ if (favorite.DisconnectedDevice)
+ ListSubItemSetW (FavoriteListControl, line, 2, (wchar_t *) (wstring (L"(") + GetString ("FAVORITE_DISCONNECTED_DEV") + L")").c_str());
+ else
+ ListSubItemSet (FavoriteListControl, line, 2, (char *) favorite.Path.c_str());
+ }
+
+
+ wstring GetFavoriteVolumeLabel (const string &volumePath)
+ {
+ foreach (const FavoriteVolume &favorite, FavoriteVolumes)
+ {
+ if (favorite.Path == volumePath)
+ return favorite.Label;
+ }
+
+ foreach (const FavoriteVolume &favorite, SystemFavoriteVolumes)
+ {
+ if (favorite.Path == volumePath)
+ return favorite.Label;
+ }
+
+ return wstring();
+ }
+
+
+ void LoadFavoriteVolumes ()
+ {
+ LoadFavoriteVolumes (FavoriteVolumes, false);
+
+ try
+ {
+ LoadFavoriteVolumes (SystemFavoriteVolumes, true, true);
+ }
+ catch (...) { } // Ignore errors as SystemFavoriteVolumes list is used only for resolving volume paths to labels
+
+ OnFavoriteVolumesUpdated();
+ }
+
+
+ void LoadFavoriteVolumes (vector <FavoriteVolume> &favorites, bool systemFavorites, bool noUacElevation)
+ {
+ favorites.clear();
+ string favoritesFilePath = systemFavorites ? GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES) : GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES);
+
+ if (systemFavorites && !IsAdmin() && !noUacElevation)
+ {
+ favoritesFilePath = GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES);
+
+ try
+ {
+ BootEncryption bootEnc (MainDlg);
+ bootEnc.CopyFileAdmin (GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES).c_str(), favoritesFilePath.c_str());
+ }
+ catch (SystemException &e)
+ {
+ if (e.ErrorCode == ERROR_FILE_NOT_FOUND)
+ return;
+
+ throw;
+ }
+ }
+
+ DWORD size;
+ char *favoritesXml = LoadFile (favoritesFilePath.c_str(), &size);
+
+ if (systemFavorites && !IsAdmin() && !noUacElevation)
+ DeleteFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES));
+
+ char *xml = favoritesXml;
+ char mountPoint[MAX_PATH], volume[MAX_PATH];
+
+ if (xml == NULL)
+ return;
+
+ while (xml = XmlFindElement (xml, "volume"))
+ {
+ FavoriteVolume favorite;
+
+ XmlGetAttributeText (xml, "mountpoint", mountPoint, sizeof (mountPoint));
+ favorite.MountPoint = mountPoint;
+
+ XmlGetNodeText (xml, volume, sizeof (volume));
+ favorite.Path = WideToSingleString (Utf8StringToWide (volume));
+
+ char label[1024];
+ XmlGetAttributeText (xml, "label", label, sizeof (label));
+ favorite.Label = Utf8StringToWide (label);
+
+ char boolVal[2];
+ XmlGetAttributeText (xml, "readonly", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.ReadOnly = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "removable", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.Removable = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "system", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.SystemEncryption = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "noHotKeyMount", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.DisableHotkeyMount = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "openExplorerWindow", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.OpenExplorerWindow = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "mountOnArrival", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.MountOnArrival = (boolVal[0] == '1');
+
+ XmlGetAttributeText (xml, "mountOnLogOn", boolVal, sizeof (boolVal));
+ if (boolVal[0])
+ favorite.MountOnLogOn = (boolVal[0] == '1');
+
+ if (favorite.Path.find ("\\\\?\\Volume{") == 0 && favorite.Path.rfind ("}\\") == favorite.Path.size() - 2)
+ {
+ string resolvedPath = VolumeGuidPathToDevicePath (favorite.Path);
+ if (!resolvedPath.empty())
+ {
+ favorite.DisconnectedDevice = false;
+ favorite.VolumePathId = favorite.Path;
+ favorite.Path = resolvedPath;
+ }
+ else
+ favorite.DisconnectedDevice = true;
+ }
+
+ favorites.push_back (favorite);
+ xml++;
+ }
+
+ free (favoritesXml);
+ }
+
+
+ static void OnFavoriteVolumesUpdated ()
+ {
+ FillFavoriteVolumesMenu();
+
+ FavoritesOnArrivalMountRequired.clear();
+
+ foreach (const FavoriteVolume favorite, FavoriteVolumes)
+ {
+ if (favorite.MountOnArrival)
+ {
+ FavoritesOnArrivalMountRequired.push_back (favorite);
+
+ if (IsMountedVolume (favorite.Path.c_str()))
+ {
+ bool present = false;
+
+ foreach (const FavoriteVolume favoriteConnected, FavoritesMountedOnArrivalStillConnected)
+ {
+ if (favorite.Path == favoriteConnected.Path)
+ {
+ present = true;
+ break;
+ }
+ }
+
+ if (!present)
+ FavoritesMountedOnArrivalStillConnected.push_back (favorite);
+ }
+ }
+ }
+ }
+
+
+ BOOL OrganizeFavoriteVolumes (HWND hwndDlg, bool systemFavorites, const FavoriteVolume &newFavorite)
+ {
+ FavoriteVolumesDlgProcArguments args;
+ args.SystemFavorites = systemFavorites;
+
+ if (!newFavorite.Path.empty())
+ {
+ args.AddFavoriteVolume = true;
+ args.NewFavoriteVolume = newFavorite;
+ }
+ else
+ args.AddFavoriteVolume = false;
+
+ return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_FAVORITE_VOLUMES), hwndDlg, (DLGPROC) FavoriteVolumesDlgProc, (LPARAM) &args) == IDOK;
+ }
+
+
+ static bool SaveFavoriteVolumes (const vector <FavoriteVolume> &favorites, bool systemFavorites)
+ {
+ FILE *f;
+ int cnt = 0;
+
+ f = fopen (GetConfigPath (systemFavorites ? TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES : TC_APPD_FILENAME_FAVORITE_VOLUMES), "w,ccs=UTF-8");
+ if (f == NULL)
+ {
+ handleWin32Error (MainDlg);
+ return false;
+ }
+
+ XmlWriteHeaderW (f);
+ fputws (L"\n\t<favorites>", f);
+
+ foreach (const FavoriteVolume &favorite, favorites)
+ {
+ char tq[2048];
+
+ if (systemFavorites && favorite.Path.find ("\\\\") == 0 && favorite.Path.find ("Volume{") == string::npos)
+ Warning ("SYSTEM_FAVORITE_NETWORK_PATH_ERR");
+
+ XmlQuoteText (!favorite.VolumePathId.empty() ? favorite.VolumePathId.c_str() : favorite.Path.c_str(), tq, sizeof (tq));
+
+ wstring s = L"\n\t\t<volume mountpoint=\"" + SingleStringToWide (favorite.MountPoint) + L"\"";
+
+ if (!favorite.Label.empty())
+ s += L" label=\"" + favorite.Label + L"\"";
+
+ if (favorite.ReadOnly)
+ s += L" readonly=\"1\"";
+
+ if (favorite.Removable)
+ s += L" removable=\"1\"";
+
+ if (favorite.SystemEncryption)
+ s += L" system=\"1\"";
+
+ if (favorite.MountOnArrival)
+ s += L" mountOnArrival=\"1\"";
+
+ if (favorite.MountOnLogOn)
+ s += L" mountOnLogOn=\"1\"";
+
+ if (favorite.DisableHotkeyMount)
+ s += L" noHotKeyMount=\"1\"";
+
+ if (favorite.OpenExplorerWindow)
+ s += L" openExplorerWindow=\"1\"";
+
+ s += L">" + SingleStringToWide (tq) + L"</volume>";
+
+ fwprintf (f, L"%ws", s.c_str());
+ cnt++;
+ }
+
+ fputws (L"\n\t</favorites>", f);
+ XmlWriteFooterW (f);
+
+ if (!CheckFileStreamWriteErrors (f, systemFavorites ? TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES : TC_APPD_FILENAME_FAVORITE_VOLUMES))
+ {
+ fclose (f);
+ return false;
+ }
+
+ fclose (f);
+
+ BootEncryption bootEnc (MainDlg);
+
+ if (systemFavorites)
+ {
+ finally_do ({ remove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); });
+
+ try
+ {
+ bootEnc.DeleteFileAdmin (GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES).c_str());
+ }
+ catch (UserAbort&) { return false; }
+ catch (...) { }
+
+ try
+ {
+ if (cnt != 0)
+ {
+ bootEnc.CopyFileAdmin (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES), GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES).c_str());
+
+ if (!(ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES))
+ Info ("SYS_FAVORITE_VOLUMES_SAVED");
+ }
+ }
+ catch (Exception &e)
+ {
+ e.Show (NULL);
+ }
+ }
+
+ if (cnt == 0)
+ {
+ if (systemFavorites)
+ {
+ try
+ {
+ bootEnc.DeleteFileAdmin (GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES).c_str());
+ }
+ catch (...) { }
+ }
+ else
+ remove (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES));
+ }
+
+ return true;
+ }
+
+
+ static void SetControls (HWND hwndDlg, const FavoriteVolume &favorite, bool systemFavoritesMode, bool enable)
+ {
+ SetDlgItemTextW (hwndDlg, IDC_FAVORITE_LABEL, favorite.Label.c_str());
+ SetCheckBox (hwndDlg, IDC_FAVORITE_MOUNT_ON_LOGON, favorite.MountOnLogOn);
+ SetCheckBox (hwndDlg, IDC_FAVORITE_MOUNT_ON_ARRIVAL, favorite.MountOnArrival);
+ SetCheckBox (hwndDlg, IDC_FAVORITE_MOUNT_READONLY, favorite.ReadOnly);
+ SetCheckBox (hwndDlg, IDC_FAVORITE_MOUNT_REMOVABLE, favorite.Removable);
+
+ if (systemFavoritesMode)
+ {
+ uint32 driverConfig = ReadDriverConfigurationFlags();
+
+ // MOUNT_SYSTEM_FAVORITES_ON_BOOT
+ CheckDlgButton (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT, (driverConfig & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES) ? BST_CHECKED : BST_UNCHECKED);
+
+ // DISABLE_NONADMIN_SYS_FAVORITES_ACCESS
+ CheckDlgButton (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY, (driverConfig & TC_DRIVER_CONFIG_DISABLE_NONADMIN_SYS_FAVORITES_ACCESS) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ else
+ {
+ SetCheckBox (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT, favorite.OpenExplorerWindow);
+ SetCheckBox (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY, favorite.DisableHotkeyMount);
+ }
+
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOVE_UP), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOVE_DOWN), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_REMOVE), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDT_FAVORITE_LABEL), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_LABEL), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOUNT_ON_LOGON), enable && !systemFavoritesMode);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOUNT_ON_ARRIVAL), enable && !systemFavoritesMode);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOUNT_READONLY), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_MOUNT_REMOVABLE), enable);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT), enable || systemFavoritesMode);
+ EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY), enable || systemFavoritesMode);
+ }
+
+
+ static void SetFavoriteVolume (HWND hwndDlg, FavoriteVolume &favorite, bool systemFavoritesMode)
+ {
+ wchar_t label[1024];
+ if (GetDlgItemTextW (hwndDlg, IDC_FAVORITE_LABEL, label, ARRAYSIZE (label)) != 0)
+ {
+ favorite.Label = label;
+
+ for (size_t i = 0; i < favorite.Label.size(); ++i)
+ {
+ if (favorite.Label[i] == L'"')
+ favorite.Label.at (i) = L'\'';
+ }
+ }
+ else
+ favorite.Label.clear();
+
+ favorite.ReadOnly = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_MOUNT_READONLY) != 0);
+ favorite.Removable = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_MOUNT_REMOVABLE) != 0);
+
+ if (!systemFavoritesMode)
+ {
+ favorite.MountOnLogOn = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_MOUNT_ON_LOGON) != 0);
+ favorite.MountOnArrival = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_MOUNT_ON_ARRIVAL) != 0);
+ favorite.DisableHotkeyMount = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY) != 0);
+ favorite.OpenExplorerWindow = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_OPEN_EXPLORER_WIN_ON_MOUNT) != 0);
+ }
+
+ if (favorite.VolumePathId.empty()
+ && IsVolumeDeviceHosted (favorite.Path.c_str())
+ && favorite.Path.find ("\\\\?\\Volume{") != 0)
+ {
+ bool partition = (favorite.Path.find ("\\Partition0") == string::npos);
+
+ if (!favorite.Label.empty())
+ {
+ ErrorDirect ((GetString (partition ? "FAVORITE_LABEL_PARTITION_TYPE_ERR" : "FAVORITE_LABEL_DEVICE_PATH_ERR") + wstring (L"\n\n") + SingleStringToWide (favorite.Path)).c_str());
+ favorite.Label.clear();
+ }
+
+ if (favorite.MountOnArrival)
+ {
+ ErrorDirect ((GetString (partition ? "FAVORITE_ARRIVAL_MOUNT_PARTITION_TYPE_ERR" : "FAVORITE_ARRIVAL_MOUNT_DEVICE_PATH_ERR") + wstring (L"\n\n") + SingleStringToWide (favorite.Path)).c_str());
+ favorite.MountOnArrival = false;
+ }
+ }
+
+ if (favorite.MountOnArrival && favorite.Path.find ("\\\\") == 0 && favorite.Path.find ("Volume{") == string::npos)
+ {
+ Error ("FAVORITE_ARRIVAL_MOUNT_NETWORK_PATH_ERR");
+ favorite.MountOnArrival = false;
+ }
+ }
+
+
+ void UpdateDeviceHostedFavoriteVolumes ()
+ {
+ try
+ {
+ LoadFavoriteVolumes();
+ }
+ catch (Exception &e)
+ {
+ e.Show (MainDlg);
+ }
+ }
+}