@joebigelow / wix / commits / f5d880cc

Update Burn to handle ExePackages that don't support uninstalling.

Partial fix for #6459

Sean Hall committed Jan 16, 2022 at 12:17 UTC f5d880cc70ad7350b0da1ea825141f95cbdb4c7b
4 files changed +43 -20
src/burn/engine/exeengine.cpp
+24 -20
@@ -11,36 +11,43 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
11 )
12 {
13 HRESULT hr = S_OK;
14 + BOOL fFoundXml = FALSE;
15 IXMLDOMNodeList* pixnNodes = NULL;
16 IXMLDOMNode* pixnNode = NULL;
17 LPWSTR scz = NULL;
18
19 // @DetectCondition
20 hr = XmlGetAttributeEx(pixnExePackage, L"DetectCondition", &pPackage->Exe.sczDetectCondition);
20 - ExitOnFailure(hr, "Failed to get @DetectCondition.");
21 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @DetectCondition.");
22
23 // @InstallArguments
24 hr = XmlGetAttributeEx(pixnExePackage, L"InstallArguments", &pPackage->Exe.sczInstallArguments);
24 - ExitOnFailure(hr, "Failed to get @InstallArguments.");
25 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments.");
26
27 // @UninstallArguments
28 hr = XmlGetAttributeEx(pixnExePackage, L"UninstallArguments", &pPackage->Exe.sczUninstallArguments);
28 - ExitOnFailure(hr, "Failed to get @UninstallArguments.");
29 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @UninstallArguments.");
30
31 // @RepairArguments
32 hr = XmlGetAttributeEx(pixnExePackage, L"RepairArguments", &pPackage->Exe.sczRepairArguments);
32 - ExitOnFailure(hr, "Failed to get @RepairArguments.");
33 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments.");
34
35 // @Repairable
36 hr = XmlGetYesNoAttribute(pixnExePackage, L"Repairable", &pPackage->Exe.fRepairable);
36 - if (E_NOTFOUND != hr)
37 - {
38 - ExitOnFailure(hr, "Failed to get @Repairable.");
39 - }
37 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Repairable.");
38 +
39 + // @Uninstallable
40 + pPackage->Exe.fUninstallable = TRUE; // TODO: https://github.com/wixtoolset/issues/issues/6459
41 + /*
42 + hr = XmlGetYesNoAttribute(pixnNode, L"Uninstallable", &pPackage->Exe.fUninstallable);
43 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable.");
44 + */
45
46 // @Protocol
47 hr = XmlGetAttributeEx(pixnExePackage, L"Protocol", &scz);
43 - if (SUCCEEDED(hr))
48 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Protocol.");
49 +
50 + if (fFoundXml)
51 {
52 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"burn", -1))
53 {
@@ -60,10 +67,6 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
67 ExitOnFailure(hr, "Invalid protocol type: %ls", scz);
68 }
69 }
63 - else if (E_NOTFOUND != hr)
64 - {
65 - ExitOnFailure(hr, "Failed to get @Protocol.");
66 - }
70
71 hr = ExeEngineParseExitCodesFromXml(pixnExePackage, &pPackage->Exe.rgExitCodes, &pPackage->Exe.cExitCodes);
72 ExitOnFailure(hr, "Failed to parse exit codes.");
@@ -172,7 +175,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
175 execute = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
176 break;
177 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
175 - execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
178 + execute = pPackage->Exe.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
179 break;
180 default:
181 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -552,11 +555,11 @@ extern "C" HRESULT ExeEngineParseExitCodesFromXml(
555
556 // @Type
557 hr = XmlGetAttributeNumber(pixnNode, L"Type", (DWORD*)&pExitCode->type);
555 - ExitOnFailure(hr, "Failed to get @Type.");
558 + ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Type.");
559
560 // @Code
561 hr = XmlGetAttributeEx(pixnNode, L"Code", &scz);
559 - ExitOnFailure(hr, "Failed to get @Code.");
562 + ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Code.");
563
564 if (L'*' == scz[0])
565 {
@@ -614,25 +617,26 @@ extern "C" HRESULT ExeEngineParseCommandLineArgumentsFromXml(
617 for (DWORD i = 0; i < cNodes; ++i)
618 {
619 BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = *prgCommandLineArguments + i;
620 + BOOL fFoundXml = FALSE;
621
622 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
623 ExitOnFailure(hr, "Failed to get next command-line argument node.");
624
625 // @InstallArgument
626 hr = XmlGetAttributeEx(pixnNode, L"InstallArgument", &pCommandLineArgument->sczInstallArgument);
623 - ExitOnFailure(hr, "Failed to get @InstallArgument.");
627 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArgument.");
628
629 // @UninstallArgument
630 hr = XmlGetAttributeEx(pixnNode, L"UninstallArgument", &pCommandLineArgument->sczUninstallArgument);
627 - ExitOnFailure(hr, "Failed to get @UninstallArgument.");
631 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @UninstallArgument.");
632
633 // @RepairArgument
634 hr = XmlGetAttributeEx(pixnNode, L"RepairArgument", &pCommandLineArgument->sczRepairArgument);
631 - ExitOnFailure(hr, "Failed to get @RepairArgument.");
635 + ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArgument.");
636
637 // @Condition
638 hr = XmlGetAttributeEx(pixnNode, L"Condition", &pCommandLineArgument->sczCondition);
635 - ExitOnFailure(hr, "Failed to get @Condition.");
639 + ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Condition.");
640
641 // Prepare next iteration.
642 ReleaseNullObject(pixnNode);
src/burn/engine/package.cpp
+17
@@ -235,6 +235,23 @@ extern "C" HRESULT PackagesParseFromXml(
235 // ignore other package types for now
236 }
237
238 + if (!pPackage->fPermanent)
239 + {
240 + BOOL fUninstallable = TRUE;
241 +
242 + switch (pPackage->type)
243 + {
244 + case BURN_PACKAGE_TYPE_EXE:
245 + fUninstallable = pPackage->Exe.fUninstallable;
246 + break;
247 + }
248 +
249 + if (!fUninstallable)
250 + {
251 + ExitWithRootFailure(hr, E_INVALIDDATA, "Non-permanent packages must be uninstallable.");
252 + }
253 + }
254 +
255 // parse payload references
256 hr = ParsePayloadRefsFromXml(pPackage, pPayloads, pixnNode);
257 ExitOnFailure(hr, "Failed to parse payload references.");
src/burn/engine/package.h
+1
@@ -323,6 +323,7 @@ typedef struct _BURN_PACKAGE
323 BOOL fPseudoBundle;
324 BOOL fFireAndForget;
325 BOOL fRepairable;
326 + BOOL fUninstallable;
327 BURN_EXE_PROTOCOL_TYPE protocol;
328
329 BURN_EXE_EXIT_CODE* rgExitCodes;
src/burn/engine/pseudobundle.cpp
+1
@@ -115,6 +115,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
115 pPassthroughPackage->fPermanent = TRUE;
116
117 pPassthroughPackage->Exe.fPseudoBundle = TRUE;
118 + pPassthroughPackage->Exe.fUninstallable = FALSE;
119 pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
120
121 hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0);