diff options
| author | Rob Mensching <rob@firegiant.com> | 2021-04-22 17:06:54 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2021-04-29 16:36:06 -0700 |
| commit | af10c45d7b3a44af0b461a557847fe03263dcc10 (patch) | |
| tree | 6a5c1532304782c36ffe4200b38f3afb76789a43 /src/burn/engine/burnextension.cpp | |
| parent | 9c2aed97299fb96aeee3f1471ce40225437aaecf (diff) | |
| download | wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.gz wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.bz2 wix-af10c45d7b3a44af0b461a557847fe03263dcc10.zip | |
Move burn into burn
Diffstat (limited to 'src/burn/engine/burnextension.cpp')
| -rw-r--r-- | src/burn/engine/burnextension.cpp | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/src/burn/engine/burnextension.cpp b/src/burn/engine/burnextension.cpp new file mode 100644 index 00000000..475df1c5 --- /dev/null +++ b/src/burn/engine/burnextension.cpp | |||
| @@ -0,0 +1,264 @@ | |||
| 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 | |||
| 6 | static HRESULT SendRequiredBextMessage( | ||
| 7 | __in BURN_EXTENSION* pExtension, | ||
| 8 | __in BUNDLE_EXTENSION_MESSAGE message, | ||
| 9 | __in const LPVOID pvArgs, | ||
| 10 | __inout LPVOID pvResults | ||
| 11 | ); | ||
| 12 | |||
| 13 | // function definitions | ||
| 14 | |||
| 15 | /******************************************************************* | ||
| 16 | BurnExtensionParseFromXml - | ||
| 17 | |||
| 18 | *******************************************************************/ | ||
| 19 | EXTERN_C HRESULT BurnExtensionParseFromXml( | ||
| 20 | __in BURN_EXTENSIONS* pBurnExtensions, | ||
| 21 | __in BURN_PAYLOADS* pBaPayloads, | ||
| 22 | __in IXMLDOMNode* pixnBundle | ||
| 23 | ) | ||
| 24 | { | ||
| 25 | HRESULT hr = S_OK; | ||
| 26 | IXMLDOMNodeList* pixnNodes = NULL; | ||
| 27 | IXMLDOMNode* pixnNode = NULL; | ||
| 28 | DWORD cNodes = 0; | ||
| 29 | |||
| 30 | // Select BundleExtension nodes. | ||
| 31 | hr = XmlSelectNodes(pixnBundle, L"BundleExtension", &pixnNodes); | ||
| 32 | ExitOnFailure(hr, "Failed to select BundleExtension nodes."); | ||
| 33 | |||
| 34 | // Get BundleExtension node count. | ||
| 35 | hr = pixnNodes->get_length((long*)&cNodes); | ||
| 36 | ExitOnFailure(hr, "Failed to get BundleExtension node count."); | ||
| 37 | |||
| 38 | if (!cNodes) | ||
| 39 | { | ||
| 40 | ExitFunction(); | ||
| 41 | } | ||
| 42 | |||
| 43 | // Allocate memory for BundleExtensions. | ||
| 44 | pBurnExtensions->rgExtensions = (BURN_EXTENSION*)MemAlloc(sizeof(BURN_EXTENSION) * cNodes, TRUE); | ||
| 45 | ExitOnNull(pBurnExtensions->rgExtensions, hr, E_OUTOFMEMORY, "Failed to allocate memory for BundleExtension structs."); | ||
| 46 | |||
| 47 | pBurnExtensions->cExtensions = cNodes; | ||
| 48 | |||
| 49 | // parse search elements | ||
| 50 | for (DWORD i = 0; i < cNodes; ++i) | ||
| 51 | { | ||
| 52 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 53 | |||
| 54 | hr = XmlNextElement(pixnNodes, &pixnNode, NULL); | ||
| 55 | ExitOnFailure(hr, "Failed to get next node."); | ||
| 56 | |||
| 57 | // @Id | ||
| 58 | hr = XmlGetAttributeEx(pixnNode, L"Id", &pExtension->sczId); | ||
| 59 | ExitOnFailure(hr, "Failed to get @Id."); | ||
| 60 | |||
| 61 | // @EntryPayloadId | ||
| 62 | hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadId", &pExtension->sczEntryPayloadId); | ||
| 63 | ExitOnFailure(hr, "Failed to get @EntryPayloadId."); | ||
| 64 | |||
| 65 | hr = PayloadFindById(pBaPayloads, pExtension->sczEntryPayloadId, &pExtension->pEntryPayload); | ||
| 66 | ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczEntryPayloadId); | ||
| 67 | |||
| 68 | // prepare next iteration | ||
| 69 | ReleaseNullObject(pixnNode); | ||
| 70 | } | ||
| 71 | |||
| 72 | hr = S_OK; | ||
| 73 | |||
| 74 | LExit: | ||
| 75 | ReleaseObject(pixnNode); | ||
| 76 | ReleaseObject(pixnNodes); | ||
| 77 | |||
| 78 | return hr; | ||
| 79 | } | ||
| 80 | |||
| 81 | /******************************************************************* | ||
| 82 | BurnExtensionUninitialize - | ||
| 83 | |||
| 84 | *******************************************************************/ | ||
| 85 | EXTERN_C void BurnExtensionUninitialize( | ||
| 86 | __in BURN_EXTENSIONS* pBurnExtensions | ||
| 87 | ) | ||
| 88 | { | ||
| 89 | if (pBurnExtensions->rgExtensions) | ||
| 90 | { | ||
| 91 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 92 | { | ||
| 93 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 94 | |||
| 95 | ReleaseStr(pExtension->sczEntryPayloadId); | ||
| 96 | ReleaseStr(pExtension->sczId); | ||
| 97 | } | ||
| 98 | MemFree(pBurnExtensions->rgExtensions); | ||
| 99 | } | ||
| 100 | |||
| 101 | // clear struct | ||
| 102 | memset(pBurnExtensions, 0, sizeof(BURN_EXTENSIONS)); | ||
| 103 | } | ||
| 104 | |||
| 105 | /******************************************************************* | ||
| 106 | BurnExtensionLoad - | ||
| 107 | |||
| 108 | *******************************************************************/ | ||
| 109 | EXTERN_C HRESULT BurnExtensionLoad( | ||
| 110 | __in BURN_EXTENSIONS * pBurnExtensions, | ||
| 111 | __in BURN_EXTENSION_ENGINE_CONTEXT* pEngineContext | ||
| 112 | ) | ||
| 113 | { | ||
| 114 | HRESULT hr = S_OK; | ||
| 115 | LPWSTR sczBundleExtensionDataPath = NULL; | ||
| 116 | BUNDLE_EXTENSION_CREATE_ARGS args = { }; | ||
| 117 | BUNDLE_EXTENSION_CREATE_RESULTS results = { }; | ||
| 118 | |||
| 119 | if (!pBurnExtensions->rgExtensions || !pBurnExtensions->cExtensions) | ||
| 120 | { | ||
| 121 | ExitFunction(); | ||
| 122 | } | ||
| 123 | |||
| 124 | hr = PathConcat(pEngineContext->pEngineState->userExperience.sczTempDirectory, L"BundleExtensionData.xml", &sczBundleExtensionDataPath); | ||
| 125 | ExitOnFailure(hr, "Failed to get BundleExtensionDataPath."); | ||
| 126 | |||
| 127 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 128 | { | ||
| 129 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 130 | |||
| 131 | memset(&args, 0, sizeof(BUNDLE_EXTENSION_CREATE_ARGS)); | ||
| 132 | memset(&results, 0, sizeof(BUNDLE_EXTENSION_CREATE_RESULTS)); | ||
| 133 | |||
| 134 | args.cbSize = sizeof(BUNDLE_EXTENSION_CREATE_ARGS); | ||
| 135 | args.pfnBundleExtensionEngineProc = EngineForExtensionProc; | ||
| 136 | args.pvBundleExtensionEngineProcContext = pEngineContext; | ||
| 137 | args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 4, 27, 0); | ||
| 138 | args.wzBootstrapperWorkingFolder = pEngineContext->pEngineState->userExperience.sczTempDirectory; | ||
| 139 | args.wzBundleExtensionDataPath = sczBundleExtensionDataPath; | ||
| 140 | args.wzExtensionId = pExtension->sczId; | ||
| 141 | |||
| 142 | results.cbSize = sizeof(BUNDLE_EXTENSION_CREATE_RESULTS); | ||
| 143 | |||
| 144 | // Load BundleExtension DLL. | ||
| 145 | pExtension->hBextModule = ::LoadLibraryExW(pExtension->pEntryPayload->sczLocalFilePath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | ||
| 146 | ExitOnNullWithLastError(pExtension->hBextModule, hr, "Failed to load BundleExtension DLL '%ls': '%ls'.", pExtension->sczId, pExtension->pEntryPayload->sczLocalFilePath); | ||
| 147 | |||
| 148 | // Get BundleExtensionCreate entry-point. | ||
| 149 | PFN_BUNDLE_EXTENSION_CREATE pfnCreate = (PFN_BUNDLE_EXTENSION_CREATE)::GetProcAddress(pExtension->hBextModule, "BundleExtensionCreate"); | ||
| 150 | ExitOnNullWithLastError(pfnCreate, hr, "Failed to get BundleExtensionCreate entry-point '%ls'.", pExtension->sczId); | ||
| 151 | |||
| 152 | // Create BundleExtension. | ||
| 153 | hr = pfnCreate(&args, &results); | ||
| 154 | ExitOnFailure(hr, "Failed to create BundleExtension '%ls'.", pExtension->sczId); | ||
| 155 | |||
| 156 | pExtension->pfnBurnExtensionProc = results.pfnBundleExtensionProc; | ||
| 157 | pExtension->pvBurnExtensionProcContext = results.pvBundleExtensionProcContext; | ||
| 158 | } | ||
| 159 | |||
| 160 | LExit: | ||
| 161 | ReleaseStr(sczBundleExtensionDataPath); | ||
| 162 | |||
| 163 | return hr; | ||
| 164 | } | ||
| 165 | |||
| 166 | /******************************************************************* | ||
| 167 | BurnExtensionUnload - | ||
| 168 | |||
| 169 | *******************************************************************/ | ||
| 170 | EXTERN_C void BurnExtensionUnload( | ||
| 171 | __in BURN_EXTENSIONS * pBurnExtensions | ||
| 172 | ) | ||
| 173 | { | ||
| 174 | HRESULT hr = S_OK; | ||
| 175 | |||
| 176 | if (pBurnExtensions->rgExtensions) | ||
| 177 | { | ||
| 178 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 179 | { | ||
| 180 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 181 | |||
| 182 | if (pExtension->hBextModule) | ||
| 183 | { | ||
| 184 | // Get BundleExtensionDestroy entry-point and call it if it exists. | ||
| 185 | PFN_BUNDLE_EXTENSION_DESTROY pfnDestroy = (PFN_BUNDLE_EXTENSION_DESTROY)::GetProcAddress(pExtension->hBextModule, "BundleExtensionDestroy"); | ||
| 186 | if (pfnDestroy) | ||
| 187 | { | ||
| 188 | pfnDestroy(); | ||
| 189 | } | ||
| 190 | |||
| 191 | // Free BundleExtension DLL. | ||
| 192 | if (!::FreeLibrary(pExtension->hBextModule)) | ||
| 193 | { | ||
| 194 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
| 195 | TraceError(hr, "Failed to unload BundleExtension DLL."); | ||
| 196 | } | ||
| 197 | pExtension->hBextModule = NULL; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | EXTERN_C HRESULT BurnExtensionFindById( | ||
| 204 | __in BURN_EXTENSIONS* pBurnExtensions, | ||
| 205 | __in_z LPCWSTR wzId, | ||
| 206 | __out BURN_EXTENSION** ppExtension | ||
| 207 | ) | ||
| 208 | { | ||
| 209 | HRESULT hr = S_OK; | ||
| 210 | BURN_EXTENSION* pExtension = NULL; | ||
| 211 | |||
| 212 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 213 | { | ||
| 214 | pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 215 | |||
| 216 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pExtension->sczId, -1, wzId, -1)) | ||
| 217 | { | ||
| 218 | *ppExtension = pExtension; | ||
| 219 | ExitFunction1(hr = S_OK); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | hr = E_NOTFOUND; | ||
| 224 | |||
| 225 | LExit: | ||
| 226 | return hr; | ||
| 227 | } | ||
| 228 | |||
| 229 | EXTERN_C BEEAPI BurnExtensionPerformSearch( | ||
| 230 | __in BURN_EXTENSION* pExtension, | ||
| 231 | __in LPWSTR wzSearchId, | ||
| 232 | __in LPWSTR wzVariable | ||
| 233 | ) | ||
| 234 | { | ||
| 235 | HRESULT hr = S_OK; | ||
| 236 | BUNDLE_EXTENSION_SEARCH_ARGS args = { }; | ||
| 237 | BUNDLE_EXTENSION_SEARCH_RESULTS results = { }; | ||
| 238 | |||
| 239 | args.cbSize = sizeof(args); | ||
| 240 | args.wzId = wzSearchId; | ||
| 241 | args.wzVariable = wzVariable; | ||
| 242 | |||
| 243 | results.cbSize = sizeof(results); | ||
| 244 | |||
| 245 | hr = SendRequiredBextMessage(pExtension, BUNDLE_EXTENSION_MESSAGE_SEARCH, &args, &results); | ||
| 246 | ExitOnFailure(hr, "BundleExtension '%ls' Search '%ls' failed.", pExtension->sczId, wzSearchId); | ||
| 247 | |||
| 248 | LExit: | ||
| 249 | return hr; | ||
| 250 | } | ||
| 251 | |||
| 252 | static HRESULT SendRequiredBextMessage( | ||
| 253 | __in BURN_EXTENSION* pExtension, | ||
| 254 | __in BUNDLE_EXTENSION_MESSAGE message, | ||
| 255 | __in const LPVOID pvArgs, | ||
| 256 | __inout LPVOID pvResults | ||
| 257 | ) | ||
| 258 | { | ||
| 259 | HRESULT hr = S_OK; | ||
| 260 | |||
| 261 | hr = pExtension->pfnBurnExtensionProc(message, pvArgs, pvResults, pExtension->pvBurnExtensionProcContext); | ||
| 262 | |||
| 263 | return hr; | ||
| 264 | } | ||
