diff options
| author | Rob Mensching <rob@firegiant.com> | 2021-05-03 15:55:48 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2021-05-03 15:55:48 -0700 |
| commit | ba7bab476501c16e437b0aee71c1be02c3dda176 (patch) | |
| tree | 814fba485c29a7dfe1adb396169e27ed641ef9a3 /src/ext/Bal/dnchost/dnchost.cpp | |
| parent | 14987a72cc1a3493ca8f80693d273352fc314bd9 (diff) | |
| download | wix-ba7bab476501c16e437b0aee71c1be02c3dda176.tar.gz wix-ba7bab476501c16e437b0aee71c1be02c3dda176.tar.bz2 wix-ba7bab476501c16e437b0aee71c1be02c3dda176.zip | |
Move Bal.wixext into ext
Diffstat (limited to 'src/ext/Bal/dnchost/dnchost.cpp')
| -rw-r--r-- | src/ext/Bal/dnchost/dnchost.cpp | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp new file mode 100644 index 00000000..8ca326fc --- /dev/null +++ b/src/ext/Bal/dnchost/dnchost.cpp | |||
| @@ -0,0 +1,309 @@ | |||
| 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 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 | ||
| 33 | |||
| 34 | extern "C" BOOL WINAPI DllMain( | ||
| 35 | IN HINSTANCE hInstance, | ||
| 36 | IN DWORD dwReason, | ||
| 37 | IN LPVOID /* pvReserved */ | ||
| 38 | ) | ||
| 39 | { | ||
| 40 | switch (dwReason) | ||
| 41 | { | ||
| 42 | case DLL_PROCESS_ATTACH: | ||
| 43 | ::DisableThreadLibraryCalls(hInstance); | ||
| 44 | vstate.hInstance = hInstance; | ||
| 45 | break; | ||
| 46 | |||
| 47 | case DLL_PROCESS_DETACH: | ||
| 48 | vstate.hInstance = NULL; | ||
| 49 | break; | ||
| 50 | } | ||
| 51 | |||
| 52 | return TRUE; | ||
| 53 | } | ||
| 54 | |||
| 55 | extern "C" HRESULT WINAPI BootstrapperApplicationCreate( | ||
| 56 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 57 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 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. | ||
| 65 | // This means we also can't unload. | ||
| 66 | pResults->fDisableUnloading = TRUE; | ||
| 67 | |||
| 68 | hr = BalInitializeFromCreateArgs(pArgs, &pEngine); | ||
| 69 | ExitOnFailure(hr, "Failed to initialize Bal."); | ||
| 70 | |||
| 71 | if (!vstate.fInitialized) | ||
| 72 | { | ||
| 73 | hr = XmlInitialize(); | ||
| 74 | BalExitOnFailure(hr, "Failed to initialize XML."); | ||
| 75 | |||
| 76 | hr = LoadModulePaths(&vstate); | ||
| 77 | BalExitOnFailure(hr, "Failed to get the host base path."); | ||
| 78 | |||
| 79 | hr = LoadDncConfiguration(&vstate, pArgs); | ||
| 80 | BalExitOnFailure(hr, "Failed to get the dnc configuration."); | ||
| 81 | |||
| 82 | vstate.fInitialized = TRUE; | ||
| 83 | } | ||
| 84 | |||
| 85 | if (!vstate.fInitializedRuntime) | ||
| 86 | { | ||
| 87 | hr = LoadRuntime(&vstate); | ||
| 88 | |||
| 89 | vstate.fInitializedRuntime = SUCCEEDED(hr); | ||
| 90 | } | ||
| 91 | |||
| 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 %ls bootstrapper application.", DNCHOSTTYPE_FDD == vstate.type ? L"FDD" : L"SCD"); | ||
| 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 | if (DNCHOSTTYPE_SCD == vstate.type) | ||
| 108 | { | ||
| 109 | hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE; | ||
| 110 | BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error."); | ||
| 111 | } | ||
| 112 | else | ||
| 113 | { | ||
| 114 | hrHostInitialization = S_OK; | ||
| 115 | } | ||
| 116 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr); | ||
| 117 | |||
| 118 | hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults); | ||
| 119 | BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); | ||
| 120 | } | ||
| 121 | |||
| 122 | LExit: | ||
| 123 | ReleaseNullObject(pEngine); | ||
| 124 | |||
| 125 | return hr; | ||
| 126 | } | ||
| 127 | |||
| 128 | extern "C" void WINAPI BootstrapperApplicationDestroy() | ||
| 129 | { | ||
| 130 | if (vstate.hMbapreqModule) | ||
| 131 | { | ||
| 132 | PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy")); | ||
| 133 | if (pfnDestroy) | ||
| 134 | { | ||
| 135 | (*pfnDestroy)(); | ||
| 136 | } | ||
| 137 | |||
| 138 | ::FreeLibrary(vstate.hMbapreqModule); | ||
| 139 | vstate.hMbapreqModule = NULL; | ||
| 140 | } | ||
| 141 | |||
| 142 | BalUninitialize(); | ||
| 143 | } | ||
| 144 | |||
| 145 | static HRESULT LoadModulePaths( | ||
| 146 | __in DNCSTATE* pState | ||
| 147 | ) | ||
| 148 | { | ||
| 149 | HRESULT hr = S_OK; | ||
| 150 | |||
| 151 | hr = PathForCurrentProcess(&pState->sczModuleFullPath, pState->hInstance); | ||
| 152 | BalExitOnFailure(hr, "Failed to get the full host path."); | ||
| 153 | |||
| 154 | hr = PathGetDirectory(pState->sczModuleFullPath, &pState->sczAppBase); | ||
| 155 | BalExitOnFailure(hr, "Failed to get the directory of the full process path."); | ||
| 156 | |||
| 157 | hr = PathConcat(pState->sczAppBase, DNC_ASSEMBLY_FILE_NAME, &pState->sczManagedHostPath); | ||
| 158 | BalExitOnFailure(hr, "Failed to create managed host path."); | ||
| 159 | |||
| 160 | LExit: | ||
| 161 | return hr; | ||
| 162 | } | ||
| 163 | |||
| 164 | static HRESULT LoadDncConfiguration( | ||
| 165 | __in DNCSTATE* pState, | ||
| 166 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs | ||
| 167 | ) | ||
| 168 | { | ||
| 169 | HRESULT hr = S_OK; | ||
| 170 | IXMLDOMDocument* pixdManifest = NULL; | ||
| 171 | IXMLDOMNode* pixnHost = NULL; | ||
| 172 | LPWSTR sczPayloadName = NULL; | ||
| 173 | DWORD dwBool = 0; | ||
| 174 | |||
| 175 | hr = XmlLoadDocumentFromFile(pArgs->pCommand->wzBootstrapperApplicationDataPath, &pixdManifest); | ||
| 176 | BalExitOnFailure(hr, "Failed to load BalManifest '%ls'", pArgs->pCommand->wzBootstrapperApplicationDataPath); | ||
| 177 | |||
| 178 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBalBAFactoryAssembly", &pixnHost); | ||
| 179 | BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly element."); | ||
| 180 | |||
| 181 | if (S_FALSE == hr) | ||
| 182 | { | ||
| 183 | hr = E_NOTFOUND; | ||
| 184 | BalExitOnRootFailure(hr, "Failed to find WixBalBAFactoryAssembly element in bootstrapper application config."); | ||
| 185 | } | ||
| 186 | |||
| 187 | hr = XmlGetAttributeEx(pixnHost, L"FilePath", &sczPayloadName); | ||
| 188 | BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly/@FilePath."); | ||
| 189 | |||
| 190 | hr = PathConcat(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath); | ||
| 191 | BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath."); | ||
| 192 | |||
| 193 | LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath); | ||
| 194 | LPCWSTR wzExtension = PathExtension(pState->sczBaFactoryAssemblyPath); | ||
| 195 | if (!wzExtension) | ||
| 196 | { | ||
| 197 | BalExitOnFailure(hr = E_FAIL, "BaFactoryAssemblyPath has no extension."); | ||
| 198 | } | ||
| 199 | |||
| 200 | hr = StrAllocString(&pState->sczBaFactoryAssemblyName, wzFileName, wzExtension - wzFileName); | ||
| 201 | BalExitOnFailure(hr, "Failed to copy BAFactoryAssembly payload Name."); | ||
| 202 | |||
| 203 | hr = StrAllocString(&pState->sczBaFactoryDepsJsonPath, pState->sczBaFactoryAssemblyPath, wzExtension - pState->sczBaFactoryAssemblyPath); | ||
| 204 | BalExitOnFailure(hr, "Failed to initialize deps json path."); | ||
| 205 | |||
| 206 | hr = StrAllocString(&pState->sczBaFactoryRuntimeConfigPath, pState->sczBaFactoryDepsJsonPath, 0); | ||
| 207 | BalExitOnFailure(hr, "Failed to initialize runtime config path."); | ||
| 208 | |||
| 209 | hr = StrAllocConcat(&pState->sczBaFactoryDepsJsonPath, L".deps.json", 0); | ||
| 210 | BalExitOnFailure(hr, "Failed to concat extension to deps json path."); | ||
| 211 | |||
| 212 | hr = StrAllocConcat(&pState->sczBaFactoryRuntimeConfigPath, L".runtimeconfig.json", 0); | ||
| 213 | BalExitOnFailure(hr, "Failed to concat extension to runtime config path."); | ||
| 214 | |||
| 215 | pState->type = DNCHOSTTYPE_FDD; | ||
| 216 | |||
| 217 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixDncOptions", &pixnHost); | ||
| 218 | if (S_FALSE == hr) | ||
| 219 | { | ||
| 220 | ExitFunction1(hr = S_OK); | ||
| 221 | } | ||
| 222 | BalExitOnFailure(hr, "Failed to find WixDncOptions element in bootstrapper application config."); | ||
| 223 | |||
| 224 | hr = XmlGetAttributeNumber(pixnHost, L"SelfContainedDeployment", &dwBool); | ||
| 225 | if (S_FALSE == hr) | ||
| 226 | { | ||
| 227 | hr = S_OK; | ||
| 228 | } | ||
| 229 | else if (SUCCEEDED(hr) && dwBool) | ||
| 230 | { | ||
| 231 | pState->type = DNCHOSTTYPE_SCD; | ||
| 232 | } | ||
| 233 | BalExitOnFailure(hr, "Failed to get SelfContainedDeployment value."); | ||
| 234 | |||
| 235 | LExit: | ||
| 236 | ReleaseStr(sczPayloadName); | ||
| 237 | ReleaseObject(pixnHost); | ||
| 238 | ReleaseObject(pixdManifest); | ||
| 239 | |||
| 240 | return hr; | ||
| 241 | } | ||
| 242 | |||
| 243 | static HRESULT LoadRuntime( | ||
| 244 | __in DNCSTATE* pState | ||
| 245 | ) | ||
| 246 | { | ||
| 247 | HRESULT hr = S_OK; | ||
| 248 | |||
| 249 | hr = DnchostLoadRuntime( | ||
| 250 | &pState->hostfxrState, | ||
| 251 | pState->sczModuleFullPath, | ||
| 252 | pState->sczManagedHostPath, | ||
| 253 | pState->sczBaFactoryDepsJsonPath, | ||
| 254 | pState->sczBaFactoryRuntimeConfigPath); | ||
| 255 | |||
| 256 | return hr; | ||
| 257 | } | ||
| 258 | |||
| 259 | static HRESULT LoadManagedBootstrapperApplicationFactory( | ||
| 260 | __in DNCSTATE* pState | ||
| 261 | ) | ||
| 262 | { | ||
| 263 | HRESULT hr = S_OK; | ||
| 264 | |||
| 265 | hr = DnchostCreateFactory( | ||
| 266 | &pState->hostfxrState, | ||
| 267 | pState->sczBaFactoryAssemblyName, | ||
| 268 | pState->sczBaFactoryAssemblyPath, | ||
| 269 | &pState->pAppFactory); | ||
| 270 | |||
| 271 | return hr; | ||
| 272 | } | ||
| 273 | |||
| 274 | static HRESULT CreatePrerequisiteBA( | ||
| 275 | __in HRESULT hrHostInitialization, | ||
| 276 | __in IBootstrapperEngine* pEngine, | ||
| 277 | __in LPCWSTR wzAppBase, | ||
| 278 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 279 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 280 | ) | ||
| 281 | { | ||
| 282 | HRESULT hr = S_OK; | ||
| 283 | LPWSTR sczDncpreqPath = NULL; | ||
| 284 | HMODULE hModule = NULL; | ||
| 285 | |||
| 286 | hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath); | ||
| 287 | BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); | ||
| 288 | |||
| 289 | hModule = ::LoadLibraryW(sczDncpreqPath); | ||
| 290 | BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); | ||
| 291 | |||
| 292 | PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate")); | ||
| 293 | BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath); | ||
| 294 | |||
| 295 | hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); | ||
| 296 | BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); | ||
| 297 | |||
| 298 | vstate.hMbapreqModule = hModule; | ||
| 299 | hModule = NULL; | ||
| 300 | |||
| 301 | LExit: | ||
| 302 | if (hModule) | ||
| 303 | { | ||
| 304 | ::FreeLibrary(hModule); | ||
| 305 | } | ||
| 306 | ReleaseStr(sczDncpreqPath); | ||
| 307 | |||
| 308 | return hr; | ||
| 309 | } | ||
