aboutsummaryrefslogtreecommitdiff
path: root/src/engine/burnextension.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/engine/burnextension.cpp184
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*******************************************************************/
11EXTERN_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
66LExit:
67 ReleaseObject(pixnNode);
68 ReleaseObject(pixnNodes);
69
70 return hr;
71}
72
73/*******************************************************************
74 BurnExtensionUninitialize -
75
76*******************************************************************/
77EXTERN_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*******************************************************************/
101EXTERN_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
145LExit:
146 return hr;
147}
148
149/*******************************************************************
150 BurnExtensionUnload -
151
152*******************************************************************/
153EXTERN_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}