/* Derived from source code of TrueCrypt 7.1a, which is Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2016 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ #include "Tcdefs.h" #include "Platform/Finally.h" #include "Platform/ForEach.h" #include "BootEncryption.h" #include "Dlgcode.h" #include "Language.h" #include "Mount.h" #include "Common/Resource.h" #include "Resource.h" #include "Xml.h" #include "Favorites.h" using namespace std; namespace VeraCrypt { vector FavoriteVolumes; vector SystemFavoriteVolumes; list FavoritesOnArrivalMountRequired; list 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, SRC_POS); return FALSE; } FavoriteVolume favorite; favorite.MountPoint = L"X:\\"; favorite.MountPoint[0] = (wchar_t) (prop.driveNo + L'A'); favorite.Path = prop.wszVolume; if (favorite.Path.find (L"\\??\\") == 0) favorite.Path = favorite.Path.substr (4); if (wcslen (prop.wszLabel)) { favorite.Label = prop.wszLabel; favorite.UseLabelInExplorer = true; } if (IsVolumeDeviceHosted (favorite.Path.c_str())) { // Get GUID path wstring volumeDevPath = favorite.Path; wchar_t resolvedVolumeDevPath[TC_MAX_PATH]; if (ResolveSymbolicLink (volumeDevPath.c_str(), resolvedVolumeDevPath, sizeof(resolvedVolumeDevPath))) volumeDevPath = resolvedVolumeDevPath; wchar_t volumeName[TC_MAX_PATH]; HANDLE find = FindFirstVolume (volumeName, ARRAYSIZE (volumeName)); if (find != INVALID_HANDLE_VALUE) { do { wchar_t findVolumeDevPath[TC_MAX_PATH]; wstring vn = volumeName; if (QueryDosDevice (vn.substr (4, vn.size() - 5).c_str(), findVolumeDevPath, ARRAYSIZE (findVolumeDevPath)) != 0 && volumeDevPath == findVolumeDevPath) { favorite.VolumePathId = volumeName; break; } } while (FindNextVolume (find, volumeName, ARRAYSIZE (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); favorite.Pim = prop.volumePim; memcpy (favorite.VolumeID, prop.volumeID, VOLUME_ID_SIZE); if (favorite.VolumePathId.empty() && IsVolumeDeviceHosted (favorite.Path.c_str()) && favorite.Path.find (L"\\\\?\\Volume{") != 0) { Warning (favorite.Path.find (L"\\Partition0") == wstring::npos ? "FAVORITE_ADD_PARTITION_TYPE_WARNING" : "FAVORITE_ADD_DRIVE_DEV_WARNING", hwndDlg); } 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); WORD hw = HIWORD (wParam); static bool SystemFavoritesMode; static vector 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", SRC_POS); 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 (95), 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 (hwndDlg, 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", hwndDlg); break; } } } FavoriteVolumes = Favorites; ManageStartupSeq(); SaveSettings (hwndDlg); } else SystemFavoriteVolumes = Favorites; OnFavoriteVolumesUpdated(); LoadDriveLetters (hwndDlg, 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(), hwndDlg); if (!IsServerOS() && !IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_DISABLE_HOTKEY)) Info ("SYS_FAVORITES_ADMIN_ONLY_INFO", hwndDlg); } } 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(), hwndDlg); else Warning ("SETTING_REQUIRES_REBOOT", hwndDlg); } return 1; case IDC_FAVORITES_HELP_LINK: Applink (SystemFavoritesMode ? "sysfavorites" : "favorites", TRUE, ""); return 1; case IDC_SHOW_PIM: HandleShowPasswordFieldAction (hwndDlg, IDC_SHOW_PIM, IDC_PIM, 0); return 1; case IDC_PIM: if (hw == EN_CHANGE) { int pim = GetPim (hwndDlg, IDC_PIM); if (pim > (SystemFavoritesMode? MAX_BOOT_PIM_VALUE: MAX_PIM_VALUE)) { SetDlgItemText (hwndDlg, IDC_PIM, L""); SetFocus (GetDlgItem(hwndDlg, IDC_PIM)); Warning (SystemFavoritesMode? "PIM_SYSENC_TOO_BIG": "PIM_TOO_BIG", hwndDlg); return 1; } } break; } 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; case WM_CTLCOLORSTATIC: { HDC hdc = (HDC) wParam; HWND hw = (HWND) lParam; if (hw == GetDlgItem(hwndDlg, IDC_FAVORITE_VOLUME_ID)) { // This the favorite ID field. Make its background like normal edit HBRUSH hbr = GetSysColorBrush (COLOR_WINDOW); ::SelectObject(hdc, hbr); return (BOOL) hbr; } } break; } return 0; } static void FillFavoriteVolumesMenu () { while (DeleteMenu (FavoriteVolumesMenu, 7, MF_BYPOSITION)) { } if (FavoriteVolumes.empty()) return; AppendMenu (FavoriteVolumesMenu, MF_SEPARATOR, 0, L""); int i = 0; foreach (const FavoriteVolume &favorite, FavoriteVolumes) { UINT flags = MF_STRING; if (favorite.DisconnectedDevice) flags |= MF_GRAYED; wstring menuText = 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" + favorite.MountPoint.substr (0, 2)).c_str()); } } static void FillListControl (HWND favoriteListControl, vector &favorites) { SendMessage (favoriteListControl, LVM_DELETEALLITEMS, 0, 0); int line = 0; foreach (const FavoriteVolume favorite, favorites) { ListItemAdd (favoriteListControl, line, (wchar_t *) favorite.MountPoint.substr (0, 2).c_str()); FillListControlSubItems (favoriteListControl, line++, favorite); } } static void FillListControlSubItems (HWND FavoriteListControl, int line, const FavoriteVolume &favorite) { ListSubItemSet (FavoriteListControl, line, 1, (wchar_t *) favorite.Label.c_str()); if (favorite.DisconnectedDevice) ListSubItemSet (FavoriteListControl, line, 2, (wchar_t *) (wstring (L"(") + GetString ("FAVORITE_DISCONNECTED_DEV") + L")").c_str()); else ListSubItemSet (FavoriteListControl, line, 2, (wchar_t *) favorite.Path.c_str()); } wstring GetFavoriteVolumeLabel (const wstring &volumePath, bool& useInExplorer) { foreach (const FavoriteVolume &favorite, FavoriteVolumes) { if (favorite.Path == volumePath) { useInExplorer = favorite.UseLabelInExplorer; return favorite.Label; } } foreach (const FavoriteVolume &favorite, SystemFavoriteVolumes) { if (favorite.Path == volumePath) { useInExplorer = favorite.UseLabelInExplorer; return favorite.Label; } } useInExplorer = false; 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 &favorites, bool systemFavorites, bool noUacElevation) { favorites.clear(); wstring favoritesFilePath = systemFavorites ? GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false) : 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, false).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 = Utf8StringToWide (mountPoint); XmlGetNodeText (xml, volume, sizeof (volume)); favorite.Path = Utf8StringToWide (volume); char label[1024]; XmlGetAttributeText (xml, "ID", label, sizeof (label)); if (strlen (label) == (2*VOLUME_ID_SIZE)) { std::vector arr; if (HexWideStringToArray (Utf8StringToWide (label).c_str(), arr) && arr.size() == VOLUME_ID_SIZE) { memcpy (favorite.VolumeID, &arr[0], VOLUME_ID_SIZE); } } XmlGetAttributeText (xml, "label", label, sizeof (label)); favorite.Label = Utf8StringToWide (label); XmlGetAttributeText (xml, "pim", label, sizeof (label)); if (strlen(label) == 0) { /* support old attribute name before it was changed to PIM*/ XmlGetAttributeText (xml, "pin", label, sizeof (label)); } favorite.Pim = strtol (label, NULL, 10); if (favorite.Pim < 0 || favorite.Pim > (systemFavorites? MAX_BOOT_PIM_VALUE : MAX_PIM_VALUE)) favorite.Pim = 0; 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'); XmlGetAttributeText (xml, "useLabelInExplorer", boolVal, sizeof (boolVal)); if (boolVal[0]) favorite.UseLabelInExplorer = (boolVal[0] == '1') && !favorite.ReadOnly; XmlGetAttributeText (xml, "useVolumeID", boolVal, sizeof (boolVal)); if (boolVal[0]) favorite.UseVolumeID = (boolVal[0] == '1') && !IsRepeatedByteArray (0, favorite.VolumeID, sizeof (favorite.VolumeID)); if (favorite.Path.find (L"\\\\?\\Volume{") == 0 && favorite.Path.rfind (L"}\\") == favorite.Path.size() - 2) { wstring 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; } bool SaveFavoriteVolumes (HWND hwndDlg, const vector &favorites, bool systemFavorites) { FILE *f; int cnt = 0; f = _wfopen (GetConfigPath (systemFavorites ? TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES : TC_APPD_FILENAME_FAVORITE_VOLUMES), L"w,ccs=UTF-8"); if (f == NULL) { handleWin32Error (MainDlg, SRC_POS); return false; } XmlWriteHeader (f); fputws (L"\n\t", f); foreach (const FavoriteVolume &favorite, favorites) { wchar_t tq[2048]; if (systemFavorites && favorite.Path.find (L"\\\\") == 0 && favorite.Path.find (L"Volume{") == wstring::npos) Warning ("SYSTEM_FAVORITE_NETWORK_PATH_ERR", hwndDlg); XmlQuoteTextW (!favorite.VolumePathId.empty() ? favorite.VolumePathId.c_str() : favorite.Path.c_str(), tq, ARRAYSIZE (tq)); wstring s = L"\n\t\t 0) s += L" pim=\"" + IntToWideString(favorite.Pim) + 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\""; if (favorite.UseLabelInExplorer && !favorite.ReadOnly) s += L" useLabelInExplorer=\"1\""; if (favorite.UseVolumeID && !IsRepeatedByteArray (0, favorite.VolumeID, sizeof (favorite.VolumeID))) s += L" useVolumeID=\"1\""; s += L">" + wstring (tq) + L""; fwprintf (f, L"%ws", s.c_str()); cnt++; } fputws (L"\n\t", f); XmlWriteFooter (f); if (!CheckFileStreamWriteErrors (hwndDlg, 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 ({ _wremove (GetConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES)); }); try { bootEnc.DeleteFileAdmin (GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false).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, false).c_str()); if (!(ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_CACHE_BOOT_PASSWORD_FOR_SYS_FAVORITES)) Info ("SYS_FAVORITE_VOLUMES_SAVED", hwndDlg); } } catch (Exception &e) { e.Show (NULL); } } if (cnt == 0) { if (systemFavorites) { try { bootEnc.DeleteFileAdmin (GetServiceConfigPath (TC_APPD_FILENAME_SYSTEM_FAVORITE_VOLUMES, false).c_str()); } catch (...) { } } else _wremove (GetConfigPath (TC_APPD_FILENAME_FAVORITE_VOLUMES)); } return true; } static void SetControls (HWND hwndDlg, const FavoriteVolume &favorite, bool systemFavoritesMode, bool enable) { BOOL bIsDevice = favorite.DisconnectedDevice || IsVolumeDeviceHosted (favorite.Path.c_str()) || !enable; if (favorite.Pim > 0) { wchar_t szTmp[MAX_PIM + 1]; StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", favorite.Pim); SetDlgItemText (hwndDlg, IDC_PIM, szTmp); } else SetDlgItemText (hwndDlg, IDC_PIM, L""); SetDlgItemTextW (hwndDlg, IDC_FAVORITE_LABEL, favorite.Label.c_str()); SetCheckBox (hwndDlg, IDC_FAVORITE_USE_LABEL_IN_EXPLORER, favorite.UseLabelInExplorer); 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); SetCheckBox (hwndDlg, IDC_FAVORITE_USE_VOLUME_ID, favorite.UseVolumeID && bIsDevice); if (IsRepeatedByteArray (0, favorite.VolumeID, sizeof (favorite.VolumeID)) || !bIsDevice) { SetDlgItemText (hwndDlg, IDC_FAVORITE_VOLUME_ID, L""); } else SetDlgItemText (hwndDlg, IDC_FAVORITE_VOLUME_ID, ArrayToHexWideString (favorite.VolumeID, sizeof (favorite.VolumeID)).c_str()); 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_PIM), enable); EnableWindow (GetDlgItem (hwndDlg, IDC_PIM), enable); EnableWindow (GetDlgItem (hwndDlg, IDC_SHOW_PIM), enable); EnableWindow (GetDlgItem (hwndDlg, IDC_PIM_HELP), enable); EnableWindow (GetDlgItem (hwndDlg, IDT_FAVORITE_LABEL), enable); EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_LABEL), enable); EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_USE_LABEL_IN_EXPLORER), 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); EnableWindow (GetDlgItem (hwndDlg, IDT_VOLUME_ID), enable && bIsDevice); EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_VOLUME_ID), enable && bIsDevice); EnableWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_USE_VOLUME_ID), enable && bIsDevice && !IsRepeatedByteArray (0, favorite.VolumeID, sizeof (favorite.VolumeID))); ShowWindow (GetDlgItem (hwndDlg, IDT_VOLUME_ID), bIsDevice? SW_SHOW : SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_VOLUME_ID), bIsDevice? SW_SHOW : SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDC_FAVORITE_USE_VOLUME_ID), bIsDevice? SW_SHOW : SW_HIDE); // Group box RECT boxRect, checkRect, labelRect; GetWindowRect (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), &boxRect); GetWindowRect (GetDlgItem (hwndDlg, IDC_FAVORITE_USE_VOLUME_ID), &checkRect); GetWindowRect (GetDlgItem (hwndDlg, IDT_VOLUME_ID), &labelRect); if (!bIsDevice && (boxRect.top < checkRect.top)) { POINT pt = {boxRect.left, checkRect.bottom}; ScreenToClient (hwndDlg, &pt); SetWindowPos (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), 0, pt.x, pt.y, boxRect.right - boxRect.left, boxRect.bottom - checkRect.bottom, SWP_NOZORDER); InvalidateRect (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), NULL, TRUE); } if (bIsDevice && (boxRect.top >= checkRect.top)) { POINT pt = {boxRect.left, labelRect.top - CompensateYDPI (10)}; ScreenToClient (hwndDlg, &pt); SetWindowPos (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), 0, pt.x, pt.y, boxRect.right - boxRect.left, boxRect.bottom - labelRect.top + CompensateYDPI (10), SWP_NOZORDER); InvalidateRect (GetDlgItem (hwndDlg, IDC_FAV_VOL_OPTIONS_GROUP_BOX), NULL, TRUE); } } 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.Pim = GetPim (hwndDlg, IDC_PIM); favorite.UseLabelInExplorer = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_USE_LABEL_IN_EXPLORER) != 0); favorite.UseVolumeID = (IsDlgButtonChecked (hwndDlg, IDC_FAVORITE_USE_VOLUME_ID) != 0); 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 (L"\\\\?\\Volume{") != 0) { bool partition = (favorite.Path.find (L"\\Partition0") == wstring::npos); if (!favorite.Label.empty()) { ErrorDirect ((GetString (partition ? "FAVORITE_LABEL_PARTITION_TYPE_ERR" : "FAVORITE_LABEL_DEVICE_PATH_ERR") + wstring (L"\n\n") + favorite.Path).c_str(), hwndDlg); 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") + favorite.Path).c_str(), hwndDlg); favorite.MountOnArrival = false; } } if (favorite.MountOnArrival && favorite.Path.find (L"\\\\") == 0 && favorite.Path.find (L"Volume{") == wstring::npos) { Error ("FAVORITE_ARRIVAL_MOUNT_NETWORK_PATH_ERR", hwndDlg); favorite.MountOnArrival = false; } } void UpdateDeviceHostedFavoriteVolumes () { try { LoadFavoriteVolumes(); } catch (Exception &e) { e.Show (MainDlg); } } } (const ChsAddress &chs) { Print (chs.Cylinder); PrintChar ('/'); Print (chs.Head); PrintChar ('/'); Print (chs.Sector); } void PrintSectorCountInMB (const uint64 &sectorCount) { Print (sectorCount >> (TC_LB_SIZE_BIT_SHIFT_DIVISOR + 2)); Print (" MiB "); } BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) { CheckStack(); byte cylinderLow = (byte) chs.Cylinder; byte sector = chs.Sector; sector |= byte (chs.Cylinder >> 2) & 0xc0; byte function = write ? 0x03 : 0x02; BiosResult result; byte tryCount = TC_MAX_BIOS_DISK_IO_RETRIES; do { result = BiosResultSuccess; __asm { push es mov ax, bufferSegment mov es, ax mov bx, bufferOffset mov dl, drive mov ch, cylinderLow mov si, chs mov dh, [si].Head mov cl, sector mov al, sectorCount mov ah, function int 0x13 jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes mov result, ah ok: pop es } if (result == BiosResultEccCorrected) result = BiosResultSuccess; // Some BIOSes report I/O errors prematurely in some cases } while (result != BiosResultSuccess && --tryCount != 0); if (!silent && result != BiosResultSuccess) PrintDiskError (result, write, drive, nullptr, &chs); return result; } #ifdef TC_WINDOWS_BOOT_RESCUE_DISK_MODE BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) { uint16 codeSeg; __asm mov codeSeg, cs return ReadWriteSectors (write, codeSeg, (uint16) buffer, drive, chs, sectorCount, silent); } BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) { return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent); } #if 0 BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) { return ReadWriteSectors (true, buffer, drive, chs, sectorCount, silent); } #endif #endif static BiosResult ReadWriteSectors (bool write, BiosLbaPacket &dapPacket, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { CheckStack(); if (!IsLbaSupported (drive)) { DriveGeometry geometry; BiosResult result = GetDriveGeometry (drive, geometry, silent); if (result != BiosResultSuccess) return result; ChsAddress chs; LbaToChs (geometry, sector, chs); return ReadWriteSectors (write, (uint16) (dapPacket.Buffer >> 16), (uint16) dapPacket.Buffer, drive, chs, sectorCount, silent); } dapPacket.Size = sizeof (dapPacket); dapPacket.Reserved = 0; dapPacket.SectorCount = sectorCount; dapPacket.Sector = sector; byte function = write ? 0x43 : 0x42; BiosResult result; byte tryCount = TC_MAX_BIOS_DISK_IO_RETRIES; do { result = BiosResultSuccess; __asm { mov bx, 0x55aa mov dl, drive mov si, [dapPacket] mov ah, function xor al, al int 0x13 jnc ok // If CF=0, ignore AH to prevent issues caused by potential bugs in BIOSes mov result, ah ok: } if (result == BiosResultEccCorrected) result = BiosResultSuccess; // Some BIOSes report I/O errors prematurely in some cases } while (result != BiosResultSuccess && --tryCount != 0); if (!silent && result != BiosResultSuccess) PrintDiskError (result, write, drive, &sector); return result; } BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { BiosLbaPacket dapPacket; dapPacket.Buffer = (uint32) buffer; return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); } BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { BiosLbaPacket dapPacket; dapPacket.Buffer = ((uint32) bufferSegment << 16) | bufferOffset; return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); } BiosResult ReadSectors (uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { return ReadWriteSectors (false, bufferSegment, bufferOffset, drive, sector, sectorCount, silent); } BiosResult ReadSectors (byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { BiosResult result; uint16 codeSeg; __asm mov codeSeg, cs result = ReadSectors (BootStarted ? codeSeg : TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, drive, sector, sectorCount, silent); // Alternative segment is used to prevent memory corruption caused by buggy BIOSes if (!BootStarted) CopyMemory (TC_BOOT_LOADER_ALT_SEGMENT, (uint16) buffer, buffer, sectorCount * TC_LB_SIZE); return result; } BiosResult WriteSectors (byte *buffer, byte drive, const uint64 &sector, uint16 sectorCount, bool silent) { return ReadWriteSectors (true, buffer, drive, sector, sectorCount, silent); } BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent) { CheckStack(); byte maxCylinderLow, maxHead, maxSector; BiosResult result; __asm { push es mov dl, drive mov ah, 0x08 int 0x13 mov result, ah mov maxCylinderLow, ch mov maxSector, cl mov maxHead, dh pop es } if (result == BiosResultSuccess) { geometry.Cylinders = (maxCylinderLow | (uint16 (maxSector & 0xc0) << 2)) + 1; geometry.Heads = maxHead + 1; geometry.Sectors = maxSector & ~0xc0; } else if (!silent) { Print ("Drive "); Print (drive ^ 0x80); Print (" not found: "); PrintErrorNoEndl (""); Print (result); PrintEndl(); } return result; } void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba) { lba.HighPart = 0; lba.LowPart = (uint32 (chs.Cylinder) * geometry.Heads + chs.Head) * geometry.Sectors + chs.Sector - 1; } void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs) { chs.Sector = (byte) ((lba.LowPart % geometry.Sectors) + 1); uint32 ch = lba.LowPart / geometry.Sectors; chs.Head = (byte) (ch % geometry.Heads); chs.Cylinder = (uint16) (ch / geometry.Heads); } void PartitionEntryMBRToPartition (const PartitionEntryMBR &partEntry, Partition &partition) { partition.Active = partEntry.BootIndicator == 0x80; partition.EndSector.HighPart = 0; partition.EndSector.LowPart = partEntry.StartLBA + partEntry.SectorCountLBA - 1; partition.SectorCount.HighPart = 0; partition.SectorCount.LowPart = partEntry.SectorCountLBA; partition.StartSector.HighPart = 0; partition.StartSector.LowPart = partEntry.StartLBA; partition.Type = partEntry.Type; } BiosResult ReadWriteMBR (bool write, byte drive, bool silent) { uint64 mbrSector; mbrSector.HighPart = 0; mbrSector.LowPart = 0; if (write) return WriteSectors (SectorBuffer, drive, mbrSector, 1, silent); return ReadSectors (SectorBuffer, drive, mbrSector, 1, silent); // Uses alternative segment } BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, Partition *findPartitionFollowingThis, bool silent) { Partition *followingPartition; Partition tmpPartition; if (findPartitionFollowingThis) { assert (partitionArrayCapacity == 1); partitionArrayCapacity = 0xff; followingPartition = partitionArray; partitionArray = &tmpPartition; followingPartition->Drive = TC_INVALID_BIOS_DRIVE; followingPartition->StartSector.LowPart = 0xFFFFffffUL; } AcquireSectorBuffer(); BiosResult result = ReadWriteMBR (false, drive, silent); ReleaseSectorBuffer(); partitionCount = 0; MBR *mbr = (MBR *) SectorBuffer; if (result != BiosResultSuccess || mbr->Signature != 0xaa55) return result; PartitionEntryMBR mbrPartitions[4]; memcpy (mbrPartitions, mbr->Partitions, sizeof (mbrPartitions)); size_t partitionArrayPos = 0, partitionNumber; for (partitionNumber = 0; partitionNumber < array_capacity (mbrPartitions) && partitionArrayPos < partitionArrayCapacity; ++partitionNumber) { const PartitionEntryMBR &partEntry = mbrPartitions[partitionNumber]; if (partEntry.SectorCountLBA > 0) { Partition &partition = partitionArray[partitionArrayPos]; PartitionEntryMBRToPartition (partEntry, partition); if (activeOnly && !partition.Active) continue; partition.Drive = drive; partition.Number = partitionArrayPos; if (partEntry.Type == 0x5 || partEntry.Type == 0xf) // Extended partition { if (IsLbaSupported (drive)) { // Find all extended partitions uint64 firstExtStartLBA = partition.StartSector; uint64 extStartLBA = partition.StartSector; MBR *extMbr = (MBR *) SectorBuffer; while (partitionArrayPos < partitionArrayCapacity && (result = ReadSectors ((byte *) extMbr, drive, extStartLBA, 1, silent)) == BiosResultSuccess && extMbr->Signature == 0xaa55) { if (extMbr->Partitions[0].SectorCountLBA > 0) { Partition &logPart = partitionArray[partitionArrayPos]; PartitionEntryMBRToPartition (extMbr->Partitions[0], logPart); logPart.Drive = drive; logPart.Number = partitionArrayPos; logPart.Primary = false; logPart.StartSector.LowPart += extStartLBA.LowPart; logPart.EndSector.LowPart += extStartLBA.LowPart; if (findPartitionFollowingThis) { if (logPart.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart && logPart.StartSector.LowPart < followingPartition->StartSector.LowPart) { *followingPartition = logPart; } } else ++partitionArrayPos; } // Secondary extended if (extMbr->Partitions[1].Type != 0x5 && extMbr->Partitions[1].Type == 0xf || extMbr->Partitions[1].SectorCountLBA == 0) break; extStartLBA.LowPart = extMbr->Partitions[1].StartLBA + firstExtStartLBA.LowPart; } } } else { partition.Primary = true; if (findPartitionFollowingThis) { if (partition.StartSector.LowPart > findPartitionFollowingThis->EndSector.LowPart && partition.StartSector.LowPart < followingPartition->StartSector.LowPart) { *followingPartition = partition; } } else ++partitionArrayPos; } } } partitionCount = partitionArrayPos; return result; } bool GetActivePartition (byte drive) { size_t partCount; if (GetDrivePartitions (drive, &ActivePartition, 1, partCount, true) != BiosResultSuccess || partCount < 1) { ActivePartition.Drive = TC_INVALID_BIOS_DRIVE; PrintError (TC_BOOT_STR_NO_BOOT_PARTITION); return false; } return true; }