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.cpp232
1 files changed, 100 insertions, 132 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/butil.cpp b/src/libs/dutil/WixToolset.DUtil/butil.cpp
index 4262d573..2f45da56 100644
--- a/src/libs/dutil/WixToolset.DUtil/butil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/butil.cpp
@@ -63,13 +63,6 @@ static HRESULT CopyStringToBuffer(
63 __in_z_opt LPWSTR wzBuffer, 63 __in_z_opt LPWSTR wzBuffer,
64 __inout SIZE_T* pcchBuffer 64 __inout SIZE_T* pcchBuffer
65 ); 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 66
74 67
75DAPI_(HRESULT) BundleGetBundleInfo( 68DAPI_(HRESULT) BundleGetBundleInfo(
@@ -156,11 +149,21 @@ LExit:
156DAPI_(HRESULT) BundleEnumRelatedBundle( 149DAPI_(HRESULT) BundleEnumRelatedBundle(
157 __in_z LPCWSTR wzUpgradeCode, 150 __in_z LPCWSTR wzUpgradeCode,
158 __in BUNDLE_INSTALL_CONTEXT context, 151 __in BUNDLE_INSTALL_CONTEXT context,
152 __in REG_KEY_BITNESS kbKeyBitness,
159 __inout PDWORD pdwStartIndex, 153 __inout PDWORD pdwStartIndex,
160 __deref_out_z LPWSTR* psczBundleId 154 __deref_out_z LPWSTR* psczBundleId
161 ) 155 )
162{ 156{
163 HRESULT hr = S_OK; 157 HRESULT hr = S_OK;
158 BOOL fUpgradeCodeFound = FALSE;
159 HKEY hkUninstall = NULL;
160 HKEY hkBundle = NULL;
161 LPWSTR sczUninstallSubKey = NULL;
162 LPWSTR sczUninstallSubKeyPath = NULL;
163 LPWSTR sczValue = NULL;
164 DWORD dwType = 0;
165 LPWSTR* rgsczBundleUpgradeCodes = NULL;
166 DWORD cBundleUpgradeCodes = 0;
164 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; 167 HKEY hkRoot = BUNDLE_INSTALL_CONTEXT_USER == context ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
165 168
166 if (!wzUpgradeCode || !pdwStartIndex) 169 if (!wzUpgradeCode || !pdwStartIndex)
@@ -168,27 +171,105 @@ DAPI_(HRESULT) BundleEnumRelatedBundle(
168 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function."); 171 ButilExitOnFailure(hr = E_INVALIDARG, "An invalid parameter was passed to the function.");
169 } 172 }
170 173
171 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_DEFAULT, wzUpgradeCode, pdwStartIndex, psczBundleId); 174 hr = RegOpenEx(hkRoot, BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, KEY_READ, kbKeyBitness, &hkUninstall);
172 ButilExitOnFailure(hr, "Failed to enumerate default-bitness bundles."); 175 ButilExitOnFailure(hr, "Failed to open bundle uninstall key path.");
173 if (S_FALSE == hr) 176
177 for (DWORD dwIndex = *pdwStartIndex; !fUpgradeCodeFound; dwIndex++)
174 { 178 {
175#if defined(_WIN64) 179 hr = RegKeyEnum(hkUninstall, dwIndex, &sczUninstallSubKey);
176 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_32BIT, wzUpgradeCode, pdwStartIndex, psczBundleId); 180 ButilExitOnFailure(hr, "Failed to enumerate bundle uninstall key path.");
177 ButilExitOnFailure(hr, "Failed to enumerate 32-bit bundles."); 181
178#else 182 hr = StrAllocFormatted(&sczUninstallSubKeyPath, L"%ls\\%ls", BUNDLE_REGISTRATION_REGISTRY_UNINSTALL_KEY, sczUninstallSubKey);
179 hr = DoBundleEnumRelatedBundle(hkRoot, REG_KEY_64BIT, wzUpgradeCode, pdwStartIndex, psczBundleId); 183 ButilExitOnFailure(hr, "Failed to allocate bundle uninstall key path.");
180 ButilExitOnFailure(hr, "Failed to enumerate 64-bit bundles."); 184
181#endif 185 hr = RegOpenEx(hkRoot, sczUninstallSubKeyPath, KEY_READ, kbKeyBitness, &hkBundle);
186 ButilExitOnFailure(hr, "Failed to open uninstall key path.");
187
188 // If it's a bundle, it should have a BundleUpgradeCode value of type REG_SZ (old) or REG_MULTI_SZ
189 hr = RegGetType(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &dwType);
190 if (FAILED(hr))
191 {
192 ReleaseRegKey(hkBundle);
193 ReleaseNullStr(sczUninstallSubKey);
194 ReleaseNullStr(sczUninstallSubKeyPath);
195 // Not a bundle
196 continue;
197 }
198
199 switch (dwType)
200 {
201 case REG_SZ:
202 hr = RegReadString(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &sczValue);
203 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode string property.");
204
205 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, sczValue, -1, wzUpgradeCode, -1))
206 {
207 *pdwStartIndex = dwIndex;
208 fUpgradeCodeFound = TRUE;
209 break;
210 }
211
212 ReleaseNullStr(sczValue);
213
214 break;
215 case REG_MULTI_SZ:
216 hr = RegReadStringArray(hkBundle, BUNDLE_REGISTRATION_REGISTRY_BUNDLE_UPGRADE_CODE, &rgsczBundleUpgradeCodes, &cBundleUpgradeCodes);
217 ButilExitOnFailure(hr, "Failed to read BundleUpgradeCode multi-string property.");
218
219 for (DWORD i = 0; i < cBundleUpgradeCodes; i++)
220 {
221 LPWSTR wzBundleUpgradeCode = rgsczBundleUpgradeCodes[i];
222 if (wzBundleUpgradeCode && *wzBundleUpgradeCode)
223 {
224 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzBundleUpgradeCode, -1, wzUpgradeCode, -1))
225 {
226 *pdwStartIndex = dwIndex;
227 fUpgradeCodeFound = TRUE;
228 break;
229 }
230 }
231 }
232 ReleaseNullStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
233
234 break;
235
236 default:
237 ButilExitWithRootFailure(hr, E_NOTIMPL, "BundleUpgradeCode of type 0x%x not implemented.", dwType);
238 }
239
240 if (fUpgradeCodeFound)
241 {
242 if (psczBundleId)
243 {
244 *psczBundleId = sczUninstallSubKey;
245 sczUninstallSubKey = NULL;
246 }
247
248 break;
249 }
250
251 // Cleanup before next iteration
252 ReleaseRegKey(hkBundle);
253 ReleaseNullStr(sczUninstallSubKey);
254 ReleaseNullStr(sczUninstallSubKeyPath);
182 } 255 }
183 256
184LExit: 257LExit:
185 return hr; 258 ReleaseStr(sczValue);
259 ReleaseStr(sczUninstallSubKey);
260 ReleaseStr(sczUninstallSubKeyPath);
261 ReleaseRegKey(hkBundle);
262 ReleaseRegKey(hkUninstall);
263 ReleaseStrArray(rgsczBundleUpgradeCodes, cBundleUpgradeCodes);
264
265 return FAILED(hr) ? hr : fUpgradeCodeFound ? S_OK : S_FALSE;
186} 266}
187 267
188 268
189DAPI_(HRESULT) BundleEnumRelatedBundleFixed( 269DAPI_(HRESULT) BundleEnumRelatedBundleFixed(
190 __in_z LPCWSTR wzUpgradeCode, 270 __in_z LPCWSTR wzUpgradeCode,
191 __in BUNDLE_INSTALL_CONTEXT context, 271 __in BUNDLE_INSTALL_CONTEXT context,
272 __in REG_KEY_BITNESS kbKeyBitness,
192 __inout PDWORD pdwStartIndex, 273 __inout PDWORD pdwStartIndex,
193 __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId 274 __out_ecount(MAX_GUID_CHARS+1) LPWSTR wzBundleId
194 ) 275 )
@@ -197,7 +278,7 @@ DAPI_(HRESULT) BundleEnumRelatedBundleFixed(
197 LPWSTR sczValue = NULL; 278 LPWSTR sczValue = NULL;
198 size_t cchValue = 0; 279 size_t cchValue = 0;
199 280
200 hr = BundleEnumRelatedBundle(wzUpgradeCode, context, pdwStartIndex, &sczValue); 281 hr = BundleEnumRelatedBundle(wzUpgradeCode, context, kbKeyBitness, pdwStartIndex, &sczValue);
201 if (S_OK == hr && wzBundleId) 282 if (S_OK == hr && wzBundleId)
202 { 283 {
203 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue); 284 hr = ::StringCchLengthW(sczValue, STRSAFE_MAX_CCH, &cchValue);
@@ -396,116 +477,3 @@ static HRESULT CopyStringToBuffer(
396 477
397 return hr; 478 return hr;
398} 479}
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}