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