VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Mount
diff options
context:
space:
mode:
authorMounir IDRASSI <mounir.idrassi@idrix.fr>2015-07-13 15:16:01 +0200
committerMounir IDRASSI <mounir.idrassi@idrix.fr>2015-07-13 23:35:17 +0200
commit52146825de865a2be55bf087f380c3bd0f3182fc (patch)
treeda009f48b09df7c31ae20710e52127aad27598c1 /src/Mount
parenta43a5ebb2136a77be8e79546f329412e4bef14c4 (diff)
downloadVeraCrypt-52146825de865a2be55bf087f380c3bd0f3182fc.tar.gz
VeraCrypt-52146825de865a2be55bf087f380c3bd0f3182fc.zip
Windows: workaround to solve system favorites failing to mount because underlying drive takes long time to be recognized by Windows.
Diffstat (limited to 'src/Mount')
-rw-r--r--src/Mount/Mount.c305
1 files changed, 183 insertions, 122 deletions
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index 3213a693..66941b15 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -8155,33 +8155,34 @@ void ExtractCommandLine (HWND hwndDlg, char *lpszCommandLine)
static SERVICE_STATUS SystemFavoritesServiceStatus;
static SERVICE_STATUS_HANDLE SystemFavoritesServiceStatusHandle;
-
-static void SystemFavoritesServiceLogError (const string &errorMessage)
+static void SystemFavoritesServiceLogMessage (const string &errorMessage, WORD wType)
{
HANDLE eventSource = RegisterEventSource (NULL, TC_SYSTEM_FAVORITES_SERVICE_NAME);
if (eventSource)
{
LPCTSTR strings[] = { TC_SYSTEM_FAVORITES_SERVICE_NAME, errorMessage.c_str() };
- ReportEvent (eventSource, EVENTLOG_ERROR_TYPE, 0, 0xC0000001, NULL, array_capacity (strings), 0, strings, NULL);
+ ReportEvent (eventSource, wType, 0, 0xC0000000 + wType, NULL, array_capacity (strings), 0, strings, NULL);
DeregisterEventSource (eventSource);
}
}
-static void SystemFavoritesServiceLogInfo (const string &errorMessage)
+static void SystemFavoritesServiceLogError (const string &errorMessage)
{
- HANDLE eventSource = RegisterEventSource (NULL, TC_SYSTEM_FAVORITES_SERVICE_NAME);
+ SystemFavoritesServiceLogMessage (errorMessage, EVENTLOG_ERROR_TYPE);
+}
- if (eventSource)
- {
- LPCTSTR strings[] = { TC_SYSTEM_FAVORITES_SERVICE_NAME, errorMessage.c_str() };
- ReportEvent (eventSource, EVENTLOG_INFORMATION_TYPE, 0, 0xC0000002, NULL, array_capacity (strings), 0, strings, NULL);
+static void SystemFavoritesServiceLogWarning (const string &warningMessage)
+{
+ SystemFavoritesServiceLogMessage (warningMessage, EVENTLOG_WARNING_TYPE);
+}
- DeregisterEventSource (eventSource);
- }
+static void SystemFavoritesServiceLogInfo (const string &infoMessage)
+{
+ SystemFavoritesServiceLogMessage (infoMessage, EVENTLOG_INFORMATION_TYPE);
}
static void SystemFavoritesServiceSetStatus (DWORD status, DWORD waitHint = 0)
@@ -8486,12 +8487,141 @@ void DismountIdleVolumes ()
}
}
}
+static BOOL MountFavoriteVolumeBase (const FavoriteVolume &favorite, BOOL& lastbExplore, BOOL& userForcedReadOnly, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount)
+{
+ BOOL status = TRUE;
+ int drive;
+ drive = toupper (favorite.MountPoint[0]) - 'A';
+
+ mountOptions.ReadOnly = favorite.ReadOnly || userForcedReadOnly;
+ mountOptions.Removable = favorite.Removable;
+
+ if (favorite.SystemEncryption)
+ {
+ mountOptions.PartitionInInactiveSysEncScope = TRUE;
+ bPrebootPasswordDlgMode = TRUE;
+ }
+ else
+ {
+ mountOptions.PartitionInInactiveSysEncScope = FALSE;
+ bPrebootPasswordDlgMode = FALSE;
+ }
+
+ if ((LastKnownMountList.ulMountedDrives & (1 << drive)) == 0)
+ {
+ MountVolumesAsSystemFavorite = systemFavorites;
+
+ string mountPoint = (char) (drive + 'A') + string (":\\");
+ char prevVolumeAtMountPoint[MAX_PATH] = { 0 };
+
+ if (systemFavorites)
+ {
+ // Partitions of new drives are assigned free drive letters by Windows on boot. Make sure this does not prevent system favorite volumes
+ // from being mounted. Each partition (using the same drive letter as a system favorite volume) is assigned another free drive letter.
+
+ if (GetVolumeNameForVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint, sizeof (prevVolumeAtMountPoint)))
+ DeleteVolumeMountPoint (mountPoint.c_str());
+ else
+ prevVolumeAtMountPoint[0] = 0;
+ }
+
+ lastbExplore = bExplore;
+
+ bExplore = (BOOL) favorite.OpenExplorerWindow;
+
+ if (!systemFavorites
+ && !logOnMount
+ && !hotKeyMount
+ && !favoriteVolumeToMount.Path.empty()
+ && GetAsyncKeyState (VK_CONTROL) < 0)
+ {
+ /* Priority is given to command line parameters
+ * Default values used only when nothing specified in command line
+ */
+ if (CmdVolumePkcs5 == 0)
+ mountOptions.ProtectedHidVolPkcs5Prf = DefaultVolumePkcs5;
+ else
+ mountOptions.ProtectedHidVolPkcs5Prf = CmdVolumePkcs5;
+ mountOptions.ProtectedHidVolPim = CmdVolumePim;
+ if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), MainDlg, (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions) == IDCANCEL)
+ {
+ status = FALSE;
+ goto skipMount;
+ }
+ }
+
+ BOOL prevReadOnly = mountOptions.ReadOnly;
+
+ if (ServiceMode)
+ SystemFavoritesServiceLogInfo (string ("Mounting system favorite \"") + favorite.Path + "\"");
+
+ status = Mount (MainDlg, drive, (char *) favorite.Path.c_str(), favorite.Pim);
+
+ if (ServiceMode)
+ {
+ // Update the service status to avoid being killed
+ SystemFavoritesServiceStatus.dwCheckPoint++;
+ SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 120000);
+
+ if (status)
+ {
+ SystemFavoritesServiceLogInfo (string ("Favorite \"") + favorite.Path + string ("\" mounted successfully as ") + (char) (drive + 'A') + ":");
+ }
+ else
+ {
+ SystemFavoritesServiceLogError (string ("Favorite \"") + favorite.Path + "\" failed to mount");
+ }
+ }
+
+ if (status && mountOptions.ReadOnly != prevReadOnly)
+ userForcedReadOnly = mountOptions.ReadOnly;
+
+skipMount:
+ bExplore = lastbExplore;
+
+ if (systemFavorites && prevVolumeAtMountPoint[0])
+ {
+ if (status)
+ {
+ int freeDrive = GetFirstAvailableDrive();
+ if (freeDrive != -1)
+ {
+ mountPoint[0] = (char) (freeDrive + 'A');
+ SetVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint);
+ }
+ }
+ else
+ SetVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint);
+ }
+
+ LoadDriveLetters (MainDlg, GetDlgItem (MainDlg, IDC_DRIVELIST), 0);
+
+ MountVolumesAsSystemFavorite = FALSE;
+
+ if (ServiceMode && LastMountedVolumeDirty)
+ {
+ DWORD bytesOut;
+ DeviceIoControl (hDriver, TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY, NULL, 0, NULL, 0, &bytesOut, NULL);
+
+ SystemFavoritesServiceLogError (string ("The filesystem of the volume mounted as ") + (char) (drive + 'A') + ": was not cleanly dismounted and needs to be checked for errors.");
+ }
+ }
+ else if (!systemFavorites && !favoriteVolumeToMount.Path.empty())
+ Error ("DRIVE_LETTER_UNAVAILABLE", MainDlg);
+ else if (ServiceMode && systemFavorites)
+ {
+ SystemFavoritesServiceLogError (string ("The drive letter ") + (char) (drive + 'A') + string (" used by favorite \"") + favorite.Path + "\" is already taken.\nThis system favorite will not be mounted");
+ }
+
+ return status;
+}
+
BOOL MountFavoriteVolumes (BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount)
{
- BOOL bRet = TRUE;
+ BOOL bRet = TRUE, status = TRUE;
BOOL lastbExplore;
BOOL userForcedReadOnly = FALSE;
if (ServiceMode)
@@ -8505,9 +8635,9 @@ BOOL MountFavoriteVolumes (BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMou
VolumePassword.Length = 0;
MultipleMountOperationInProgress = (favoriteVolumeToMount.Path.empty() || FavoriteMountOnArrivalInProgress);
- vector <FavoriteVolume> favorites;
+ vector <FavoriteVolume> favorites, skippedSystemFavorites;
if (systemFavorites)
{
try
@@ -8538,9 +8668,10 @@ BOOL MountFavoriteVolumes (BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMou
foreach (const FavoriteVolume &favorite, favorites)
{
if (ServiceMode && systemFavorites && favorite.DisconnectedDevice)
{
- SystemFavoritesServiceLogError (string ("Favorite \"") + favorite.Path + "\" is disconnected. It will be ignored.");
+ skippedSystemFavorites.push_back (favorite);
+ SystemFavoritesServiceLogWarning (string ("Favorite \"") + favorite.Path + "\" is disconnected. It will be ignored.");
}
if (favorite.DisconnectedDevice
|| (logOnMount && !favorite.MountOnLogOn)
@@ -8548,132 +8679,62 @@ BOOL MountFavoriteVolumes (BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMou
{
continue;
}
- BOOL status = TRUE;
- int drive;
- drive = toupper (favorite.MountPoint[0]) - 'A';
-
- mountOptions.ReadOnly = favorite.ReadOnly || userForcedReadOnly;
- mountOptions.Removable = favorite.Removable;
-
- if (favorite.SystemEncryption)
- {
- mountOptions.PartitionInInactiveSysEncScope = TRUE;
- bPrebootPasswordDlgMode = TRUE;
- }
- else
- {
- mountOptions.PartitionInInactiveSysEncScope = FALSE;
- bPrebootPasswordDlgMode = FALSE;
- }
+ status = MountFavoriteVolumeBase (favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount);
+ if (!status)
+ bRet = FALSE;
+ }
- if ((LastKnownMountList.ulMountedDrives & (1 << drive)) == 0)
+ if (systemFavorites && ServiceMode && !skippedSystemFavorites.empty())
+ {
+ // Some drives need more time to initialize correctly.
+ // We retry 4 times after sleeping 5 seconds
+ int retryCounter = 0;
+ size_t remainingFavorites = skippedSystemFavorites.size();
+ while ((remainingFavorites > 0) && (retryCounter++ < 4))
{
- MountVolumesAsSystemFavorite = systemFavorites;
-
- string mountPoint = (char) (drive + 'A') + string (":\\");
- char prevVolumeAtMountPoint[MAX_PATH] = { 0 };
-
- if (systemFavorites)
- {
- // Partitions of new drives are assigned free drive letters by Windows on boot. Make sure this does not prevent system favorite volumes
- // from being mounted. Each partition (using the same drive letter as a system favorite volume) is assigned another free drive letter.
-
- if (GetVolumeNameForVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint, sizeof (prevVolumeAtMountPoint)))
- DeleteVolumeMountPoint (mountPoint.c_str());
- else
- prevVolumeAtMountPoint[0] = 0;
- }
+ Sleep (5000);
- lastbExplore = bExplore;
+ SystemFavoritesServiceLogInfo (string ("Trying to mount skipped system favorites"));
- bExplore = (BOOL) favorite.OpenExplorerWindow;
+ // Update the service status to avoid being killed
+ SystemFavoritesServiceStatus.dwCheckPoint++;
+ SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 120000);
- if (!systemFavorites
- && !logOnMount
- && !hotKeyMount
- && !favoriteVolumeToMount.Path.empty()
- && GetAsyncKeyState (VK_CONTROL) < 0)
+ for (vector <FavoriteVolume>::iterator favorite = skippedSystemFavorites.begin();
+ favorite != skippedSystemFavorites.end(); favorite++)
{
- /* Priority is given to command line parameters
- * Default values used only when nothing specified in command line
- */
- if (CmdVolumePkcs5 == 0)
- mountOptions.ProtectedHidVolPkcs5Prf = DefaultVolumePkcs5;
- else
- mountOptions.ProtectedHidVolPkcs5Prf = CmdVolumePkcs5;
- mountOptions.ProtectedHidVolPim = CmdVolumePim;
- if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), MainDlg, (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions) == IDCANCEL)
+ if (favorite->DisconnectedDevice)
{
- status = FALSE;
- goto skipMount;
- }
- }
-
- BOOL prevReadOnly = mountOptions.ReadOnly;
-
- if (ServiceMode)
- SystemFavoritesServiceLogInfo (string ("Mounting system favorite \"") + favorite.Path + "\"");
-
- status = Mount (MainDlg, drive, (char *) favorite.Path.c_str(), favorite.Pim);
-
- if (ServiceMode)
- {
- if (status)
- {
- SystemFavoritesServiceLogInfo (string ("Favorite \"") + favorite.Path + string ("\" mounted successfully as ") + (char) (drive + 'A') + ":");
- }
- else
- {
- SystemFavoritesServiceLogError (string ("Favorite \"") + favorite.Path + "\" failed to mount");
- // Update the service status to avoid being killed
- SystemFavoritesServiceStatus.dwCheckPoint++;
- SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 120000);
- }
- }
+ // check if the favorite is here and get its path
+ string resolvedPath = VolumeGuidPathToDevicePath (favorite->Path);
+ if (!resolvedPath.empty())
+ {
+ favorite->DisconnectedDevice = false;
+ favorite->VolumePathId = favorite->Path;
+ favorite->Path = resolvedPath;
- if (status && mountOptions.ReadOnly != prevReadOnly)
- userForcedReadOnly = mountOptions.ReadOnly;
+ remainingFavorites--;
-skipMount:
- bExplore = lastbExplore;
+ // favorite OK.
+ SystemFavoritesServiceLogInfo (string ("Favorite \"") + favorite->VolumePathId + "\" is connected. Performing mount.");
- if (systemFavorites && prevVolumeAtMountPoint[0])
- {
- if (status)
- {
- int freeDrive = GetFirstAvailableDrive();
- if (freeDrive != -1)
- {
- mountPoint[0] = (char) (freeDrive + 'A');
- SetVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint);
+ status = MountFavoriteVolumeBase (*favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount);
+ if (!status)
+ bRet = FALSE;
}
}
- else
- SetVolumeMountPoint (mountPoint.c_str(), prevVolumeAtMountPoint);
}
- LoadDriveLetters (MainDlg, GetDlgItem (MainDlg, IDC_DRIVELIST), 0);
-
- MountVolumesAsSystemFavorite = FALSE;
-
- if (ServiceMode && LastMountedVolumeDirty)
+ if (remainingFavorites == 0)
+ SystemFavoritesServiceLogInfo (string ("All skipped system favorites have been processed"));
+ else
{
- DWORD bytesOut;
- DeviceIoControl (hDriver, TC_IOCTL_SET_SYSTEM_FAVORITE_VOLUME_DIRTY, NULL, 0, NULL, 0, &bytesOut, NULL);
-
- SystemFavoritesServiceLogError (string ("The filesystem of the volume mounted as ") + (char) (drive + 'A') + ": was not cleanly dismounted and needs to be checked for errors.");
+ char szTmp[32];
+ StringCbPrintfA (szTmp, sizeof(szTmp), "%d", (int) remainingFavorites);
+ SystemFavoritesServiceLogWarning (string ("Number of unprocessed system favorites is ") + szTmp);
}
-
- if (!status)
- bRet = FALSE;
- }
- else if (!systemFavorites && !favoriteVolumeToMount.Path.empty())
- Error ("DRIVE_LETTER_UNAVAILABLE", MainDlg);
- else if (ServiceMode && systemFavorites)
- {
- SystemFavoritesServiceLogError (string ("The drive letter ") + (char) (drive + 'A') + string (" used by favorite \"") + favorite.Path + "\" is already taken.\nThis system favorite will not be mounted");
}
}
MultipleMountOperationInProgress = FALSE;