summaryrefslogtreecommitdiff
path: root/src/burn/engine/payload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/payload.cpp')
-rw-r--r--src/burn/engine/payload.cpp314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp
new file mode 100644
index 00000000..72eb3476
--- /dev/null
+++ b/src/burn/engine/payload.cpp
@@ -0,0 +1,314 @@
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// internal function declarations
7
8static HRESULT FindEmbeddedBySourcePath(
9 __in BURN_PAYLOADS* pPayloads,
10 __in_opt BURN_CONTAINER* pContainer,
11 __in_z LPCWSTR wzStreamName,
12 __out BURN_PAYLOAD** ppPayload
13 );
14
15
16// function definitions
17
18extern "C" HRESULT PayloadsParseFromXml(
19 __in BURN_PAYLOADS* pPayloads,
20 __in_opt BURN_CONTAINERS* pContainers,
21 __in_opt BURN_PAYLOAD_GROUP* pLayoutPayloads,
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 payload nodes
32 hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes);
33 ExitOnFailure(hr, "Failed to select payload nodes.");
34
35 // get payload node count
36 hr = pixnNodes->get_length((long*)&cNodes);
37 ExitOnFailure(hr, "Failed to get payload node count.");
38
39 if (!cNodes)
40 {
41 ExitFunction();
42 }
43
44 // allocate memory for payloads
45 pPayloads->rgPayloads = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD) * cNodes, TRUE);
46 ExitOnNull(pPayloads->rgPayloads, hr, E_OUTOFMEMORY, "Failed to allocate memory for payload structs.");
47
48 pPayloads->cPayloads = cNodes;
49
50 // parse search elements
51 for (DWORD i = 0; i < cNodes; ++i)
52 {
53 BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[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", &pPayload->sczKey);
60 ExitOnFailure(hr, "Failed to get @Id.");
61
62 // @FilePath
63 hr = XmlGetAttributeEx(pixnNode, L"FilePath", &pPayload->sczFilePath);
64 ExitOnFailure(hr, "Failed to get @FilePath.");
65
66 // @Packaging
67 hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz);
68 ExitOnFailure(hr, "Failed to get @Packaging.");
69
70 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1))
71 {
72 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED;
73 }
74 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1))
75 {
76 pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
77 }
78 else
79 {
80 hr = E_INVALIDARG;
81 ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz);
82 }
83
84 // @Container
85 if (pContainers)
86 {
87 hr = XmlGetAttributeEx(pixnNode, L"Container", &scz);
88 if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging)
89 {
90 ExitOnFailure(hr, "Failed to get @Container.");
91
92 // find container
93 hr = ContainerFindById(pContainers, scz, &pPayload->pContainer);
94 ExitOnFailure(hr, "Failed to to find container: %ls", scz);
95 }
96 }
97
98 // @LayoutOnly
99 hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly);
100 if (E_NOTFOUND != hr)
101 {
102 ExitOnFailure(hr, "Failed to get @LayoutOnly.");
103 }
104
105 // @SourcePath
106 hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath);
107 ExitOnFailure(hr, "Failed to get @SourcePath.");
108
109 // @DownloadUrl
110 hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl);
111 if (E_NOTFOUND != hr)
112 {
113 ExitOnFailure(hr, "Failed to get @DownloadUrl.");
114 }
115
116 // @FileSize
117 hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz);
118 if (E_NOTFOUND != hr)
119 {
120 ExitOnFailure(hr, "Failed to get @FileSize.");
121
122 hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize);
123 ExitOnFailure(hr, "Failed to parse @FileSize.");
124 }
125
126 // @Hash
127 hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz);
128 ExitOnFailure(hr, "Failed to get @Hash.");
129
130 hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash);
131 ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash.");
132
133 if (pPayload->fLayoutOnly && pLayoutPayloads)
134 {
135 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5);
136 ExitOnFailure(hr, "Failed to allocate memory for layout payloads.");
137
138 pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload;
139 ++pLayoutPayloads->cItems;
140
141 pLayoutPayloads->qwTotalSize += pPayload->qwFileSize;
142 }
143
144 // prepare next iteration
145 ReleaseNullObject(pixnNode);
146 }
147
148 hr = S_OK;
149
150LExit:
151 ReleaseObject(pixnNodes);
152 ReleaseObject(pixnNode);
153 ReleaseStr(scz);
154
155 return hr;
156}
157
158extern "C" void PayloadUninitialize(
159 __in BURN_PAYLOAD* pPayload
160 )
161{
162 if (pPayload)
163 {
164 ReleaseStr(pPayload->sczKey);
165 ReleaseStr(pPayload->sczFilePath);
166 ReleaseMem(pPayload->pbHash);
167 ReleaseStr(pPayload->sczSourcePath);
168 ReleaseStr(pPayload->sczLocalFilePath);
169 ReleaseStr(pPayload->downloadSource.sczUrl);
170 ReleaseStr(pPayload->downloadSource.sczUser);
171 ReleaseStr(pPayload->downloadSource.sczPassword);
172 ReleaseStr(pPayload->sczUnverifiedPath);
173 }
174}
175
176extern "C" void PayloadsUninitialize(
177 __in BURN_PAYLOADS* pPayloads
178 )
179{
180 if (pPayloads->rgPayloads)
181 {
182 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
183 {
184 PayloadUninitialize(pPayloads->rgPayloads + i);
185 }
186 MemFree(pPayloads->rgPayloads);
187 }
188
189 // clear struct
190 memset(pPayloads, 0, sizeof(BURN_PAYLOADS));
191}
192
193extern "C" HRESULT PayloadExtractUXContainer(
194 __in BURN_PAYLOADS* pPayloads,
195 __in BURN_CONTAINER_CONTEXT* pContainerContext,
196 __in_z LPCWSTR wzTargetDir
197 )
198{
199 HRESULT hr = S_OK;
200 LPWSTR sczStreamName = NULL;
201 LPWSTR sczDirectory = NULL;
202 BURN_PAYLOAD* pPayload = NULL;
203
204 // extract all payloads
205 for (;;)
206 {
207 // get next stream
208 hr = ContainerNextStream(pContainerContext, &sczStreamName);
209 if (E_NOMOREITEMS == hr)
210 {
211 hr = S_OK;
212 break;
213 }
214 ExitOnFailure(hr, "Failed to get next stream.");
215
216 // find payload by stream name
217 hr = PayloadFindEmbeddedBySourcePath(pPayloads, sczStreamName, &pPayload);
218 ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName);
219
220 // make file path
221 hr = PathConcat(wzTargetDir, pPayload->sczFilePath, &pPayload->sczLocalFilePath);
222 ExitOnFailure(hr, "Failed to concat file paths.");
223
224 // extract file
225 hr = PathGetDirectory(pPayload->sczLocalFilePath, &sczDirectory);
226 ExitOnFailure(hr, "Failed to get directory portion of local file path");
227
228 hr = DirEnsureExists(sczDirectory, NULL);
229 ExitOnFailure(hr, "Failed to ensure directory exists");
230
231 hr = ContainerStreamToFile(pContainerContext, pPayload->sczLocalFilePath);
232 ExitOnFailure(hr, "Failed to extract file.");
233
234 // flag that the payload has been acquired
235 pPayload->state = BURN_PAYLOAD_STATE_ACQUIRED;
236 }
237
238 // locate any payloads that were not extracted
239 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
240 {
241 pPayload = &pPayloads->rgPayloads[i];
242
243 // if the payload has not been acquired
244 if (BURN_PAYLOAD_STATE_ACQUIRED > pPayload->state)
245 {
246 hr = E_INVALIDDATA;
247 ExitOnRootFailure(hr, "Payload was not found in container: %ls", pPayload->sczKey);
248 }
249 }
250
251LExit:
252 ReleaseStr(sczStreamName);
253 ReleaseStr(sczDirectory);
254
255 return hr;
256}
257
258extern "C" HRESULT PayloadFindById(
259 __in BURN_PAYLOADS* pPayloads,
260 __in_z LPCWSTR wzId,
261 __out BURN_PAYLOAD** ppPayload
262 )
263{
264 HRESULT hr = S_OK;
265 BURN_PAYLOAD* pPayload = NULL;
266
267 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
268 {
269 pPayload = &pPayloads->rgPayloads[i];
270
271 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczKey, -1, wzId, -1))
272 {
273 *ppPayload = pPayload;
274 ExitFunction1(hr = S_OK);
275 }
276 }
277
278 hr = E_NOTFOUND;
279
280LExit:
281 return hr;
282}
283
284extern "C" HRESULT PayloadFindEmbeddedBySourcePath(
285 __in BURN_PAYLOADS* pPayloads,
286 __in_z LPCWSTR wzStreamName,
287 __out BURN_PAYLOAD** ppPayload
288 )
289{
290 HRESULT hr = S_OK;
291 BURN_PAYLOAD* pPayload = NULL;
292
293 for (DWORD i = 0; i < pPayloads->cPayloads; ++i)
294 {
295 pPayload = &pPayloads->rgPayloads[i];
296
297 if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging)
298 {
299 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1))
300 {
301 *ppPayload = pPayload;
302 ExitFunction1(hr = S_OK);
303 }
304 }
305 }
306
307 hr = E_NOTFOUND;
308
309LExit:
310 return hr;
311}
312
313
314// internal function definitions