main
cpp 265 lines 8.76 KB
Raw
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 BOOTSTRAPPER_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 LPWSTR scz = NULL;
30
31 // Select BootstrapperExtension nodes.
32 hr = XmlSelectNodes(pixnBundle, L"BootstrapperExtension", &pixnNodes);
33 ExitOnFailure(hr, "Failed to select BootstrapperExtension nodes.");
34
35 // Get BootstrapperExtension node count.
36 hr = pixnNodes->get_length((long*)&cNodes);
37 ExitOnFailure(hr, "Failed to get BootstrapperExtension node count.");
38
39 if (!cNodes)
40 {
41 ExitFunction();
42 }
43
44 // Allocate memory for BootstrapperExtensions.
45 pBurnExtensions->rgExtensions = (BURN_EXTENSION*)MemAlloc(sizeof(BURN_EXTENSION) * cNodes, TRUE);
46 ExitOnNull(pBurnExtensions->rgExtensions, hr, E_OUTOFMEMORY, "Failed to allocate memory for BootstrapperExtension structs.");
47
48 pBurnExtensions->cExtensions = cNodes;
49
50 // parse search elements
51 for (DWORD i = 0; i < cNodes; ++i)
52 {
53 BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
54
55 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
56 ExitOnFailure(hr, "Failed to get next node.");
57
58 // @Id
59 hr = XmlGetAttributeEx(pixnNode, L"Id", &pExtension->sczId);
60 ExitOnFailure(hr, "Failed to get @Id.");
61
62 // @EntryPayloadId
63 hr = XmlGetAttributeEx(pixnNode, L"EntryPayloadSourcePath", &scz);
64 ExitOnFailure(hr, "Failed to get @EntryPayloadSourcePath.");
65
66 hr = PayloadFindEmbeddedBySourcePath(pBaPayloads->sdhPayloads, scz, &pExtension->pEntryPayload);
67 ExitOnFailure(hr, "Failed to find BootstrapperExtension EntryPayload '%ls'.", pExtension->sczId);
68
69 // prepare next iteration
70 ReleaseNullObject(pixnNode);
71 }
72
73 hr = S_OK;
74
75 LExit:
76 ReleaseStr(scz);
77 ReleaseObject(pixnNode);
78 ReleaseObject(pixnNodes);
79
80 return hr;
81 }
82
83 /*******************************************************************
84 BurnExtensionUninitialize -
85
86 *******************************************************************/
87 EXTERN_C void BurnExtensionUninitialize(
88 __in BURN_EXTENSIONS* pBurnExtensions
89 )
90 {
91 if (pBurnExtensions->rgExtensions)
92 {
93 for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i)
94 {
95 BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
96
97 ReleaseStr(pExtension->sczId);
98 }
99 MemFree(pBurnExtensions->rgExtensions);
100 }
101
102 // clear struct
103 memset(pBurnExtensions, 0, sizeof(BURN_EXTENSIONS));
104 }
105
106 /*******************************************************************
107 BurnExtensionLoad -
108
109 *******************************************************************/
110 EXTERN_C HRESULT BurnExtensionLoad(
111 __in BURN_EXTENSIONS * pBurnExtensions,
112 __in BURN_EXTENSION_ENGINE_CONTEXT* pEngineContext
113 )
114 {
115 HRESULT hr = S_OK;
116 LPWSTR sczBootstrapperExtensionDataPath = NULL;
117 BOOTSTRAPPER_EXTENSION_CREATE_ARGS args = { };
118 BOOTSTRAPPER_EXTENSION_CREATE_RESULTS results = { };
119
120 if (!pBurnExtensions->rgExtensions || !pBurnExtensions->cExtensions)
121 {
122 ExitFunction();
123 }
124
125 hr = PathConcat(pEngineContext->pEngineState->userExperience.sczTempDirectory, L"BootstrapperExtensionData.xml", &sczBootstrapperExtensionDataPath);
126 ExitOnFailure(hr, "Failed to get BootstrapperExtensionDataPath.");
127
128 for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i)
129 {
130 BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
131
132 memset(&args, 0, sizeof(BOOTSTRAPPER_EXTENSION_CREATE_ARGS));
133 memset(&results, 0, sizeof(BOOTSTRAPPER_EXTENSION_CREATE_RESULTS));
134
135 args.cbSize = sizeof(BOOTSTRAPPER_EXTENSION_CREATE_ARGS);
136 args.pfnBootstrapperExtensionEngineProc = EngineForExtensionProc;
137 args.pvBootstrapperExtensionEngineProcContext = pEngineContext;
138 args.qwEngineAPIVersion = MAKEQWORDVERSION(2021, 4, 27, 0);
139 args.wzBootstrapperWorkingFolder = pEngineContext->pEngineState->userExperience.sczTempDirectory;
140 args.wzBootstrapperExtensionDataPath = sczBootstrapperExtensionDataPath;
141 args.wzExtensionId = pExtension->sczId;
142
143 results.cbSize = sizeof(BOOTSTRAPPER_EXTENSION_CREATE_RESULTS);
144
145 // Load BootstrapperExtension DLL.
146 pExtension->hBextModule = ::LoadLibraryExW(pExtension->pEntryPayload->sczLocalFilePath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
147 ExitOnNullWithLastError(pExtension->hBextModule, hr, "Failed to load BootstrapperExtension DLL '%ls': '%ls'.", pExtension->sczId, pExtension->pEntryPayload->sczLocalFilePath);
148
149 // Get BootstrapperExtensionCreate entry-point.
150 PFN_BOOTSTRAPPER_EXTENSION_CREATE pfnCreate = (PFN_BOOTSTRAPPER_EXTENSION_CREATE)::GetProcAddress(pExtension->hBextModule, "BootstrapperExtensionCreate");
151 ExitOnNullWithLastError(pfnCreate, hr, "Failed to get BootstrapperExtensionCreate entry-point '%ls'.", pExtension->sczId);
152
153 // Create BootstrapperExtension.
154 hr = pfnCreate(&args, &results);
155 ExitOnFailure(hr, "Failed to create BootstrapperExtension '%ls'.", pExtension->sczId);
156
157 pExtension->pfnBurnExtensionProc = results.pfnBootstrapperExtensionProc;
158 pExtension->pvBurnExtensionProcContext = results.pvBootstrapperExtensionProcContext;
159 }
160
161 LExit:
162 ReleaseStr(sczBootstrapperExtensionDataPath);
163
164 return hr;
165 }
166
167 /*******************************************************************
168 BurnExtensionUnload -
169
170 *******************************************************************/
171 EXTERN_C void BurnExtensionUnload(
172 __in BURN_EXTENSIONS * pBurnExtensions
173 )
174 {
175 HRESULT hr = S_OK;
176
177 if (pBurnExtensions->rgExtensions)
178 {
179 for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i)
180 {
181 BURN_EXTENSION* pExtension = &pBurnExtensions->rgExtensions[i];
182
183 if (pExtension->hBextModule)
184 {
185 // Get BootstrapperExtensionDestroy entry-point and call it if it exists.
186 PFN_BOOTSTRAPPER_EXTENSION_DESTROY pfnDestroy = (PFN_BOOTSTRAPPER_EXTENSION_DESTROY)::GetProcAddress(pExtension->hBextModule, "BootstrapperExtensionDestroy");
187 if (pfnDestroy)
188 {
189 pfnDestroy();
190 }
191
192 // Free BootstrapperExtension DLL.
193 if (!::FreeLibrary(pExtension->hBextModule))
194 {
195 hr = HRESULT_FROM_WIN32(::GetLastError());
196 TraceError(hr, "Failed to unload BootstrapperExtension DLL.");
197 }
198 pExtension->hBextModule = NULL;
199 }
200 }
201 }
202 }
203
204 EXTERN_C HRESULT BurnExtensionFindById(
205 __in BURN_EXTENSIONS* pBurnExtensions,
206 __in_z LPCWSTR wzId,
207 __out BURN_EXTENSION** ppExtension
208 )
209 {
210 HRESULT hr = S_OK;
211 BURN_EXTENSION* pExtension = NULL;
212
213 for (DWORD i = 0; i < pBurnExtensions->cExtensions; ++i)
214 {
215 pExtension = &pBurnExtensions->rgExtensions[i];
216
217 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pExtension->sczId, -1, wzId, -1))
218 {
219 *ppExtension = pExtension;
220 ExitFunction1(hr = S_OK);
221 }
222 }
223
224 hr = E_NOTFOUND;
225
226 LExit:
227 return hr;
228 }
229
230 EXTERN_C BEEAPI BurnExtensionPerformSearch(
231 __in BURN_EXTENSION* pExtension,
232 __in LPWSTR wzSearchId,
233 __in LPWSTR wzVariable
234 )
235 {
236 HRESULT hr = S_OK;
237 BOOTSTRAPPER_EXTENSION_SEARCH_ARGS args = { };
238 BOOTSTRAPPER_EXTENSION_SEARCH_RESULTS results = { };
239
240 args.cbSize = sizeof(args);
241 args.wzId = wzSearchId;
242 args.wzVariable = wzVariable;
243
244 results.cbSize = sizeof(results);
245
246 hr = SendRequiredBextMessage(pExtension, BOOTSTRAPPER_EXTENSION_MESSAGE_SEARCH, &args, &results);
247 ExitOnFailure(hr, "BootstrapperExtension '%ls' Search '%ls' failed.", pExtension->sczId, wzSearchId);
248
249 LExit:
250 return hr;
251 }
252
253 static HRESULT SendRequiredBextMessage(
254 __in BURN_EXTENSION* pExtension,
255 __in BOOTSTRAPPER_EXTENSION_MESSAGE message,
256 __in const LPVOID pvArgs,
257 __inout LPVOID pvResults
258 )
259 {
260 HRESULT hr = S_OK;
261
262 hr = pExtension->pfnBurnExtensionProc(message, pvArgs, pvResults, pExtension->pvBurnExtensionProcContext);
263
264 return hr;
265 }