@@ -106,7 +106,7 @@ extern "C" HRESULT BundlePackageEngineParsePackageFromXml(
106106 hr = PackageParseScopeFromXml (pixnBundlePackage, &pPackage->scope );
107107 ExitOnRequiredXmlQueryFailure (hr, " Failed to get @Scope." );
108108
109- hr = BundlePackageEngineParseRelatedCodes (pixnBundlePackage, &pPackage->Bundle .rgsczDetectCodes , &pPackage->Bundle .cDetectCodes , &pPackage->Bundle .rgsczUpgradeCodes , &pPackage->Bundle .cUpgradeCodes , &pPackage->Bundle .rgsczAddonCodes , &pPackage->Bundle .cAddonCodes , &pPackage->Bundle .rgsczPatchCodes , &pPackage->Bundle .cPatchCodes );
109+ hr = BundlePackageEngineParseRelatedCodes (pixnBundlePackage, &pPackage->Bundle .rgsczDetectCodes , &pPackage->Bundle .cDetectCodes , &pPackage->Bundle .rgsczUpgradeCodes , &pPackage->Bundle .cUpgradeCodes , &pPackage->Bundle .rgsczAddonCodes , &pPackage->Bundle .cAddonCodes , &pPackage->Bundle .rgsczPatchCodes , &pPackage->Bundle .cPatchCodes , &pPackage-> Bundle . rgsczUninstallCodes , &pPackage-> Bundle . cUninstallCodes );
110110 ExitOnFailure (hr, " Failed to parse related codes." );
111111
112112 hr = ExeEngineParseExitCodesFromXml (pixnBundlePackage, &pPackage->Bundle .rgExitCodes , &pPackage->Bundle .cExitCodes );
@@ -134,7 +134,9 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
134134 __in LPWSTR ** prgsczAddonCodes,
135135 __in DWORD * pcAddonCodes,
136136 __in LPWSTR ** prgsczPatchCodes,
137- __in DWORD * pcPatchCodes
137+ __in DWORD * pcPatchCodes,
138+ __in LPWSTR ** prgsczUninstallCodes,
139+ __in DWORD * pcUninstallCodes
138140 )
139141{
140142 HRESULT hr = S_OK ;
@@ -197,6 +199,15 @@ extern "C" HRESULT BundlePackageEngineParseRelatedCodes(
197199 sczCode = NULL ;
198200 *pcPatchCodes += 1 ;
199201 }
202+ else if (CSTR_EQUAL == ::CompareStringOrdinal (sczAction, -1 , L" Uninstall" , -1 , FALSE ))
203+ {
204+ hr = MemEnsureArraySizeForNewItems (reinterpret_cast <LPVOID *>(prgsczUninstallCodes), *pcUninstallCodes, 1 , sizeof (LPWSTR ), 5 );
205+ ExitOnFailure (hr, " Failed to resize Uninstall code array" );
206+
207+ (*prgsczUninstallCodes)[*pcUninstallCodes] = sczCode;
208+ sczCode = NULL ;
209+ *pcUninstallCodes += 1 ;
210+ }
200211 else
201212 {
202213 hr = E_INVALIDARG ;
@@ -226,6 +237,7 @@ extern "C" void BundlePackageEnginePackageUninitialize(
226237 ReleaseStr (pPackage->Bundle .sczRepairArguments );
227238 ReleaseStr (pPackage->Bundle .sczUninstallArguments );
228239 ReleaseStr (pPackage->Bundle .sczIgnoreDependencies );
240+ ReleaseStr (pPackage->Bundle .sczIgnoreRelatedBundleCodes );
229241 ReleaseMem (pPackage->Bundle .rgExitCodes );
230242
231243 // free command-line arguments
@@ -262,6 +274,12 @@ extern "C" void BundlePackageEnginePackageUninitialize(
262274 }
263275 ReleaseMem (pPackage->Bundle .rgsczPatchCodes );
264276
277+ for (DWORD i = 0 ; i < pPackage->Bundle .cUninstallCodes ; ++i)
278+ {
279+ ReleaseStr (pPackage->Bundle .rgsczUninstallCodes [i]);
280+ }
281+ ReleaseMem (pPackage->Bundle .rgsczUninstallCodes );
282+
265283 // clear struct
266284 memset (&pPackage->Bundle , 0 , sizeof (pPackage->Bundle ));
267285}
@@ -288,6 +306,8 @@ extern "C" HRESULT BundlePackageEngineDetectPackage(
288306 pPackage->Bundle .cAddonCodes ,
289307 const_cast <LPCWSTR *>(pPackage->Bundle .rgsczPatchCodes ),
290308 pPackage->Bundle .cPatchCodes ,
309+ const_cast <LPCWSTR *>(pPackage->Bundle .rgsczUninstallCodes ),
310+ pPackage->Bundle .cUninstallCodes ,
291311 QueryRelatedBundlesCallback,
292312 &queryContext);
293313 ExitOnFailure (hr, " Failed to query per-machine related bundle packages." );
@@ -302,6 +322,8 @@ extern "C" HRESULT BundlePackageEngineDetectPackage(
302322 pPackage->Bundle .cAddonCodes ,
303323 const_cast <LPCWSTR *>(pPackage->Bundle .rgsczPatchCodes ),
304324 pPackage->Bundle .cPatchCodes ,
325+ const_cast <LPCWSTR *>(pPackage->Bundle .rgsczUninstallCodes ),
326+ pPackage->Bundle .cUninstallCodes ,
305327 QueryRelatedBundlesCallback,
306328 &queryContext);
307329 ExitOnFailure (hr, " Failed to query per-user related bundle packages." );
@@ -660,8 +682,29 @@ extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
660682 BURN_RELATED_BUNDLE * pRelatedBundle = pExecuteAction->relatedBundle .pRelatedBundle ;
661683 BOOTSTRAPPER_RELATION_TYPE relationType = ConvertRelationType (pRelatedBundle->planRelationType );
662684 BURN_PACKAGE * pPackage = &pRelatedBundle->package ;
685+ BOOL fRegsitered = FALSE ;
686+ LPWSTR szQuietUninstallString = NULL ;
687+ HRESULT hr = S_OK ;
688+
689+ // Check if an uninstall related bundle was already uninstalled by one of the chain packages. If so, we don't need to uninstall it, and can't install it on rollback.
690+ if (BOOTSTRAPPER_RELATION_UNINSTALL == pRelatedBundle->detectRelationType )
691+ {
692+ hr = DetectArpEntry (pPackage, &fRegsitered , &szQuietUninstallString);
693+ ExitOnFailure (hr, " Failed to read ARP data for related bundle: %ls" , pPackage->sczId );
663694
664- return ExecuteBundle (pCache, pVariables, fRollback , TRUE , pfnGenericMessageHandler, pvContext, action, relationType, pPackage, TRUE , fPerMachine , wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
695+ if (!fRegsitered )
696+ {
697+ LogId (REPORT_STANDARD , MSG_SKIP_RELATED_BUNDLE_UNINSTALL , pPackage->sczId , LoggingActionStateToString (action));
698+ ExitFunction ();
699+ }
700+ }
701+
702+ hr = ExecuteBundle (pCache, pVariables, fRollback , TRUE , pfnGenericMessageHandler, pvContext, action, relationType, pPackage, TRUE , fPerMachine , wzParent, wzIgnoreDependencies, wzAncestors, wzEngineWorkingDirectory, pRestart);
703+
704+ LExit:
705+ ReleaseStr (szQuietUninstallString);
706+
707+ return hr;
665708}
666709
667710extern " C" void BundlePackageEngineUpdateInstallRegistrationState (
@@ -1140,7 +1183,9 @@ static HRESULT DetectArpEntry(
11401183
11411184 if (!pPackage->Bundle .sczArpKeyPath )
11421185 {
1143- hr = PathConcatRelativeToBase (L" SOFTWARE\\ Microsoft\\ Windows\\ CurrentVersion\\ Uninstall\\ " , pPackage->Bundle .sczBundleCode , &pPackage->Bundle .sczArpKeyPath );
1186+ LPCWSTR szCode = pPackage->Bundle .sczBundleCode && *pPackage->Bundle .sczBundleCode ? pPackage->Bundle .sczBundleCode : pPackage->sczId ;
1187+
1188+ hr = PathConcatRelativeToBase (L" SOFTWARE\\ Microsoft\\ Windows\\ CurrentVersion\\ Uninstall\\ " , szCode, &pPackage->Bundle .sczArpKeyPath );
11441189 ExitOnFailure (hr, " Failed to build full key path." );
11451190 }
11461191
@@ -1176,10 +1221,14 @@ static BOOTSTRAPPER_RELATION_TYPE ConvertRelationType(
11761221 return BOOTSTRAPPER_RELATION_ADDON ;
11771222 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH :
11781223 return BOOTSTRAPPER_RELATION_PATCH ;
1224+ case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UNINSTALL :
1225+ return BOOTSTRAPPER_RELATION_UNINSTALL ;
11791226 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON :
11801227 return BOOTSTRAPPER_RELATION_DEPENDENT_ADDON ;
11811228 case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH :
11821229 return BOOTSTRAPPER_RELATION_DEPENDENT_PATCH ;
1230+ case BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_UNINSTALL :
1231+ return BOOTSTRAPPER_RELATION_DEPENDENT_UNINSTALL ;
11831232 default :
11841233 AssertSz (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE == relationType, " Unknown BUNDLE_RELATION_TYPE" );
11851234 return BOOTSTRAPPER_RELATION_NONE ;
0 commit comments