aboutsummaryrefslogtreecommitdiff
path: root/src/api/burn/balutil/balinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/burn/balutil/balinfo.cpp')
-rw-r--r--src/api/burn/balutil/balinfo.cpp373
1 files changed, 373 insertions, 0 deletions
diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp
new file mode 100644
index 00000000..3abb9286
--- /dev/null
+++ b/src/api/burn/balutil/balinfo.cpp
@@ -0,0 +1,373 @@
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// prototypes
6static HRESULT ParsePackagesFromXml(
7 __in BAL_INFO_PACKAGES* pPackages,
8 __in IXMLDOMDocument* pixdManifest
9 );
10static HRESULT ParseBalPackageInfoFromXml(
11 __in BAL_INFO_PACKAGES* pPackages,
12 __in IXMLDOMDocument* pixdManifest
13 );
14
15
16DAPI_(HRESULT) BalInfoParseFromXml(
17 __in BAL_INFO_BUNDLE* pBundle,
18 __in IXMLDOMDocument* pixdManifest
19 )
20{
21 HRESULT hr = S_OK;
22 IXMLDOMNode* pNode = NULL;
23
24 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBundleProperties", &pNode);
25 ExitOnFailure(hr, "Failed to select bundle information.");
26
27 if (S_OK == hr)
28 {
29 hr = XmlGetYesNoAttribute(pNode, L"PerMachine", &pBundle->fPerMachine);
30 if (E_NOTFOUND != hr)
31 {
32 ExitOnFailure(hr, "Failed to read bundle information per-machine.");
33 }
34
35 hr = XmlGetAttributeEx(pNode, L"DisplayName", &pBundle->sczName);
36 if (E_NOTFOUND != hr)
37 {
38 ExitOnFailure(hr, "Failed to read bundle information display name.");
39 }
40
41 hr = XmlGetAttributeEx(pNode, L"LogPathVariable", &pBundle->sczLogVariable);
42 if (E_NOTFOUND != hr)
43 {
44 ExitOnFailure(hr, "Failed to read bundle information log path variable.");
45 }
46 }
47
48 hr = ParsePackagesFromXml(&pBundle->packages, pixdManifest);
49 BalExitOnFailure(hr, "Failed to parse package information from bootstrapper application data.");
50
51 hr = ParseBalPackageInfoFromXml(&pBundle->packages, pixdManifest);
52 BalExitOnFailure(hr, "Failed to parse bal package information from bootstrapper application data.");
53
54LExit:
55 ReleaseObject(pNode);
56
57 return hr;
58}
59
60
61DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
62 __in BAL_INFO_PACKAGES* pPackages,
63 __in LPCWSTR wzId,
64 __in BOOTSTRAPPER_RELATION_TYPE relationType,
65 __in BOOL /*fPerMachine*/,
66 __out_opt BAL_INFO_PACKAGE** ppPackage
67 )
68{
69 HRESULT hr = S_OK;
70 BAL_INFO_PACKAGE_TYPE type = BAL_INFO_PACKAGE_TYPE_UNKNOWN;
71 BAL_INFO_PACKAGE* pPackage = NULL;
72
73 // Ensure we have a supported relation type.
74 switch (relationType)
75 {
76 case BOOTSTRAPPER_RELATION_ADDON:
77 type = BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON;
78 break;
79
80 case BOOTSTRAPPER_RELATION_PATCH:
81 type = BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH;
82 break;
83
84 case BOOTSTRAPPER_RELATION_UPGRADE:
85 type = BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE;
86 break;
87
88 default:
89 ExitOnFailure(hr = E_INVALIDARG, "Unknown related bundle type: %u", relationType);
90 }
91
92 // Check to see if the bundle is already in the list of packages.
93 for (DWORD i = 0; i < pPackages->cPackages; ++i)
94 {
95 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzId, -1, pPackages->rgPackages[i].sczId, -1))
96 {
97 ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
98 }
99 }
100
101 // Add the related bundle as a package.
102 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackages->rgPackages), pPackages->cPackages + 1, sizeof(BAL_INFO_PACKAGE), 2);
103 ExitOnFailure(hr, "Failed to allocate memory for related bundle package information.");
104
105 pPackage = pPackages->rgPackages + pPackages->cPackages;
106 ++pPackages->cPackages;
107
108 hr = StrAllocString(&pPackage->sczId, wzId, 0);
109 ExitOnFailure(hr, "Failed to copy related bundle package id.");
110
111 pPackage->type = type;
112
113 // TODO: try to look up the DisplayName and Description in Add/Remove Programs with the wzId.
114
115 if (ppPackage)
116 {
117 *ppPackage = pPackage;
118 }
119
120LExit:
121 return hr;
122}
123
124
125DAPI_(HRESULT) BalInfoFindPackageById(
126 __in BAL_INFO_PACKAGES* pPackages,
127 __in LPCWSTR wzId,
128 __out BAL_INFO_PACKAGE** ppPackage
129 )
130{
131 *ppPackage = NULL;
132
133 for (DWORD i = 0; i < pPackages->cPackages; ++i)
134 {
135 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzId, -1, pPackages->rgPackages[i].sczId, -1))
136 {
137 *ppPackage = pPackages->rgPackages + i;
138 break;
139 }
140 }
141
142 return *ppPackage ? S_OK : E_NOTFOUND;
143}
144
145
146DAPI_(void) BalInfoUninitialize(
147 __in BAL_INFO_BUNDLE* pBundle
148 )
149{
150 for (DWORD i = 0; i < pBundle->packages.cPackages; ++i)
151 {
152 ReleaseStr(pBundle->packages.rgPackages[i].sczDisplayName);
153 ReleaseStr(pBundle->packages.rgPackages[i].sczDescription);
154 ReleaseStr(pBundle->packages.rgPackages[i].sczId);
155 ReleaseStr(pBundle->packages.rgPackages[i].sczDisplayInternalUICondition);
156 ReleaseStr(pBundle->packages.rgPackages[i].sczProductCode);
157 ReleaseStr(pBundle->packages.rgPackages[i].sczUpgradeCode);
158 ReleaseStr(pBundle->packages.rgPackages[i].sczVersion);
159 ReleaseStr(pBundle->packages.rgPackages[i].sczInstallCondition);
160 ReleaseStr(pBundle->packages.rgPackages[i].sczPrereqLicenseFile);
161 ReleaseStr(pBundle->packages.rgPackages[i].sczPrereqLicenseUrl);
162 }
163
164 ReleaseMem(pBundle->packages.rgPackages);
165
166 ReleaseStr(pBundle->sczName);
167 ReleaseStr(pBundle->sczLogVariable);
168 memset(pBundle, 0, sizeof(BAL_INFO_BUNDLE));
169}
170
171
172static HRESULT ParsePackagesFromXml(
173 __in BAL_INFO_PACKAGES* pPackages,
174 __in IXMLDOMDocument* pixdManifest
175 )
176{
177 HRESULT hr = S_OK;
178 IXMLDOMNodeList* pNodeList = NULL;
179 IXMLDOMNode* pNode = NULL;
180 BAL_INFO_PACKAGE* prgPackages = NULL;
181 DWORD cPackages = 0;
182 LPWSTR scz = NULL;
183
184 hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixPackageProperties", &pNodeList);
185 ExitOnFailure(hr, "Failed to select all packages.");
186
187 hr = pNodeList->get_length(reinterpret_cast<long*>(&cPackages));
188 ExitOnFailure(hr, "Failed to get the package count.");
189
190 prgPackages = static_cast<BAL_INFO_PACKAGE*>(MemAlloc(sizeof(BAL_INFO_PACKAGE) * cPackages, TRUE));
191 ExitOnNull(prgPackages, hr, E_OUTOFMEMORY, "Failed to allocate memory for packages.");
192
193 DWORD iPackage = 0;
194 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL)))
195 {
196 hr = XmlGetAttributeEx(pNode, L"Package", &prgPackages[iPackage].sczId);
197 ExitOnFailure(hr, "Failed to get package identifier for package.");
198
199 hr = XmlGetAttributeEx(pNode, L"DisplayName", &prgPackages[iPackage].sczDisplayName);
200 if (E_NOTFOUND != hr)
201 {
202 ExitOnFailure(hr, "Failed to get display name for package.");
203 }
204
205 hr = XmlGetAttributeEx(pNode, L"Description", &prgPackages[iPackage].sczDescription);
206 if (E_NOTFOUND != hr)
207 {
208 ExitOnFailure(hr, "Failed to get description for package.");
209 }
210
211 hr = XmlGetAttributeEx(pNode, L"PackageType", &scz);
212 ExitOnFailure(hr, "Failed to get package type for package.");
213
214 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, L"Exe", -1, scz, -1))
215 {
216 prgPackages[iPackage].type = BAL_INFO_PACKAGE_TYPE_EXE;
217 }
218 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, L"Msi", -1, scz, -1))
219 {
220 prgPackages[iPackage].type = BAL_INFO_PACKAGE_TYPE_MSI;
221 }
222 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, L"Msp", -1, scz, -1))
223 {
224 prgPackages[iPackage].type = BAL_INFO_PACKAGE_TYPE_MSP;
225 }
226 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, L"Msu", -1, scz, -1))
227 {
228 prgPackages[iPackage].type = BAL_INFO_PACKAGE_TYPE_MSU;
229 }
230
231 hr = XmlGetYesNoAttribute(pNode, L"Permanent", &prgPackages[iPackage].fPermanent);
232 ExitOnFailure(hr, "Failed to get permanent setting for package.");
233
234 hr = XmlGetYesNoAttribute(pNode, L"Vital", &prgPackages[iPackage].fVital);
235 ExitOnFailure(hr, "Failed to get vital setting for package.");
236
237 hr = XmlGetAttributeEx(pNode, L"ProductCode", &prgPackages[iPackage].sczProductCode);
238 if (E_NOTFOUND != hr)
239 {
240 ExitOnFailure(hr, "Failed to get product code for package.");
241 }
242
243 hr = XmlGetAttributeEx(pNode, L"UpgradeCode", &prgPackages[iPackage].sczUpgradeCode);
244 if (E_NOTFOUND != hr)
245 {
246 ExitOnFailure(hr, "Failed to get upgrade code for package.");
247 }
248
249 hr = XmlGetAttributeEx(pNode, L"Version", &prgPackages[iPackage].sczVersion);
250 if (E_NOTFOUND != hr)
251 {
252 ExitOnFailure(hr, "Failed to get version for package.");
253 }
254
255 hr = XmlGetAttributeEx(pNode, L"InstallCondition", &prgPackages[iPackage].sczInstallCondition);
256 if (E_NOTFOUND != hr)
257 {
258 ExitOnFailure(hr, "Failed to get install condition for package.");
259 }
260
261 hr = XmlGetAttributeEx(pNode, L"Cache", &scz);
262 ExitOnFailure(hr, "Failed to get cache type for package.");
263
264 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, scz, -1, L"remove", -1))
265 {
266 prgPackages[iPackage].cacheType = BOOTSTRAPPER_CACHE_TYPE_REMOVE;
267 }
268 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, scz, -1, L"keep", -1))
269 {
270 prgPackages[iPackage].cacheType = BOOTSTRAPPER_CACHE_TYPE_KEEP;
271 }
272 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, scz, -1, L"force", -1))
273 {
274 prgPackages[iPackage].cacheType = BOOTSTRAPPER_CACHE_TYPE_FORCE;
275 }
276
277 ++iPackage;
278 ReleaseNullObject(pNode);
279 }
280 ExitOnFailure(hr, "Failed to parse all package property elements.");
281
282 if (S_FALSE == hr)
283 {
284 hr = S_OK;
285 }
286
287 pPackages->cPackages = cPackages;
288 pPackages->rgPackages = prgPackages;
289 prgPackages = NULL;
290
291LExit:
292 ReleaseStr(scz);
293 ReleaseMem(prgPackages);
294 ReleaseObject(pNode);
295 ReleaseObject(pNodeList);
296
297 return hr;
298}
299
300
301static HRESULT ParseBalPackageInfoFromXml(
302 __in BAL_INFO_PACKAGES* pPackages,
303 __in IXMLDOMDocument* pixdManifest
304 )
305{
306 HRESULT hr = S_OK;
307 IXMLDOMNodeList* pNodeList = NULL;
308 IXMLDOMNode* pNode = NULL;
309 LPWSTR scz = NULL;
310 BAL_INFO_PACKAGE* pPackage = NULL;
311
312 hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixBalPackageInfo", &pNodeList);
313 ExitOnFailure(hr, "Failed to select all packages.");
314
315 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL)))
316 {
317 hr = XmlGetAttributeEx(pNode, L"PackageId", &scz);
318 ExitOnFailure(hr, "Failed to get package identifier for WixBalPackageInfo.");
319
320 hr = BalInfoFindPackageById(pPackages, scz, &pPackage);
321 ExitOnFailure(hr, "Failed to find package specified in WixBalPackageInfo: %ls", scz);
322
323 hr = XmlGetAttributeEx(pNode, L"DisplayInternalUICondition", &pPackage->sczDisplayInternalUICondition);
324 if (E_NOTFOUND != hr)
325 {
326 ExitOnFailure(hr, "Failed to get DisplayInternalUICondition setting for package.");
327 }
328
329 ReleaseNullObject(pNode);
330 }
331 ExitOnFailure(hr, "Failed to parse all WixBalPackageInfo elements.");
332
333 hr = XmlSelectNodes(pixdManifest, L"/BootstrapperApplicationData/WixMbaPrereqInformation", &pNodeList);
334 ExitOnFailure(hr, "Failed to select all packages.");
335
336 while (S_OK == (hr = XmlNextElement(pNodeList, &pNode, NULL)))
337 {
338 hr = XmlGetAttributeEx(pNode, L"PackageId", &scz);
339 ExitOnFailure(hr, "Failed to get package identifier for WixMbaPrereqInformation.");
340
341 hr = BalInfoFindPackageById(pPackages, scz, &pPackage);
342 ExitOnFailure(hr, "Failed to find package specified in WixMbaPrereqInformation: %ls", scz);
343
344 pPackage->fPrereqPackage = TRUE;
345
346 hr = XmlGetAttributeEx(pNode, L"LicenseFile", &pPackage->sczPrereqLicenseFile);
347 if (E_NOTFOUND != hr)
348 {
349 ExitOnFailure(hr, "Failed to get LicenseFile setting for prereq package.");
350 }
351
352 hr = XmlGetAttributeEx(pNode, L"LicenseUrl", &pPackage->sczPrereqLicenseUrl);
353 if (E_NOTFOUND != hr)
354 {
355 ExitOnFailure(hr, "Failed to get LicenseUrl setting for prereq package.");
356 }
357
358 ReleaseNullObject(pNode);
359 }
360 ExitOnFailure(hr, "Failed to parse all WixMbaPrereqInformation elements.");
361
362 if (S_FALSE == hr)
363 {
364 hr = S_OK;
365 }
366
367LExit:
368 ReleaseStr(scz);
369 ReleaseObject(pNode);
370 ReleaseObject(pNodeList);
371
372 return hr;
373}