Windows: flush shell notifications when dismounting with /q (#1852)

* Windows: flush shell notifications when dismounting with /q

* Windows: limit the /q notification flush to the command line dismount

ProcessExitsAfterCommand was set while parsing /q and stayed set when
the process went on as the background task (/q background, and
/q preferences, which is also used at logon). Later interactive
dismounts, automatic dismounts through DismountAll and the hotkeys then
flushed as well, which would also delay the cache wipe that the force
dismount and wipe hotkeys issue after DismountAll.

Set the flag only for the dismount requested on the command line and
clear it right after, whatever Silent is. Rename it to
FlushDriveRemovalNotifications, as /q doesn't necessarily end the
process.

Reword the comments: according to the documentation, SHCNF_FLUSH makes
SHChangeNotify return once the notification has been delivered, which
doesn't mean that Explorer has finished updating its display, and the
cause of the reported ghost drive letters hasn't been established.
This commit is contained in:
amail80
2026-10-17 12:09:03 +09:00
committed by GitHub
parent 7eab121669
commit de04285ddf
3 changed files with 20 additions and 11 deletions
+11 -7
View File
@@ -162,6 +162,10 @@ HWND MainDlg = NULL;
wchar_t *lpszTitle = NULL;
BOOL Silent = FALSE;
/* Set by Mount.c only while it carries out a dismount requested on the command line
with /q. UnmountVolumeBase and DismountAll then send the drive removal notification
again with SHCNF_FLUSH, as they do when Silent is set. */
BOOL FlushDriveRemovalNotifications = FALSE;
BOOL bPreserveTimestamp = TRUE;
BOOL bShowDisconnectedNetworkDrives = FALSE;
BOOL bHideWaitingDialog = FALSE;
@@ -9826,13 +9830,13 @@ retry:
BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, nDosDriveNo, 0);
/* GH #337, GH #1426: When running in silent/CLI mode, the process may
exit immediately after unmount. BroadcastDeviceChange sends
SHChangeNotify asynchronously, so Explorer may not process the drive
removal before the process exits, leaving a ghost drive letter.
Re-send the notification with SHCNF_FLUSH to force synchronous
processing by Explorer before we return. */
if (Silent && !DeviceChangeBroadcastDisabled)
/* GH #337, GH #1426: ghost drive letters were reported after dismounts
requested on the command line; their cause hasn't been established.
When Silent or FlushDriveRemovalNotifications is set, the notification
is sent again with SHCNF_FLUSH. According to the documentation,
SHChangeNotify then returns only once it has been delivered, which
doesn't mean that Explorer has finished updating its display. */
if ((Silent || FlushDriveRemovalNotifications) && !DeviceChangeBroadcastDisabled)
{
wchar_t root[] = { (wchar_t) (nDosDriveNo + L'A'), L':', L'\\', 0 };
SHChangeNotify (SHCNE_DRIVEREMOVED, SHCNF_PATH | SHCNF_FLUSH, root, NULL);
+1
View File
@@ -133,6 +133,7 @@ extern int ScreenDPI;
extern double DlgAspectRatio;
extern HWND MainDlg;
extern BOOL Silent;
extern BOOL FlushDriveRemovalNotifications;
extern BOOL bHistory;
extern BOOL bPreserveTimestamp;
extern BOOL bShowDisconnectedNetworkDrives;
+8 -4
View File
@@ -6351,10 +6351,9 @@ retry:
if (removedDrives)
BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, removedDrives);
/* GH #337, GH #1426: Flush shell notifications synchronously in
silent/CLI mode to prevent ghost drive letters when the process
exits immediately after dismount. */
if (Silent && !DeviceChangeBroadcastDisabled)
/* GH #337, GH #1426: as in UnmountVolumeBase, send the notifications again
with SHCNF_FLUSH when Silent or FlushDriveRemovalNotifications is set. */
if ((Silent || FlushDriveRemovalNotifications) && !DeviceChangeBroadcastDisabled)
{
for (i = 0; i < 26; i++)
{
@@ -8446,6 +8445,10 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
}
// Dismount
/* With /q, flush the drive removal notifications of this dismount even
without /s (see UnmountVolumeBase). Only for this request: a process
that goes on as the background task doesn't flush later dismounts. */
FlushDriveRemovalNotifications = Quit;
if (cmdUnmountDrive >= 0)
{
MOUNT_LIST_STRUCT mountList;
@@ -8467,6 +8470,7 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
if (!DismountAll (hwndDlg, bForceUnmount, !Silent, UNMOUNT_MAX_AUTO_RETRIES, UNMOUNT_AUTO_RETRY_DELAY))
exitCode = 1;
}
FlushDriveRemovalNotifications = FALSE;
// TaskBar icon
if (bEnableBkgTask)