@joebigelow / wix-1 / commits / b7faab06

Treat failing to load SCD like mbahost treats .NET 4.5.2 on Win7 RTM.

Sean Hall committed Apr 29, 2020 at 19:31 UTC b7faab06259d3afdc3205024a0004ace72157cbe
9 files changed +228 -9
src/dnchost/dnchost.cpp
+79 -8
@@ -20,6 +20,13 @@ static HRESULT LoadRuntime(
20 static HRESULT LoadManagedBootstrapperApplicationFactory(
21 __in DNCSTATE* pState
22 );
23 +static HRESULT CreatePrerequisiteBA(
24 + __in HRESULT hrHostInitialization,
25 + __in IBootstrapperEngine* pEngine,
26 + __in LPCWSTR wzAppBase,
27 + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
28 + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
29 + );
30
31
32 // function definitions
@@ -51,6 +58,7 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
58 )
59 {
60 HRESULT hr = S_OK;
61 + HRESULT hrHostInitialization = S_OK;
62 IBootstrapperEngine* pEngine = NULL;
63
64 // coreclr.dll doesn't support unloading, so the rest of the .NET Core hosting stack doesn't support it either.
@@ -77,18 +85,32 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
85 if (!vstate.fInitializedRuntime)
86 {
87 hr = LoadRuntime(&vstate);
80 - BalExitOnFailure(hr, "Failed to load .NET Core runtime.");
81 -
82 - vstate.fInitializedRuntime = TRUE;
88
84 - hr = LoadManagedBootstrapperApplicationFactory(&vstate);
85 - BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory.");
89 + vstate.fInitializedRuntime = SUCCEEDED(hr);
90 }
91
88 - BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core SCD bootstrapper application.");
92 + if (vstate.fInitializedRuntime)
93 + {
94 + if (!vstate.pAppFactory)
95 + {
96 + hr = LoadManagedBootstrapperApplicationFactory(&vstate);
97 + BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory.");
98 + }
99 +
100 + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core SCD bootstrapper application.");
101 +
102 + hr = vstate.pAppFactory->Create(pArgs, pResults);
103 + BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application.");
104 + }
105 + else // fallback to the prerequisite BA.
106 + {
107 + hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
108 + BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error.");
109 + BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr);
110
90 - hr = vstate.pAppFactory->Create(pArgs, pResults);
91 - BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application.");
111 + hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults);
112 + BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
113 + }
114
115 LExit:
116 ReleaseNullObject(pEngine);
@@ -98,6 +120,18 @@ LExit:
120
121 extern "C" void WINAPI BootstrapperApplicationDestroy()
122 {
123 + if (vstate.hMbapreqModule)
124 + {
125 + PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy"));
126 + if (pfnDestroy)
127 + {
128 + (*pfnDestroy)();
129 + }
130 +
131 + ::FreeLibrary(vstate.hMbapreqModule);
132 + vstate.hMbapreqModule = NULL;
133 + }
134 +
135 BalUninitialize();
136 }
137
@@ -227,3 +261,40 @@ static HRESULT LoadManagedBootstrapperApplicationFactory(
261
262 return hr;
263 }
264 +
265 +static HRESULT CreatePrerequisiteBA(
266 + __in HRESULT hrHostInitialization,
267 + __in IBootstrapperEngine* pEngine,
268 + __in LPCWSTR wzAppBase,
269 + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
270 + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
271 + )
272 +{
273 + HRESULT hr = S_OK;
274 + LPWSTR sczDncpreqPath = NULL;
275 + HMODULE hModule = NULL;
276 +
277 + hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath);
278 + BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
279 +
280 + hModule = ::LoadLibraryW(sczDncpreqPath);
281 + BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
282 +
283 + PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate"));
284 + BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath);
285 +
286 + hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults);
287 + BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
288 +
289 + vstate.hMbapreqModule = hModule;
290 + hModule = NULL;
291 +
292 +LExit:
293 + if (hModule)
294 + {
295 + ::FreeLibrary(hModule);
296 + }
297 + ReleaseStr(sczDncpreqPath);
298 +
299 + return hr;
300 +}
src/dnchost/dnchost.h
+8
@@ -2,6 +2,13 @@
2 // 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.
3
4
5 +extern "C" typedef HRESULT(WINAPI* PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
6 + __in HRESULT hrHostInitialization,
7 + __in IBootstrapperEngine* pEngine,
8 + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
9 + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
10 + );
11 +
12 struct DNCSTATE
13 {
14 BOOL fInitialized;
@@ -16,4 +23,5 @@ struct DNCSTATE
23 LPWSTR sczBaFactoryRuntimeConfigPath;
24 HOSTFXR_STATE hostfxrState;
25 IBootstrapperApplicationFactory* pAppFactory;
26 + HMODULE hMbapreqModule;
27 };
src/mbahost/mbahost.cpp
+2
@@ -129,6 +129,8 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
129 }
130
131 LExit:
132 + ReleaseNullObject(pEngine);
133 +
134 return hr;
135 }
136
src/wixlib/Dnc.wxs
+10
@@ -9,6 +9,7 @@
9 <Fragment>
10 <BootstrapperApplication Id='DotNetCoreBootstrapperApplicationHost' SourceFile='dnchost.dll'>
11 <PayloadGroupRef Id='Dnc' />
12 + <PayloadGroupRef Id='DncPreqStandard' />
13 </BootstrapperApplication>
14 </Fragment>
15
@@ -16,6 +17,15 @@
17 <PayloadGroup Id='Dnc'>
18 <Payload Compressed='yes' SourceFile='nethost.dll' />
19 <Payload Compressed='yes' SourceFile='WixToolset.Dnc.Host.dll' />
20 + <Payload Compressed='yes' SourceFile='wixstdba.dll' Name='dncpreq.dll' />
21 + </PayloadGroup>
22 + </Fragment>
23 +
24 + <Fragment>
25 + <PayloadGroup Id='DncPreqStandard'>
26 + <Payload Name='mbapreq.thm' Compressed='yes' SourceFile='!(wix.DncPreqbaThemeXml=SourceDir\dncpreq.thm)' />
27 + <Payload Name='mbapreq.png' Compressed='yes' SourceFile='!(wix.DncPreqbaLogo=SourceDir\mbapreq.png)' />
28 + <Payload Name='mbapreq.wxl' Compressed='yes' SourceFile='!(wix.DncPreqbaThemeWxl=SourceDir\dncpreq.wxl)' />
29 </PayloadGroup>
30 </Fragment>
31 </Wix>
src/wixstdba/Resources/dncpreq.thm new
+47
@@ -0,0 +1,47 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<Theme xmlns="http://wixtoolset.org/schemas/v4/thmutil">
3 + <Font Id="0" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
4 + <Font Id="1" Height="-24" Weight="500" Foreground="windowtext">Segoe UI</Font>
5 + <Font Id="2" Height="-22" Weight="500" Foreground="graytext">Segoe UI</Font>
6 + <Font Id="3" Height="-12" Weight="500" Foreground="windowtext" Background="window">Segoe UI</Font>
7 +
8 + <Window Width="485" Height="300" HexStyle="100a0000" FontId="0" Caption="#(loc.Caption)">
9 + <ImageControl X="11" Y="11" Width="64" Height="64" ImageFile="mbapreq.png" Visible="yes"/>
10 + <Label X="80" Y="11" Width="-11" Height="96" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Label>
11 +
12 + <Page Name="Help">
13 + <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Label>
14 + <Label X="11" Y="153" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Label>
15 + <Button Name="HelpCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
16 + <Text>#(loc.HelpCloseButton)</Text>
17 + <CloseWindowAction />
18 + </Button>
19 + </Page>
20 + <Page Name="Install">
21 + <Hypertext Name="EulaHyperlink" X="11" Y="121" Width="-11" Height="34" TabStop="yes" FontId="3">#(loc.InstallLicenseTerms)</Hypertext>
22 + <Button Name="InstallButton" X="-91" Y="-11" Width="130" Height="23" TabStop="yes" FontId="0">#(loc.InstallAcceptAndInstallButton)</Button>
23 + <Button Name="InstallDeclineButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
24 + <Text>#(loc.InstallDeclineButton)</Text>
25 + <CloseWindowAction />
26 + </Button>
27 + </Page>
28 + <Page Name="Progress">
29 + <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Label>
30 + <Label X="11" Y="153" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Label>
31 + <Label Name="OverallProgressPackageText" X="85" Y="153" Width="-11" Height="17" FontId="3" DisablePrefix="yes">[ProgressPackageName]</Label>
32 + <Progressbar Name="OverallCalculatedProgressbar" X="11" Y="175" Width="-11" Height="15" />
33 + <Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
34 + </Page>
35 + <Page Name="Failure">
36 + <Label X="11" Y="112" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FailureHeader)</Label>
37 + <Hypertext Name="FailureLogFileLink" X="11" Y="153" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureLogLinkText)</Hypertext>
38 + <Hypertext Name="FailureMessageText" X="22" Y="190" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes"/>
39 + <Label X="-11" Y="-20" Width="400" Height="34" FontId="3" DisablePrefix="yes" VisibleCondition="WixStdBARestartRequired">#(loc.FailureRestartText)</Label>
40 + <Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
41 + <Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">
42 + <Text>#(loc.FailureCloseButton)</Text>
43 + <CloseWindowAction />
44 + </Button>
45 + </Page>
46 + </Window>
47 +</Theme>
src/wixstdba/Resources/dncpreq.wxl new
+29
@@ -0,0 +1,29 @@
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<!-- 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. -->
3 +
4 +
5 +<WixLocalization Culture="en-us" Language="1033" xmlns="http://wixtoolset.org/schemas/v4/wxl">
6 + <String Id="Caption">[WixBundleName] Setup</String>
7 + <String Id="Title">Microsoft .NET Core required for [WixBundleName] setup</String>
8 + <String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
9 + <String Id="HelpHeader">Setup Help</String>
10 + <String Id="HelpText">/passive | /quiet - displays minimal UI with no prompts or displays no UI and
11 + no prompts. By default UI and all prompts are displayed.
12 +
13 +/norestart - suppress any attempts to restart. By default UI will prompt before restart.
14 +/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.</String>
15 + <String Id="HelpCloseButton">&amp;Close</String>
16 + <String Id="InstallLicenseTerms">Click the "Accept and Install" button to accept the Microsoft .NET Core &lt;a href="#"&gt;license terms&lt;/a&gt;.</String>
17 + <String Id="InstallAcceptAndInstallButton">&amp;Accept and Install</String>
18 + <String Id="InstallDeclineButton">&amp;Decline</String>
19 + <String Id="ProgressHeader">Setup Progress</String>
20 + <String Id="ProgressLabel">Processing:</String>
21 + <String Id="ProgressCancelButton">&amp;Cancel</String>
22 + <String Id="FailureHeader">Setup Failed</String>
23 + <String Id="FailureLogLinkText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
24 + <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
25 + <String Id="FailureRestartButton">&amp;Restart</String>
26 + <String Id="FailureCloseButton">&amp;Close</String>
27 + <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>
28 + <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
29 +</WixLocalization>
src/wixstdba/WixStandardBootstrapperApplication.cpp
+25 -1
@@ -2892,6 +2892,23 @@ private: // privates
2892 }
2893 }
2894 }
2895 + else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal)
2896 + {
2897 + HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.SCDRUNTIMEFAILUREErrorMessage)", 0);
2898 + if (FAILED(hr))
2899 + {
2900 + BalLogError(hr, "Failed to initialize SCDRUNTIMEFAILUREErrorMessage loc identifier.");
2901 + }
2902 + else
2903 + {
2904 + hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText);
2905 + if (FAILED(hr))
2906 + {
2907 + BalLogError(hr, "Failed to localize SCDRUNTIMEFAILUREErrorMessage: %ls", sczUnformattedText);
2908 + ReleaseNullStr(sczUnformattedText);
2909 + }
2910 + }
2911 + }
2912 else // try to get the error message from the error code.
2913 {
2914 StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL);
@@ -2915,6 +2932,13 @@ private: // privates
2932 BalFormatString(sczUnformattedText, &sczText);
2933 }
2934 }
2935 + else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal)
2936 + {
2937 + if (sczUnformattedText)
2938 + {
2939 + BalFormatString(sczUnformattedText, &sczText);
2940 + }
2941 + }
2942 else
2943 {
2944 StrAllocFormatted(&sczText, L"0x%08x - %ls", m_hrFinal, sczUnformattedText);
@@ -3754,7 +3778,7 @@ HRESULT CreateBootstrapperApplication(
3778
3779 if (BOOTSTRAPPER_DISPLAY_UNKNOWN == pArgs->pCommand->display)
3780 {
3757 - ExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type.");
3781 + BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type.");
3782 }
3783
3784 pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine, pArgs);
src/wixstdba/wixstdba.cpp
+26
@@ -55,6 +55,32 @@ extern "C" void WINAPI BootstrapperApplicationDestroy()
55 }
56
57
58 +extern "C" HRESULT WINAPI DncPrereqBootstrapperApplicationCreate(
59 + __in HRESULT hrHostInitialization,
60 + __in IBootstrapperEngine* pEngine,
61 + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
62 + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
63 + )
64 +{
65 + HRESULT hr = S_OK;
66 +
67 + BalInitialize(pEngine);
68 +
69 + hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication);
70 + BalExitOnFailure(hr, "Failed to create .NET Core prerequisite bootstrapper application interface.");
71 +
72 +LExit:
73 + return hr;
74 +}
75 +
76 +
77 +extern "C" void WINAPI DncPrereqBootstrapperApplicationDestroy()
78 +{
79 + ReleaseNullObject(vpApplication);
80 + BalUninitialize();
81 +}
82 +
83 +
84 extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate(
85 __in HRESULT hrHostInitialization,
86 __in IBootstrapperEngine* pEngine,
src/wixstdba/wixstdba.def
+2
@@ -4,5 +4,7 @@
4 EXPORTS
5 BootstrapperApplicationCreate
6 BootstrapperApplicationDestroy
7 + DncPrereqBootstrapperApplicationCreate
8 + DncPrereqBootstrapperApplicationDestroy
9 MbaPrereqBootstrapperApplicationCreate
10 MbaPrereqBootstrapperApplicationDestroy