diff --git a/doc/html/en/Command Line Usage for Windows.html b/doc/html/en/Command Line Usage for Windows.html
index bbfa3e3a..9c1ea35b 100644
--- a/doc/html/en/Command Line Usage for Windows.html
+++ b/doc/html/en/Command Line Usage for Windows.html
@@ -111,7 +111,7 @@ If it is followed by n or no: force the displa
| /cancelmount |
-Cancels any currently running mount operation and exits without displaying a status message. The process returns exit code 0 when the cancel request is accepted by the driver, or 1 otherwise. |
+Cancels any currently running mount operation and exits without displaying a status message. The process returns exit code 0 when the cancel request is accepted by the driver, or 1 otherwise. This switch only has an effect while a mount operation is active; if an auto-mount scan is between mount attempts, the scan is not stopped by this command. |
| /secureDesktop |
diff --git a/src/Common/Cmdline.c b/src/Common/Cmdline.c
index 466079fb..a3cf5d07 100644
--- a/src/Common/Cmdline.c
+++ b/src/Common/Cmdline.c
@@ -67,6 +67,7 @@ BOOL CALLBACK CommandHelpDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM
}
#if defined(TCMOUNT) && !defined(VCEXPANDER)
StringCchCatW (tmp, 8192, L"\nExamples:\n\nMount a volume as X:\tveracrypt.exe /q /v volume.hc /l X\nUnmount a volume X:\tveracrypt.exe /q /u X");
+ StringCchCatW (tmp, 8192, L"\n\nNote: /cancelmount requests cancellation of the currently active mount operation only. If auto-mount scanning is between mount attempts, the scan is not stopped by this command.");
#endif
SetWindowTextW (GetDlgItem (hwndDlg, IDC_COMMANDHELP_TEXT), tmp);
diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c
index e54ee739..b133e483 100644
--- a/src/Common/Dlgcode.c
+++ b/src/Common/Dlgcode.c
@@ -8883,8 +8883,6 @@ static UINT g_wmWaitDlg = ::RegisterWindowMessage(L"VeraCryptWaitDlgMessage");
#define WAIT_DLG_CANCEL_RETRY_TIMER_ID 1
#define WAIT_DLG_CANCEL_RETRY_INTERVAL 250
-typedef BOOL (CALLBACK* WaitCancelProc)(void* pArg, HWND hWaitDlg);
-
typedef struct
{
HWND hwnd;
@@ -9064,7 +9062,7 @@ static LRESULT CALLBACK ShowWaitDialogParentWndProc (HWND hWnd, UINT message, WP
}
-static void ShowWaitDialogEx(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, WaitCancelProc cancelCallback, void* pArg)
+void ShowWaitDialogEx(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, WaitCancelProc cancelCallback, void* pArg)
{
BOOL bEffectiveHideWaitingDialog = bCmdHideWaitingDialogValid? bCmdHideWaitingDialog : bHideWaitingDialog;
WaitThreadParam threadParam;
@@ -9512,7 +9510,10 @@ retry:
if (mount.nReturnCode != 0)
{
if (mount.nReturnCode == ERR_USER_ABORT)
+ {
+ SetLastError (ERROR_CANCELLED);
return -1;
+ }
if (mount.nReturnCode == ERR_PASSWORD_WRONG)
{
diff --git a/src/Common/Dlgcode.h b/src/Common/Dlgcode.h
index f4308b8b..c8cdb6df 100644
--- a/src/Common/Dlgcode.h
+++ b/src/Common/Dlgcode.h
@@ -767,7 +767,9 @@ INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::
// Display a wait dialog while calling the provided callback with the given parameter
typedef void (CALLBACK* WaitThreadProc)(void* pArg, HWND hWaitDlg);
+typedef BOOL (CALLBACK* WaitCancelProc)(void* pArg, HWND hWaitDlg);
void BringToForeground(HWND hWnd);
+void ShowWaitDialogEx(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, WaitCancelProc cancelCallback, void* pArg);
void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, void* pArg);
// classes used to implement support for password drag-n-drop from KeePass Password Safe
diff --git a/src/Mount/Favorites.cpp b/src/Mount/Favorites.cpp
index 6be45ed0..c65d94eb 100644
--- a/src/Mount/Favorites.cpp
+++ b/src/Mount/Favorites.cpp
@@ -733,6 +733,7 @@ namespace VeraCrypt
{
FillFavoriteVolumesMenu();
+ ::ClearFavoriteVolumeArrivalMountSuppressions ();
FavoritesOnArrivalMountRequired.clear();
for (const FavoriteVolume& favorite: FavoriteVolumes)
diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c
index a2d22457..9607a9f8 100644
--- a/src/Mount/Mount.c
+++ b/src/Mount/Mount.c
@@ -188,6 +188,273 @@ VOLUME_NOTIFICATIONS_LIST VolumeNotificationsList;
static DWORD LastKnownLogicalDrives;
static volatile LONG FavoriteMountOnGoing = 0;
+static list SuppressedFavoritesOnArrivalMount;
+
+typedef enum
+{
+ MountResultFailed = 0,
+ MountResultSucceeded,
+ MountResultSkipped,
+ MountResultCancelled,
+ MountResultArrivalPasswordPromptDeclined,
+ /* Preserves legacy favorite-on-arrival behavior: a drive-letter conflict is a
+ handled skip so the timer does not repeatedly show the same error while the
+ device remains connected. */
+ MountResultDriveLetterUnavailable
+} MountResult;
+
+typedef struct
+{
+ volatile LONG bAbortRequested;
+ volatile LONG nCurrentMountDriveNo;
+} MountBatchContext;
+
+typedef struct
+{
+ BOOL systemFavorites;
+ BOOL logOnMount;
+ BOOL hotKeyMount;
+ MountBatchContext mountBatch;
+ /* Owned by the thread parameter when non-NULL. */
+ FavoriteVolume* favoriteVolumeToMount;
+} mountFavoriteVolumeThreadParam;
+
+static void __cdecl mountFavoriteVolumeThreadFunction (void *pArg);
+static BOOL MountFavoriteVolumesWithAbort (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount, MountBatchContext* pMountBatch, MountResult* pBatchResult);
+
+
+static void MountBatchInitialize (MountBatchContext* pMountBatch)
+{
+ if (pMountBatch)
+ {
+ InterlockedExchange (&pMountBatch->bAbortRequested, FALSE);
+ InterlockedExchange (&pMountBatch->nCurrentMountDriveNo, -1);
+ }
+}
+
+
+static void MountBatchSetCurrentMountDriveNo (MountBatchContext* pMountBatch, int nDosDriveNo)
+{
+ if (pMountBatch)
+ InterlockedExchange (&pMountBatch->nCurrentMountDriveNo, nDosDriveNo);
+}
+
+
+static void MountBatchClearCurrentMountDriveNo (MountBatchContext* pMountBatch)
+{
+ MountBatchSetCurrentMountDriveNo (pMountBatch, -1);
+}
+
+
+static BOOL MountBatchAbortRequested (MountBatchContext* pMountBatch)
+{
+ return pMountBatch && InterlockedCompareExchange (&pMountBatch->bAbortRequested, 0, 0) != 0;
+}
+
+
+static void MountBatchRequestAbort (MountBatchContext* pMountBatch)
+{
+ if (pMountBatch)
+ InterlockedExchange (&pMountBatch->bAbortRequested, TRUE);
+}
+
+
+static BOOL MountBatchAbortCurrentMountOperation (MountBatchContext* pMountBatch)
+{
+ LONG nDosDriveNo;
+
+ if (!pMountBatch)
+ return FALSE;
+
+ nDosDriveNo = InterlockedCompareExchange (&pMountBatch->nCurrentMountDriveNo, 0, 0);
+
+ /* No mount is registered yet. The abort flag has already been set by the caller,
+ and MountVolumeWithBatchCancel re-checks that flag after publishing the drive
+ number, so the worker is guaranteed to honor it before launching the (possibly
+ long) KDF. Reporting the cancel as handled is therefore safe. */
+ if (nDosDriveNo < 0)
+ return TRUE;
+
+ return AbortMountOperation ((int) nDosDriveNo);
+}
+
+
+/* Shared wait-dialog cancel handler for batch mount operations: requests the batch abort
+ and tries to abort the mount currently in flight. Returns TRUE if the cancel has been
+ fully handled (so the wait dialog can stop retrying). */
+static BOOL MountBatchCancel (MountBatchContext* pMountBatch)
+{
+ MountBatchRequestAbort (pMountBatch);
+ return MountBatchAbortCurrentMountOperation (pMountBatch);
+}
+
+
+/* Returns TRUE if a MountVolume()/MountVolumeWithBatchCancel() result indicates the
+ operation was aborted (either cooperatively through the batch abort flag or through
+ the driver, e.g. an external /cancelmount). Must be called immediately after the
+ mount call, before any other Win32 call clobbers the thread's last-error value. */
+static BOOL MountVolumeWasCancelled (int mountResult)
+{
+ return (mountResult < 0) && (GetLastError () == ERROR_CANCELLED);
+}
+
+
+static int MountVolumeWithBatchCancel (
+ HWND hwndDlg,
+ int nDosDriveNo,
+ wchar_t *szVolFileName,
+ Password *password,
+ int pkcs5,
+ int pim,
+ BOOL cachePassword,
+ BOOL cachePim,
+ BOOL sharedAccess,
+ const MountOptions* const mountOptionsParam,
+ BOOL quiet,
+ BOOL bReportWrongPassword,
+ MountBatchContext* pMountBatch)
+{
+ int mounted;
+
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ SetLastError (ERROR_CANCELLED);
+ return -1;
+ }
+
+ MountBatchSetCurrentMountDriveNo (pMountBatch, nDosDriveNo);
+
+ /* Close the cancel race: the cancel callback sets the abort flag before reading the
+ current drive number, while we publish the drive number before re-reading the flag.
+ This Dekker-style handshake (both sides use full-barrier Interlocked ops) guarantees
+ that either the cancel callback sees our drive number and aborts the driver, or we
+ see the abort flag here and bail out before starting the long mount. */
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ MountBatchClearCurrentMountDriveNo (pMountBatch);
+ SetLastError (ERROR_CANCELLED);
+ return -1;
+ }
+
+ SetLastError (ERROR_SUCCESS);
+ mounted = MountVolume (hwndDlg, nDosDriveNo, szVolFileName, password, pkcs5, pim, cachePassword, cachePim, sharedAccess, mountOptionsParam, quiet, bReportWrongPassword);
+
+ MountBatchClearCurrentMountDriveNo (pMountBatch);
+ return mounted;
+}
+
+
+static bool FavoriteVolumesMatchForArrivalCancel (const FavoriteVolume& left, const FavoriteVolume& right)
+{
+ if (left.UseVolumeID && right.UseVolumeID
+ && !IsRepeatedByteArray (0, left.VolumeID, sizeof (left.VolumeID))
+ && !IsRepeatedByteArray (0, right.VolumeID, sizeof (right.VolumeID)))
+ {
+ return memcmp (left.VolumeID, right.VolumeID, VOLUME_ID_SIZE) == 0;
+ }
+
+ if (!left.VolumePathId.empty() && !right.VolumePathId.empty())
+ return _wcsicmp (left.VolumePathId.c_str(), right.VolumePathId.c_str()) == 0;
+
+ if (!left.Path.empty() && !right.Path.empty())
+ return _wcsicmp (left.Path.c_str(), right.Path.c_str()) == 0;
+
+ return false;
+}
+
+
+static bool FavoriteVolumeArrivalMountSuppressed (const list & suppressedFavorites, const FavoriteVolume& favorite)
+{
+ for (const FavoriteVolume& suppressedFavorite: suppressedFavorites)
+ {
+ if (FavoriteVolumesMatchForArrivalCancel (suppressedFavorite, favorite))
+ return true;
+ }
+
+ return false;
+}
+
+
+static void SuppressFavoriteVolumeArrivalMount (list & suppressedFavorites, const FavoriteVolume& favorite)
+{
+ if (!FavoriteVolumeArrivalMountSuppressed (suppressedFavorites, favorite))
+ suppressedFavorites.push_back (favorite);
+}
+
+
+static void ResumeFavoriteVolumeArrivalMount (list & suppressedFavorites, const FavoriteVolume& favorite)
+{
+ for (list ::iterator suppressedFavorite = suppressedFavorites.begin();
+ suppressedFavorite != suppressedFavorites.end();)
+ {
+ if (FavoriteVolumesMatchForArrivalCancel (*suppressedFavorite, favorite))
+ suppressedFavorite = suppressedFavorites.erase (suppressedFavorite);
+ else
+ ++suppressedFavorite;
+ }
+}
+
+
+void ClearFavoriteVolumeArrivalMountSuppressions ()
+{
+ SuppressedFavoritesOnArrivalMount.clear ();
+}
+
+
+/* Determines whether a "mount on arrival" favorite currently refers to a present,
+ not-yet-mounted volume, normalizing favorite.Path/VolumePathId/DisconnectedDevice
+ along the way (the favorite is taken by reference). Returns FALSE when the favorite
+ is already mounted or its device is not present; in that case the caller clears any
+ arrival-mount suppression and skips it this round. */
+static BOOL FavoriteVolumeArrivalMountCandidate (FavoriteVolume& favorite)
+{
+ if (favorite.UseVolumeID)
+ {
+ if (IsMountedVolumeID (favorite.VolumeID))
+ return FALSE;
+
+ std::wstring volDevPath = FindDeviceByVolumeID (favorite.VolumeID, FALSE);
+ if (volDevPath.length() == 0)
+ return FALSE;
+
+ favorite.Path = volDevPath;
+ favorite.DisconnectedDevice = false;
+ }
+ else if (!favorite.VolumePathId.empty())
+ {
+ if (IsMountedVolume (favorite.Path.c_str()))
+ return FALSE;
+
+ wchar_t volDevPath[TC_MAX_PATH];
+ if (QueryDosDevice (favorite.VolumePathId.substr (4, favorite.VolumePathId.size() - 5).c_str(), volDevPath, TC_MAX_PATH) == 0)
+ return FALSE;
+
+ favorite.DisconnectedDevice = false;
+ }
+ else if (favorite.Path.find (L"\\\\?\\Volume{") == 0)
+ {
+ wstring resolvedPath = VolumeGuidPathToDevicePath (favorite.Path);
+ if (resolvedPath.empty())
+ return FALSE;
+
+ favorite.DisconnectedDevice = false;
+ favorite.VolumePathId = favorite.Path;
+ favorite.Path = resolvedPath;
+ }
+
+ if (IsMountedVolume (favorite.Path.c_str()))
+ return FALSE;
+
+ if (!IsVolumeDeviceHosted (favorite.Path.c_str()))
+ {
+ if (!FileExists (favorite.Path.c_str()))
+ return FALSE;
+ }
+ else if (favorite.VolumePathId.empty())
+ return FALSE;
+
+ return TRUE;
+}
static mountFavoriteVolumeThreadParam* AllocateMountFavoriteVolumeThreadParam (BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume* favoriteVolumeToMount)
@@ -199,6 +466,7 @@ static mountFavoriteVolumeThreadParam* AllocateMountFavoriteVolumeThreadParam (B
pParam->systemFavorites = systemFavorites;
pParam->logOnMount = logOnMount;
pParam->hotKeyMount = hotKeyMount;
+ MountBatchInitialize (&pParam->mountBatch);
if (favoriteVolumeToMount)
{
@@ -5403,9 +5671,10 @@ static int AskVolumePassword (HWND hwndDlg, Password *password, int *pkcs5, int
// GUI actions
-static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pim, int pkcs5)
+static MountResult Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pim, int pkcs5, MountBatchContext* pMountBatch)
{
- BOOL status = FALSE;
+ BOOL bMountCancelled = FALSE;
+ MountResult result = MountResultFailed;
wchar_t fileName[MAX_PATH];
int mounted = 0, EffectiveVolumePkcs5 = 0;
int EffectiveVolumePim = (pim < 0)? CmdVolumePim : pim;
@@ -5444,13 +5713,11 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (wcslen(fileName) == 0)
{
- status = FALSE;
goto ret;
}
if (!TranslateVolumeID (hwndDlg, fileName, ARRAYSIZE (fileName)))
{
- status = FALSE;
goto ret;
}
@@ -5459,7 +5726,6 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (IsMountedVolume (szVolFileName))
{
Warning ("VOL_ALREADY_MOUNTED", hwndDlg);
- status = FALSE;
goto ret;
}
@@ -5468,7 +5734,6 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (!MultipleMountOperationInProgress)
handleWin32Error (hwndDlg, SRC_POS);
- status = FALSE;
goto ret;
}
@@ -5479,26 +5744,32 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (!bUseCmdVolumePassword)
{
// First try cached passwords and if they fail ask user for a new one
- mounted = MountVolume (hwndDlg, nDosDriveNo, szVolFileName, NULL, EffectiveVolumePkcs5, EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE);
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szVolFileName, NULL, EffectiveVolumePkcs5, EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ bMountCancelled = TRUE;
// If keyfiles are enabled, test empty password first
- if (!mounted && KeyFilesEnable && FirstKeyFile && bEffectiveTryEmptyPasswordWhenKeyfileUsed)
+ if (!bMountCancelled && !mounted && KeyFilesEnable && FirstKeyFile && bEffectiveTryEmptyPasswordWhenKeyfileUsed)
{
Password emptyPassword = {0};
KeyFilesApply (hwndDlg, &emptyPassword, FirstKeyFile, szVolFileName);
- mounted = MountVolume (hwndDlg, nDosDriveNo, szVolFileName, &emptyPassword, EffectiveVolumePkcs5, EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE);
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szVolFileName, &emptyPassword, EffectiveVolumePkcs5, EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ bMountCancelled = TRUE;
burn (&emptyPassword, sizeof (emptyPassword));
}
}
// Test password and/or keyfiles used for the previous volume
- if (!mounted && bEffectiveCacheDuringMultipleMount && MultipleMountOperationInProgress && VolumePassword.Length != 0)
+ if (!bMountCancelled && !mounted && bEffectiveCacheDuringMultipleMount && MultipleMountOperationInProgress && VolumePassword.Length != 0)
{
// if no PIM specified for favorite, we use also the PIM of the previous volume alongside its password.
- mounted = MountVolume (hwndDlg, nDosDriveNo, szVolFileName, &VolumePassword, EffectiveVolumePkcs5, (EffectiveVolumePim < 0)? VolumePim : EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE);
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szVolFileName, &VolumePassword, EffectiveVolumePkcs5, (EffectiveVolumePim < 0)? VolumePim : EffectiveVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ bMountCancelled = TRUE;
}
NormalCursor ();
@@ -5513,6 +5784,12 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
while (mounted == 0)
{
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ bMountCancelled = TRUE;
+ goto ret;
+ }
+
if (bUseCmdVolumePassword)
{
VolumePassword = CmdVolumePassword;
@@ -5526,7 +5803,11 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
StringCbCopyW (PasswordDlgVolume, sizeof(PasswordDlgVolume), szVolFileName);
if (!AskVolumePassword (hwndDlg, &VolumePassword, &GuiPkcs5, &GuiPim, NULL, TRUE))
+ {
+ if (FavoriteMountOnArrivalInProgress)
+ result = MountResultArrivalPasswordPromptDeclined;
goto ret;
+ }
else
{
VolumePkcs5 = GuiPkcs5;
@@ -5541,7 +5822,9 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (KeyFilesEnable)
KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile, szVolFileName);
- mounted = MountVolume (hwndDlg, nDosDriveNo, szVolFileName, &VolumePassword, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, !Silent);
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szVolFileName, &VolumePassword, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, !Silent, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ bMountCancelled = TRUE;
NormalCursor ();
// Check for problematic file extensions (exe, dll, sys)
@@ -5564,7 +5847,7 @@ static BOOL Mount (HWND hwndDlg, int nDosDriveNo, wchar_t *szVolFileName, int pi
if (mounted > 0)
{
- status = TRUE;
+ result = MountResultSucceeded;
if (bBeep)
MessageBeep (0xFFFFFFFF);
@@ -5600,10 +5883,16 @@ ret:
if (UsePreferences)
bCacheInDriver = bCacheInDriverDefault;
- if (status && CloseSecurityTokenSessionsAfterMount && !MultipleMountOperationInProgress)
+ if (result == MountResultSucceeded && CloseSecurityTokenSessionsAfterMount && !MultipleMountOperationInProgress)
SecurityToken::CloseAllSessions(); // TODO Use Token
- return status;
+ if (bMountCancelled)
+ {
+ result = MountResultCancelled;
+ SetLastError (ERROR_CANCELLED);
+ }
+
+ return result;
}
@@ -5649,7 +5938,7 @@ void __cdecl mountThreadFunction (void *hwndDlgArg)
EnableWindow(hwndDlg, FALSE);
finally_do_arg2 (HWND, hwndDlg, BOOL, bIsForeground, { EnableWindow(finally_arg, TRUE); if (finally_arg2) BringToForeground (finally_arg); bPrebootPasswordDlgMode = FALSE;});
- Mount (hwndDlg, -1, 0, -1, -1);
+ Mount (hwndDlg, -1, 0, -1, -1, NULL);
}
typedef struct
@@ -5871,11 +6160,21 @@ retry:
return status;
}
-static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
+typedef struct
{
+ BOOL bPasswordPrompt;
+ BOOL bRet;
+ MountBatchContext mountBatch;
+} MountAllDevicesThreadParam;
+
+static BOOL MountAllDevicesThreadCode (HWND hwndDlg, MountAllDevicesThreadParam* threadParam)
+{
+ BOOL bPasswordPrompt = threadParam->bPasswordPrompt;
+ MountBatchContext* pMountBatch = &threadParam->mountBatch;
HWND driveList = GetDlgItem (MainDlg, IDC_DRIVELIST);
int selDrive = ListView_GetSelectionMark (driveList);
BOOL shared = FALSE, status = FALSE, bHeaderBakRetry = FALSE;
+ BOOL bCancelled = FALSE;
int mountedVolCount = 0;
vector devices;
int EffectiveVolumePkcs5 = CmdVolumePkcs5;
@@ -5901,6 +6200,9 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
do
{
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
if (!bHeaderBakRetry)
{
if (!CmdVolumePasswordValid && bPasswordPrompt)
@@ -5937,13 +6239,22 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
if (devices.empty())
devices = GetAvailableHostDevices (true, false, true, true);
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
for (const HostDevice& drive: devices)
{
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
vector partitions = drive.Partitions;
partitions.insert (partitions.begin(), drive);
for (const HostDevice &device: partitions)
{
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
wchar_t szPartPath[TC_MAX_PATH];
StringCbCopyW (szPartPath, sizeof (szPartPath), device.Path.c_str());
BOOL mounted = IsMountedVolume (szPartPath);
@@ -6006,8 +6317,27 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
}
// First try user password then cached passwords
- if ((mounted = MountVolume (hwndDlg, nDosDriveNo, szPartPath, &VolumePassword, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, TRUE, FALSE)) > 0
- || ((VolumePassword.Length > 0) && ((mounted = MountVolume (hwndDlg, nDosDriveNo, szPartPath, NULL, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, TRUE, FALSE)) > 0)))
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szPartPath, &VolumePassword, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, TRUE, FALSE, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ {
+ MountBatchRequestAbort (pMountBatch);
+ goto post_mount;
+ }
+
+ if (mounted <= 0 && VolumePassword.Length > 0)
+ {
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
+ mounted = MountVolumeWithBatchCancel (hwndDlg, nDosDriveNo, szPartPath, NULL, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, TRUE, FALSE, pMountBatch);
+ if (MountVolumeWasCancelled (mounted))
+ {
+ MountBatchRequestAbort (pMountBatch);
+ goto post_mount;
+ }
+ }
+
+ if (mounted > 0)
{
// A volume has been successfully mounted
@@ -6041,6 +6371,9 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
}
}
+ if (MountBatchAbortRequested (pMountBatch))
+ goto post_mount;
+
if (mountedVolCount < 1)
{
// Failed to mount any volume
@@ -6093,7 +6426,10 @@ static BOOL MountAllDevicesThreadCode (HWND hwndDlg, BOOL bPasswordPrompt)
} while (bPasswordPrompt && mountedVolCount < 1);
- /* One or more volumes successfully mounted */
+post_mount:
+ /* Finalize any successfully mounted volumes before restoring shared state. */
+
+ bCancelled = MountBatchAbortRequested (pMountBatch);
ResetWrongPwdRetryCount ();
@@ -6131,21 +6467,27 @@ ret:
NormalCursor();
+ if (bCancelled || MountBatchAbortRequested (pMountBatch))
+ {
+ status = FALSE;
+ SetLastError (ERROR_CANCELLED);
+ }
+
return status;
}
-typedef struct
-{
- BOOL bPasswordPrompt;
- BOOL bRet;
-} MountAllDevicesThreadParam;
-
void CALLBACK mountAllDevicesThreadProc(void* pArg, HWND hwndDlg)
{
MountAllDevicesThreadParam* threadParam =(MountAllDevicesThreadParam*) pArg;
- BOOL bPasswordPrompt = threadParam->bPasswordPrompt;
- threadParam->bRet = MountAllDevicesThreadCode (hwndDlg, bPasswordPrompt);
+ threadParam->bRet = MountAllDevicesThreadCode (hwndDlg, threadParam);
+}
+
+BOOL CALLBACK mountAllDevicesCancelProc(void* pArg, HWND )
+{
+ MountAllDevicesThreadParam* threadParam = (MountAllDevicesThreadParam*) pArg;
+
+ return MountBatchCancel (threadParam ? &threadParam->mountBatch : NULL);
}
static BOOL MountAllDevices (HWND hwndDlg, BOOL bPasswordPrompt)
@@ -6153,11 +6495,18 @@ static BOOL MountAllDevices (HWND hwndDlg, BOOL bPasswordPrompt)
MountAllDevicesThreadParam param;
param.bPasswordPrompt = bPasswordPrompt;
param.bRet = FALSE;
+ MountBatchInitialize (¶m.mountBatch);
if (Silent)
mountAllDevicesThreadProc (¶m, hwndDlg);
else
- ShowWaitDialog (hwndDlg, FALSE, mountAllDevicesThreadProc, ¶m);
+ ShowWaitDialogEx (hwndDlg, FALSE, mountAllDevicesThreadProc, mountAllDevicesCancelProc, ¶m);
+
+ if (MountBatchAbortRequested (¶m.mountBatch))
+ {
+ param.bRet = FALSE;
+ SetLastError (ERROR_CANCELLED);
+ }
return param.bRet;
}
@@ -7536,6 +7885,8 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
// Automount
if (bAuto || (Quit && szFileName[0] != 0))
{
+ BOOL autoMountCancelled = FALSE;
+
// No drive letter specified on command line
if (commandLineDrive == 0)
szDriveLetter[0] = (wchar_t) GetFirstAvailableDrive () + L'A';
@@ -7550,11 +7901,17 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
KeyFileCloneAll (FirstCmdKeyFile, &defaultKeyFilesParam.FirstKeyFile);
}
+ SetLastError (ERROR_SUCCESS);
if (!MountAllDevices (hwndDlg, !Silent && !CmdVolumePasswordValid && IsPasswordCacheEmpty()))
+ {
+ if (GetLastError () == ERROR_CANCELLED)
+ autoMountCancelled = TRUE;
+
exitCode = 1;
+ }
}
- if (bAutoMountFavorites)
+ if (!autoMountCancelled && bAutoMountFavorites)
{
defaultMountOptions = mountOptions;
if (FirstCmdKeyFile)
@@ -7564,15 +7921,21 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
KeyFileCloneAll (FirstCmdKeyFile, &defaultKeyFilesParam.FirstKeyFile);
}
+ SetLastError (ERROR_SUCCESS);
if (!MountFavoriteVolumes (hwndDlg, FALSE, LogOn))
+ {
+ if (GetLastError () == ERROR_CANCELLED)
+ autoMountCancelled = TRUE;
+
exitCode = 1;
+ }
}
- if (szFileName[0] != 0 && !TranslateVolumeID (hwndDlg, szFileName, ARRAYSIZE (szFileName)))
+ if (!autoMountCancelled && szFileName[0] != 0 && !TranslateVolumeID (hwndDlg, szFileName, ARRAYSIZE (szFileName)))
{
exitCode = 1;
}
- else if (szFileName[0] != 0 && !IsMountedVolume (szFileName))
+ else if (!autoMountCancelled && szFileName[0] != 0 && !IsMountedVolume (szFileName))
{
BOOL mounted = FALSE;
int EffectiveVolumePkcs5 = CmdVolumePkcs5;
@@ -7598,6 +7961,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (FirstCmdKeyFile)
KeyFilesApply (hwndDlg, &CmdVolumePassword, FirstCmdKeyFile, szFileName);
+ SetLastError (ERROR_SUCCESS);
mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A',
szFileName, &CmdVolumePassword, EffectiveVolumePkcs5, CmdVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount,
&mountOptions, Silent, reportBadPasswd);
@@ -7607,6 +7971,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
else
{
// Cached password
+ SetLastError (ERROR_SUCCESS);
mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', szFileName, NULL, EffectiveVolumePkcs5, CmdVolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, Silent, FALSE);
}
@@ -7640,6 +8005,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (KeyFilesEnable && FirstKeyFile)
KeyFilesApply (hwndDlg, &VolumePassword, FirstKeyFile, szFileName);
+ SetLastError (ERROR_SUCCESS);
mounted = MountVolume (hwndDlg, szDriveLetter[0] - L'A', szFileName, &VolumePassword, VolumePkcs5, VolumePim, bCacheInDriver, bIncludePimInCache, bForceMount, &mountOptions, FALSE, TRUE);
burn (&VolumePassword, sizeof (VolumePassword));
@@ -7676,11 +8042,16 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
}
}
else
+ {
+ if (GetLastError () == ERROR_CANCELLED)
+ autoMountCancelled = TRUE;
+
exitCode = 1;
+ }
}
- else if (bExplore && GetMountedVolumeDriveNo (szFileName) != -1)
+ else if (!autoMountCancelled && bExplore && GetMountedVolumeDriveNo (szFileName) != -1)
OpenVolumeExplorerWindow (GetMountedVolumeDriveNo (szFileName));
- else if (szFileName[0] != 0 && IsMountedVolume (szFileName))
+ else if (!autoMountCancelled && szFileName[0] != 0 && IsMountedVolume (szFileName))
Warning ("VOL_ALREADY_MOUNTED", hwndDlg);
if (!Quit)
@@ -8061,51 +8432,13 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
for (FavoriteVolume& favorite: FavoritesOnArrivalMountRequired)
{
- if (favorite.UseVolumeID)
+ if (!FavoriteVolumeArrivalMountCandidate (favorite))
{
- if (IsMountedVolumeID (favorite.VolumeID))
- continue;
-
- std::wstring volDevPath = FindDeviceByVolumeID (favorite.VolumeID, FALSE);
- if (volDevPath.length() > 0)
- {
- favorite.Path = volDevPath;
- favorite.DisconnectedDevice = false;
- }
- else
- continue;
- }
- else if (!favorite.VolumePathId.empty())
- {
- if (IsMountedVolume (favorite.Path.c_str()))
- continue;
-
- wchar_t volDevPath[TC_MAX_PATH];
- if (QueryDosDevice (favorite.VolumePathId.substr (4, favorite.VolumePathId.size() - 5).c_str(), volDevPath, TC_MAX_PATH) == 0)
- continue;
-
- favorite.DisconnectedDevice = false;
- }
- else if (favorite.Path.find (L"\\\\?\\Volume{") == 0)
- {
- wstring resolvedPath = VolumeGuidPathToDevicePath (favorite.Path);
- if (resolvedPath.empty())
- continue;
-
- favorite.DisconnectedDevice = false;
- favorite.VolumePathId = favorite.Path;
- favorite.Path = resolvedPath;
- }
-
- if (IsMountedVolume (favorite.Path.c_str()))
+ ResumeFavoriteVolumeArrivalMount (SuppressedFavoritesOnArrivalMount, favorite);
continue;
-
- if (!IsVolumeDeviceHosted (favorite.Path.c_str()))
- {
- if (!FileExists (favorite.Path.c_str()))
- continue;
}
- else if (favorite.VolumePathId.empty())
+
+ if (FavoriteVolumeArrivalMountSuppressed (SuppressedFavoritesOnArrivalMount, favorite))
continue;
bool mountedAndNotDisconnected = false;
@@ -8121,14 +8454,26 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (!mountedAndNotDisconnected)
{
BOOL mounted = FALSE;
+ MountResult mountResult = MountResultFailed;
+ MountBatchContext mountBatch;
+ MountBatchInitialize (&mountBatch);
{
FavoriteMountOnArrivalInProgress = TRUE;
finally_do ({ FavoriteMountOnArrivalInProgress = FALSE; });
- mounted = MountFavoriteVolumes (hwndDlg, FALSE, FALSE, FALSE, favorite);
+ SetLastError (ERROR_SUCCESS);
+ mounted = MountFavoriteVolumesWithAbort (hwndDlg, FALSE, FALSE, FALSE, favorite, &mountBatch, &mountResult);
}
if (mounted)
+ {
+ ResumeFavoriteVolumeArrivalMount (SuppressedFavoritesOnArrivalMount, favorite);
FavoritesMountedOnArrivalStillConnected.push_back (favorite);
+ }
+ else if (mountResult == MountResultCancelled || mountResult == MountResultArrivalPasswordPromptDeclined)
+ {
+ SuppressFavoriteVolumeArrivalMount (SuppressedFavoritesOnArrivalMount, favorite);
+ break;
+ }
}
}
@@ -9323,8 +9668,13 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
{
if (0 == _InterlockedCompareExchange(&FavoriteMountOnGoing, 1, 0))
{
- if (_beginthread(mountFavoriteVolumeThreadFunction, 0, NULL) == (uintptr_t) -1L)
+ mountFavoriteVolumeThreadParam* pParam = AllocateMountFavoriteVolumeThreadParam (FALSE, FALSE, FALSE, NULL);
+
+ if (!pParam || _beginthread(mountFavoriteVolumeThreadFunction, 0, pParam) == (uintptr_t) -1L)
+ {
+ FreeMountFavoriteVolumeThreadParam (pParam);
_InterlockedExchange(&FavoriteMountOnGoing, 0);
+ }
}
return 1;
}
@@ -10877,9 +11227,9 @@ void DismountIdleVolumes ()
}
}
-static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite, BOOL& lastbExplore, BOOL& userForcedReadOnly, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount)
+static MountResult MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite, BOOL& lastbExplore, BOOL& userForcedReadOnly, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount, MountBatchContext* pMountBatch)
{
- BOOL status = TRUE;
+ MountResult result = MountResultSkipped;
int drive;
std::wstring effectiveVolumePath;
drive = towupper (favorite.MountPoint[0]) - L'A';
@@ -10892,7 +11242,7 @@ static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite,
{
SystemFavoritesServiceLogError (wstring (L"The drive letter ") + (wchar_t) (drive + L'A') + wstring (L" used by favorite \"") + favorite.Path + L"\" is invalid.\nThis system favorite will not be mounted");
}
- return FALSE;
+ return MountResultFailed;
}
mountOptions.ReadOnly = favorite.ReadOnly || userForcedReadOnly;
@@ -10958,7 +11308,7 @@ static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite,
mountOptions.ProtectedHidVolPim = CmdVolumePim;
if (Silent || (SecureDesktopDialogBoxParam (hInst, MAKEINTRESOURCEW (IDD_MOUNT_OPTIONS), hwnd, (DLGPROC) MountOptionsDlgProc, (LPARAM) &mountOptions) == IDCANCEL))
{
- status = FALSE;
+ result = MountResultFailed;
goto skipMount;
}
}
@@ -10968,7 +11318,7 @@ static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite,
if (ServiceMode)
SystemFavoritesServiceLogInfo (wstring (L"Mounting system favorite \"") + effectiveVolumePath + L"\"");
- status = Mount (hwnd, drive, (wchar_t *) effectiveVolumePath.c_str(), favorite.Pim, favorite.Pkcs5);
+ result = Mount (hwnd, drive, (wchar_t *) effectiveVolumePath.c_str(), favorite.Pim, favorite.Pkcs5, pMountBatch);
if (ServiceMode)
{
@@ -10976,7 +11326,7 @@ static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite,
SystemFavoritesServiceStatus.dwCheckPoint++;
SystemFavoritesServiceSetStatus (SERVICE_START_PENDING, 120000);
- if (status)
+ if (result == MountResultSucceeded)
{
SystemFavoritesServiceLogInfo (wstring (L"Favorite \"") + effectiveVolumePath + wstring (L"\" mounted successfully as ") + (wchar_t) (drive + L'A') + L":");
}
@@ -10986,7 +11336,7 @@ static BOOL MountFavoriteVolumeBase (HWND hwnd, const FavoriteVolume &favorite,
}
}
- if (status && mountOptions.ReadOnly != prevReadOnly)
+ if (result == MountResultSucceeded && mountOptions.ReadOnly != prevReadOnly)
userForcedReadOnly = mountOptions.ReadOnly;
skipMount:
@@ -10994,7 +11344,7 @@ skipMount:
if (systemFavorites && prevVolumeAtMountPoint[0])
{
- if (status)
+ if (result == MountResultSucceeded)
{
int freeDrive = GetFirstAvailableDrive();
if (freeDrive != -1)
@@ -11020,19 +11370,71 @@ skipMount:
}
}
else if (!systemFavorites && !favoriteVolumeToMount.Path.empty())
+ {
Error ("DRIVE_LETTER_UNAVAILABLE", MainDlg);
+ result = MountResultDriveLetterUnavailable;
+ }
else if (ServiceMode && systemFavorites)
{
SystemFavoritesServiceLogError (wstring (L"The drive letter ") + (wchar_t) (drive + L'A') + wstring (L" used by favorite \"") + effectiveVolumePath + L"\" is already taken.\nThis system favorite will not be mounted");
}
- return status;
+ if (result == MountResultCancelled)
+ SetLastError (ERROR_CANCELLED);
+
+ return result;
}
-BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount)
+/* Applies a single favorite's mount result to the running batch state. Updates *pbRet
+ (overall success), *pbMountedAny (whether any volume mounted, for token-session cleanup)
+ and *pBatchResult (the reason a batch stopped). Returns FALSE if the batch must stop
+ after this favorite. All out-pointers must be valid. */
+static BOOL HandleFavoriteMountResult (MountResult mountResult, MountBatchContext* pMountBatch, BOOL* pbRet, BOOL* pbMountedAny, MountResult* pBatchResult)
{
- BOOL bRet = TRUE, status = TRUE;
+ switch (mountResult)
+ {
+ case MountResultSucceeded:
+ *pbMountedAny = TRUE;
+ return TRUE;
+
+ case MountResultFailed:
+ *pbRet = FALSE;
+ return TRUE;
+
+ case MountResultCancelled:
+ /* Wait-dialog/driver abort: stop the whole batch. */
+ MountBatchRequestAbort (pMountBatch);
+ *pBatchResult = mountResult;
+ *pbRet = FALSE;
+ return FALSE;
+
+ case MountResultArrivalPasswordPromptDeclined:
+ /* Arrival password-prompt cancel suppresses this favorite without aborting the batch. */
+ *pBatchResult = mountResult;
+ *pbRet = FALSE;
+ return FALSE;
+
+ case MountResultDriveLetterUnavailable:
+ /* The favorite's drive letter is taken by another volume. Treat this as a non-fatal
+ skip (it does not flip overall success to failure): the favorite-on-arrival scan
+ relies on this so it parks the favorite instead of re-prompting and re-showing the
+ error on every timer tick. */
+ return TRUE;
+
+ case MountResultSkipped:
+ default:
+ return TRUE;
+ }
+}
+
+
+static BOOL MountFavoriteVolumesWithAbort (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount, MountBatchContext* pMountBatch, MountResult* pBatchResult)
+{
+ BOOL bRet = TRUE;
+ BOOL bMountedAny = FALSE;
+ MountResult mountResult = MountResultSkipped;
+ MountResult batchResult = MountResultSucceeded;
BOOL lastbExplore;
BOOL userForcedReadOnly = FALSE;
@@ -11090,7 +11492,8 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
{
if (ServiceMode)
SystemFavoritesServiceLogError (wstring (L"An error occured while reading System Favorites XML file"));
- return false;
+ bRet = FALSE;
+ goto ret;
}
}
else if (!favoriteVolumeToMount.Path.empty())
@@ -11100,6 +11503,13 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
for (const FavoriteVolume& favorite: favorites)
{
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ batchResult = MountResultCancelled;
+ bRet = FALSE;
+ goto ret;
+ }
+
if (ServiceMode && systemFavorites && favorite.DisconnectedDevice)
{
skippedSystemFavorites.push_back (favorite);
@@ -11116,9 +11526,10 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
continue;
}
- status = MountFavoriteVolumeBase (hwnd, favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount);
- if (!status)
- bRet = FALSE;
+ SetLastError (ERROR_SUCCESS);
+ mountResult = MountFavoriteVolumeBase (hwnd, favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount, pMountBatch);
+ if (!HandleFavoriteMountResult (mountResult, pMountBatch, &bRet, &bMountedAny, &batchResult))
+ goto ret;
}
if (systemFavorites && ServiceMode && !skippedSystemFavorites.empty())
@@ -11129,8 +11540,22 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
size_t remainingFavorites = skippedSystemFavorites.size();
while ((remainingFavorites > 0) && (retryCounter++ < 4))
{
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ batchResult = MountResultCancelled;
+ bRet = FALSE;
+ goto ret;
+ }
+
Sleep (5000);
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ batchResult = MountResultCancelled;
+ bRet = FALSE;
+ goto ret;
+ }
+
SystemFavoritesServiceLogInfo (wstring (L"Trying to mount skipped system favorites"));
// Update the service status to avoid being killed
@@ -11140,6 +11565,13 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
for (vector ::iterator favorite = skippedSystemFavorites.begin();
favorite != skippedSystemFavorites.end(); favorite++)
{
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ batchResult = MountResultCancelled;
+ bRet = FALSE;
+ goto ret;
+ }
+
if (favorite->DisconnectedDevice)
{
// check if the favorite is here and get its path
@@ -11164,9 +11596,10 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
else
SystemFavoritesServiceLogInfo (wstring (L"Favorite \"") + favorite->VolumePathId + L"\" is connected. Performing mount.");
- status = MountFavoriteVolumeBase (hwnd, *favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount);
- if (!status)
- bRet = FALSE;
+ SetLastError (ERROR_SUCCESS);
+ mountResult = MountFavoriteVolumeBase (hwnd, *favorite, lastbExplore, userForcedReadOnly, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount, pMountBatch);
+ if (!HandleFavoriteMountResult (mountResult, pMountBatch, &bRet, &bMountedAny, &batchResult))
+ goto ret;
}
}
}
@@ -11182,39 +11615,64 @@ BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOO
}
}
+ret:
+ if (MountBatchAbortRequested (pMountBatch))
+ {
+ batchResult = MountResultCancelled;
+ bRet = FALSE;
+ }
+
MultipleMountOperationInProgress = FALSE;
burn (&VolumePassword, sizeof (VolumePassword));
burn (&VolumePkcs5, sizeof (VolumePkcs5));
burn (&VolumePim, sizeof (VolumePim));
- if (bRet && CloseSecurityTokenSessionsAfterMount)
+ if ((bRet || ((batchResult == MountResultCancelled || batchResult == MountResultArrivalPasswordPromptDeclined) && bMountedAny)) && CloseSecurityTokenSessionsAfterMount)
SecurityToken::CloseAllSessions(); // TODO Use Token
+ if (batchResult == MountResultCancelled)
+ SetLastError (ERROR_CANCELLED);
+
+ if (pBatchResult)
+ *pBatchResult = batchResult;
+
return bRet;
}
-void CALLBACK mountFavoriteVolumeCallbackFunction (void *pArg, HWND hwnd)
+BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites, BOOL logOnMount, BOOL hotKeyMount, const FavoriteVolume &favoriteVolumeToMount)
+{
+ MountBatchContext mountBatch;
+ MountBatchInitialize (&mountBatch);
+
+ return MountFavoriteVolumesWithAbort (hwnd, systemFavorites, logOnMount, hotKeyMount, favoriteVolumeToMount, &mountBatch, NULL);
+}
+
+static void CALLBACK mountFavoriteVolumeCallbackFunction (void *pArg, HWND hwnd)
{
mountFavoriteVolumeThreadParam* pParam = (mountFavoriteVolumeThreadParam*) pArg;
- if (pParam)
- {
- finally_do_arg (mountFavoriteVolumeThreadParam*, pParam, { FreeMountFavoriteVolumeThreadParam (finally_arg); });
+ // pArg is always the thread parameter allocated by the caller before _beginthread.
+ if (!pParam)
+ return;
- if (pParam->favoriteVolumeToMount)
- MountFavoriteVolumes (hwnd, pParam->systemFavorites, pParam->logOnMount, pParam->hotKeyMount, *(pParam->favoriteVolumeToMount));
- else
- MountFavoriteVolumes (hwnd, pParam->systemFavorites, pParam->logOnMount, pParam->hotKeyMount);
- }
- else
- MountFavoriteVolumes (hwnd);
+ const FavoriteVolume& favoriteVolumeToMount = pParam->favoriteVolumeToMount ? *(pParam->favoriteVolumeToMount) : FavoriteVolume();
+ MountFavoriteVolumesWithAbort (hwnd, pParam->systemFavorites, pParam->logOnMount, pParam->hotKeyMount, favoriteVolumeToMount, &pParam->mountBatch, NULL);
}
-void __cdecl mountFavoriteVolumeThreadFunction (void *pArg)
+BOOL CALLBACK mountFavoriteVolumeCancelProc(void* pArg, HWND )
+{
+ mountFavoriteVolumeThreadParam* threadParam = (mountFavoriteVolumeThreadParam*) pArg;
+
+ return MountBatchCancel (threadParam ? &threadParam->mountBatch : NULL);
+}
+
+static void __cdecl mountFavoriteVolumeThreadFunction (void *pArg)
{
ScreenCaptureBlocker screenCaptureBlocker;
+ mountFavoriteVolumeThreadParam* pParam = (mountFavoriteVolumeThreadParam*) pArg;
finally_do ({ _InterlockedExchange(&FavoriteMountOnGoing, 0); });
- ShowWaitDialog (MainDlg, FALSE, mountFavoriteVolumeCallbackFunction, pArg);
+ finally_do_arg (mountFavoriteVolumeThreadParam*, pParam, { FreeMountFavoriteVolumeThreadParam (finally_arg); });
+ ShowWaitDialogEx (MainDlg, FALSE, mountFavoriteVolumeCallbackFunction, mountFavoriteVolumeCancelProc, pParam);
}
static void SaveDefaultKeyFilesParam (HWND hwnd)
diff --git a/src/Mount/Mount.h b/src/Mount/Mount.h
index 91bdded1..a2fa2056 100644
--- a/src/Mount/Mount.h
+++ b/src/Mount/Mount.h
@@ -116,18 +116,9 @@ static BOOL CALLBACK DefaultMountParametersDlgProc (HWND hwndDlg, UINT msg, WPAR
#ifdef __cplusplus
}
-typedef struct
-{
- BOOL systemFavorites;
- BOOL logOnMount;
- BOOL hotKeyMount;
- /* Owned by the thread parameter when non-NULL. */
- VeraCrypt::FavoriteVolume* favoriteVolumeToMount;
-} mountFavoriteVolumeThreadParam;
-
void SetDriverConfigurationFlag (uint32 flag, BOOL state);
BOOL MountFavoriteVolumes (HWND hwnd, BOOL systemFavorites = FALSE, BOOL logOnMount = FALSE, BOOL hotKeyMount = FALSE, const VeraCrypt::FavoriteVolume &favoriteVolumeToMount = VeraCrypt::FavoriteVolume());
-void __cdecl mountFavoriteVolumeThreadFunction (void *pArg);
+void ClearFavoriteVolumeArrivalMountSuppressions ();
// A class that represents a device based on its device ID
class CDevice