diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2020-03-29 19:14:06 +1000 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2020-03-30 21:40:34 +1000 |
| commit | 0354a00e74492ad8d930c5bf499bc8606e48b1c9 (patch) | |
| tree | 5640d653449287699b4cd08cb6b64fe27c4fa8af /src/engine/burnextension.cpp | |
| parent | 6ce359752afac0d3d70c2cf5fabd7d92859564ee (diff) | |
| download | wix-0354a00e74492ad8d930c5bf499bc8606e48b1c9.tar.gz wix-0354a00e74492ad8d930c5bf499bc8606e48b1c9.tar.bz2 wix-0354a00e74492ad8d930c5bf499bc8606e48b1c9.zip | |
Add support for BundleExtensions.
Diffstat (limited to 'src/engine/burnextension.cpp')
| -rw-r--r-- | src/engine/burnextension.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/src/engine/burnextension.cpp b/src/engine/burnextension.cpp new file mode 100644 index 00000000..99673cd9 --- /dev/null +++ b/src/engine/burnextension.cpp | |||
| @@ -0,0 +1,184 @@ | |||
| 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 | // function definitions | ||
| 6 | |||
| 7 | /******************************************************************* | ||
| 8 | BurnExtensionParseFromXml - | ||
| 9 | |||
| 10 | *******************************************************************/ | ||
| 11 | EXTERN_C HRESULT BurnExtensionParseFromXml( | ||
| 12 | __in BURN_EXTENSIONS* pBurnExtensions, | ||
| 13 | __in BURN_PAYLOADS* pBaPayloads, | ||
| 14 | __in IXMLDOMNode* pixnBundle | ||
| 15 | ) | ||
| 16 | { | ||
| 17 | HRESULT hr = S_OK; | ||
| 18 | IXMLDOMNodeList* pixnNodes = NULL; | ||
| 19 | IXMLDOMNode* pixnNode = NULL; | ||
| 20 | DWORD cNodes = 0; | ||
| 21 | |||
| 22 | // Select BundleExtension nodes. | ||
| 23 | hr = XmlSelectNodes(pixnBundle, L"BundleExtension", &pixnNodes); | ||
| 24 | ExitOnFailure(hr, "Failed to select BundleExtension nodes."); | ||
| 25 | |||
| 26 | // Get BundleExtension node count. | ||
| 27 | hr = pixnNodes->get_length((long*)&cNodes); | ||
| 28 | ExitOnFailure(hr, "Failed to get BundleExtension node count."); | ||
| 29 | |||
| 30 | if (!cNodes) | ||
| 31 | { | ||
| 32 | ExitFunction(); | ||
| 33 | } | ||
| 34 | |||
| 35 | // Allocate memory for BundleExtensions. | ||
| 36 | pBurnExtensions->rgExtensions = (BURN_EXTENSION*)MemAlloc(sizeof(BURN_EXTENSION) * cNodes, TRUE); | ||
| 37 | ExitOnNull(pBurnExtensions->rgExtensions, hr, E_OUTOFMEMORY, "Failed to allocate memory for BundleExtension structs."); | ||
| 38 | |||
| 39 | pBurnExtensions->cExtensions = cNodes; | ||
| 40 | |||
| 41 | // parse search elements | ||
| 42 | for (DWORD i = 0; i < cNodes; ++i) | ||
| 43 | { | ||
| 44 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 45 | |||
| 46 | hr = XmlNextElement(pixnNodes, &pixnNode, NULL); | ||
| 47 | ExitOnFailure(hr, "Failed to get next node."); | ||
| 48 | |||
| 49 | // @Id | ||
| 50 | hr = XmlGetAttributeEx(pixnNode, L"Id", &pExtension->sczId); | ||
| 51 | ExitOnFailure(hr, "Failed to get @Id."); | ||
| 52 | |||
| 53 | // @EntryPayloadId | ||
| 54 | hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadId", &pExtension->sczEntryPayloadId); | ||
| 55 | ExitOnFailure(hr, "Failed to get @EntryPayloadId."); | ||
| 56 | |||
| 57 | hr = PayloadFindById(pBaPayloads, pExtension->sczEntryPayloadId, &pExtension->pEntryPayload); | ||
| 58 | ExitOnFailure(hr, "Failed to find BundleExtension EntryPayload '%ls'.", pExtension->sczEntryPayloadId); | ||
| 59 | |||
| 60 | // prepare next iteration | ||
| 61 | ReleaseNullObject(pixnNode); | ||
| 62 | } | ||
| 63 | |||
| 64 | hr = S_OK; | ||
| 65 | |||
| 66 | LExit: | ||
| 67 | ReleaseObject(pixnNode); | ||
| 68 | ReleaseObject(pixnNodes); | ||
| 69 | |||
| 70 | return hr; | ||
| 71 | } | ||
| 72 | |||
| 73 | /******************************************************************* | ||
| 74 | BurnExtensionUninitialize - | ||
| 75 | |||
| 76 | *******************************************************************/ | ||
| 77 | EXTERN_C void BurnExtensionUninitialize( | ||
| 78 | __in BURN_EXTENSIONS* pBurnExtensions | ||
| 79 | ) | ||
| 80 | { | ||
| 81 | if (pBurnExtensions->rgExtensions) | ||
| 82 | { | ||
| 83 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 84 | { | ||
| 85 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 86 | |||
| 87 | ReleaseStr(pExtension->sczEntryPayloadId); | ||
| 88 | ReleaseStr(pExtension->sczId); | ||
| 89 | } | ||
| 90 | MemFree(pBurnExtensions->rgExtensions); | ||
| 91 | } | ||
| 92 | |||
| 93 | // clear struct | ||
| 94 | memset(pBurnExtensions, 0, sizeof(BURN_EXTENSIONS)); | ||
| 95 | } | ||
| 96 | |||
| 97 | /******************************************************************* | ||
| 98 | BurnExtensionLoad - | ||
| 99 | |||
| 100 | *******************************************************************/ | ||
| 101 | EXTERN_C HRESULT BurnExtensionLoad( | ||
| 102 | __in BURN_EXTENSIONS * pBurnExtensions, | ||
| 103 | __in BURN_EXTENSION_ENGINE_CONTEXT* pEngineContext | ||
| 104 | ) | ||
| 105 | { | ||
| 106 | HRESULT hr = S_OK; | ||
| 107 | BUNDLE_EXTENSION_CREATE_ARGS args = { }; | ||
| 108 | BUNDLE_EXTENSION_CREATE_RESULTS results = { }; | ||
| 109 | |||
| 110 | if (!pBurnExtensions->rgExtensions || !pBurnExtensions->cExtensions) | ||
| 111 | { | ||
| 112 | ExitFunction(); | ||
| 113 | } | ||
| 114 | |||
| 115 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 116 | { | ||
| 117 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 118 | |||
| 119 | memset(&args, 0, sizeof(BUNDLE_EXTENSION_CREATE_ARGS)); | ||
| 120 | memset(&results, 0, sizeof(BUNDLE_EXTENSION_CREATE_RESULTS)); | ||
| 121 | |||
| 122 | args.cbSize = sizeof(BUNDLE_EXTENSION_CREATE_ARGS); | ||
| 123 | args.pfnBundleExtensionEngineProc = EngineForExtensionProc; | ||
| 124 | args.pvBundleExtensionEngineProcContext = pEngineContext; | ||
| 125 | args.qwEngineAPIVersion = MAKEQWORDVERSION(0, 0, 0, 1); // TODO: need to decide whether to keep this, and if so when to update it. | ||
| 126 | |||
| 127 | results.cbSize = sizeof(BUNDLE_EXTENSION_CREATE_RESULTS); | ||
| 128 | |||
| 129 | // Load BundleExtension DLL. | ||
| 130 | pExtension->hBextModule = ::LoadLibraryExW(pExtension->pEntryPayload->sczLocalFilePath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | ||
| 131 | ExitOnNullWithLastError(pExtension->hBextModule, hr, "Failed to load BundleExtension DLL '%ls': '%ls'.", pExtension->sczId, pExtension->pEntryPayload->sczLocalFilePath); | ||
| 132 | |||
| 133 | // Get BundleExtensionCreate entry-point. | ||
| 134 | PFN_BUNDLE_EXTENSION_CREATE pfnCreate = (PFN_BUNDLE_EXTENSION_CREATE)::GetProcAddress(pExtension->hBextModule, "BundleExtensionCreate"); | ||
| 135 | ExitOnNullWithLastError(pfnCreate, hr, "Failed to get BundleExtensionCreate entry-point '%ls'.", pExtension->sczId); | ||
| 136 | |||
| 137 | // Create BundleExtension. | ||
| 138 | hr = pfnCreate(&args, &results); | ||
| 139 | ExitOnFailure(hr, "Failed to create BundleExtension '%ls'.", pExtension->sczId); | ||
| 140 | |||
| 141 | pExtension->pfnBurnExtensionProc = results.pfnBundleExtensionProc; | ||
| 142 | pExtension->pvBurnExtensionProcContext = results.pvBundleExtensionProcContext; | ||
| 143 | } | ||
| 144 | |||
| 145 | LExit: | ||
| 146 | return hr; | ||
| 147 | } | ||
| 148 | |||
| 149 | /******************************************************************* | ||
| 150 | BurnExtensionUnload - | ||
| 151 | |||
| 152 | *******************************************************************/ | ||
| 153 | EXTERN_C void BurnExtensionUnload( | ||
| 154 | __in BURN_EXTENSIONS * pBurnExtensions | ||
| 155 | ) | ||
| 156 | { | ||
| 157 | HRESULT hr = S_OK; | ||
| 158 | |||
| 159 | if (pBurnExtensions->rgExtensions) | ||
| 160 | { | ||
| 161 | for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i) | ||
| 162 | { | ||
| 163 | BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i]; | ||
| 164 | |||
| 165 | if (pExtension->hBextModule) | ||
| 166 | { | ||
| 167 | // Get BundleExtensionDestroy entry-point and call it if it exists. | ||
| 168 | PFN_BUNDLE_EXTENSION_DESTROY pfnDestroy = (PFN_BUNDLE_EXTENSION_DESTROY)::GetProcAddress(pExtension->hBextModule, "BundleExtensionDestroy"); | ||
| 169 | if (pfnDestroy) | ||
| 170 | { | ||
| 171 | pfnDestroy(); | ||
| 172 | } | ||
| 173 | |||
| 174 | // Free BundleExtension DLL. | ||
| 175 | if (!::FreeLibrary(pExtension->hBextModule)) | ||
| 176 | { | ||
| 177 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
| 178 | TraceError(hr, "Failed to unload BundleExtension DLL."); | ||
| 179 | } | ||
| 180 | pExtension->hBextModule = NULL; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | } | ||
