Skip to content

Commit e173e85

Browse files
committed
Add RelatedBundle action: Uninstall
1 parent edd2260 commit e173e85

45 files changed

Lines changed: 720 additions & 13 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/api/burn/WixToolset.BootstrapperApplicationApi/IBootstrapperApplication.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,12 @@ public enum RelationType
15761576
/// </summary>
15771577
Patch,
15781578

1579+
/// <summary>
1580+
/// The related bundle is an uninstall for the running bundle.
1581+
/// This relationship is reversed for <see cref="IBootstrapperCommand.Relation" />
1582+
/// </summary>
1583+
Uninstall,
1584+
15791585
/// <summary>
15801586
/// The running bundle is an add-on for the related bundle.
15811587
/// This relationship is reversed for <see cref="IBootstrapperCommand.Relation" />
@@ -1588,6 +1594,12 @@ public enum RelationType
15881594
/// </summary>
15891595
DependentPatch,
15901596

1597+
/// <summary>
1598+
/// The running bundle is an uninstall for the related bundle.
1599+
/// This relationship is reversed for <see cref="IBootstrapperCommand.Relation" />
1600+
/// </summary>
1601+
DependentUninstall,
1602+
15911603
/// <summary>
15921604
/// The related bundle is a newer version of the running bundle.
15931605
/// This relationship is reversed for <see cref="IBootstrapperCommand.Relation" />
@@ -1631,6 +1643,11 @@ public enum RelatedBundlePlanType
16311643
/// </summary>
16321644
Patch,
16331645

1646+
/// <summary>
1647+
/// The related bundle is an uninstall for the running bundle.
1648+
/// </summary>
1649+
Uninstall,
1650+
16341651
/// <summary>
16351652
/// The running bundle is an add-on for the related bundle.
16361653
/// </summary>

src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public enum PackageType
5252
/// </summary>
5353
PatchBundle,
5454

55+
/// <summary>
56+
/// Related bundle of type Uninstall
57+
/// </summary>
58+
UninstallBundle,
59+
5560
/// <summary>
5661
/// Related bundle of type Update
5762
/// </summary>
@@ -322,6 +327,9 @@ public static IPackageInfo GetRelatedBundleAsPackage(string id, RelationType rel
322327
case RelationType.Patch:
323328
package.Type = PackageType.PatchBundle;
324329
break;
330+
case RelationType.Uninstall:
331+
package.Type = PackageType.UninstallBundle;
332+
break;
325333
case RelationType.Upgrade:
326334
package.Type = PackageType.UpgradeBundle;
327335
break;

src/api/burn/balutil/balinfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
179179
type = BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH;
180180
break;
181181

182+
case BOOTSTRAPPER_RELATION_UNINSTALL:
183+
type = BAL_INFO_PACKAGE_TYPE_BUNDLE_UNINSTALL;
184+
break;
185+
182186
case BOOTSTRAPPER_RELATION_UPGRADE:
183187
type = BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE;
184188
break;

src/api/burn/balutil/inc/balinfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ typedef enum BAL_INFO_PACKAGE_TYPE
1616
BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE,
1717
BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON,
1818
BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH,
19+
BAL_INFO_PACKAGE_TYPE_BUNDLE_UNINSTALL,
1920
BAL_INFO_PACKAGE_TYPE_BUNDLE_UPDATE,
2021
BAL_INFO_PACKAGE_TYPE_BUNDLE_CHAIN,
2122
} BAL_INFO_PACKAGE_TYPE;

src/api/burn/inc/BootstrapperApplicationTypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,10 @@ enum BOOTSTRAPPER_RELATION_TYPE
124124
BOOTSTRAPPER_RELATION_UPGRADE,
125125
BOOTSTRAPPER_RELATION_ADDON,
126126
BOOTSTRAPPER_RELATION_PATCH,
127+
BOOTSTRAPPER_RELATION_UNINSTALL,
127128
BOOTSTRAPPER_RELATION_DEPENDENT_ADDON,
128129
BOOTSTRAPPER_RELATION_DEPENDENT_PATCH,
130+
BOOTSTRAPPER_RELATION_DEPENDENT_UNINSTALL,
129131
BOOTSTRAPPER_RELATION_UPDATE,
130132
BOOTSTRAPPER_RELATION_CHAIN_PACKAGE,
131133
};
@@ -137,8 +139,10 @@ enum BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE
137139
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UPGRADE,
138140
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_ADDON,
139141
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_PATCH,
142+
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_UNINSTALL,
140143
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_ADDON,
141144
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_PATCH,
145+
BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_DEPENDENT_UNINSTALL,
142146
};
143147

144148
enum BOOTSTRAPPER_CACHE_TYPE

src/api/wix/WixToolset.Data/Symbols/WixRelatedBundleSymbol.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ public enum RelatedBundleActionType
3434
Detect,
3535
Upgrade,
3636
Addon,
37-
Patch
37+
Patch,
38+
Uninstall,
3839
}
3940

4041
public class WixRelatedBundleSymbol : IntermediateSymbol

src/burn/engine/bundlepackageengine.cpp

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

667710
extern "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;

src/burn/engine/bundlepackageengine.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ HRESULT BundlePackageEngineParseRelatedCodes(
2222
__in LPWSTR** prgsczAddonCodes,
2323
__in DWORD* pcAddonCodes,
2424
__in LPWSTR** prgsczPatchCodes,
25-
__in DWORD* pcPatchCodes
25+
__in DWORD* pcPatchCodes,
26+
__in LPWSTR** prgsczUninstallCodes,
27+
__in DWORD* pcUninstallCodes
2628
);
2729
void BundlePackageEnginePackageUninitialize(
2830
__in BURN_PACKAGE* pPackage

src/burn/engine/core.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ extern "C" HRESULT CorePlan(
557557
DWORD dwExecuteActionEarlyIndex = pEngineState->plan.cExecuteActions;
558558

559559
// Plan the related bundles first to support downgrades with ref-counting.
560-
hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
560+
hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->packages, &pEngineState->plan);
561561
ExitOnFailure(hr, "Failed to plan related bundles.");
562562

563563
hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
@@ -1013,6 +1013,9 @@ extern "C" LPCWSTR CoreRelationTypeToCommandLineString(
10131013
case BOOTSTRAPPER_RELATION_PATCH:
10141014
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_PATCH;
10151015
break;
1016+
case BOOTSTRAPPER_RELATION_UNINSTALL:
1017+
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_UNINSTALL;
1018+
break;
10161019
case BOOTSTRAPPER_RELATION_UPDATE:
10171020
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_UPDATE;
10181021
break;
@@ -1022,6 +1025,9 @@ extern "C" LPCWSTR CoreRelationTypeToCommandLineString(
10221025
case BOOTSTRAPPER_RELATION_DEPENDENT_PATCH:
10231026
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH;
10241027
break;
1028+
case BOOTSTRAPPER_RELATION_DEPENDENT_UNINSTALL:
1029+
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_UNINSTALL;
1030+
break;
10251031
case BOOTSTRAPPER_RELATION_CHAIN_PACKAGE:
10261032
wzRelationTypeCommandLine = BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE;
10271033
break;
@@ -1761,6 +1767,18 @@ extern "C" HRESULT CoreParseCommandLine(
17611767

17621768
LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
17631769
}
1770+
else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UNINSTALL, -1, TRUE))
1771+
{
1772+
pCommand->relationType = BOOTSTRAPPER_RELATION_UNINSTALL;
1773+
1774+
LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1775+
}
1776+
else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_UNINSTALL, -1, TRUE))
1777+
{
1778+
pCommand->relationType = BOOTSTRAPPER_RELATION_DEPENDENT_UNINSTALL;
1779+
1780+
LogId(REPORT_STANDARD, MSG_BURN_RUN_BY_RELATED_BUNDLE, LoggingRelationTypeToString(pCommand->relationType));
1781+
}
17641782
else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, BURN_COMMANDLINE_SWITCH_RELATED_UPDATE, -1, TRUE))
17651783
{
17661784
pCommand->relationType = BOOTSTRAPPER_RELATION_UPDATE;

src/burn/engine/core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_ADDON = L"burn.related.addon";
2626
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_ADDON = L"burn.related.dependent.addon";
2727
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_PATCH = L"burn.related.patch";
2828
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_PATCH = L"burn.related.dependent.patch";
29+
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_UNINSTALL = L"burn.related.uninstall";
30+
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_DEPENDENT_UNINSTALL = L"burn.related.dependent.uninstall";
2931
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_UPDATE = L"burn.related.update";
3032
const LPCWSTR BURN_COMMANDLINE_SWITCH_RELATED_CHAIN_PACKAGE = L"burn.related.chain.package";
3133
const LPCWSTR BURN_COMMANDLINE_SWITCH_PASSTHROUGH = L"burn.passthrough";

0 commit comments

Comments
 (0)