From ec7b5cd7e63bf78fa98c9b9713846b99b835dd71 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 9 Sep 2015 15:53:18 +0200 Subject: [PATCH] Windows: Implement waiting dialog for Dismount operations to avoid freezing GUI when dismounting takes long time. --- src/Common/Dlgcode.c | 58 +++++++++++++++---- src/Mount/Mount.c | 133 ++++++++++++++++++++++++++++++------------- 2 files changed, 141 insertions(+), 50 deletions(-) diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index e858c3b4..4e8dc015 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -6370,7 +6370,7 @@ int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) unmount.ignoreOpenFiles = forced; bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, - sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); + sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); if (bResult == FALSE) { @@ -6384,7 +6384,8 @@ int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) if (unmount.nReturnCode == ERR_SUCCESS && unmount.HiddenVolumeProtectionTriggered - && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo]) + && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] + && !Silent) { wchar_t msg[4096]; @@ -7017,26 +7018,63 @@ int MountVolume (HWND hwndDlg, return 1; } +typedef struct +{ + int nDosDriveNo; + BOOL forced; + int dismountMaxRetries; + DWORD retryDelay; + int* presult; + DWORD dwLastError; +} UnmountThreadParam; + +void CALLBACK UnmountWaitThreadProc(void* pArg, HWND hwnd) +{ + UnmountThreadParam* pThreadParam = (UnmountThreadParam*) pArg; + int dismountMaxRetries = pThreadParam->dismountMaxRetries; + DWORD retryDelay = pThreadParam->retryDelay; + + do + { + *pThreadParam->presult = DriverUnmountVolume (hwnd, pThreadParam->nDosDriveNo, pThreadParam->forced); + + if (*pThreadParam->presult == ERR_FILES_OPEN) + Sleep (retryDelay); + else + break; + + } while (--dismountMaxRetries > 0); + + pThreadParam->dwLastError = GetLastError (); +} + static BOOL UnmountVolumeBase (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount, BOOL ntfsFormatCase) { int result; BOOL forced = forceUnmount; int dismountMaxRetries = ntfsFormatCase? 5 : UNMOUNT_MAX_AUTO_RETRIES; DWORD retryDelay = ntfsFormatCase? 2000: UNMOUNT_AUTO_RETRY_DELAY; + UnmountThreadParam param; retry: BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, nDosDriveNo, 0); - do + param.nDosDriveNo = nDosDriveNo; + param.forced = forced; + param.dismountMaxRetries = dismountMaxRetries; + param.retryDelay = retryDelay; + param.presult = &result; + + if (Silent) { - result = DriverUnmountVolume (hwndDlg, nDosDriveNo, forced); + UnmountWaitThreadProc (¶m, hwndDlg); + } + else + { + ShowWaitDialog (hwndDlg, TRUE, UnmountWaitThreadProc, ¶m); + } - if (result == ERR_FILES_OPEN) - Sleep (retryDelay); - else - break; - - } while (--dismountMaxRetries > 0); + SetLastError (param.dwLastError); if (result != 0) { diff --git a/src/Mount/Mount.c b/src/Mount/Mount.c index 0d8cace2..5c28bf93 100644 --- a/src/Mount/Mount.c +++ b/src/Mount/Mount.c @@ -4584,6 +4584,81 @@ void __cdecl mountThreadFunction (void *hwndDlgArg) Mount (hwndDlg, 0, 0, -1); } +typedef struct +{ + UNMOUNT_STRUCT* punmount; + BOOL interact; + int dismountMaxRetries; + int dismountAutoRetryDelay; + BOOL* pbResult; + DWORD* pdwResult; + DWORD dwLastError; + BOOL bReturn; +} DismountAllThreadParam; + +void CALLBACK DismountAllThreadProc(void* pArg, HWND hwndDlg) +{ + DismountAllThreadParam* pThreadParam = (DismountAllThreadParam*) pArg; + UNMOUNT_STRUCT* punmount = pThreadParam->punmount; + BOOL* pbResult = pThreadParam->pbResult; + DWORD* pdwResult = pThreadParam->pdwResult; + int dismountMaxRetries = pThreadParam->dismountMaxRetries; + int dismountAutoRetryDelay = pThreadParam->dismountAutoRetryDelay; + + do + { + *pbResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_ALL_VOLUMES, punmount, + sizeof (UNMOUNT_STRUCT), punmount, sizeof (UNMOUNT_STRUCT), pdwResult, NULL); + + if ( punmount->nDosDriveNo < 0 || punmount->nDosDriveNo > 25 + || (punmount->ignoreOpenFiles != TRUE && punmount->ignoreOpenFiles != FALSE) + || (punmount->HiddenVolumeProtectionTriggered != TRUE && punmount->HiddenVolumeProtectionTriggered != FALSE) + || (punmount->nReturnCode < 0) + ) + { + if (*pbResult) + SetLastError (ERROR_INTERNAL_ERROR); + *pbResult = FALSE; + } + + if (*pbResult == FALSE) + { + NormalCursor(); + handleWin32Error (hwndDlg, SRC_POS); + pThreadParam->dwLastError = GetLastError (); + pThreadParam->bReturn = FALSE; + return; + } + + if (punmount->nReturnCode == ERR_SUCCESS + && punmount->HiddenVolumeProtectionTriggered + && !VolumeNotificationsList.bHidVolDamagePrevReported [punmount->nDosDriveNo] + && pThreadParam->interact + && !Silent) + { + wchar_t msg[4096]; + + VolumeNotificationsList.bHidVolDamagePrevReported [punmount->nDosDriveNo] = TRUE; + + StringCbPrintfW (msg, sizeof(msg), GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), punmount->nDosDriveNo + 'A'); + SetForegroundWindow (hwndDlg); + MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); + + punmount->HiddenVolumeProtectionTriggered = FALSE; + continue; + } + + if (punmount->nReturnCode == ERR_FILES_OPEN) + Sleep (dismountAutoRetryDelay); + else + break; + + } while (--dismountMaxRetries > 0); + + pThreadParam->dwLastError = GetLastError (); + pThreadParam->bReturn = TRUE; +} + static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dismountMaxRetries, int dismountAutoRetryDelay) { BOOL status = TRUE; @@ -4593,6 +4668,7 @@ static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dis BOOL bResult; MOUNT_LIST_STRUCT prevMountList = {0}; int i; + DismountAllThreadParam dismountAllThreadParam; retry: WaitCursor(); @@ -4620,51 +4696,28 @@ static BOOL DismountAll (HWND hwndDlg, BOOL forceUnmount, BOOL interact, int dis unmount.nDosDriveNo = 0; unmount.ignoreOpenFiles = forceUnmount; + + dismountAllThreadParam.punmount = &unmount; + dismountAllThreadParam.interact = interact; + dismountAllThreadParam.dismountMaxRetries = dismountMaxRetries; + dismountAllThreadParam.dismountAutoRetryDelay = dismountAutoRetryDelay; + dismountAllThreadParam.pbResult = &bResult; + dismountAllThreadParam.pdwResult = &dwResult; + dismountAllThreadParam.dwLastError = ERROR_SUCCESS; + dismountAllThreadParam.bReturn = TRUE; - do + if (interact && !Silent) { - bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_ALL_VOLUMES, &unmount, - sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); - if ( unmount.nDosDriveNo < 0 || unmount.nDosDriveNo > 25 - || (unmount.ignoreOpenFiles != TRUE && unmount.ignoreOpenFiles != FALSE) - || (unmount.HiddenVolumeProtectionTriggered != TRUE && unmount.HiddenVolumeProtectionTriggered != FALSE) - || (unmount.nReturnCode < 0) - ) - { - if (bResult) - SetLastError (ERROR_INTERNAL_ERROR); - bResult = FALSE; - } + ShowWaitDialog (hwndDlg, TRUE, DismountAllThreadProc, &dismountAllThreadParam); + } + else + DismountAllThreadProc (&dismountAllThreadParam, hwndDlg); - if (bResult == FALSE) - { - NormalCursor(); - handleWin32Error (hwndDlg, SRC_POS); - return FALSE; - } + SetLastError (dismountAllThreadParam.dwLastError); - if (unmount.nReturnCode == ERR_SUCCESS - && unmount.HiddenVolumeProtectionTriggered - && !VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo]) - { - wchar_t msg[4096]; - - VolumeNotificationsList.bHidVolDamagePrevReported [unmount.nDosDriveNo] = TRUE; - StringCbPrintfW (msg, sizeof(msg), GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), unmount.nDosDriveNo + 'A'); - SetForegroundWindow (hwndDlg); - MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); - - unmount.HiddenVolumeProtectionTriggered = FALSE; - continue; - } - - if (unmount.nReturnCode == ERR_FILES_OPEN) - Sleep (dismountAutoRetryDelay); - else - break; - - } while (--dismountMaxRetries > 0); + if (!dismountAllThreadParam.bReturn) + return FALSE; memset (&mountList, 0, sizeof (mountList)); DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mountList, sizeof (mountList), &mountList, sizeof (mountList), &dwResult, NULL);