From 9e2cda60e3852660f235beb5e0af1c746d0045e6 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 15 Dec 2021 10:48:06 -0600 Subject: FilesInUse messages are too different to unify in the Burn engine. Fixes #6348 --- src/burn/engine/apply.cpp | 44 ++++++++++++++++++------------ src/burn/engine/apply.h | 4 +-- src/burn/engine/detect.cpp | 4 +-- src/burn/engine/elevation.cpp | 36 +++++++++++++++--------- src/burn/engine/embedded.cpp | 4 +-- src/burn/engine/exeengine.cpp | 2 +- src/burn/engine/msuengine.cpp | 2 +- src/burn/engine/netfxchainer.cpp | 8 +++--- src/burn/engine/userexperience.cpp | 56 ++++++++++++++++++++++++++++++++++---- src/burn/engine/userexperience.h | 6 +++- 10 files changed, 117 insertions(+), 49 deletions(-) (limited to 'src/burn') diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index dfaba3f2..9e552ee0 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp @@ -1931,8 +1931,8 @@ static HRESULT WINAPI AuthenticationRequired( APPLY_AUTHENTICATION_REQUIRED_DATA* authenticationData = reinterpret_cast(pData); - UserExperienceOnError(authenticationData->pUX, errorType, authenticationData->wzPackageOrContainerId, ERROR_ACCESS_DENIED, sczError, MB_RETRYTRYAGAIN, 0, NULL, &nResult); // ignore return value; - nResult = UserExperienceCheckExecuteResult(authenticationData->pUX, FALSE, MB_RETRYTRYAGAIN, nResult); + UserExperienceOnError(authenticationData->pUX, errorType, authenticationData->wzPackageOrContainerId, ERROR_ACCESS_DENIED, sczError, MB_RETRYCANCEL, 0, NULL, &nResult); // ignore return value; + nResult = UserExperienceCheckExecuteResult(authenticationData->pUX, FALSE, BURN_MB_RETRYTRYAGAIN, nResult); if (IDTRYAGAIN == nResult && authenticationData->pUX->hwndApply) { er = ::InternetErrorDlg(authenticationData->pUX->hwndApply, hUrl, ERROR_INTERNET_INCORRECT_PASSWORD, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, NULL); @@ -2495,10 +2495,10 @@ static HRESULT ExecuteExePackage( ExitOnRootFailure(hr, "BA aborted execute EXE package begin."); message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = fRollback ? 100 : 0; nResult = GenericExecuteMessageHandler(&message, pContext); - hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); ExitOnRootFailure(hr, "BA aborted EXE progress."); fExecuted = TRUE; @@ -2516,10 +2516,10 @@ static HRESULT ExecuteExePackage( } message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = fRollback ? 0 : 100; nResult = GenericExecuteMessageHandler(&message, pContext); - hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); ExitOnRootFailure(hr, "BA aborted EXE progress."); pContext->cExecutedPackages += fRollback ? -1 : 1; @@ -2712,10 +2712,10 @@ static HRESULT ExecuteMsuPackage( ExitOnRootFailure(hr, "BA aborted execute MSU package begin."); message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = fRollback ? 100 : 0; nResult = GenericExecuteMessageHandler(&message, pContext); - hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); ExitOnRootFailure(hr, "BA aborted MSU progress."); fExecuted = TRUE; @@ -2733,10 +2733,10 @@ static HRESULT ExecuteMsuPackage( } message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = fRollback ? 0 : 100; nResult = GenericExecuteMessageHandler(&message, pContext); - hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwAllowedResults, nResult); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); ExitOnRootFailure(hr, "BA aborted MSU progress."); pContext->cExecutedPackages += fRollback ? -1 : 1; @@ -3047,6 +3047,7 @@ static int GenericExecuteMessageHandler( ) { BURN_EXECUTE_CONTEXT* pContext = (BURN_EXECUTE_CONTEXT*)pvContext; + DWORD dwAllowedResults = pMessage->dwUIHint & MB_TYPEMASK; int nResult = IDNOACTION; switch (pMessage->type) @@ -3059,15 +3060,16 @@ static int GenericExecuteMessageHandler( break; case GENERIC_EXECUTE_MESSAGE_ERROR: - UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->pExecutingPackage->sczId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwAllowedResults, 0, NULL, &nResult); // ignore return value. + UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_EXE_PACKAGE, pContext->pExecutingPackage->sczId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, 0, NULL, &nResult); // ignore return value. break; - case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE: - UserExperienceOnExecuteFilesInUse(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->filesInUse.cFiles, pMessage->filesInUse.rgwzFiles, &nResult); // ignore return value. + case GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE: + UserExperienceOnExecuteFilesInUse(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->filesInUse.cFiles, pMessage->filesInUse.rgwzFiles, BOOTSTRAPPER_FILES_IN_USE_TYPE_NETFX, &nResult); // ignore return value. + dwAllowedResults = BURN_MB_NETFX_FILES_IN_USE; break; } - nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, pMessage->dwAllowedResults, nResult); + nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, dwAllowedResults, nResult); return nResult; } @@ -3077,7 +3079,9 @@ static int MsiExecuteMessageHandler( ) { BURN_EXECUTE_CONTEXT* pContext = (BURN_EXECUTE_CONTEXT*)pvContext; + DWORD dwAllowedResults = pMessage->dwUIHint & MB_TYPEMASK; int nResult = IDNOACTION; + BOOL fRestartManager = FALSE; switch (pMessage->type) { @@ -3090,20 +3094,24 @@ static int MsiExecuteMessageHandler( case WIU_MSI_EXECUTE_MESSAGE_ERROR: nResult = pMessage->nResultRecommendation; - UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER, pContext->pExecutingPackage->sczId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwAllowedResults, pMessage->cData, pMessage->rgwzData, &nResult); // ignore return value. + UserExperienceOnError(pContext->pUX, BOOTSTRAPPER_ERROR_TYPE_WINDOWS_INSTALLER, pContext->pExecutingPackage->sczId, pMessage->error.dwErrorCode, pMessage->error.wzMessage, pMessage->dwUIHint, pMessage->cData, pMessage->rgwzData, &nResult); // ignore return value. break; case WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE: nResult = pMessage->nResultRecommendation; - UserExperienceOnExecuteMsiMessage(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->msiMessage.mt, pMessage->dwAllowedResults, pMessage->msiMessage.wzMessage, pMessage->cData, pMessage->rgwzData, &nResult); // ignore return value. + UserExperienceOnExecuteMsiMessage(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->msiMessage.mt, pMessage->dwUIHint, pMessage->msiMessage.wzMessage, pMessage->cData, pMessage->rgwzData, &nResult); // ignore return value. break; + case WIU_MSI_EXECUTE_MESSAGE_MSI_RM_FILES_IN_USE: + fRestartManager = TRUE; + __fallthrough; case WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE: - UserExperienceOnExecuteFilesInUse(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->msiFilesInUse.cFiles, pMessage->msiFilesInUse.rgwzFiles, &nResult); // ignore return value. + UserExperienceOnExecuteFilesInUse(pContext->pUX, pContext->pExecutingPackage->sczId, pMessage->msiFilesInUse.cFiles, pMessage->msiFilesInUse.rgwzFiles, fRestartManager ? BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI_RM : BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI, &nResult); // ignore return value. + dwAllowedResults = fRestartManager ? BURN_MB_MSI_RM_FILES_IN_USE : BURN_MB_MSI_FILES_IN_USE; break; } - nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, pMessage->dwAllowedResults, nResult); + nResult = UserExperienceCheckExecuteResult(pContext->pUX, pContext->fRollback, dwAllowedResults, nResult); return nResult; } diff --git a/src/burn/engine/apply.h b/src/burn/engine/apply.h index 45270f92..1717a71a 100644 --- a/src/burn/engine/apply.h +++ b/src/burn/engine/apply.h @@ -12,7 +12,7 @@ enum GENERIC_EXECUTE_MESSAGE_TYPE GENERIC_EXECUTE_MESSAGE_NONE, GENERIC_EXECUTE_MESSAGE_ERROR, GENERIC_EXECUTE_MESSAGE_PROGRESS, - GENERIC_EXECUTE_MESSAGE_FILES_IN_USE, + GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE, }; typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA @@ -25,7 +25,7 @@ typedef struct _APPLY_AUTHENTICATION_REQUIRED_DATA typedef struct _GENERIC_EXECUTE_MESSAGE { GENERIC_EXECUTE_MESSAGE_TYPE type; - DWORD dwAllowedResults; + DWORD dwUIHint; union { diff --git a/src/burn/engine/detect.cpp b/src/burn/engine/detect.cpp index 5f68a240..4eda240e 100644 --- a/src/burn/engine/detect.cpp +++ b/src/burn/engine/detect.cpp @@ -306,8 +306,8 @@ static HRESULT WINAPI AuthenticationRequired( hr = StrAllocFromError(&sczError, HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), NULL); ExitOnFailure(hr, "Failed to allocation error string."); - UserExperienceOnError(pAuthenticationData->pUX, errorType, pAuthenticationData->wzPackageOrContainerId, ERROR_ACCESS_DENIED, sczError, MB_RETRYTRYAGAIN, 0, NULL, &nResult); // ignore return value. - nResult = UserExperienceCheckExecuteResult(pAuthenticationData->pUX, FALSE, MB_RETRYTRYAGAIN, nResult); + UserExperienceOnError(pAuthenticationData->pUX, errorType, pAuthenticationData->wzPackageOrContainerId, ERROR_ACCESS_DENIED, sczError, MB_RETRYCANCEL, 0, NULL, &nResult); // ignore return value. + nResult = UserExperienceCheckExecuteResult(pAuthenticationData->pUX, FALSE, BURN_MB_RETRYTRYAGAIN, nResult); if (IDTRYAGAIN == nResult && pAuthenticationData->pUX->hwndDetect) { er = ::InternetErrorDlg(pAuthenticationData->pUX->hwndDetect, hUrl, ERROR_INTERNET_INCORRECT_PASSWORD, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, NULL); diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 12c9f296..6c4a775f 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp @@ -42,7 +42,8 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, - BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE, + BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE, + BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE, } BURN_ELEVATION_MESSAGE_TYPE; @@ -1618,7 +1619,7 @@ static HRESULT ProcessGenericExecuteMessages( LPWSTR* rgwzFiles = NULL; GENERIC_EXECUTE_MESSAGE message = { }; - hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwAllowedResults); + hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint); ExitOnFailure(hr, "Failed to allowed results."); // Process the message. @@ -1645,8 +1646,8 @@ static HRESULT ProcessGenericExecuteMessages( message.error.wzMessage = sczMessage; break; - case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE: - message.type = GENERIC_EXECUTE_MESSAGE_FILES_IN_USE; + case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE: + message.type = GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE; // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cFiles); @@ -1701,6 +1702,7 @@ static HRESULT ProcessMsiPackageMessages( LPWSTR* rgwzMsiData = NULL; BURN_ELEVATION_MSI_MESSAGE_CONTEXT* pContext = static_cast(pvContext); LPWSTR sczMessage = NULL; + BOOL fRestartManager = FALSE; // Read MSI extended message data. hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cMsiData); @@ -1721,7 +1723,7 @@ static HRESULT ProcessMsiPackageMessages( message.rgwzData = (LPCWSTR*)rgwzMsiData; } - hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwAllowedResults); + hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint); ExitOnFailure(hr, "Failed to read UI flags."); // Process the rest of the message. @@ -1759,8 +1761,11 @@ static HRESULT ProcessMsiPackageMessages( message.msiMessage.wzMessage = sczMessage; break; - case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE: - message.type = WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE; + case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE: + hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, (DWORD*)&fRestartManager); + ExitOnFailure(hr, "Failed to read fRestartManager."); + + message.type = fRestartManager ? WIU_MSI_EXECUTE_MESSAGE_MSI_RM_FILES_IN_USE : WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE; message.msiFilesInUse.cFiles = cMsiData; message.msiFilesInUse.rgwzFiles = (LPCWSTR*)rgwzMsiData; break; @@ -3006,7 +3011,7 @@ static int GenericExecuteMessageHandler( SIZE_T cbData = 0; DWORD dwMessage = 0; - hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwAllowedResults); + hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwUIHint); ExitOnFailure(hr, "Failed to write UI flags."); switch(pMessage->type) @@ -3030,7 +3035,7 @@ static int GenericExecuteMessageHandler( dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR; break; - case GENERIC_EXECUTE_MESSAGE_FILES_IN_USE: + case GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE: hr = BuffWriteNumber(&pbData, &cbData, pMessage->filesInUse.cFiles); ExitOnFailure(hr, "Failed to count of files in use to message buffer."); @@ -3040,7 +3045,7 @@ static int GenericExecuteMessageHandler( ExitOnFailure(hr, "Failed to write file in use to message buffer."); } - dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE; + dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE; break; } @@ -3065,6 +3070,7 @@ static int MsiExecuteMessageHandler( BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwMessage = 0; + BOOL fRestartManager = FALSE; // Always send any extra data via the struct first. hr = BuffWriteNumber(&pbData, &cbData, pMessage->cData); @@ -3076,7 +3082,7 @@ static int MsiExecuteMessageHandler( ExitOnFailure(hr, "Failed to write MSI data to message buffer."); } - hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwAllowedResults); + hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwUIHint); ExitOnFailure(hr, "Failed to write UI flags."); switch (pMessage->type) @@ -3114,11 +3120,15 @@ static int MsiExecuteMessageHandler( dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE; break; + case WIU_MSI_EXECUTE_MESSAGE_MSI_RM_FILES_IN_USE: + fRestartManager = TRUE; + __fallthrough; case WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE: - // NOTE: we do not serialize other message data here because all the "files in use" are in the data above. + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRestartManager); + ExitOnFailure(hr, "Failed to write fRestartManager to message buffer."); // set message id - dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE; + dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE; break; default: diff --git a/src/burn/engine/embedded.cpp b/src/burn/engine/embedded.cpp index 03898ebd..1c295d59 100644 --- a/src/burn/engine/embedded.cpp +++ b/src/burn/engine/embedded.cpp @@ -161,7 +161,7 @@ static HRESULT OnEmbeddedErrorMessage( message.error.wzMessage = sczMessage; - hr = BuffReadNumber(pbData, cbData, &iData, &message.dwAllowedResults); + hr = BuffReadNumber(pbData, cbData, &iData, &message.dwUIHint); ExitOnFailure(hr, "Failed to read UI hint from buffer."); *pdwResult = (DWORD)pfnMessageHandler(&message, pvContext); @@ -185,7 +185,7 @@ static HRESULT OnEmbeddedProgress( GENERIC_EXECUTE_MESSAGE message = { }; message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; hr = BuffReadNumber(pbData, cbData, &iData, &message.progress.dwPercentage); ExitOnFailure(hr, "Failed to read progress from buffer."); diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index 67da3bdd..b728f599 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp @@ -533,7 +533,7 @@ extern "C" HRESULT ExeEngineExecutePackage( do { message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = 50; nResult = pfnGenericMessageHandler(&message, pvContext); hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp index 1ce2dd11..693bb64b 100644 --- a/src/burn/engine/msuengine.cpp +++ b/src/burn/engine/msuengine.cpp @@ -339,7 +339,7 @@ extern "C" HRESULT MsuEngineExecutePackage( do { message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = 50; nResult = pfnGenericMessageHandler(&message, pvContext); hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); diff --git a/src/burn/engine/netfxchainer.cpp b/src/burn/engine/netfxchainer.cpp index 4e7a7720..af4f03f5 100644 --- a/src/burn/engine/netfxchainer.cpp +++ b/src/burn/engine/netfxchainer.cpp @@ -233,8 +233,8 @@ static HRESULT OnNetFxFilesInUse( } // send message - message.type = GENERIC_EXECUTE_MESSAGE_FILES_IN_USE; - message.dwAllowedResults = MB_ABORTRETRYIGNORE; + message.type = GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE; + message.dwUIHint = MB_ABORTRETRYIGNORE; message.filesInUse.cFiles = cFiles; message.filesInUse.rgwzFiles = (LPCWSTR*)rgwzFiles; dwResponse = (DWORD)pfnMessageHandler(&message, pvContext); @@ -259,7 +259,7 @@ static HRESULT OnNetFxProgress( // send message message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; - message.dwAllowedResults = MB_OKCANCEL; + message.dwUIHint = MB_OKCANCEL; message.progress.dwPercentage = 100 * (DWORD)bProgress / BYTE_MAX; dwResponse = (DWORD)pfnMessageHandler(&message, pvContext); @@ -283,7 +283,7 @@ static HRESULT OnNetFxError( // send message message.type = GENERIC_EXECUTE_MESSAGE_ERROR; - message.dwAllowedResults = MB_OK; + message.dwUIHint = MB_OK; message.error.dwErrorCode = hrError; message.error.wzMessage = NULL; dwResponse = (DWORD)pfnMessageHandler(&message, pvContext); diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index a6d670ea..7cc6f049 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp @@ -1494,6 +1494,7 @@ EXTERN_C BAAPI UserExperienceOnExecuteFilesInUse( __in_z LPCWSTR wzPackageId, __in DWORD cFiles, __in_ecount_z_opt(cFiles) LPCWSTR* rgwzFiles, + __in BOOTSTRAPPER_FILES_IN_USE_TYPE source, __inout int* pnResult ) { @@ -1506,6 +1507,7 @@ EXTERN_C BAAPI UserExperienceOnExecuteFilesInUse( args.cFiles = cFiles; args.rgwzFiles = rgwzFiles; args.nRecommendation = *pnResult; + args.source = source; results.cbSize = sizeof(results); results.nResult = *pnResult; @@ -2492,13 +2494,12 @@ static int FilterResult( __in int nResult ) { - DWORD dwFilteredAllowedResults = dwAllowedResults & MB_TYPEMASK; if (IDNOACTION == nResult || IDERROR == nResult) // do nothing and errors pass through. { } else { - switch (dwFilteredAllowedResults) + switch (dwAllowedResults) { case MB_OK: nResult = IDOK; @@ -2606,7 +2607,28 @@ static int FilterResult( } break; - case WIU_MB_OKIGNORECANCELRETRY: // custom Windows Installer utility return code. + case BURN_MB_MSI_FILES_IN_USE: + // https://docs.microsoft.com/en-us/windows/win32/msi/installvalidate-action + if (IDRETRY == nResult || IDTRYAGAIN == nResult) + { + nResult = IDRETRY; + } + else if (IDCANCEL == nResult || IDABORT == nResult) + { + nResult = IDCANCEL; + } + else if (IDCONTINUE == nResult || IDIGNORE == nResult) + { + nResult = IDIGNORE; + } + else + { + nResult = IDNOACTION; + } + break; + + case BURN_MB_MSI_RM_FILES_IN_USE: + // https://docs.microsoft.com/en-us/windows/win32/msi/using-restart-manager-with-an-external-ui- if (IDOK == nResult || IDYES == nResult) { nResult = IDOK; @@ -2615,11 +2637,15 @@ static int FilterResult( { nResult = IDIGNORE; } + else if (IDNO == nResult) + { + nResult = IDNO; + } else if (IDCANCEL == nResult || IDABORT == nResult) { nResult = IDCANCEL; } - else if (IDRETRY == nResult || IDTRYAGAIN == nResult || IDNO == nResult) + else if (IDRETRY == nResult || IDTRYAGAIN == nResult) { nResult = IDRETRY; } @@ -2629,13 +2655,33 @@ static int FilterResult( } break; - case MB_RETRYTRYAGAIN: // custom return code. + case BURN_MB_RETRYTRYAGAIN: // custom return code. if (IDRETRY != nResult && IDTRYAGAIN != nResult) { nResult = IDNOACTION; } break; + case BURN_MB_NETFX_FILES_IN_USE: + // https://docs.microsoft.com/en-us/dotnet/framework/deployment/how-to-get-progress-from-the-dotnet-installer + if (IDOK == nResult || IDYES == nResult) + { + nResult = IDYES; + } + else if (IDRETRY == nResult || IDTRYAGAIN == nResult) + { + nResult = IDRETRY; + } + else if (IDCANCEL == nResult || IDABORT == nResult) + { + nResult = IDCANCEL; + } + else + { + nResult = IDNO; + } + break; + default: AssertSz(FALSE, "Unknown allowed results."); break; diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h index f7ac962c..75723afa 100644 --- a/src/burn/engine/userexperience.h +++ b/src/burn/engine/userexperience.h @@ -10,7 +10,10 @@ extern "C" { // constants -const DWORD MB_RETRYTRYAGAIN = 0xF; +const DWORD BURN_MB_RETRYTRYAGAIN = 0x10; +const DWORD BURN_MB_MSI_FILES_IN_USE = 0x11; +const DWORD BURN_MB_MSI_RM_FILES_IN_USE = 0x12; +const DWORD BURN_MB_NETFX_FILES_IN_USE = 0x13; // structs @@ -356,6 +359,7 @@ BAAPI UserExperienceOnExecuteFilesInUse( __in_z LPCWSTR wzPackageId, __in DWORD cFiles, __in_ecount_z_opt(cFiles) LPCWSTR* rgwzFiles, + __in BOOTSTRAPPER_FILES_IN_USE_TYPE source, __inout int* pnResult ); BAAPI UserExperienceOnExecuteMsiMessage( -- cgit v1.2.3-55-g6feb