aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/butil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/butil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/butil.cpp239
1 files changed, 138 insertions, 101 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp
index 4c96dfc1..4262d573 100644
--- a/src/libs/dutil/WixToolset.DUtil/butil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp
@@ -55,6 +55,7 @@ static HRESULT OpenBundleKey(
55 __in_z LPCWSTR wzBundleId, 55 __in_z LPCWSTR wzBundleId,
56 __in BUNDLE_INSTALL_CONTEXT context, 56 __in BUNDLE_INSTALL_CONTEXT context,
57 __in_opt LPCWSTR wzSubKey, 57 __in_opt LPCWSTR wzSubKey,
58 __in REG_KEY_BITNESS kbKeyBitness,
58 __inout HKEY* phKey 59 __inout HKEY* phKey
59 ); 60 );
60static HRESULT CopyStringToBuffer( 61static HRESULT CopyStringToBuffer(
@@ -62,6 +63,14 @@ static HRESULT CopyStringToBuffer(
62 __in_z_opt LPWSTR wzBuffer, 63 __in_z_opt LPWSTR wzBuffer,
63 __inout SIZE_T* pcchBuffer 64 __inout SIZE_T* pcchBuffer
64 ); 65 );
66static HRESULT DoBundleEnumRelatedBundle(
67 __in HKEY hkRoot,
68 __in REG_KEY_BITNESS kbKeyBitness,
69 __in_z LPCWSTR wzUpgradeCode,
70 __inout PDWORD pdwStartIndex,
71 __deref_out_z LPWSTR* psczBundleId
72 );
73
65 74
66DAPI_(HRESULT) BundleGetBundleInfo( 75DAPI_(HRESULT) BundleGetBundleInfo(
67 __in_z LPCWSTR wzBundleId, 76 __in_z LPCWSTR wzBundleId,
@@ -153,113 +162,26 @@ DAPI_(HRESULT) BundleEnumRelatedBundle(
153{ 162{
154 HRESULT hr = S_OK; 163 HRESULT hr = S_OK;
155 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 164 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
156 HKEY hkUninstall = NULL;
157 HKEY hkBundle = NULL;
158 LPWSTR sczUninstallSubKey = NULL;
159 LPWSTR sczUninstallSubKeyPath = NULL;
160 LPWSTR sczValue = NULL;
161 DWORD dwType = 0;
162
163 LPWSTR* rgsczBundleUpgradeCodes = NULL;
164 DWORD cBundleUpgradeCodes = 0;
165 BOOL fUpgradeCodeFound = FALSE;
166 165
167 if (!wzUpgradeCode || !pdwStartIndex) 166 if (!wzUpgradeCode || !pdwStartIndex)
168 { 167 {
169 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); 168 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function.");
170 } 169 }
171 170
172 hr = RegOpen(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, &hkUninstall); 171 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_DEFAULT, wzUpgradeCode, pdwStartIndex, psczBundleId);
173 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); 172 ButilExitOnFailure(hr, "Failed to enumerate default-bitness bundles.");
174 173 if (S_FALSE == hr)
175 for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++)
176 { 174 {
177 hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey); 175#if defined(_WIN64)
178 ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path."); 176 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_32BIT, wzUpgradeCode, pdwStartIndex, psczBundleId);
179 177 ButilExitOnFailure(hr, "Failed to enumerate 32-bit bundles.");
180 hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey); 178#else
181 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); 179 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_64BIT, wzUpgradeCode, pdwStartIndex, psczBundleId);
182 180 ButilExitOnFailure(hr, "Failed to enumerate 64-bit bundles.");
183 hr = RegOpen(hkRoot, sczUninstallSubKeyPath, KEY_READ, &hkBundle); 181#endif
184 ButilExitOnFailure(hr, "Failed to open uninstall key path.");
185
186 // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ
187 hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType);
188 if (FAILED(hr))
189 {
190 ReleaseRegKey(hkBundle);
191 ReleaseNullStr(sczUninstallSubKey);
192 ReleaseNullStr(sczUninstallSubKeyPath);
193 // Not a bundle
194 continue;
195 }
196
197 switch (dwType)
198 {
199 case REG_SZ:
200 hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
201 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
202
203 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
204 {
205 *pdwStartIndex = dwIndex;
206 fUpgradeCodeFound = TRUE;
207 break;
208 }
209
210 ReleaseNullStr(sczValue);
211
212 break;
213 case REG_MULTI_SZ:
214 hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes);
215 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property.");
216
217 for (DWORD i = 0; i < cBundleUpgradeCodes; i++)
218 {
219 LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i];
220 if (wzBundleUpgradeCode && *wzBundleUpgradeCode)
221 {
222 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1))
223 {
224 *pdwStartIndex = dwIndex;
225 fUpgradeCodeFound = TRUE;
226 break;
227 }
228 }
229 }
230 ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
231
232 break;
233
234 default:
235 ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
236 }
237
238 if (fUpgradeCodeFound)
239 {
240 if (psczBundleId)
241 {
242 *psczBundleId = sczUninstallSubKey;
243 sczUninstallSubKey = NULL;
244 }
245
246 break;
247 }
248
249 // Cleanup before next iteration
250 ReleaseRegKey(hkBundle);
251 ReleaseNullStr(sczUninstallSubKey);
252 ReleaseNullStr(sczUninstallSubKeyPath);
253 } 182 }
254 183
255LExit: 184LExit:
256 ReleaseStr(sczValue);
257 ReleaseStr(sczUninstallSubKey);
258 ReleaseStr(sczUninstallSubKeyPath);
259 ReleaseRegKey(hkBundle);
260 ReleaseRegKey(hkUninstall);
261 ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
262
263 return hr; 185 return hr;
264} 186}
265 187
@@ -276,7 +198,7 @@ DAPI_(HRESULT) BundleEnumRelatedBundleFixed(
276 size_t cchValue = 0; 198 size_t cchValue = 0;
277 199
278 hr = BundleEnumRelatedBundle(wzUpgradeCode, context, pdwStartIndex, &sczValue); 200 hr = BundleEnumRelatedBundle(wzUpgradeCode, context, pdwStartIndex, &sczValue);
279 if (SUCCEEDED(hr) && wzBundleId) 201 if (S_OK == hr && wzBundleId)
280 { 202 {
281 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue); 203 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue);
282 ButilExitOnRootFailure(hr, "Failed to calculate length of string."); 204 ButilExitOnRootFailure(hr, "Failed to calculate length of string.");
@@ -380,8 +302,9 @@ static HRESULT LocateAndQueryBundleValue(
380 302
381 *pStatus = INTERNAL_BUNDLE_STATUS_SUCCESS; 303 *pStatus = INTERNAL_BUNDLE_STATUS_SUCCESS;
382 304
383 if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, wzSubKey, phKey)) && 305 if (FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, wzSubKey, REG_KEY_32BIT, phKey)) &&
384 FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, wzSubKey, phKey))) 306 FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_MACHINE, wzSubKey, REG_KEY_64BIT, phKey)) &&
307 FAILED(hr = OpenBundleKey(wzBundleId, BUNDLE_INSTALL_CONTEXT_USER, wzSubKey, REG_KEY_DEFAULT, phKey)))
385 { 308 {
386 if (E_FILENOTFOUND == hr) 309 if (E_FILENOTFOUND == hr)
387 { 310 {
@@ -413,6 +336,7 @@ static HRESULT OpenBundleKey(
413 __in_z LPCWSTR wzBundleId, 336 __in_z LPCWSTR wzBundleId,
414 __in BUNDLE_INSTALL_CONTEXT context, 337 __in BUNDLE_INSTALL_CONTEXT context,
415 __in_opt LPCWSTR wzSubKey, 338 __in_opt LPCWSTR wzSubKey,
339 __in REG_KEY_BITNESS kbKeyBitness,
416 __inout HKEY* phKey 340 __inout HKEY* phKey
417 ) 341 )
418{ 342{
@@ -433,7 +357,7 @@ static HRESULT OpenBundleKey(
433 } 357 }
434 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path."); 358 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
435 359
436 hr = RegOpen(hkRoot, sczKeypath, KEY_READ, phKey); 360 hr = RegOpenEx(hkRoot, sczKeypath, KEY_READ, kbKeyBitness, phKey);
437 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path."); 361 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
438 362
439LExit: 363LExit:
@@ -472,3 +396,116 @@ static HRESULT CopyStringToBuffer(
472 396
473 return hr; 397 return hr;
474} 398}
399
400static HRESULT DoBundleEnumRelatedBundle(
401 __in HKEY hkRoot,
402 __in REG_KEY_BITNESS kbKeyBitness,
403 __in_z LPCWSTR wzUpgradeCode,
404 __inout PDWORD pdwStartIndex,
405 __deref_out_z LPWSTR* psczBundleId
406)
407{
408 HRESULT hr = S_OK;
409 BOOL fUpgradeCodeFound = FALSE;
410 HKEY hkUninstall = NULL;
411 HKEY hkBundle = NULL;
412 LPWSTR sczUninstallSubKey = NULL;
413 LPWSTR sczUninstallSubKeyPath = NULL;
414 LPWSTR sczValue = NULL;
415 DWORD dwType = 0;
416 LPWSTR* rgsczBundleUpgradeCodes = NULL;
417 DWORD cBundleUpgradeCodes = 0;
418
419 hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall);
420 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
421
422 for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++)
423 {
424 hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey);
425 ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path.");
426
427 hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey);
428 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
429
430 hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle);
431 ButilExitOnFailure(hr, "Failed to open uninstall key path.");
432
433 // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ
434 hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType);
435 if (FAILED(hr))
436 {
437 ReleaseRegKey(hkBundle);
438 ReleaseNullStr(sczUninstallSubKey);
439 ReleaseNullStr(sczUninstallSubKeyPath);
440 // Not a bundle
441 continue;
442 }
443
444 switch (dwType)
445 {
446 case REG_SZ:
447 hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
448 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
449
450 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
451 {
452 *pdwStartIndex = dwIndex;
453 fUpgradeCodeFound = TRUE;
454 break;
455 }
456
457 ReleaseNullStr(sczValue);
458
459 break;
460 case REG_MULTI_SZ:
461 hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes);
462 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property.");
463
464 for (DWORD i = 0; i < cBundleUpgradeCodes; i++)
465 {
466 LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i];
467 if (wzBundleUpgradeCode && *wzBundleUpgradeCode)
468 {
469 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1))
470 {
471 *pdwStartIndex = dwIndex;
472 fUpgradeCodeFound = TRUE;
473 break;
474 }
475 }
476 }
477 ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
478
479 break;
480
481 default:
482 ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
483 }
484
485 if (fUpgradeCodeFound)
486 {
487 if (psczBundleId)
488 {
489 *psczBundleId = sczUninstallSubKey;
490 sczUninstallSubKey = NULL;
491 }
492
493 break;
494 }
495
496 // Cleanup before next iteration
497 ReleaseRegKey(hkBundle);
498 ReleaseNullStr(sczUninstallSubKey);
499 ReleaseNullStr(sczUninstallSubKeyPath);
500 }
501
502LExit:
503 ReleaseStr(sczValue);
504 ReleaseStr(sczUninstallSubKey);
505 ReleaseStr(sczUninstallSubKeyPath);
506 ReleaseRegKey(hkBundle);
507 ReleaseRegKey(hkUninstall);
508 ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
509
510 return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE;
511}