diff options
| author | Rob Mensching <rob@firegiant.com> | 2024-01-11 18:26:20 -0800 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2024-03-06 18:03:38 -0800 |
| commit | 0d3d54992104288e9ee0c834d0b96e8502fd2d42 (patch) | |
| tree | 9efa49c4983cd2ba1becab64bd1f2faccac88acf /src/ext/Bal/dnchost/dnchost.cpp | |
| parent | 2824298d9dd817a47527c920363556b54ead5d5d (diff) | |
| download | wix-0d3d54992104288e9ee0c834d0b96e8502fd2d42.tar.gz wix-0d3d54992104288e9ee0c834d0b96e8502fd2d42.tar.bz2 wix-0d3d54992104288e9ee0c834d0b96e8502fd2d42.zip | |
Move the BootstrapperApplication out of proc
Diffstat (limited to 'src/ext/Bal/dnchost/dnchost.cpp')
| -rw-r--r-- | src/ext/Bal/dnchost/dnchost.cpp | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp deleted file mode 100644 index 1868e3f8..00000000 --- a/src/ext/Bal/dnchost/dnchost.cpp +++ /dev/null | |||
| @@ -1,328 +0,0 @@ | |||
| 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 | #include "precomp.h" | ||
| 4 | |||
| 5 | static DNCSTATE vstate = { }; | ||
| 6 | |||
| 7 | |||
| 8 | // internal function declarations | ||
| 9 | |||
| 10 | static HRESULT LoadModulePaths( | ||
| 11 | __in DNCSTATE* pState | ||
| 12 | ); | ||
| 13 | static HRESULT LoadDncConfiguration( | ||
| 14 | __in DNCSTATE* pState, | ||
| 15 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs | ||
| 16 | ); | ||
| 17 | static HRESULT LoadRuntime( | ||
| 18 | __in DNCSTATE* pState | ||
| 19 | ); | ||
| 20 | static HRESULT LoadManagedBootstrapperApplicationFactory( | ||
| 21 | __in DNCSTATE* pState | ||
| 22 | ); | ||
| 23 | static HRESULT CreatePrerequisiteBA( | ||
| 24 | __in DNCSTATE* pState, | ||
| 25 | __in IBootstrapperEngine* pEngine, | ||
| 26 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 27 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 28 | ); | ||
| 29 | |||
| 30 | |||
| 31 | // function definitions | ||
| 32 | |||
| 33 | extern "C" BOOL WINAPI DllMain( | ||
| 34 | IN HINSTANCE hInstance, | ||
| 35 | IN DWORD dwReason, | ||
| 36 | IN LPVOID /* pvReserved */ | ||
| 37 | ) | ||
| 38 | { | ||
| 39 | switch (dwReason) | ||
| 40 | { | ||
| 41 | case DLL_PROCESS_ATTACH: | ||
| 42 | ::DisableThreadLibraryCalls(hInstance); | ||
| 43 | vstate.hInstance = hInstance; | ||
| 44 | break; | ||
| 45 | |||
| 46 | case DLL_PROCESS_DETACH: | ||
| 47 | vstate.hInstance = NULL; | ||
| 48 | break; | ||
| 49 | } | ||
| 50 | |||
| 51 | return TRUE; | ||
| 52 | } | ||
| 53 | |||
| 54 | extern "C" HRESULT WINAPI BootstrapperApplicationCreate( | ||
| 55 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 56 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 57 | ) | ||
| 58 | { | ||
| 59 | HRESULT hr = S_OK; | ||
| 60 | IBootstrapperEngine* pEngine = NULL; | ||
| 61 | |||
| 62 | hr = BalInitializeFromCreateArgs(pArgs, &pEngine); | ||
| 63 | ExitOnFailure(hr, "Failed to initialize Bal."); | ||
| 64 | |||
| 65 | if (!vstate.fInitialized) | ||
| 66 | { | ||
| 67 | hr = XmlInitialize(); | ||
| 68 | BalExitOnFailure(hr, "Failed to initialize XML."); | ||
| 69 | |||
| 70 | hr = LoadModulePaths(&vstate); | ||
| 71 | BalExitOnFailure(hr, "Failed to get the host base path."); | ||
| 72 | |||
| 73 | hr = LoadDncConfiguration(&vstate, pArgs); | ||
| 74 | BalExitOnFailure(hr, "Failed to get the dnc configuration."); | ||
| 75 | |||
| 76 | vstate.fInitialized = TRUE; | ||
| 77 | } | ||
| 78 | |||
| 79 | if (vstate.prereqData.fAlwaysInstallPrereqs && !vstate.prereqData.fCompleted) | ||
| 80 | { | ||
| 81 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application since it's configured to always run before loading the runtime."); | ||
| 82 | |||
| 83 | hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults); | ||
| 84 | BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); | ||
| 85 | |||
| 86 | ExitFunction(); | ||
| 87 | } | ||
| 88 | |||
| 89 | if (!vstate.fInitializedRuntime) | ||
| 90 | { | ||
| 91 | hr = LoadRuntime(&vstate); | ||
| 92 | |||
| 93 | vstate.fInitializedRuntime = SUCCEEDED(hr); | ||
| 94 | } | ||
| 95 | |||
| 96 | if (vstate.fInitializedRuntime) | ||
| 97 | { | ||
| 98 | if (!vstate.pAppFactory) | ||
| 99 | { | ||
| 100 | hr = LoadManagedBootstrapperApplicationFactory(&vstate); | ||
| 101 | BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory."); | ||
| 102 | } | ||
| 103 | |||
| 104 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core %ls bootstrapper application.", DNCHOSTTYPE_FDD == vstate.type ? L"FDD" : L"SCD"); | ||
| 105 | |||
| 106 | hr = vstate.pAppFactory->Create(pArgs, pResults); | ||
| 107 | BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application."); | ||
| 108 | } | ||
| 109 | else // fallback to the prerequisite BA. | ||
| 110 | { | ||
| 111 | if (DNCHOSTTYPE_SCD == vstate.type) | ||
| 112 | { | ||
| 113 | vstate.prereqData.hrFatalError = E_DNCHOST_SCD_RUNTIME_FAILURE; | ||
| 114 | BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error."); | ||
| 115 | } | ||
| 116 | else if (vstate.prereqData.fCompleted) | ||
| 117 | { | ||
| 118 | hr = E_PREREQBA_INFINITE_LOOP; | ||
| 119 | BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop."); | ||
| 120 | vstate.prereqData.hrFatalError = hr; | ||
| 121 | } | ||
| 122 | else | ||
| 123 | { | ||
| 124 | vstate.prereqData.hrFatalError = S_OK; | ||
| 125 | } | ||
| 126 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr); | ||
| 127 | |||
| 128 | hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults); | ||
| 129 | BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); | ||
| 130 | } | ||
| 131 | |||
| 132 | LExit: | ||
| 133 | ReleaseNullObject(pEngine); | ||
| 134 | |||
| 135 | return hr; | ||
| 136 | } | ||
| 137 | |||
| 138 | extern "C" void WINAPI BootstrapperApplicationDestroy( | ||
| 139 | __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs, | ||
| 140 | __in BOOTSTRAPPER_DESTROY_RESULTS* pResults | ||
| 141 | ) | ||
| 142 | { | ||
| 143 | BOOTSTRAPPER_DESTROY_RESULTS childResults = { }; | ||
| 144 | |||
| 145 | childResults.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS); | ||
| 146 | |||
| 147 | if (vstate.hMbapreqModule) | ||
| 148 | { | ||
| 149 | PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy")); | ||
| 150 | if (pfnDestroy) | ||
| 151 | { | ||
| 152 | (*pfnDestroy)(pArgs, &childResults); | ||
| 153 | } | ||
| 154 | |||
| 155 | ::FreeLibrary(vstate.hMbapreqModule); | ||
| 156 | vstate.hMbapreqModule = NULL; | ||
| 157 | } | ||
| 158 | |||
| 159 | BalUninitialize(); | ||
| 160 | |||
| 161 | // Need to keep track of state between reloads. | ||
| 162 | pResults->fDisableUnloading = TRUE; | ||
| 163 | } | ||
| 164 | |||
| 165 | static HRESULT LoadModulePaths( | ||
| 166 | __in DNCSTATE* pState | ||
| 167 | ) | ||
| 168 | { | ||
| 169 | HRESULT hr = S_OK; | ||
| 170 | |||
| 171 | hr = PathForCurrentProcess(&pState->sczModuleFullPath, pState->hInstance); | ||
| 172 | BalExitOnFailure(hr, "Failed to get the full host path."); | ||
| 173 | |||
| 174 | hr = PathGetDirectory(pState->sczModuleFullPath, &pState->sczAppBase); | ||
| 175 | BalExitOnFailure(hr, "Failed to get the directory of the full process path."); | ||
| 176 | |||
| 177 | LExit: | ||
| 178 | return hr; | ||
| 179 | } | ||
| 180 | |||
| 181 | static HRESULT LoadDncConfiguration( | ||
| 182 | __in DNCSTATE* pState, | ||
| 183 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs | ||
| 184 | ) | ||
| 185 | { | ||
| 186 | HRESULT hr = S_OK; | ||
| 187 | IXMLDOMDocument* pixdManifest = NULL; | ||
| 188 | IXMLDOMNode* pixnHost = NULL; | ||
| 189 | LPWSTR sczPayloadName = NULL; | ||
| 190 | DWORD dwBool = 0; | ||
| 191 | BOOL fXmlFound = FALSE; | ||
| 192 | |||
| 193 | hr = XmlLoadDocumentFromFile(pArgs->pCommand->wzBootstrapperApplicationDataPath, &pixdManifest); | ||
| 194 | BalExitOnFailure(hr, "Failed to load BalManifest '%ls'", pArgs->pCommand->wzBootstrapperApplicationDataPath); | ||
| 195 | |||
| 196 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBalBAFactoryAssembly", &pixnHost); | ||
| 197 | BalExitOnRequiredXmlQueryFailure(hr, "Failed to get WixBalBAFactoryAssembly element."); | ||
| 198 | |||
| 199 | hr = XmlGetAttributeEx(pixnHost, L"FilePath", &sczPayloadName); | ||
| 200 | BalExitOnRequiredXmlQueryFailure(hr, "Failed to get WixBalBAFactoryAssembly/@FilePath."); | ||
| 201 | |||
| 202 | hr = PathConcatRelativeToBase(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath); | ||
| 203 | BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath."); | ||
| 204 | |||
| 205 | LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath); | ||
| 206 | LPCWSTR wzExtension = PathExtension(pState->sczBaFactoryAssemblyPath); | ||
| 207 | if (!wzExtension) | ||
| 208 | { | ||
| 209 | BalExitOnFailure(hr = E_FAIL, "BaFactoryAssemblyPath has no extension."); | ||
| 210 | } | ||
| 211 | |||
| 212 | hr = StrAllocString(&pState->sczBaFactoryAssemblyName, wzFileName, wzExtension - wzFileName); | ||
| 213 | BalExitOnFailure(hr, "Failed to copy BAFactoryAssembly payload Name."); | ||
| 214 | |||
| 215 | hr = StrAllocString(&pState->sczBaFactoryDepsJsonPath, pState->sczBaFactoryAssemblyPath, wzExtension - pState->sczBaFactoryAssemblyPath); | ||
| 216 | BalExitOnFailure(hr, "Failed to initialize deps json path."); | ||
| 217 | |||
| 218 | hr = StrAllocString(&pState->sczBaFactoryRuntimeConfigPath, pState->sczBaFactoryDepsJsonPath, 0); | ||
| 219 | BalExitOnFailure(hr, "Failed to initialize runtime config path."); | ||
| 220 | |||
| 221 | hr = StrAllocConcat(&pState->sczBaFactoryDepsJsonPath, L".deps.json", 0); | ||
| 222 | BalExitOnFailure(hr, "Failed to concat extension to deps json path."); | ||
| 223 | |||
| 224 | hr = StrAllocConcat(&pState->sczBaFactoryRuntimeConfigPath, L".runtimeconfig.json", 0); | ||
| 225 | BalExitOnFailure(hr, "Failed to concat extension to runtime config path."); | ||
| 226 | |||
| 227 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqOptions", &pixnHost); | ||
| 228 | BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find WixMbaPrereqOptions element in bootstrapper application config."); | ||
| 229 | |||
| 230 | if (fXmlFound) | ||
| 231 | { | ||
| 232 | hr = XmlGetAttributeNumber(pixnHost, L"AlwaysInstallPrereqs", reinterpret_cast<DWORD*>(&pState->prereqData.fAlwaysInstallPrereqs)); | ||
| 233 | BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get AlwaysInstallPrereqs value."); | ||
| 234 | } | ||
| 235 | |||
| 236 | pState->prereqData.fPerformHelp = !pState->prereqData.fAlwaysInstallPrereqs; | ||
| 237 | |||
| 238 | pState->type = DNCHOSTTYPE_FDD; | ||
| 239 | |||
| 240 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixDncOptions", &pixnHost); | ||
| 241 | BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find WixDncOptions element in bootstrapper application config."); | ||
| 242 | |||
| 243 | if (!fXmlFound) | ||
| 244 | { | ||
| 245 | ExitFunction(); | ||
| 246 | } | ||
| 247 | |||
| 248 | hr = XmlGetAttributeNumber(pixnHost, L"SelfContainedDeployment", &dwBool); | ||
| 249 | BalExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get SelfContainedDeployment value."); | ||
| 250 | |||
| 251 | if (fXmlFound && dwBool) | ||
| 252 | { | ||
| 253 | pState->type = DNCHOSTTYPE_SCD; | ||
| 254 | } | ||
| 255 | |||
| 256 | LExit: | ||
| 257 | ReleaseStr(sczPayloadName); | ||
| 258 | ReleaseObject(pixnHost); | ||
| 259 | ReleaseObject(pixdManifest); | ||
| 260 | |||
| 261 | return hr; | ||
| 262 | } | ||
| 263 | |||
| 264 | static HRESULT LoadRuntime( | ||
| 265 | __in DNCSTATE* pState | ||
| 266 | ) | ||
| 267 | { | ||
| 268 | HRESULT hr = S_OK; | ||
| 269 | |||
| 270 | hr = DnchostLoadRuntime( | ||
| 271 | &pState->hostfxrState, | ||
| 272 | pState->sczModuleFullPath, | ||
| 273 | pState->sczBaFactoryAssemblyPath, | ||
| 274 | pState->sczBaFactoryDepsJsonPath, | ||
| 275 | pState->sczBaFactoryRuntimeConfigPath); | ||
| 276 | |||
| 277 | return hr; | ||
| 278 | } | ||
| 279 | |||
| 280 | static HRESULT LoadManagedBootstrapperApplicationFactory( | ||
| 281 | __in DNCSTATE* pState | ||
| 282 | ) | ||
| 283 | { | ||
| 284 | HRESULT hr = S_OK; | ||
| 285 | |||
| 286 | hr = DnchostCreateFactory( | ||
| 287 | &pState->hostfxrState, | ||
| 288 | pState->sczBaFactoryAssemblyName, | ||
| 289 | &pState->pAppFactory); | ||
| 290 | |||
| 291 | return hr; | ||
| 292 | } | ||
| 293 | |||
| 294 | static HRESULT CreatePrerequisiteBA( | ||
| 295 | __in DNCSTATE* pState, | ||
| 296 | __in IBootstrapperEngine* pEngine, | ||
| 297 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 298 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 299 | ) | ||
| 300 | { | ||
| 301 | HRESULT hr = S_OK; | ||
| 302 | LPWSTR sczDncpreqPath = NULL; | ||
| 303 | HMODULE hModule = NULL; | ||
| 304 | |||
| 305 | hr = PathConcat(pState->sczAppBase, L"dncpreq.dll", &sczDncpreqPath); | ||
| 306 | BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); | ||
| 307 | |||
| 308 | hModule = ::LoadLibraryExW(sczDncpreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | ||
| 309 | BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); | ||
| 310 | |||
| 311 | PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate")); | ||
| 312 | BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath); | ||
| 313 | |||
| 314 | hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults); | ||
| 315 | BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); | ||
| 316 | |||
| 317 | pState->hMbapreqModule = hModule; | ||
| 318 | hModule = NULL; | ||
| 319 | |||
| 320 | LExit: | ||
| 321 | if (hModule) | ||
| 322 | { | ||
| 323 | ::FreeLibrary(hModule); | ||
| 324 | } | ||
| 325 | ReleaseStr(sczDncpreqPath); | ||
| 326 | |||
| 327 | return hr; | ||
| 328 | } | ||
