diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-07-24 14:09:53 -0500 |
---|---|---|
committer | Bob Arnson <github@bobs.org> | 2022-07-25 13:04:12 -0400 |
commit | b86beafe859dea600209d19502bc194affd5fe2b (patch) | |
tree | 4eaeeb3cfb51f06119b21a9990daa530571e24da | |
parent | 2e327df0b7c785a6cad36f6b3bf79ba8becf9000 (diff) | |
download | wix-b86beafe859dea600209d19502bc194affd5fe2b.tar.gz wix-b86beafe859dea600209d19502bc194affd5fe2b.tar.bz2 wix-b86beafe859dea600209d19502bc194affd5fe2b.zip |
Add dialog for non-RM FilesInUse and Netfx FilesInUse.
Fixes 5208
-rw-r--r-- | src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl | 4 | ||||
-rw-r--r-- | src/ext/Bal/wixstdba/Resources/RtfTheme.wxl | 4 | ||||
-rw-r--r-- | src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp | 266 |
3 files changed, 246 insertions, 28 deletions
diff --git a/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl b/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl index 9fd0be43..cb1f8da4 100644 --- a/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl +++ b/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl | |||
@@ -65,6 +65,10 @@ | |||
65 | <String Id="FailureCloseButton">&Close</String> | 65 | <String Id="FailureCloseButton">&Close</String> |
66 | <String Id="FilesInUseTitle">Files In Use</String> | 66 | <String Id="FilesInUseTitle">Files In Use</String> |
67 | <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> | 67 | <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> |
68 | <String Id="FilesInUseNetfxCloseRadioButton">Close the &applications.</String> | ||
68 | <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> | 69 | <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> |
69 | <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> | 70 | <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> |
71 | <String Id="FilesInUseRetryButton">&Retry</String> | ||
72 | <String Id="FilesInUseIgnoreButton">&Ignore</String> | ||
73 | <String Id="FilesInUseExitButton">E&xit</String> | ||
70 | </WixLocalization> | 74 | </WixLocalization> |
diff --git a/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl b/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl index 4948cd75..efe66f41 100644 --- a/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl +++ b/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl | |||
@@ -62,6 +62,10 @@ | |||
62 | <String Id="FailureCloseButton">&Close</String> | 62 | <String Id="FailureCloseButton">&Close</String> |
63 | <String Id="FilesInUseTitle">Files In Use</String> | 63 | <String Id="FilesInUseTitle">Files In Use</String> |
64 | <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> | 64 | <String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String> |
65 | <String Id="FilesInUseNetfxCloseRadioButton">Close the &applications.</String> | ||
65 | <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> | 66 | <String Id="FilesInUseCloseRadioButton">Close the &applications and attempt to restart them.</String> |
66 | <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> | 67 | <String Id="FilesInUseDontCloseRadioButton">&Do not close applications. A reboot will be required.</String> |
68 | <String Id="FilesInUseRetryButton">&Retry</String> | ||
69 | <String Id="FilesInUseIgnoreButton">&Ignore</String> | ||
70 | <String Id="FilesInUseExitButton">E&xit</String> | ||
67 | </WixLocalization> | 71 | </WixLocalization> |
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp index 2ef829d7..5fc20368 100644 --- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp +++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp | |||
@@ -604,6 +604,8 @@ public: // IBootstrapperApplication | |||
604 | m_fStartedExecution = FALSE; | 604 | m_fStartedExecution = FALSE; |
605 | m_dwCalculatedCacheProgress = 0; | 605 | m_dwCalculatedCacheProgress = 0; |
606 | m_dwCalculatedExecuteProgress = 0; | 606 | m_dwCalculatedExecuteProgress = 0; |
607 | m_nLastMsiFilesInUseResult = IDNOACTION; | ||
608 | m_nLastNetfxFilesInUseResult = IDNOACTION; | ||
607 | 609 | ||
608 | return __super::OnApplyBegin(dwPhaseCount, pfCancel); | 610 | return __super::OnApplyBegin(dwPhaseCount, pfCancel); |
609 | } | 611 | } |
@@ -1049,15 +1051,15 @@ public: // IBootstrapperApplication | |||
1049 | 1051 | ||
1050 | if (!m_fShowingInternalUiThisPackage && !m_fPrereq && wzPackageId && *wzPackageId) | 1052 | if (!m_fShowingInternalUiThisPackage && !m_fPrereq && wzPackageId && *wzPackageId) |
1051 | { | 1053 | { |
1052 | // If this is an MSI package, display the files-in-use dialog. | 1054 | BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Package %ls has %d applications holding files in use.", wzPackageId, cFiles); |
1053 | BAL_INFO_PACKAGE* pPackage = NULL; | ||
1054 | BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage); | ||
1055 | 1055 | ||
1056 | if (pPackage && BAL_INFO_PACKAGE_TYPE_MSI == pPackage->type) | 1056 | switch (source) |
1057 | { | 1057 | { |
1058 | BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Package %ls has %d applications holding files in use.", wzPackageId, cFiles); | 1058 | case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI: |
1059 | 1059 | case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI_RM: | |
1060 | return ShowFilesInUse(cFiles, rgwzFiles, source); | 1060 | return ShowMsiFilesInUse(cFiles, rgwzFiles, source, pResult); |
1061 | case BOOTSTRAPPER_FILES_IN_USE_TYPE_NETFX: | ||
1062 | return ShowNetfxFilesInUse(cFiles, rgwzFiles, pResult); | ||
1061 | } | 1063 | } |
1062 | } | 1064 | } |
1063 | 1065 | ||
@@ -2213,10 +2215,11 @@ private: // privates | |||
2213 | } | 2215 | } |
2214 | 2216 | ||
2215 | 2217 | ||
2216 | int ShowFilesInUse( | 2218 | HRESULT ShowMsiFilesInUse( |
2217 | __in DWORD cFiles, | 2219 | __in DWORD cFiles, |
2218 | __in_ecount_z(cFiles) LPCWSTR* rgwzFiles, | 2220 | __in_ecount_z(cFiles) LPCWSTR* rgwzFiles, |
2219 | __in BOOTSTRAPPER_FILES_IN_USE_TYPE /*source*/ | 2221 | __in BOOTSTRAPPER_FILES_IN_USE_TYPE source, |
2222 | __inout int* pResult | ||
2220 | ) | 2223 | ) |
2221 | { | 2224 | { |
2222 | HRESULT hr = S_OK; | 2225 | HRESULT hr = S_OK; |
@@ -2226,9 +2229,9 @@ private: // privates | |||
2226 | 2229 | ||
2227 | // If the user has chosen to ignore on a previously displayed "files in use" page, | 2230 | // If the user has chosen to ignore on a previously displayed "files in use" page, |
2228 | // we will return the same result for other cases. No need to display the page again. | 2231 | // we will return the same result for other cases. No need to display the page again. |
2229 | if (IDIGNORE == m_nLastFilesInUseResult) | 2232 | if (IDIGNORE == m_nLastMsiFilesInUseResult) |
2230 | { | 2233 | { |
2231 | nResult = m_nLastFilesInUseResult; | 2234 | nResult = m_nLastMsiFilesInUseResult; |
2232 | } | 2235 | } |
2233 | else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) // Only show files in use when using full display mode. | 2236 | else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) // Only show files in use when using full display mode. |
2234 | { | 2237 | { |
@@ -2246,8 +2249,16 @@ private: // privates | |||
2246 | } | 2249 | } |
2247 | 2250 | ||
2248 | // Show applications using the files. | 2251 | // Show applications using the files. |
2249 | hr = ShowFilesInUseDialog(sczFilesInUse, &nResult); | 2252 | if (BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI_RM == source) |
2250 | ExitOnFailure(hr, "Failed to show files-in-use task dialog."); | 2253 | { |
2254 | hr = ShowRestartManagerMsiFilesInUseDialog(sczFilesInUse, &nResult); | ||
2255 | ExitOnFailure(hr, "Failed to show RM files-in-use dialog."); | ||
2256 | } | ||
2257 | else | ||
2258 | { | ||
2259 | hr = ShowStandardMsiFilesInUseDialog(sczFilesInUse, &nResult); | ||
2260 | ExitOnFailure(hr, "Failed to show files-in-use dialog."); | ||
2261 | } | ||
2251 | } | 2262 | } |
2252 | else | 2263 | else |
2253 | { | 2264 | { |
@@ -2260,13 +2271,14 @@ private: // privates | |||
2260 | ReleaseStr(sczFilesInUse); | 2271 | ReleaseStr(sczFilesInUse); |
2261 | 2272 | ||
2262 | // Remember the answer from the user. | 2273 | // Remember the answer from the user. |
2263 | m_nLastFilesInUseResult = FAILED(hr) ? IDERROR : nResult; | 2274 | m_nLastMsiFilesInUseResult = FAILED(hr) ? IDERROR : nResult; |
2275 | *pResult = m_nLastMsiFilesInUseResult; | ||
2264 | 2276 | ||
2265 | return m_nLastFilesInUseResult; | 2277 | return hr; |
2266 | } | 2278 | } |
2267 | 2279 | ||
2268 | 2280 | ||
2269 | int ShowFilesInUseDialog( | 2281 | int ShowRestartManagerMsiFilesInUseDialog( |
2270 | __in_z_opt LPCWSTR sczFilesInUse, | 2282 | __in_z_opt LPCWSTR sczFilesInUse, |
2271 | __out int* pnResult | 2283 | __out int* pnResult |
2272 | ) | 2284 | ) |
@@ -2283,28 +2295,28 @@ private: // privates | |||
2283 | 2295 | ||
2284 | // Get the loc strings for the files-in-use task dialog text. | 2296 | // Get the loc strings for the files-in-use task dialog text. |
2285 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseTitle)", &pLocString); | 2297 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseTitle)", &pLocString); |
2286 | ExitOnFailure(hr, "Failed to get FilesInUseTitle loc string."); | 2298 | BalExitOnFailure(hr, "Failed to get FilesInUseTitle loc string."); |
2287 | 2299 | ||
2288 | hr = StrAllocString(&sczTitle, pLocString->wzText, 0); | 2300 | hr = StrAllocString(&sczTitle, pLocString->wzText, 0); |
2289 | ExitOnFailure(hr, "Failed to copy FilesInUseTitle loc string."); | 2301 | BalExitOnFailure(hr, "Failed to copy FilesInUseTitle loc string."); |
2290 | 2302 | ||
2291 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseLabel)", &pLocString); | 2303 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseLabel)", &pLocString); |
2292 | ExitOnFailure(hr, "Failed to get FilesInUseLabel loc string."); | 2304 | BalExitOnFailure(hr, "Failed to get FilesInUseLabel loc string."); |
2293 | 2305 | ||
2294 | hr = StrAllocString(&sczLabel, pLocString->wzText, 0); | 2306 | hr = StrAllocString(&sczLabel, pLocString->wzText, 0); |
2295 | ExitOnFailure(hr, "Failed to copy FilesInUseLabel loc string."); | 2307 | BalExitOnFailure(hr, "Failed to copy FilesInUseLabel loc string."); |
2296 | 2308 | ||
2297 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseCloseRadioButton)", &pLocString); | 2309 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseCloseRadioButton)", &pLocString); |
2298 | ExitOnFailure(hr, "Failed to get FilesInUseCloseRadioButton loc string."); | 2310 | BalExitOnFailure(hr, "Failed to get FilesInUseCloseRadioButton loc string."); |
2299 | 2311 | ||
2300 | hr = StrAllocString(&sczCloseRadioButton, pLocString->wzText, 0); | 2312 | hr = StrAllocString(&sczCloseRadioButton, pLocString->wzText, 0); |
2301 | ExitOnFailure(hr, "Failed to copy FilesInUseCloseRadioButton loc string."); | 2313 | BalExitOnFailure(hr, "Failed to copy FilesInUseCloseRadioButton loc string."); |
2302 | 2314 | ||
2303 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseDontCloseRadioButton)", &pLocString); | 2315 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseDontCloseRadioButton)", &pLocString); |
2304 | ExitOnFailure(hr, "Failed to get FilesInUseDontCloseRadioButton loc string."); | 2316 | BalExitOnFailure(hr, "Failed to get FilesInUseDontCloseRadioButton loc string."); |
2305 | 2317 | ||
2306 | hr = StrAllocString(&sczDontCloseRadioButton, pLocString->wzText, 0); | 2318 | hr = StrAllocString(&sczDontCloseRadioButton, pLocString->wzText, 0); |
2307 | ExitOnFailure(hr, "Failed to copy FilesInUseDontCloseRadioButton loc string."); | 2319 | BalExitOnFailure(hr, "Failed to copy FilesInUseDontCloseRadioButton loc string."); |
2308 | 2320 | ||
2309 | const TASKDIALOG_BUTTON rgRadioButtons[] = { | 2321 | const TASKDIALOG_BUTTON rgRadioButtons[] = { |
2310 | { IDOK, sczCloseRadioButton }, | 2322 | { IDOK, sczCloseRadioButton }, |
@@ -2325,12 +2337,208 @@ private: // privates | |||
2325 | config.nDefaultRadioButton = IDOK; | 2337 | config.nDefaultRadioButton = IDOK; |
2326 | 2338 | ||
2327 | hr = ::TaskDialogIndirect(&config, &nButton, &nRadioButton, NULL); | 2339 | hr = ::TaskDialogIndirect(&config, &nButton, &nRadioButton, NULL); |
2328 | ExitOnFailure(hr, "Failed to show files-in-use task dialog."); | 2340 | BalExitOnFailure(hr, "Failed to show RM files-in-use task dialog."); |
2341 | |||
2342 | *pnResult = IDOK == nButton ? nRadioButton : nButton; | ||
2343 | |||
2344 | #ifdef DEBUG | ||
2345 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: RMFilesInUse task dialog result: button - %d, radio button - %d, result - %d", nButton, nRadioButton, *pnResult); | ||
2346 | #endif | ||
2347 | |||
2348 | LExit: | ||
2349 | return hr; | ||
2350 | } | ||
2351 | |||
2352 | |||
2353 | int ShowStandardMsiFilesInUseDialog( | ||
2354 | __in_z_opt LPCWSTR sczFilesInUse, | ||
2355 | __out int* pnResult | ||
2356 | ) | ||
2357 | { | ||
2358 | HRESULT hr = S_OK; | ||
2359 | TASKDIALOGCONFIG config = { }; | ||
2360 | LPWSTR sczTitle = NULL; | ||
2361 | LPWSTR sczLabel = NULL; | ||
2362 | LPWSTR sczRetryButton = NULL; | ||
2363 | LPWSTR sczIgnoreButton = NULL; | ||
2364 | LPWSTR sczExitButton = NULL; | ||
2365 | LOC_STRING* pLocString = NULL; | ||
2366 | |||
2367 | // Get the loc strings for the files-in-use task dialog text. | ||
2368 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseTitle)", &pLocString); | ||
2369 | BalExitOnFailure(hr, "Failed to get FilesInUseTitle loc string."); | ||
2370 | |||
2371 | hr = StrAllocString(&sczTitle, pLocString->wzText, 0); | ||
2372 | BalExitOnFailure(hr, "Failed to copy FilesInUseTitle loc string."); | ||
2373 | |||
2374 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseLabel)", &pLocString); | ||
2375 | BalExitOnFailure(hr, "Failed to get FilesInUseLabel loc string."); | ||
2376 | |||
2377 | hr = StrAllocString(&sczLabel, pLocString->wzText, 0); | ||
2378 | BalExitOnFailure(hr, "Failed to copy FilesInUseLabel loc string."); | ||
2379 | |||
2380 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseRetryButton)", &pLocString); | ||
2381 | BalExitOnFailure(hr, "Failed to get FilesInUseRetryButton loc string."); | ||
2382 | |||
2383 | hr = StrAllocString(&sczRetryButton, pLocString->wzText, 0); | ||
2384 | BalExitOnFailure(hr, "Failed to copy FilesInUseRetryButton loc string."); | ||
2385 | |||
2386 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseIgnoreButton)", &pLocString); | ||
2387 | BalExitOnFailure(hr, "Failed to get FilesInUseIgnoreButton loc string."); | ||
2388 | |||
2389 | hr = StrAllocString(&sczIgnoreButton, pLocString->wzText, 0); | ||
2390 | BalExitOnFailure(hr, "Failed to copy FilesInUseIgnoreButton loc string."); | ||
2391 | |||
2392 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseExitButton)", &pLocString); | ||
2393 | BalExitOnFailure(hr, "Failed to get FilesInUseExitButton loc string."); | ||
2394 | |||
2395 | hr = StrAllocString(&sczExitButton, pLocString->wzText, 0); | ||
2396 | BalExitOnFailure(hr, "Failed to copy FilesInUseExitButton loc string."); | ||
2397 | |||
2398 | const TASKDIALOG_BUTTON rgButtons[] = { | ||
2399 | { IDRETRY, sczRetryButton }, | ||
2400 | { IDIGNORE, sczIgnoreButton }, | ||
2401 | { IDCANCEL, sczExitButton }, | ||
2402 | }; | ||
2403 | |||
2404 | config.cbSize = sizeof(config); | ||
2405 | config.hwndParent = m_hWnd; | ||
2406 | config.hInstance = m_hModule; | ||
2407 | config.dwFlags = TDF_SIZE_TO_CONTENT | TDF_POSITION_RELATIVE_TO_WINDOW; | ||
2408 | config.pszWindowTitle = sczTitle; | ||
2409 | config.pszMainInstruction = sczLabel; | ||
2410 | config.pszContent = sczFilesInUse ? sczFilesInUse : L""; | ||
2411 | config.pButtons = rgButtons; | ||
2412 | config.cButtons = countof(rgButtons); | ||
2413 | |||
2414 | hr = ::TaskDialogIndirect(&config, pnResult, NULL, NULL); | ||
2415 | BalExitOnFailure(hr, "Failed to show files-in-use task dialog."); | ||
2416 | |||
2417 | #ifdef DEBUG | ||
2418 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: FilesInUse task dialog result: %d", *pnResult); | ||
2419 | #endif | ||
2420 | |||
2421 | LExit: | ||
2422 | return hr; | ||
2423 | } | ||
2424 | |||
2425 | |||
2426 | HRESULT ShowNetfxFilesInUse( | ||
2427 | __in DWORD cFiles, | ||
2428 | __in_ecount_z(cFiles) LPCWSTR* rgwzFiles, | ||
2429 | __inout int* pResult | ||
2430 | ) | ||
2431 | { | ||
2432 | HRESULT hr = S_OK; | ||
2433 | LPWSTR sczFilesInUse = NULL; | ||
2434 | DWORD_PTR cchLen = 0; | ||
2435 | int nResult = IDERROR; | ||
2436 | |||
2437 | // If the user has chosen to ignore on a previously displayed "files in use" page, | ||
2438 | // we will return the same result for other cases. No need to display the page again. | ||
2439 | if (IDNO == m_nLastNetfxFilesInUseResult) | ||
2440 | { | ||
2441 | nResult = m_nLastNetfxFilesInUseResult; | ||
2442 | } | ||
2443 | else if (BOOTSTRAPPER_DISPLAY_FULL != m_command.display) // Only show files in use when using full display mode. | ||
2444 | { | ||
2445 | nResult = IDYES; | ||
2446 | } | ||
2447 | else | ||
2448 | { | ||
2449 | for (DWORD i = 0; i < cFiles; ++i) | ||
2450 | { | ||
2451 | hr = ::StringCchLengthW(rgwzFiles[i], STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen)); | ||
2452 | BalExitOnFailure(hr, "Failed to calculate length of string."); | ||
2453 | |||
2454 | if (cchLen) | ||
2455 | { | ||
2456 | hr = StrAllocConcatFormatted(&sczFilesInUse, L"%ls\r\n", rgwzFiles[i]); | ||
2457 | BalExitOnFailure(hr, "Failed to concat files in use."); | ||
2458 | } | ||
2459 | } | ||
2460 | |||
2461 | // Show applications using the files. | ||
2462 | hr = ShowNetfxFilesInUseDialog(sczFilesInUse, &nResult); | ||
2463 | ExitOnFailure(hr, "Failed to show Netfx files-in-use dialog."); | ||
2464 | } | ||
2465 | |||
2466 | LExit: | ||
2467 | ReleaseStr(sczFilesInUse); | ||
2468 | |||
2469 | // Remember the answer from the user. | ||
2470 | m_nLastNetfxFilesInUseResult = FAILED(hr) ? IDERROR : nResult; | ||
2471 | *pResult = m_nLastNetfxFilesInUseResult; | ||
2472 | |||
2473 | return hr; | ||
2474 | } | ||
2475 | |||
2476 | |||
2477 | int ShowNetfxFilesInUseDialog( | ||
2478 | __in_z_opt LPCWSTR sczFilesInUse, | ||
2479 | __out int* pnResult | ||
2480 | ) | ||
2481 | { | ||
2482 | HRESULT hr = S_OK; | ||
2483 | TASKDIALOGCONFIG config = { }; | ||
2484 | LPWSTR sczTitle = NULL; | ||
2485 | LPWSTR sczLabel = NULL; | ||
2486 | LPWSTR sczNetfxCloseRadioButton = NULL; | ||
2487 | LPWSTR sczDontCloseRadioButton = NULL; | ||
2488 | LOC_STRING* pLocString = NULL; | ||
2489 | int nButton = 0; | ||
2490 | int nRadioButton = 0; | ||
2491 | |||
2492 | // Get the loc strings for the files-in-use task dialog text. | ||
2493 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseTitle)", &pLocString); | ||
2494 | BalExitOnFailure(hr, "Failed to get FilesInUseTitle loc string."); | ||
2495 | |||
2496 | hr = StrAllocString(&sczTitle, pLocString->wzText, 0); | ||
2497 | BalExitOnFailure(hr, "Failed to copy FilesInUseTitle loc string."); | ||
2498 | |||
2499 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseLabel)", &pLocString); | ||
2500 | BalExitOnFailure(hr, "Failed to get FilesInUseLabel loc string."); | ||
2501 | |||
2502 | hr = StrAllocString(&sczLabel, pLocString->wzText, 0); | ||
2503 | BalExitOnFailure(hr, "Failed to copy FilesInUseLabel loc string."); | ||
2504 | |||
2505 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseNetfxCloseRadioButton)", &pLocString); | ||
2506 | BalExitOnFailure(hr, "Failed to get FilesInUseNetfxCloseRadioButton loc string."); | ||
2507 | |||
2508 | hr = StrAllocString(&sczNetfxCloseRadioButton, pLocString->wzText, 0); | ||
2509 | BalExitOnFailure(hr, "Failed to copy FilesInUseNetfxCloseRadioButton loc string."); | ||
2510 | |||
2511 | hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseDontCloseRadioButton)", &pLocString); | ||
2512 | BalExitOnFailure(hr, "Failed to get FilesInUseDontCloseRadioButton loc string."); | ||
2513 | |||
2514 | hr = StrAllocString(&sczDontCloseRadioButton, pLocString->wzText, 0); | ||
2515 | BalExitOnFailure(hr, "Failed to copy FilesInUseDontCloseRadioButton loc string."); | ||
2516 | |||
2517 | const TASKDIALOG_BUTTON rgRadioButtons[] = { | ||
2518 | { IDYES, sczNetfxCloseRadioButton }, | ||
2519 | { IDNO, sczDontCloseRadioButton }, | ||
2520 | }; | ||
2521 | |||
2522 | config.cbSize = sizeof(config); | ||
2523 | config.hwndParent = m_hWnd; | ||
2524 | config.hInstance = m_hModule; | ||
2525 | config.dwFlags = TDF_SIZE_TO_CONTENT | TDF_POSITION_RELATIVE_TO_WINDOW; | ||
2526 | config.dwCommonButtons = TDCBF_RETRY_BUTTON | TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON; | ||
2527 | config.pszWindowTitle = sczTitle; | ||
2528 | config.pszMainInstruction = sczLabel; | ||
2529 | config.pszContent = sczFilesInUse ? sczFilesInUse : L""; | ||
2530 | config.nDefaultButton = IDRETRY; | ||
2531 | config.pRadioButtons = rgRadioButtons; | ||
2532 | config.cRadioButtons = countof(rgRadioButtons); | ||
2533 | config.nDefaultRadioButton = IDYES; | ||
2534 | |||
2535 | hr = ::TaskDialogIndirect(&config, &nButton, &nRadioButton, NULL); | ||
2536 | BalExitOnFailure(hr, "Failed to show Netfx files-in-use task dialog."); | ||
2329 | 2537 | ||
2330 | *pnResult = IDOK == nButton ? nRadioButton : nButton; | 2538 | *pnResult = IDOK == nButton ? nRadioButton : nButton; |
2331 | 2539 | ||
2332 | #ifdef DEBUG | 2540 | #ifdef DEBUG |
2333 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: FilesInUse task dialog result: button - %d, radio button - %d, result - %d", nButton, nRadioButton, *pnResult); | 2541 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: NetfxFilesInUse task dialog result: button - %d, radio button - %d, result - %d", nButton, nRadioButton, *pnResult); |
2334 | #endif | 2542 | #endif |
2335 | 2543 | ||
2336 | LExit: | 2544 | LExit: |
@@ -4423,7 +4631,8 @@ public: | |||
4423 | m_fPrereqInstalled = FALSE; | 4631 | m_fPrereqInstalled = FALSE; |
4424 | m_fPrereqSkipped = FALSE; | 4632 | m_fPrereqSkipped = FALSE; |
4425 | 4633 | ||
4426 | m_nLastFilesInUseResult = IDNOACTION; | 4634 | m_nLastMsiFilesInUseResult = IDNOACTION; |
4635 | m_nLastNetfxFilesInUseResult = IDNOACTION; | ||
4427 | 4636 | ||
4428 | pEngine->AddRef(); | 4637 | pEngine->AddRef(); |
4429 | m_pEngine = pEngine; | 4638 | m_pEngine = pEngine; |
@@ -4717,7 +4926,8 @@ private: | |||
4717 | BOOL m_fShowingInternalUiThisPackage; | 4926 | BOOL m_fShowingInternalUiThisPackage; |
4718 | BOOL m_fTriedToLaunchElevated; | 4927 | BOOL m_fTriedToLaunchElevated; |
4719 | 4928 | ||
4720 | int m_nLastFilesInUseResult; | 4929 | int m_nLastMsiFilesInUseResult; |
4930 | int m_nLastNetfxFilesInUseResult; | ||
4721 | 4931 | ||
4722 | HMODULE m_hBAFModule; | 4932 | HMODULE m_hBAFModule; |
4723 | PFN_BA_FUNCTIONS_PROC m_pfnBAFunctionsProc; | 4933 | PFN_BA_FUNCTIONS_PROC m_pfnBAFunctionsProc; |