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">&Close</String>
16
+ <String Id="InstallLicenseTerms">Click the "Accept and Install" button to accept the Microsoft .NET Core <a href="#">license terms</a>.</String>
17
+ <String Id="InstallAcceptAndInstallButton">&Accept and Install</String>
18
+ <String Id="InstallDeclineButton">&Decline</String>
19
+ <String Id="ProgressHeader">Setup Progress</String>
20
+ <String Id="ProgressLabel">Processing:</String>
21
+ <String Id="ProgressCancelButton">&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 <a href="#">log file</a>.</String>
24
+ <String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
25
+ <String Id="FailureRestartButton">&Restart</String>
26
+ <String Id="FailureCloseButton">&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