aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clean.cmd3
-rw-r--r--src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl5
-rw-r--r--src/ext/Bal/wixstdba/Resources/RtfTheme.wxl5
-rw-r--r--src/ext/Bal/wixstdba/Resources/dncpreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp174
-rw-r--r--src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wixproj17
-rw-r--r--src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wxs10
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/FilesInUseTests.cs20
-rw-r--r--src/tools/thmviewer/precomp.h2
10 files changed, 214 insertions, 24 deletions
diff --git a/src/clean.cmd b/src/clean.cmd
index bd44bed4..9c4fa0dc 100644
--- a/src/clean.cmd
+++ b/src/clean.cmd
@@ -2,7 +2,10 @@
2 2
3setlocal 3setlocal
4pushd %~dp0 4pushd %~dp0
5
5set _NUGET_CACHE=%USERPROFILE%\.nuget\packages 6set _NUGET_CACHE=%USERPROFILE%\.nuget\packages
7if "%NUGET_PACKAGES%" NEQ "" set _NUGET_CACHE=%NUGET_PACKAGES%
8
6echo Cleaning... 9echo Cleaning...
7 10
8if exist ..\build rd /s/q ..\build 11if exist ..\build rd /s/q ..\build
diff --git a/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl b/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl
index 43b43970..9fd0be43 100644
--- a/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl
+++ b/src/ext/Bal/wixstdba/Resources/HyperlinkTheme.wxl
@@ -63,5 +63,8 @@
63 <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String> 63 <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
64 <String Id="FailureRestartButton">&amp;Restart</String> 64 <String Id="FailureRestartButton">&amp;Restart</String>
65 <String Id="FailureCloseButton">&amp;Close</String> 65 <String Id="FailureCloseButton">&amp;Close</String>
66 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</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>
68 <String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
69 <String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
67</WixLocalization> 70</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl b/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl
index 7b8e1c65..4948cd75 100644
--- a/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl
+++ b/src/ext/Bal/wixstdba/Resources/RtfTheme.wxl
@@ -60,5 +60,8 @@
60 <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String> 60 <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
61 <String Id="FailureRestartButton">&amp;Restart</String> 61 <String Id="FailureRestartButton">&amp;Restart</String>
62 <String Id="FailureCloseButton">&amp;Close</String> 62 <String Id="FailureCloseButton">&amp;Close</String>
63 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</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>
65 <String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
66 <String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
64</WixLocalization> 67</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
index 22fcd3dc..734de0ed 100644
--- a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
@@ -30,5 +30,4 @@
30 <String Id="FailureCloseButton">&amp;Close</String> 30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="SCDRUNTIMEFAILUREErrorMessage">[WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment.</String> 31 <String Id="SCDRUNTIMEFAILUREErrorMessage">[WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Core runtime even though all of the prerequisites are installed.</String> 32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Core runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34</WixLocalization> 33</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
index 77859d31..3fec4254 100644
--- a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
@@ -30,5 +30,4 @@
30 <String Id="FailureCloseButton">&amp;Close</String> 30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String> 32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
34</WixLocalization> 33</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index 1af1abeb..bd0f5a3b 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -867,25 +867,9 @@ public: // IBootstrapperApplication
867 hr = StrAllocFromError(&sczError, dwCode, NULL); 867 hr = StrAllocFromError(&sczError, dwCode, NULL);
868 if (FAILED(hr) || !sczError || !*sczError) 868 if (FAILED(hr) || !sczError || !*sczError)
869 { 869 {
870 // special case for ERROR_FAIL_NOACTION_REBOOT: use loc string for Windows XP 870 StrAllocFormatted(&sczError, L"0x%x", dwCode);
871 if (ERROR_FAIL_NOACTION_REBOOT == dwCode)
872 {
873 LOC_STRING* pLocString = NULL;
874 hr = LocGetString(m_pWixLoc, L"#(loc.ErrorFailNoActionReboot)", &pLocString);
875 if (SUCCEEDED(hr))
876 {
877 StrAllocString(&sczError, pLocString->wzText, 0);
878 }
879 else
880 {
881 StrAllocFormatted(&sczError, L"0x%x", dwCode);
882 }
883 }
884 else
885 {
886 StrAllocFormatted(&sczError, L"0x%x", dwCode);
887 }
888 } 871 }
872
889 hr = S_OK; 873 hr = S_OK;
890 } 874 }
891 875
@@ -1053,6 +1037,34 @@ public: // IBootstrapperApplication
1053 } 1037 }
1054 1038
1055 1039
1040 virtual STDMETHODIMP OnExecuteFilesInUse(
1041 __in_z LPCWSTR wzPackageId,
1042 __in DWORD cFiles,
1043 __in_ecount_z(cFiles) LPCWSTR* rgwzFiles,
1044 __in int nRecommendation,
1045 __in BOOTSTRAPPER_FILES_IN_USE_TYPE source,
1046 __inout int* pResult
1047 )
1048 {
1049
1050 if (!m_fShowingInternalUiThisPackage && !m_fPrereq && wzPackageId && *wzPackageId)
1051 {
1052 // If this is an MSI package, display the files-in-use dialog.
1053 BAL_INFO_PACKAGE* pPackage = NULL;
1054 BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
1055
1056 if (pPackage && BAL_INFO_PACKAGE_TYPE_MSI == pPackage->type)
1057 {
1058 BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Package %ls has %d applications holding files in use.", wzPackageId, cFiles);
1059
1060 return ShowFilesInUse(cFiles, rgwzFiles, source);
1061 }
1062 }
1063
1064 return __super::OnExecuteFilesInUse(wzPackageId, cFiles, rgwzFiles, nRecommendation, source, pResult);
1065 }
1066
1067
1056 virtual STDMETHODIMP OnExecutePackageComplete( 1068 virtual STDMETHODIMP OnExecutePackageComplete(
1057 __in_z LPCWSTR wzPackageId, 1069 __in_z LPCWSTR wzPackageId,
1058 __in HRESULT hrStatus, 1070 __in HRESULT hrStatus,
@@ -2201,6 +2213,126 @@ private: // privates
2201 } 2213 }
2202 2214
2203 2215
2216 int ShowFilesInUse(
2217 __in DWORD cFiles,
2218 __in_ecount_z(cFiles) LPCWSTR* rgwzFiles,
2219 __in BOOTSTRAPPER_FILES_IN_USE_TYPE /*source*/
2220 )
2221 {
2222 HRESULT hr = S_OK;
2223 LPWSTR sczFilesInUse = NULL;
2224 DWORD_PTR cchLen = 0;
2225 int nResult = IDERROR;
2226
2227 // If the user has choosen 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.
2229 if (IDIGNORE == m_nLastFilesInUseResult)
2230 {
2231 nResult = m_nLastFilesInUseResult;
2232 }
2233 else if (BOOTSTRAPPER_DISPLAY_FULL == m_command.display) // Only show files in use when using full display mode.
2234 {
2235 // Show applications using the files.
2236 if (cFiles > 0)
2237 {
2238 // See https://msdn.microsoft.com/en-us/library/aa371614%28v=vs.85%29.aspx for details.
2239 for (DWORD i = 1; i < cFiles; i += 2)
2240 {
2241 hr = ::StringCchLengthW(rgwzFiles[i], STRSAFE_MAX_CCH, reinterpret_cast<UINT_PTR*>(&cchLen));
2242 BalExitOnFailure(hr, "Failed to calculate length of string");
2243
2244 if (cchLen > 0)
2245 {
2246 hr = StrAllocConcat(&sczFilesInUse, rgwzFiles[i], 0);
2247 BalExitOnFailure(hr, "Failed to concat files in use");
2248
2249 hr = StrAllocConcat(&sczFilesInUse, L"\r\n", 2);
2250 BalExitOnFailure(hr, "Failed to concat files in use");
2251 }
2252 }
2253 }
2254
2255 hr = ShowFilesInUseDialog(sczFilesInUse, &nResult);
2256 ExitOnFailure(hr, "Failed to show files-in-use task dialog.");
2257 }
2258 else
2259 {
2260 // Silent UI level installations always shut down applications and services,
2261 // and on Windows Vista and later, use Restart Manager unless disabled.
2262 nResult = IDOK;
2263 }
2264
2265 LExit:
2266 ReleaseStr(sczFilesInUse);
2267
2268 // Remember the answer from the user.
2269 m_nLastFilesInUseResult = FAILED(hr) ? IDERROR : nResult;
2270
2271 return m_nLastFilesInUseResult;
2272 }
2273
2274
2275 int ShowFilesInUseDialog(
2276 __in_z_opt LPCWSTR sczFilesInUse,
2277 __out int* pnResult
2278 )
2279 {
2280 HRESULT hr = S_OK;
2281 TASKDIALOGCONFIG config = { };
2282 LPWSTR sczTitle = NULL;
2283 LPWSTR sczLabel = NULL;
2284 LPWSTR sczCloseRadioButton = NULL;
2285 LPWSTR sczDontCloseRadioButton = NULL;
2286 LOC_STRING* pLocString = NULL;
2287
2288 // Get the loc strings for the files-in-use task dialog text.
2289 hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseTitle)", &pLocString);
2290 ExitOnFailure(hr, "Failed to get FilesInUseTitle loc string.");
2291
2292 hr = StrAllocString(&sczTitle, pLocString->wzText, 0);
2293 ExitOnFailure(hr, "Failed to copy FilesInUseTitle loc string.");
2294
2295 hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseLabel)", &pLocString);
2296 ExitOnFailure(hr, "Failed to get FilesInUseLabel loc string.");
2297
2298 hr = StrAllocString(&sczLabel, pLocString->wzText, 0);
2299 ExitOnFailure(hr, "Failed to copy FilesInUseLabel loc string.");
2300
2301 hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseCloseRadioButton)", &pLocString);
2302 ExitOnFailure(hr, "Failed to get FilesInUseCloseRadioButton loc string.");
2303
2304 hr = StrAllocString(&sczCloseRadioButton, pLocString->wzText, 0);
2305 ExitOnFailure(hr, "Failed to copy FilesInUseCloseRadioButton loc string.");
2306
2307 hr = LocGetString(m_pWixLoc, L"#(loc.FilesInUseDontCloseRadioButton)", &pLocString);
2308 ExitOnFailure(hr, "Failed to get FilesInUseDontCloseRadioButton loc string.");
2309
2310 hr = StrAllocString(&sczDontCloseRadioButton, pLocString->wzText, 0);
2311 ExitOnFailure(hr, "Failed to copy FilesInUseDontCloseRadioButton loc string.");
2312
2313 const TASKDIALOG_BUTTON buttons[] = {
2314 { IDOK, sczCloseRadioButton },
2315 { IDIGNORE, sczDontCloseRadioButton },
2316 };
2317
2318 config.cbSize = sizeof(config);
2319 config.hInstance = m_hModule;
2320 config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_USE_COMMAND_LINKS | TDF_SIZE_TO_CONTENT;
2321 config.dwCommonButtons = TDCBF_CANCEL_BUTTON;
2322 config.pszWindowTitle = sczTitle;
2323 config.pszMainInstruction = sczLabel;
2324 config.pszContent = sczFilesInUse ? sczFilesInUse : L"";
2325 config.pButtons = buttons;
2326 config.cButtons = 2;
2327
2328 hr = TaskDialogIndirect(&config, pnResult, NULL, NULL);
2329 ExitOnFailure(hr, "Failed to show files-in-use task dialog.");
2330
2331 LExit:
2332 return hr;
2333 }
2334
2335
2204public: //CBalBaseBootstrapperApplication 2336public: //CBalBaseBootstrapperApplication
2205 virtual STDMETHODIMP Initialize( 2337 virtual STDMETHODIMP Initialize(
2206 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs 2338 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
@@ -4135,7 +4267,7 @@ LExit:
4135 if (m_fTaskbarButtonOK) 4267 if (m_fTaskbarButtonOK)
4136 { 4268 {
4137 hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags); 4269 hr = m_pTaskbarList->SetProgressState(m_hWnd, tbpFlags);
4138 BalExitOnFailure(hr, "Failed to set taskbar button state.", tbpFlags); 4270 BalExitOnFailure(hr, "Failed to set taskbar button state: %d.", tbpFlags);
4139 } 4271 }
4140 4272
4141 LExit: 4273 LExit:
@@ -4286,6 +4418,8 @@ public:
4286 m_fPrereqInstalled = FALSE; 4418 m_fPrereqInstalled = FALSE;
4287 m_fPrereqSkipped = FALSE; 4419 m_fPrereqSkipped = FALSE;
4288 4420
4421 m_nLastFilesInUseResult = IDNOACTION;
4422
4289 pEngine->AddRef(); 4423 pEngine->AddRef();
4290 m_pEngine = pEngine; 4424 m_pEngine = pEngine;
4291 4425
@@ -4578,6 +4712,8 @@ private:
4578 BOOL m_fShowingInternalUiThisPackage; 4712 BOOL m_fShowingInternalUiThisPackage;
4579 BOOL m_fTriedToLaunchElevated; 4713 BOOL m_fTriedToLaunchElevated;
4580 4714
4715 int m_nLastFilesInUseResult;
4716
4581 HMODULE m_hBAFModule; 4717 HMODULE m_hBAFModule;
4582 PFN_BA_FUNCTIONS_PROC m_pfnBAFunctionsProc; 4718 PFN_BA_FUNCTIONS_PROC m_pfnBAFunctionsProc;
4583 LPVOID m_pvBAFunctionsProcContext; 4719 LPVOID m_pvBAFunctionsProcContext;
diff --git a/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wixproj b/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wixproj
new file mode 100644
index 00000000..e0860665
--- /dev/null
+++ b/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wixproj
@@ -0,0 +1,17 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <OutputType>Bundle</OutputType>
5 <UpgradeCode>{6A348108-8ACE-4D13-A352-D8F76785BFE4}</UpgradeCode>
6 <DefineConstants>$(DefineConstants);BaseOutputPath=$(BaseOutputPath);Version=1.1</DefineConstants>
7 </PropertyGroup>
8 <ItemGroup>
9 <Compile Include="..\..\WixStdBaTests\BundleA\Bundle.wxs" Link="Bundle.wxs" />
10 </ItemGroup>
11 <ItemGroup>
12 <ProjectReference Include="..\PackageA\PackageA.wixproj" />
13 </ItemGroup>
14 <ItemGroup>
15 <PackageReference Include="WixToolset.Bal.wixext" />
16 </ItemGroup>
17</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wxs b/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wxs
new file mode 100644
index 00000000..bd164a29
--- /dev/null
+++ b/src/test/burn/TestData/FilesInUseTests/WixStdBaBundle/WixStdBaBundle.wxs
@@ -0,0 +1,10 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
5 <Fragment>
6 <PackageGroup Id="BundlePackages">
7 <MsiPackage Id="PackageA" SourceFile="$(var.PackageA.TargetPath)" />
8 </PackageGroup>
9 </Fragment>
10</Wix>
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/FilesInUseTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/FilesInUseTests.cs
index 042175f0..12eca77d 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/FilesInUseTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/FilesInUseTests.cs
@@ -33,5 +33,25 @@ namespace WixToolsetTest.BurnE2E
33 33
34 packageA.VerifyInstalled(false); 34 packageA.VerifyInstalled(false);
35 } 35 }
36
37 [RuntimeFact]
38 public void WixStdBAFailsWithLockedFile()
39 {
40 var packageA = this.CreatePackageInstaller("PackageA");
41 var bundleA = this.CreateBundleInstaller("WixStdBaBundle");
42
43 packageA.VerifyInstalled(false);
44
45 bundleA.Install();
46
47 packageA.VerifyInstalled(true);
48
49 // Lock the file that will be uninstalled.
50 var targetInstallFile = packageA.GetInstalledFilePath("Package.wxs");
51 using (var lockTargetFile = new FileStream(targetInstallFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
52 {
53 bundleA.Uninstall(expectedExitCode: (int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE);
54 }
55 }
36 } 56 }
37} 57}
diff --git a/src/tools/thmviewer/precomp.h b/src/tools/thmviewer/precomp.h
index 762a0623..41d2e9fb 100644
--- a/src/tools/thmviewer/precomp.h
+++ b/src/tools/thmviewer/precomp.h
@@ -55,7 +55,7 @@ extern "C" HRESULT DisplayStart(
55 ); 55 );
56extern "C" HRESULT LoadStart( 56extern "C" HRESULT LoadStart(
57 __in_z LPCWSTR wzThemePath, 57 __in_z LPCWSTR wzThemePath,
58 __in_z LPCWSTR wzWxlPath, 58 __in_z_opt LPCWSTR wzWxlPath,
59 __in HWND hWnd, 59 __in HWND hWnd,
60 __out HANDLE* phThread 60 __out HANDLE* phThread
61 ); 61 );