diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2020-04-29 19:28:50 +1000 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2020-04-29 19:53:29 +1000 |
| commit | 39e930d9aaff250e0fd5019eeedaa40717a6c6fe (patch) | |
| tree | bc0865bc6c9ced1b4a06b408ff60cb83ef73cad3 /src/dnchost/dnchost.cpp | |
| parent | f4b14ff16f78435285bb20f16d5d62b902e6ba17 (diff) | |
| download | wix-39e930d9aaff250e0fd5019eeedaa40717a6c6fe.tar.gz wix-39e930d9aaff250e0fd5019eeedaa40717a6c6fe.tar.bz2 wix-39e930d9aaff250e0fd5019eeedaa40717a6c6fe.zip | |
Add DotNetCoreBootstrapperApplicationHost for an SCD-style .NET Core BA.
Diffstat (limited to 'src/dnchost/dnchost.cpp')
| -rw-r--r-- | src/dnchost/dnchost.cpp | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/src/dnchost/dnchost.cpp b/src/dnchost/dnchost.cpp new file mode 100644 index 00000000..c4b0d222 --- /dev/null +++ b/src/dnchost/dnchost.cpp | |||
| @@ -0,0 +1,229 @@ | |||
| 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 | |||
| 24 | |||
| 25 | // function definitions | ||
| 26 | |||
| 27 | extern "C" BOOL WINAPI DllMain( | ||
| 28 | IN HINSTANCE hInstance, | ||
| 29 | IN DWORD dwReason, | ||
| 30 | IN LPVOID /* pvReserved */ | ||
| 31 | ) | ||
| 32 | { | ||
| 33 | switch (dwReason) | ||
| 34 | { | ||
| 35 | case DLL_PROCESS_ATTACH: | ||
| 36 | ::DisableThreadLibraryCalls(hInstance); | ||
| 37 | vstate.hInstance = hInstance; | ||
| 38 | break; | ||
| 39 | |||
| 40 | case DLL_PROCESS_DETACH: | ||
| 41 | vstate.hInstance = NULL; | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | |||
| 45 | return TRUE; | ||
| 46 | } | ||
| 47 | |||
| 48 | extern "C" HRESULT WINAPI BootstrapperApplicationCreate( | ||
| 49 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, | ||
| 50 | __inout BOOTSTRAPPER_CREATE_RESULTS* pResults | ||
| 51 | ) | ||
| 52 | { | ||
| 53 | HRESULT hr = S_OK; | ||
| 54 | IBootstrapperEngine* pEngine = NULL; | ||
| 55 | |||
| 56 | // coreclr.dll doesn't support unloading, so the rest of the .NET Core hosting stack doesn't support it either. | ||
| 57 | // This means we also can't unload. | ||
| 58 | pResults->fDisableUnloading = TRUE; | ||
| 59 | |||
| 60 | hr = BalInitializeFromCreateArgs(pArgs, &pEngine); | ||
| 61 | ExitOnFailure(hr, "Failed to initialize Bal."); | ||
| 62 | |||
| 63 | if (!vstate.fInitialized) | ||
| 64 | { | ||
| 65 | hr = XmlInitialize(); | ||
| 66 | BalExitOnFailure(hr, "Failed to initialize XML."); | ||
| 67 | |||
| 68 | hr = LoadModulePaths(&vstate); | ||
| 69 | BalExitOnFailure(hr, "Failed to get the host base path."); | ||
| 70 | |||
| 71 | hr = LoadDncConfiguration(&vstate, pArgs); | ||
| 72 | BalExitOnFailure(hr, "Failed to get the dnc configuration."); | ||
| 73 | |||
| 74 | vstate.fInitialized = TRUE; | ||
| 75 | } | ||
| 76 | |||
| 77 | if (!vstate.fInitializedRuntime) | ||
| 78 | { | ||
| 79 | hr = LoadRuntime(&vstate); | ||
| 80 | BalExitOnFailure(hr, "Failed to load .NET Core runtime."); | ||
| 81 | |||
| 82 | vstate.fInitializedRuntime = TRUE; | ||
| 83 | |||
| 84 | hr = LoadManagedBootstrapperApplicationFactory(&vstate); | ||
| 85 | BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory."); | ||
| 86 | } | ||
| 87 | |||
| 88 | BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core SCD bootstrapper application."); | ||
| 89 | |||
| 90 | hr = vstate.pAppFactory->Create(pArgs, pResults); | ||
| 91 | BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application."); | ||
| 92 | |||
| 93 | LExit: | ||
| 94 | ReleaseNullObject(pEngine); | ||
| 95 | |||
| 96 | return hr; | ||
| 97 | } | ||
| 98 | |||
| 99 | extern "C" void WINAPI BootstrapperApplicationDestroy() | ||
| 100 | { | ||
| 101 | BalUninitialize(); | ||
| 102 | } | ||
| 103 | |||
| 104 | static HRESULT LoadModulePaths( | ||
| 105 | __in DNCSTATE* pState | ||
| 106 | ) | ||
| 107 | { | ||
| 108 | HRESULT hr = S_OK; | ||
| 109 | |||
| 110 | hr = PathForCurrentProcess(&pState->sczModuleFullPath, pState->hInstance); | ||
| 111 | BalExitOnFailure(hr, "Failed to get the full host path."); | ||
| 112 | |||
| 113 | hr = PathGetDirectory(pState->sczModuleFullPath, &pState->sczAppBase); | ||
| 114 | BalExitOnFailure(hr, "Failed to get the directory of the full process path."); | ||
| 115 | |||
| 116 | hr = PathConcat(pState->sczAppBase, DNC_ASSEMBLY_FILE_NAME, &pState->sczManagedHostPath); | ||
| 117 | BalExitOnFailure(hr, "Failed to create managed host path."); | ||
| 118 | |||
| 119 | LExit: | ||
| 120 | return hr; | ||
| 121 | } | ||
| 122 | |||
| 123 | static HRESULT LoadDncConfiguration( | ||
| 124 | __in DNCSTATE* pState, | ||
| 125 | __in const BOOTSTRAPPER_CREATE_ARGS* pArgs | ||
| 126 | ) | ||
| 127 | { | ||
| 128 | HRESULT hr = S_OK; | ||
| 129 | IXMLDOMDocument* pixdManifest = NULL; | ||
| 130 | IXMLDOMNode* pixnHost = NULL; | ||
| 131 | IXMLDOMNode* pixnPayload = NULL; | ||
| 132 | LPWSTR sczPayloadId = NULL; | ||
| 133 | LPWSTR sczPayloadXPath = NULL; | ||
| 134 | LPWSTR sczPayloadName = NULL; | ||
| 135 | |||
| 136 | hr = XmlLoadDocumentFromFile(pArgs->pCommand->wzBootstrapperApplicationDataPath, &pixdManifest); | ||
| 137 | BalExitOnFailure(hr, "Failed to load BalManifest '%ls'", pArgs->pCommand->wzBootstrapperApplicationDataPath); | ||
| 138 | |||
| 139 | hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBalBAFactoryAssembly", &pixnHost); | ||
| 140 | BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly element."); | ||
| 141 | |||
| 142 | if (S_FALSE == hr) | ||
| 143 | { | ||
| 144 | hr = E_NOTFOUND; | ||
| 145 | BalExitOnRootFailure(hr, "Failed to find WixBalBAFactoryAssembly element in bootstrapper application config."); | ||
| 146 | } | ||
| 147 | |||
| 148 | hr = XmlGetAttributeEx(pixnHost, L"PayloadId", &sczPayloadId); | ||
| 149 | BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly/@PayloadId."); | ||
| 150 | |||
| 151 | hr = StrAllocFormatted(&sczPayloadXPath, L"/BootstrapperApplicationData/WixPayloadProperties[@Payload='%ls']", sczPayloadId); | ||
| 152 | BalExitOnFailure(hr, "Failed to format BAFactoryAssembly payload XPath."); | ||
| 153 | |||
| 154 | hr = XmlSelectSingleNode(pixdManifest, sczPayloadXPath, &pixnPayload); | ||
| 155 | if (S_FALSE == hr) | ||
| 156 | { | ||
| 157 | hr = E_NOTFOUND; | ||
| 158 | } | ||
| 159 | BalExitOnFailure(hr, "Failed to find WixPayloadProperties node for BAFactoryAssembly PayloadId: %ls.", sczPayloadId); | ||
| 160 | |||
| 161 | hr = XmlGetAttributeEx(pixnPayload, L"Name", &sczPayloadName); | ||
| 162 | BalExitOnFailure(hr, "Failed to get BAFactoryAssembly payload Name."); | ||
| 163 | |||
| 164 | hr = PathConcat(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath); | ||
| 165 | BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath."); | ||
| 166 | |||
| 167 | LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath); | ||
| 168 | LPCWSTR wzExtension = PathExtension(pState->sczBaFactoryAssemblyPath); | ||
| 169 | if (!wzExtension) | ||
| 170 | { | ||
| 171 | BalExitOnFailure(hr = E_FAIL, "BaFactoryAssemblyPath has no extension."); | ||
| 172 | } | ||
| 173 | |||
| 174 | hr = StrAllocString(&pState->sczBaFactoryAssemblyName, wzFileName, wzExtension - wzFileName); | ||
| 175 | BalExitOnFailure(hr, "Failed to copy BAFactoryAssembly payload Name."); | ||
| 176 | |||
| 177 | hr = StrAllocString(&pState->sczBaFactoryDepsJsonPath, pState->sczBaFactoryAssemblyPath, wzExtension - pState->sczBaFactoryAssemblyPath); | ||
| 178 | BalExitOnFailure(hr, "Failed to initialize deps json path."); | ||
| 179 | |||
| 180 | hr = StrAllocString(&pState->sczBaFactoryRuntimeConfigPath, pState->sczBaFactoryDepsJsonPath, 0); | ||
| 181 | BalExitOnFailure(hr, "Failed to initialize runtime config path."); | ||
| 182 | |||
| 183 | hr = StrAllocConcat(&pState->sczBaFactoryDepsJsonPath, L".deps.json", 0); | ||
| 184 | BalExitOnFailure(hr, "Failed to concat extension to deps json path."); | ||
| 185 | |||
| 186 | hr = StrAllocConcat(&pState->sczBaFactoryRuntimeConfigPath, L".runtimeconfig.json", 0); | ||
| 187 | BalExitOnFailure(hr, "Failed to concat extension to runtime config path."); | ||
| 188 | |||
| 189 | LExit: | ||
| 190 | ReleaseStr(sczPayloadName); | ||
| 191 | ReleaseObject(pixnPayload); | ||
| 192 | ReleaseStr(sczPayloadXPath); | ||
| 193 | ReleaseStr(sczPayloadId); | ||
| 194 | ReleaseObject(pixnHost); | ||
| 195 | ReleaseObject(pixdManifest); | ||
| 196 | |||
| 197 | return hr; | ||
| 198 | } | ||
| 199 | |||
| 200 | static HRESULT LoadRuntime( | ||
| 201 | __in DNCSTATE* pState | ||
| 202 | ) | ||
| 203 | { | ||
| 204 | HRESULT hr = S_OK; | ||
| 205 | |||
| 206 | hr = DnchostLoadRuntime( | ||
| 207 | &pState->hostfxrState, | ||
| 208 | pState->sczModuleFullPath, | ||
| 209 | pState->sczManagedHostPath, | ||
| 210 | pState->sczBaFactoryDepsJsonPath, | ||
| 211 | pState->sczBaFactoryRuntimeConfigPath); | ||
| 212 | |||
| 213 | return hr; | ||
| 214 | } | ||
| 215 | |||
| 216 | static HRESULT LoadManagedBootstrapperApplicationFactory( | ||
| 217 | __in DNCSTATE* pState | ||
| 218 | ) | ||
| 219 | { | ||
| 220 | HRESULT hr = S_OK; | ||
| 221 | |||
| 222 | hr = DnchostCreateFactory( | ||
| 223 | &pState->hostfxrState, | ||
| 224 | pState->sczBaFactoryAssemblyName, | ||
| 225 | pState->sczBaFactoryAssemblyPath, | ||
| 226 | &pState->pAppFactory); | ||
| 227 | |||
| 228 | return hr; | ||
| 229 | } | ||
