From 1ea0556cbe4a5141afdcb38ed08b61b3e6ac1a79 Mon Sep 17 00:00:00 2001 From: amail80 Date: Mon, 13 Apr 2026 11:07:32 +0500 Subject: [PATCH] Fix ghost drive letter after CLI dismount (GH #337, GH #1426) (#1658) When dismounting via CLI (/d /q /s), SHChangeNotify is called without SHCNF_FLUSH flag, making it asynchronous. The process exits before Explorer processes the notification, leaving a phantom drive letter visible in Explorer as an inaccessible Local Disk until reboot. Add SHCNF_FLUSH in Silent (CLI) mode to force synchronous shell notification processing in both single-volume (UnmountVolumeBase) and dismount-all (DismountAll) code paths. The flush is only added in CLI mode to avoid adding latency to interactive GUI operations. Co-authored-by: Contributor --- src/Common/Dlgcode.c | 12 ++++++++++++ src/Mount/Mount.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index d2c935d4..0842c94f 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -9357,6 +9357,18 @@ 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) + { + wchar_t root[] = { (wchar_t) (nDosDriveNo + L'A'), L':', L'\\', 0 }; + SHChangeNotify (SHCNE_DRIVEREMOVED, SHCNF_PATH | SHCNF_FLUSH, root, NULL); + } + return TRUE; } diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index ca5959a1..a032e214 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -5763,6 +5763,22 @@ retry: BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, 0, prevMountList.ulMountedDrives & ~mountList.ulMountedDrives); + /* 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) + { + DWORD removedDrives = prevMountList.ulMountedDrives & ~mountList.ulMountedDrives; + for (i = 0; i < 26; i++) + { + if (removedDrives & (1 << i)) + { + wchar_t root[] = { (wchar_t) (i + L'A'), L':', L'\\', 0 }; + SHChangeNotify (SHCNE_DRIVEREMOVED, SHCNF_PATH | SHCNF_FLUSH, root, NULL); + } + } + } + RefreshMainDlg (hwndDlg); NormalCursor();