diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2018-12-29 22:12:08 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2018-12-29 22:12:08 -0600 |
commit | 61847dddd4fd497057c780658e383c4627de19ec (patch) | |
tree | f85a845182922538ab9aa6ee85b0db3ab40c1f6e /src/engine/payload.cpp | |
parent | 8295f5f8fd28042e1a0a172d5afbba79178064c2 (diff) | |
download | wix-61847dddd4fd497057c780658e383c4627de19ec.tar.gz wix-61847dddd4fd497057c780658e383c4627de19ec.tar.bz2 wix-61847dddd4fd497057c780658e383c4627de19ec.zip |
Import code from old v4 repo
Diffstat (limited to 'src/engine/payload.cpp')
-rw-r--r-- | src/engine/payload.cpp | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/src/engine/payload.cpp b/src/engine/payload.cpp new file mode 100644 index 00000000..6833288f --- /dev/null +++ b/src/engine/payload.cpp | |||
@@ -0,0 +1,367 @@ | |||
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 | |||
8 | static 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 | |||
18 | extern "C" HRESULT PayloadsParseFromXml( | ||
19 | __in BURN_PAYLOADS* pPayloads, | ||
20 | __in_opt BURN_CONTAINERS* pContainers, | ||
21 | __in_opt BURN_CATALOGS* pCatalogs, | ||
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"download", -1)) | ||
71 | { | ||
72 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_DOWNLOAD; | ||
73 | } | ||
74 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1)) | ||
75 | { | ||
76 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED; | ||
77 | } | ||
78 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1)) | ||
79 | { | ||
80 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | hr = E_INVALIDARG; | ||
85 | ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz); | ||
86 | } | ||
87 | |||
88 | // @Container | ||
89 | if (pContainers) | ||
90 | { | ||
91 | hr = XmlGetAttributeEx(pixnNode, L"Container", &scz); | ||
92 | if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging) | ||
93 | { | ||
94 | ExitOnFailure(hr, "Failed to get @Container."); | ||
95 | |||
96 | // find container | ||
97 | hr = ContainerFindById(pContainers, scz, &pPayload->pContainer); | ||
98 | ExitOnFailure(hr, "Failed to to find container: %ls", scz); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | // @LayoutOnly | ||
103 | hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly); | ||
104 | if (E_NOTFOUND != hr) | ||
105 | { | ||
106 | ExitOnFailure(hr, "Failed to get @LayoutOnly."); | ||
107 | } | ||
108 | |||
109 | // @SourcePath | ||
110 | hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath); | ||
111 | if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_DOWNLOAD != pPayload->packaging) | ||
112 | { | ||
113 | ExitOnFailure(hr, "Failed to get @SourcePath."); | ||
114 | } | ||
115 | |||
116 | // @DownloadUrl | ||
117 | hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl); | ||
118 | if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_DOWNLOAD == pPayload->packaging) | ||
119 | { | ||
120 | ExitOnFailure(hr, "Failed to get @DownloadUrl."); | ||
121 | } | ||
122 | |||
123 | // @FileSize | ||
124 | hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz); | ||
125 | if (E_NOTFOUND != hr) | ||
126 | { | ||
127 | ExitOnFailure(hr, "Failed to get @FileSize."); | ||
128 | |||
129 | hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize); | ||
130 | ExitOnFailure(hr, "Failed to parse @FileSize."); | ||
131 | } | ||
132 | |||
133 | // @CertificateAuthorityKeyIdentifier | ||
134 | hr = XmlGetAttributeEx(pixnNode, L"CertificateRootPublicKeyIdentifier", &scz); | ||
135 | if (E_NOTFOUND != hr) | ||
136 | { | ||
137 | ExitOnFailure(hr, "Failed to get @CertificateRootPublicKeyIdentifier."); | ||
138 | |||
139 | hr = StrAllocHexDecode(scz, &pPayload->pbCertificateRootPublicKeyIdentifier, &pPayload->cbCertificateRootPublicKeyIdentifier); | ||
140 | ExitOnFailure(hr, "Failed to hex decode @CertificateRootPublicKeyIdentifier."); | ||
141 | } | ||
142 | |||
143 | // @CertificateThumbprint | ||
144 | hr = XmlGetAttributeEx(pixnNode, L"CertificateRootThumbprint", &scz); | ||
145 | if (E_NOTFOUND != hr) | ||
146 | { | ||
147 | ExitOnFailure(hr, "Failed to get @CertificateRootThumbprint."); | ||
148 | |||
149 | hr = StrAllocHexDecode(scz, &pPayload->pbCertificateRootThumbprint, &pPayload->cbCertificateRootThumbprint); | ||
150 | ExitOnFailure(hr, "Failed to hex decode @CertificateRootThumbprint."); | ||
151 | } | ||
152 | |||
153 | // @Hash | ||
154 | hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz); | ||
155 | ExitOnFailure(hr, "Failed to get @Hash."); | ||
156 | |||
157 | hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash); | ||
158 | ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash."); | ||
159 | |||
160 | // @Catalog | ||
161 | hr = XmlGetAttributeEx(pixnNode, L"Catalog", &scz); | ||
162 | if (E_NOTFOUND != hr) | ||
163 | { | ||
164 | ExitOnFailure(hr, "Failed to get @Catalog."); | ||
165 | |||
166 | hr = CatalogFindById(pCatalogs, scz, &pPayload->pCatalog); | ||
167 | ExitOnFailure(hr, "Failed to find catalog."); | ||
168 | } | ||
169 | |||
170 | // prepare next iteration | ||
171 | ReleaseNullObject(pixnNode); | ||
172 | } | ||
173 | |||
174 | hr = S_OK; | ||
175 | |||
176 | LExit: | ||
177 | ReleaseObject(pixnNodes); | ||
178 | ReleaseObject(pixnNode); | ||
179 | ReleaseStr(scz); | ||
180 | |||
181 | return hr; | ||
182 | } | ||
183 | |||
184 | extern "C" void PayloadsUninitialize( | ||
185 | __in BURN_PAYLOADS* pPayloads | ||
186 | ) | ||
187 | { | ||
188 | if (pPayloads->rgPayloads) | ||
189 | { | ||
190 | for (DWORD i = 0; i < pPayloads->cPayloads; ++i) | ||
191 | { | ||
192 | BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; | ||
193 | |||
194 | ReleaseStr(pPayload->sczKey); | ||
195 | ReleaseStr(pPayload->sczFilePath); | ||
196 | ReleaseMem(pPayload->pbHash); | ||
197 | ReleaseMem(pPayload->pbCertificateRootThumbprint); | ||
198 | ReleaseMem(pPayload->pbCertificateRootPublicKeyIdentifier); | ||
199 | ReleaseStr(pPayload->sczSourcePath); | ||
200 | ReleaseStr(pPayload->sczLocalFilePath); | ||
201 | ReleaseStr(pPayload->downloadSource.sczUrl); | ||
202 | ReleaseStr(pPayload->downloadSource.sczUser); | ||
203 | ReleaseStr(pPayload->downloadSource.sczPassword); | ||
204 | } | ||
205 | MemFree(pPayloads->rgPayloads); | ||
206 | } | ||
207 | |||
208 | // clear struct | ||
209 | memset(pPayloads, 0, sizeof(BURN_PAYLOADS)); | ||
210 | } | ||
211 | |||
212 | extern "C" HRESULT PayloadExtractFromContainer( | ||
213 | __in BURN_PAYLOADS* pPayloads, | ||
214 | __in_opt BURN_CONTAINER* pContainer, | ||
215 | __in BURN_CONTAINER_CONTEXT* pContainerContext, | ||
216 | __in_z LPCWSTR wzTargetDir | ||
217 | ) | ||
218 | { | ||
219 | HRESULT hr = S_OK; | ||
220 | LPWSTR sczStreamName = NULL; | ||
221 | LPWSTR sczDirectory = NULL; | ||
222 | BURN_PAYLOAD* pPayload = NULL; | ||
223 | |||
224 | // extract all payloads | ||
225 | for (;;) | ||
226 | { | ||
227 | // get next stream | ||
228 | hr = ContainerNextStream(pContainerContext, &sczStreamName); | ||
229 | if (E_NOMOREITEMS == hr) | ||
230 | { | ||
231 | hr = S_OK; | ||
232 | break; | ||
233 | } | ||
234 | ExitOnFailure(hr, "Failed to get next stream."); | ||
235 | |||
236 | // find payload by stream name | ||
237 | hr = FindEmbeddedBySourcePath(pPayloads, pContainer, sczStreamName, &pPayload); | ||
238 | ExitOnFailure(hr, "Failed to find embedded payload: %ls", sczStreamName); | ||
239 | |||
240 | // make file path | ||
241 | hr = PathConcat(wzTargetDir, pPayload->sczFilePath, &pPayload->sczLocalFilePath); | ||
242 | ExitOnFailure(hr, "Failed to concat file paths."); | ||
243 | |||
244 | // extract file | ||
245 | hr = PathGetDirectory(pPayload->sczLocalFilePath, &sczDirectory); | ||
246 | ExitOnFailure(hr, "Failed to get directory portion of local file path"); | ||
247 | |||
248 | hr = DirEnsureExists(sczDirectory, NULL); | ||
249 | ExitOnFailure(hr, "Failed to ensure directory exists"); | ||
250 | |||
251 | hr = ContainerStreamToFile(pContainerContext, pPayload->sczLocalFilePath); | ||
252 | ExitOnFailure(hr, "Failed to extract file."); | ||
253 | |||
254 | // flag that the payload has been acquired | ||
255 | pPayload->state = BURN_PAYLOAD_STATE_ACQUIRED; | ||
256 | } | ||
257 | |||
258 | // locate any payloads that were not extracted | ||
259 | for (DWORD i = 0; i < pPayloads->cPayloads; ++i) | ||
260 | { | ||
261 | pPayload = &pPayloads->rgPayloads[i]; | ||
262 | |||
263 | // if the payload is part of the container | ||
264 | if (!pContainer || pPayload->pContainer == pContainer) | ||
265 | { | ||
266 | // if the payload has not been acquired | ||
267 | if (BURN_PAYLOAD_STATE_ACQUIRED > pPayload->state) | ||
268 | { | ||
269 | hr = E_INVALIDDATA; | ||
270 | ExitOnRootFailure(hr, "Payload was not found in container: %ls", pPayload->sczKey); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | |||
275 | LExit: | ||
276 | ReleaseStr(sczStreamName); | ||
277 | ReleaseStr(sczDirectory); | ||
278 | |||
279 | return hr; | ||
280 | } | ||
281 | |||
282 | extern "C" HRESULT PayloadFindById( | ||
283 | __in BURN_PAYLOADS* pPayloads, | ||
284 | __in_z LPCWSTR wzId, | ||
285 | __out BURN_PAYLOAD** ppPayload | ||
286 | ) | ||
287 | { | ||
288 | HRESULT hr = S_OK; | ||
289 | BURN_PAYLOAD* pPayload = NULL; | ||
290 | |||
291 | for (DWORD i = 0; i < pPayloads->cPayloads; ++i) | ||
292 | { | ||
293 | pPayload = &pPayloads->rgPayloads[i]; | ||
294 | |||
295 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczKey, -1, wzId, -1)) | ||
296 | { | ||
297 | *ppPayload = pPayload; | ||
298 | ExitFunction1(hr = S_OK); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | hr = E_NOTFOUND; | ||
303 | |||
304 | LExit: | ||
305 | return hr; | ||
306 | } | ||
307 | |||
308 | extern "C" HRESULT PayloadFindEmbeddedBySourcePath( | ||
309 | __in BURN_PAYLOADS* pPayloads, | ||
310 | __in_z LPCWSTR wzStreamName, | ||
311 | __out BURN_PAYLOAD** ppPayload | ||
312 | ) | ||
313 | { | ||
314 | HRESULT hr = S_OK; | ||
315 | BURN_PAYLOAD* pPayload = NULL; | ||
316 | |||
317 | for (DWORD i = 0; i < pPayloads->cPayloads; ++i) | ||
318 | { | ||
319 | pPayload = &pPayloads->rgPayloads[i]; | ||
320 | |||
321 | if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging) | ||
322 | { | ||
323 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1)) | ||
324 | { | ||
325 | *ppPayload = pPayload; | ||
326 | ExitFunction1(hr = S_OK); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | hr = E_NOTFOUND; | ||
332 | |||
333 | LExit: | ||
334 | return hr; | ||
335 | } | ||
336 | |||
337 | |||
338 | // internal function definitions | ||
339 | |||
340 | static HRESULT FindEmbeddedBySourcePath( | ||
341 | __in BURN_PAYLOADS* pPayloads, | ||
342 | __in_opt BURN_CONTAINER* pContainer, | ||
343 | __in_z LPCWSTR wzStreamName, | ||
344 | __out BURN_PAYLOAD** ppPayload | ||
345 | ) | ||
346 | { | ||
347 | HRESULT hr = S_OK; | ||
348 | |||
349 | for (DWORD i = 0; i < pPayloads->cPayloads; ++i) | ||
350 | { | ||
351 | BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; | ||
352 | |||
353 | if (BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging && (!pContainer || pPayload->pContainer == pContainer)) | ||
354 | { | ||
355 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPayload->sczSourcePath, -1, wzStreamName, -1)) | ||
356 | { | ||
357 | *ppPayload = pPayload; | ||
358 | ExitFunction1(hr = S_OK); | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
363 | hr = E_NOTFOUND; | ||
364 | |||
365 | LExit: | ||
366 | return hr; | ||
367 | } | ||