diff options
Diffstat (limited to 'src/burn/engine')
-rw-r--r-- | src/burn/engine/approvedexe.cpp | 8 | ||||
-rw-r--r-- | src/burn/engine/approvedexe.h | 2 | ||||
-rw-r--r-- | src/burn/engine/bundlepackageengine.cpp | 6 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 2 | ||||
-rw-r--r-- | src/burn/engine/engine.mc | 7 | ||||
-rw-r--r-- | src/burn/engine/exeengine.cpp | 295 | ||||
-rw-r--r-- | src/burn/engine/package.h | 13 | ||||
-rw-r--r-- | src/burn/engine/plan.cpp | 3 |
8 files changed, 295 insertions, 41 deletions
diff --git a/src/burn/engine/approvedexe.cpp b/src/burn/engine/approvedexe.cpp index b9efd624..2a96868e 100644 --- a/src/burn/engine/approvedexe.cpp +++ b/src/burn/engine/approvedexe.cpp | |||
@@ -213,7 +213,7 @@ LExit: | |||
213 | extern "C" HRESULT ApprovedExesVerifySecureLocation( | 213 | extern "C" HRESULT ApprovedExesVerifySecureLocation( |
214 | __in BURN_CACHE* pCache, | 214 | __in BURN_CACHE* pCache, |
215 | __in BURN_VARIABLES* pVariables, | 215 | __in BURN_VARIABLES* pVariables, |
216 | __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe | 216 | __in LPCWSTR wzExecutablePath |
217 | ) | 217 | ) |
218 | { | 218 | { |
219 | HRESULT hr = S_OK; | 219 | HRESULT hr = S_OK; |
@@ -232,7 +232,7 @@ extern "C" HRESULT ApprovedExesVerifySecureLocation( | |||
232 | hr = VariableGetString(pVariables, wzSecureFolderVariable, &scz); | 232 | hr = VariableGetString(pVariables, wzSecureFolderVariable, &scz); |
233 | if (SUCCEEDED(hr)) | 233 | if (SUCCEEDED(hr)) |
234 | { | 234 | { |
235 | hr = PathDirectoryContainsPath(scz, pLaunchApprovedExe->sczExecutablePath); | 235 | hr = PathDirectoryContainsPath(scz, wzExecutablePath); |
236 | if (S_OK == hr) | 236 | if (S_OK == hr) |
237 | { | 237 | { |
238 | ExitFunction(); | 238 | ExitFunction(); |
@@ -252,14 +252,14 @@ extern "C" HRESULT ApprovedExesVerifySecureLocation( | |||
252 | // If the package cache is redirected, hr is S_FALSE. | 252 | // If the package cache is redirected, hr is S_FALSE. |
253 | if (S_FALSE == hr) | 253 | if (S_FALSE == hr) |
254 | { | 254 | { |
255 | hr = PathDirectoryContainsPath(sczSecondary, pLaunchApprovedExe->sczExecutablePath); | 255 | hr = PathDirectoryContainsPath(sczSecondary, wzExecutablePath); |
256 | if (S_OK == hr) | 256 | if (S_OK == hr) |
257 | { | 257 | { |
258 | ExitFunction(); | 258 | ExitFunction(); |
259 | } | 259 | } |
260 | } | 260 | } |
261 | 261 | ||
262 | hr = PathDirectoryContainsPath(scz, pLaunchApprovedExe->sczExecutablePath); | 262 | hr = PathDirectoryContainsPath(scz, wzExecutablePath); |
263 | if (S_OK == hr) | 263 | if (S_OK == hr) |
264 | { | 264 | { |
265 | ExitFunction(); | 265 | ExitFunction(); |
diff --git a/src/burn/engine/approvedexe.h b/src/burn/engine/approvedexe.h index 8a3f6779..cbfda601 100644 --- a/src/burn/engine/approvedexe.h +++ b/src/burn/engine/approvedexe.h | |||
@@ -67,7 +67,7 @@ HRESULT ApprovedExesLaunch( | |||
67 | HRESULT ApprovedExesVerifySecureLocation( | 67 | HRESULT ApprovedExesVerifySecureLocation( |
68 | __in BURN_CACHE* pCache, | 68 | __in BURN_CACHE* pCache, |
69 | __in BURN_VARIABLES* pVariables, | 69 | __in BURN_VARIABLES* pVariables, |
70 | __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe | 70 | __in LPCWSTR wzExecutablePath |
71 | ); | 71 | ); |
72 | 72 | ||
73 | 73 | ||
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp index 6a0343bd..81279cf6 100644 --- a/src/burn/engine/bundlepackageengine.cpp +++ b/src/burn/engine/bundlepackageengine.cpp | |||
@@ -365,8 +365,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
365 | break; | 365 | break; |
366 | 366 | ||
367 | default: | 367 | default: |
368 | hr = E_INVALIDARG; | 368 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid package current state: %d.", pPackage->currentState); |
369 | ExitOnRootFailure(hr, "Invalid package current state: %d.", pPackage->currentState); | ||
370 | } | 369 | } |
371 | 370 | ||
372 | // Calculate the rollback action if there is an execute action. | 371 | // Calculate the rollback action if there is an execute action. |
@@ -413,8 +412,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( | |||
413 | break; | 412 | break; |
414 | 413 | ||
415 | default: | 414 | default: |
416 | hr = E_INVALIDARG; | 415 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid package expected state."); |
417 | ExitOnRootFailure(hr, "Invalid package expected state."); | ||
418 | } | 416 | } |
419 | } | 417 | } |
420 | 418 | ||
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 75b24ec3..9c7cf89f 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp | |||
@@ -3858,7 +3858,7 @@ static HRESULT OnLaunchApprovedExe( | |||
3858 | hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); | 3858 | hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); |
3859 | ExitOnFailure(hr, "Failed to read the value for the approved exe path."); | 3859 | ExitOnFailure(hr, "Failed to read the value for the approved exe path."); |
3860 | 3860 | ||
3861 | hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe); | 3861 | hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath); |
3862 | ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); | 3862 | ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); |
3863 | if (S_FALSE == hr) | 3863 | if (S_FALSE == hr) |
3864 | { | 3864 | { |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index 1c03145b..52524edb 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -331,6 +331,13 @@ Language=English | |||
331 | Detected msi package with invalid version, product code: '%1!ls!', version: '%2!ls!' | 331 | Detected msi package with invalid version, product code: '%1!ls!', version: '%2!ls!' |
332 | . | 332 | . |
333 | 333 | ||
334 | MessageId=124 | ||
335 | Severity=Warning | ||
336 | SymbolicName=MSG_DETECTED_EXE_PACKAGE_INVALID_VERSION | ||
337 | Language=English | ||
338 | Detected exe package with invalid version, arp id: '%1!ls!', version: '%2!ls!' | ||
339 | . | ||
340 | |||
334 | MessageId=151 | 341 | MessageId=151 |
335 | Severity=Error | 342 | Severity=Error |
336 | SymbolicName=MSG_FAILED_DETECT_PACKAGE | 343 | SymbolicName=MSG_FAILED_DETECT_PACKAGE |
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index 808577bc..3a64ecd8 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp | |||
@@ -2,6 +2,16 @@ | |||
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | 4 | ||
5 | static HRESULT DetectArpEntry( | ||
6 | __in const BURN_PACKAGE* pPackage, | ||
7 | __out BOOTSTRAPPER_PACKAGE_STATE* pPackageState, | ||
8 | __out_opt LPWSTR* psczQuietUninstallString | ||
9 | ); | ||
10 | static HRESULT ParseArpUninstallString( | ||
11 | __in_z LPCWSTR wzArpUninstallString, | ||
12 | __inout LPWSTR* psczExecutablePath, | ||
13 | __inout LPWSTR* psczArguments | ||
14 | ); | ||
5 | 15 | ||
6 | // function definitions | 16 | // function definitions |
7 | 17 | ||
@@ -16,18 +26,73 @@ extern "C" HRESULT ExeEngineParsePackageFromXml( | |||
16 | IXMLDOMNode* pixnNode = NULL; | 26 | IXMLDOMNode* pixnNode = NULL; |
17 | LPWSTR scz = NULL; | 27 | LPWSTR scz = NULL; |
18 | 28 | ||
19 | // @DetectCondition | 29 | // @DetectionType |
20 | hr = XmlGetAttributeEx(pixnExePackage, L"DetectCondition", &pPackage->Exe.sczDetectCondition); | 30 | hr = XmlGetAttributeEx(pixnExePackage, L"DetectionType", &scz); |
21 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @DetectCondition."); | 31 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @DetectionType."); |
32 | |||
33 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"condition", -1)) | ||
34 | { | ||
35 | pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_CONDITION; | ||
36 | } | ||
37 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"arp", -1)) | ||
38 | { | ||
39 | pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_ARP; | ||
40 | } | ||
41 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"none", -1)) | ||
42 | { | ||
43 | pPackage->Exe.detectionType = BURN_EXE_DETECTION_TYPE_NONE; | ||
44 | } | ||
45 | else | ||
46 | { | ||
47 | ExitWithRootFailure(hr, E_UNEXPECTED, "Invalid detection type: %ls", scz); | ||
48 | } | ||
49 | |||
50 | if (BURN_EXE_DETECTION_TYPE_CONDITION == pPackage->Exe.detectionType) | ||
51 | { | ||
52 | // @DetectCondition | ||
53 | hr = XmlGetAttributeEx(pixnExePackage, L"DetectCondition", &pPackage->Exe.sczDetectCondition); | ||
54 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @DetectCondition."); | ||
55 | |||
56 | // @UninstallArguments | ||
57 | hr = XmlGetAttributeEx(pixnExePackage, L"UninstallArguments", &pPackage->Exe.sczUninstallArguments); | ||
58 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @UninstallArguments."); | ||
59 | |||
60 | // @Uninstallable | ||
61 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Uninstallable", &pPackage->Exe.fUninstallable); | ||
62 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable."); | ||
63 | } | ||
64 | else if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType) | ||
65 | { | ||
66 | // @ArpId | ||
67 | hr = XmlGetAttributeEx(pixnExePackage, L"ArpId", &scz); | ||
68 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ArpId."); | ||
69 | |||
70 | hr = PathConcatRelativeToBase(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\", scz, &pPackage->Exe.sczArpKeyPath); | ||
71 | ExitOnFailure(hr, "Failed to build full key path."); | ||
72 | |||
73 | // @ArpDisplayVersion | ||
74 | hr = XmlGetAttributeEx(pixnExePackage, L"ArpDisplayVersion", &scz); | ||
75 | ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ArpDisplayVersion."); | ||
76 | |||
77 | hr = VerParseVersion(scz, 0, FALSE, &pPackage->Exe.pArpDisplayVersion); | ||
78 | ExitOnFailure(hr, "Failed to parse @ArpDisplayVersion: %ls", scz); | ||
79 | |||
80 | if (pPackage->Exe.pArpDisplayVersion->fInvalid) | ||
81 | { | ||
82 | LogId(REPORT_WARNING, MSG_MANIFEST_INVALID_VERSION, scz); | ||
83 | } | ||
84 | |||
85 | // @ArpWin64 | ||
86 | hr = XmlGetYesNoAttribute(pixnExePackage, L"ArpWin64", &pPackage->Exe.fArpWin64); | ||
87 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @ArpWin64."); | ||
88 | |||
89 | pPackage->Exe.fUninstallable = TRUE; | ||
90 | } | ||
22 | 91 | ||
23 | // @InstallArguments | 92 | // @InstallArguments |
24 | hr = XmlGetAttributeEx(pixnExePackage, L"InstallArguments", &pPackage->Exe.sczInstallArguments); | 93 | hr = XmlGetAttributeEx(pixnExePackage, L"InstallArguments", &pPackage->Exe.sczInstallArguments); |
25 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments."); | 94 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallArguments."); |
26 | 95 | ||
27 | // @UninstallArguments | ||
28 | hr = XmlGetAttributeEx(pixnExePackage, L"UninstallArguments", &pPackage->Exe.sczUninstallArguments); | ||
29 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @UninstallArguments."); | ||
30 | |||
31 | // @RepairArguments | 96 | // @RepairArguments |
32 | hr = XmlGetAttributeEx(pixnExePackage, L"RepairArguments", &pPackage->Exe.sczRepairArguments); | 97 | hr = XmlGetAttributeEx(pixnExePackage, L"RepairArguments", &pPackage->Exe.sczRepairArguments); |
33 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments."); | 98 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @RepairArguments."); |
@@ -36,10 +101,6 @@ extern "C" HRESULT ExeEngineParsePackageFromXml( | |||
36 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Repairable", &pPackage->Exe.fRepairable); | 101 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Repairable", &pPackage->Exe.fRepairable); |
37 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Repairable."); | 102 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Repairable."); |
38 | 103 | ||
39 | // @Uninstallable | ||
40 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Uninstallable", &pPackage->Exe.fUninstallable); | ||
41 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Uninstallable."); | ||
42 | |||
43 | // @Bundle | 104 | // @Bundle |
44 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Bundle", &pPackage->Exe.fBundle); | 105 | hr = XmlGetYesNoAttribute(pixnExePackage, L"Bundle", &pPackage->Exe.fBundle); |
45 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Bundle."); | 106 | ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Bundle."); |
@@ -64,8 +125,7 @@ extern "C" HRESULT ExeEngineParsePackageFromXml( | |||
64 | } | 125 | } |
65 | else | 126 | else |
66 | { | 127 | { |
67 | hr = E_UNEXPECTED; | 128 | ExitWithRootFailure(hr, E_UNEXPECTED, "Invalid protocol type: %ls", scz); |
68 | ExitOnFailure(hr, "Invalid protocol type: %ls", scz); | ||
69 | } | 129 | } |
70 | } | 130 | } |
71 | 131 | ||
@@ -91,6 +151,8 @@ extern "C" void ExeEnginePackageUninitialize( | |||
91 | ReleaseStr(pPackage->Exe.sczInstallArguments); | 151 | ReleaseStr(pPackage->Exe.sczInstallArguments); |
92 | ReleaseStr(pPackage->Exe.sczRepairArguments); | 152 | ReleaseStr(pPackage->Exe.sczRepairArguments); |
93 | ReleaseStr(pPackage->Exe.sczUninstallArguments); | 153 | ReleaseStr(pPackage->Exe.sczUninstallArguments); |
154 | ReleaseStr(pPackage->Exe.sczArpKeyPath); | ||
155 | ReleaseVerutilVersion(pPackage->Exe.pArpDisplayVersion); | ||
94 | ReleaseMem(pPackage->Exe.rgExitCodes); | 156 | ReleaseMem(pPackage->Exe.rgExitCodes); |
95 | 157 | ||
96 | // free command-line arguments | 158 | // free command-line arguments |
@@ -126,15 +188,31 @@ extern "C" HRESULT ExeEngineDetectPackage( | |||
126 | HRESULT hr = S_OK; | 188 | HRESULT hr = S_OK; |
127 | BOOL fDetected = FALSE; | 189 | BOOL fDetected = FALSE; |
128 | 190 | ||
129 | // evaluate detect condition | 191 | switch (pPackage->Exe.detectionType) |
130 | if (pPackage->Exe.sczDetectCondition && *pPackage->Exe.sczDetectCondition) | ||
131 | { | 192 | { |
132 | hr = ConditionEvaluate(pVariables, pPackage->Exe.sczDetectCondition, &fDetected); | 193 | case BURN_EXE_DETECTION_TYPE_NONE: |
133 | ExitOnFailure(hr, "Failed to evaluate executable package detect condition."); | 194 | pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; |
134 | } | 195 | break; |
196 | case BURN_EXE_DETECTION_TYPE_CONDITION: | ||
197 | // evaluate detect condition | ||
198 | if (pPackage->Exe.sczDetectCondition && *pPackage->Exe.sczDetectCondition) | ||
199 | { | ||
200 | hr = ConditionEvaluate(pVariables, pPackage->Exe.sczDetectCondition, &fDetected); | ||
201 | ExitOnFailure(hr, "Failed to evaluate EXE package detect condition."); | ||
202 | } | ||
203 | |||
204 | // update detect state | ||
205 | pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | ||
135 | 206 | ||
136 | // update detect state | 207 | break; |
137 | pPackage->currentState = fDetected ? BOOTSTRAPPER_PACKAGE_STATE_PRESENT : BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | 208 | case BURN_EXE_DETECTION_TYPE_ARP: |
209 | hr = DetectArpEntry(pPackage, &pPackage->currentState, NULL); | ||
210 | ExitOnFailure(hr, "Failed to detect EXE package by ArpEntry."); | ||
211 | |||
212 | break; | ||
213 | default: | ||
214 | ExitWithRootFailure(hr, E_INVALIDARG, "Unknown EXE package detection type: %d.", pPackage->Exe.detectionType); | ||
215 | } | ||
138 | 216 | ||
139 | if (pPackage->fCanAffectRegistration) | 217 | if (pPackage->fCanAffectRegistration) |
140 | { | 218 | { |
@@ -187,6 +265,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage( | |||
187 | } | 265 | } |
188 | break; | 266 | break; |
189 | 267 | ||
268 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; | ||
190 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: | 269 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: |
191 | switch (pPackage->requested) | 270 | switch (pPackage->requested) |
192 | { | 271 | { |
@@ -205,8 +284,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage( | |||
205 | break; | 284 | break; |
206 | 285 | ||
207 | default: | 286 | default: |
208 | hr = E_INVALIDARG; | 287 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid package current state: %d.", pPackage->currentState); |
209 | ExitOnRootFailure(hr, "Invalid package current state: %d.", pPackage->currentState); | ||
210 | } | 288 | } |
211 | 289 | ||
212 | // Calculate the rollback action if there is an execute action. | 290 | // Calculate the rollback action if there is an execute action. |
@@ -232,6 +310,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage( | |||
232 | } | 310 | } |
233 | break; | 311 | break; |
234 | 312 | ||
313 | case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; | ||
235 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: | 314 | case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: |
236 | switch (pPackage->requested) | 315 | switch (pPackage->requested) |
237 | { | 316 | { |
@@ -251,8 +330,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage( | |||
251 | break; | 330 | break; |
252 | 331 | ||
253 | default: | 332 | default: |
254 | hr = E_INVALIDARG; | 333 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid package expected state."); |
255 | ExitOnRootFailure(hr, "Invalid package expected state."); | ||
256 | } | 334 | } |
257 | } | 335 | } |
258 | 336 | ||
@@ -356,10 +434,41 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
356 | LPWSTR sczUserArgs = NULL; | 434 | LPWSTR sczUserArgs = NULL; |
357 | LPWSTR sczUserArgsObfuscated = NULL; | 435 | LPWSTR sczUserArgsObfuscated = NULL; |
358 | LPWSTR sczCommandObfuscated = NULL; | 436 | LPWSTR sczCommandObfuscated = NULL; |
437 | LPWSTR sczArpUninstallString = NULL; | ||
438 | LPWSTR sczArpArguments = NULL; | ||
439 | BOOTSTRAPPER_PACKAGE_STATE applyState = BOOTSTRAPPER_PACKAGE_STATE_UNKNOWN; | ||
359 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; | 440 | HANDLE hExecutableFile = INVALID_HANDLE_VALUE; |
360 | DWORD dwExitCode = 0; | 441 | DWORD dwExitCode = 0; |
361 | BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; | 442 | BURN_PACKAGE* pPackage = pExecuteAction->exePackage.pPackage; |
362 | BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; | 443 | BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; |
444 | LPCWSTR wzUninstallArguments = pPackage->Exe.sczUninstallArguments; | ||
445 | |||
446 | if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType && | ||
447 | (BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action || | ||
448 | BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->exePackage.action && fRollback)) | ||
449 | { | ||
450 | hr = DetectArpEntry(pPackage, &applyState, &sczArpUninstallString); | ||
451 | ExitOnFailure(hr, "Failed to query ArpEntry for uninstall."); | ||
452 | |||
453 | if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT == applyState && BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action) | ||
454 | { | ||
455 | if (fRollback) | ||
456 | { | ||
457 | LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), LoggingPackageStateToString(applyState)); | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | LogId(REPORT_STANDARD, MSG_ATTEMPTED_UNINSTALL_ABSENT_PACKAGE, pPackage->sczId); | ||
462 | } | ||
463 | |||
464 | ExitFunction(); | ||
465 | } | ||
466 | else if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT != applyState && BOOTSTRAPPER_ACTION_STATE_INSTALL == pExecuteAction->exePackage.action) | ||
467 | { | ||
468 | LogId(REPORT_STANDARD, MSG_ROLLBACK_PACKAGE_SKIPPED, pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), LoggingPackageStateToString(applyState)); | ||
469 | ExitFunction(); | ||
470 | } | ||
471 | } | ||
363 | 472 | ||
364 | if (pPackage->Exe.fPseudoPackage && BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE != pPackagePayload->verification) | 473 | if (pPackage->Exe.fPseudoPackage && BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE != pPackagePayload->verification) |
365 | { | 474 | { |
@@ -372,7 +481,30 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
372 | ExitOnFailure(hr, "Failed to build executable path."); | 481 | ExitOnFailure(hr, "Failed to build executable path."); |
373 | 482 | ||
374 | hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory); | 483 | hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory); |
375 | ExitOnFailure(hr, "Failed to get cached path for pseudo-package: %ls", pPackage->sczId); | 484 | ExitOnFailure(hr, "Failed to get parent directory for pseudo-package: %ls", pPackage->sczId); |
485 | } | ||
486 | else if (BURN_EXE_DETECTION_TYPE_ARP == pPackage->Exe.detectionType && BOOTSTRAPPER_ACTION_STATE_UNINSTALL == pExecuteAction->exePackage.action) | ||
487 | { | ||
488 | ExitOnNull(sczArpUninstallString, hr, E_INVALIDARG, "QuietUninstallString is null."); | ||
489 | |||
490 | hr = ParseArpUninstallString(sczArpUninstallString, &sczExecutablePath, &sczArpArguments); | ||
491 | ExitOnFailure(hr, "Failed to parse QuietUninstallString: %ls.", sczArpUninstallString); | ||
492 | |||
493 | if (pPackage->fPerMachine) | ||
494 | { | ||
495 | hr = ApprovedExesVerifySecureLocation(pCache, pVariables, sczExecutablePath); | ||
496 | ExitOnFailure(hr, "Failed to verify the QuietUninstallString executable path is in a secure location: %ls", sczExecutablePath); | ||
497 | if (S_FALSE == hr) | ||
498 | { | ||
499 | LogStringLine(REPORT_STANDARD, "The QuietUninstallString executable path is not in a secure location: %ls", sczExecutablePath); | ||
500 | ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | hr = PathGetDirectory(sczExecutablePath, &sczCachedDirectory); | ||
505 | ExitOnFailure(hr, "Failed to get parent directory for QuietUninstallString executable path: %ls", sczExecutablePath); | ||
506 | |||
507 | wzUninstallArguments = sczArpArguments; | ||
376 | } | 508 | } |
377 | else | 509 | else |
378 | { | 510 | { |
@@ -396,7 +528,7 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
396 | break; | 528 | break; |
397 | 529 | ||
398 | case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: | 530 | case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: |
399 | wzArguments = pPackage->Exe.sczUninstallArguments; | 531 | wzArguments = wzUninstallArguments; |
400 | break; | 532 | break; |
401 | 533 | ||
402 | case BOOTSTRAPPER_ACTION_STATE_REPAIR: | 534 | case BOOTSTRAPPER_ACTION_STATE_REPAIR: |
@@ -404,8 +536,7 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
404 | break; | 536 | break; |
405 | 537 | ||
406 | default: | 538 | default: |
407 | hr = E_INVALIDARG; | 539 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid Exe package action: %d.", pExecuteAction->exePackage.action); |
408 | ExitOnFailure(hr, "Invalid Exe package action: %d.", pExecuteAction->exePackage.action); | ||
409 | } | 540 | } |
410 | 541 | ||
411 | // now add optional arguments | 542 | // now add optional arguments |
@@ -443,8 +574,7 @@ extern "C" HRESULT ExeEngineExecutePackage( | |||
443 | break; | 574 | break; |
444 | 575 | ||
445 | default: | 576 | default: |
446 | hr = E_INVALIDARG; | 577 | ExitWithRootFailure(hr, E_INVALIDARG, "Invalid Exe package action: %d.", pExecuteAction->exePackage.action); |
447 | ExitOnFailure(hr, "Invalid Exe package action: %d.", pExecuteAction->exePackage.action); | ||
448 | } | 578 | } |
449 | } | 579 | } |
450 | } | 580 | } |
@@ -524,6 +654,8 @@ LExit: | |||
524 | StrSecureZeroFreeString(sczUserArgs); | 654 | StrSecureZeroFreeString(sczUserArgs); |
525 | ReleaseStr(sczUserArgsObfuscated); | 655 | ReleaseStr(sczUserArgsObfuscated); |
526 | ReleaseStr(sczCommandObfuscated); | 656 | ReleaseStr(sczCommandObfuscated); |
657 | ReleaseStr(sczArpUninstallString); | ||
658 | ReleaseStr(sczArpArguments); | ||
527 | 659 | ||
528 | ReleaseFileHandle(hExecutableFile); | 660 | ReleaseFileHandle(hExecutableFile); |
529 | 661 | ||
@@ -894,3 +1026,106 @@ extern "C" HRESULT ExeEngineHandleExitCode( | |||
894 | //LExit: | 1026 | //LExit: |
895 | return hr; | 1027 | return hr; |
896 | } | 1028 | } |
1029 | |||
1030 | static HRESULT DetectArpEntry( | ||
1031 | __in const BURN_PACKAGE* pPackage, | ||
1032 | __out BOOTSTRAPPER_PACKAGE_STATE* pPackageState, | ||
1033 | __out_opt LPWSTR* psczQuietUninstallString | ||
1034 | ) | ||
1035 | { | ||
1036 | HRESULT hr = S_OK; | ||
1037 | HKEY hKey = NULL; | ||
1038 | VERUTIL_VERSION* pVersion = NULL; | ||
1039 | int nCompareResult = 0; | ||
1040 | HKEY hkRoot = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; | ||
1041 | REG_KEY_BITNESS keyBitness = pPackage->Exe.fArpWin64 ? REG_KEY_64BIT : REG_KEY_32BIT; | ||
1042 | |||
1043 | *pPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | ||
1044 | if (psczQuietUninstallString) | ||
1045 | { | ||
1046 | ReleaseNullStr(*psczQuietUninstallString); | ||
1047 | } | ||
1048 | |||
1049 | hr = RegOpenEx(hkRoot, pPackage->Exe.sczArpKeyPath, KEY_READ, keyBitness, &hKey); | ||
1050 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
1051 | { | ||
1052 | ExitFunction1(hr = S_OK); | ||
1053 | } | ||
1054 | ExitOnFailure(hr, "Failed to open registry key: %ls.", pPackage->Exe.sczArpKeyPath); | ||
1055 | |||
1056 | hr = RegReadWixVersion(hKey, L"DisplayVersion", &pVersion); | ||
1057 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
1058 | { | ||
1059 | ExitFunction1(hr = S_OK); | ||
1060 | } | ||
1061 | ExitOnFailure(hr, "Failed to read DisplayVersion."); | ||
1062 | |||
1063 | if (pVersion->fInvalid) | ||
1064 | { | ||
1065 | LogId(REPORT_WARNING, MSG_DETECTED_EXE_PACKAGE_INVALID_VERSION, pPackage->Exe.sczArpKeyPath, pVersion->sczVersion); | ||
1066 | } | ||
1067 | |||
1068 | hr = VerCompareParsedVersions(pPackage->Exe.pArpDisplayVersion, pVersion, &nCompareResult); | ||
1069 | ExitOnFailure(hr, "Failed to compare versions."); | ||
1070 | |||
1071 | if (nCompareResult < 0) | ||
1072 | { | ||
1073 | *pPackageState = BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE; | ||
1074 | } | ||
1075 | else if (nCompareResult > 0) | ||
1076 | { | ||
1077 | *pPackageState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; | ||
1078 | } | ||
1079 | else | ||
1080 | { | ||
1081 | *pPackageState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; | ||
1082 | } | ||
1083 | |||
1084 | if (psczQuietUninstallString) | ||
1085 | { | ||
1086 | hr = RegReadString(hKey, L"QuietUninstallString", psczQuietUninstallString); | ||
1087 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
1088 | { | ||
1089 | hr = S_OK; | ||
1090 | } | ||
1091 | ExitOnFailure(hr, "Failed to read QuietUninstallString."); | ||
1092 | } | ||
1093 | |||
1094 | LExit: | ||
1095 | ReleaseRegKey(hKey); | ||
1096 | ReleaseVerutilVersion(pVersion); | ||
1097 | |||
1098 | return hr; | ||
1099 | } | ||
1100 | |||
1101 | static HRESULT ParseArpUninstallString( | ||
1102 | __in_z LPCWSTR wzArpUninstallString, | ||
1103 | __inout LPWSTR* psczExecutablePath, | ||
1104 | __inout LPWSTR* psczArguments | ||
1105 | ) | ||
1106 | { | ||
1107 | HRESULT hr = S_OK; | ||
1108 | int argc = 0; | ||
1109 | LPWSTR* argv = NULL; | ||
1110 | |||
1111 | hr = AppParseCommandLine(wzArpUninstallString, &argc, &argv); | ||
1112 | ExitOnFailure(hr, "Failed to parse uninstall string as command line: %ls.", wzArpUninstallString); | ||
1113 | ExitOnNull(argc, hr, E_INVALIDARG, "Uninstall string must contain an executable path."); | ||
1114 | |||
1115 | hr = StrAllocString(psczExecutablePath, argv[0], 0); | ||
1116 | ExitOnFailure(hr, "Failed to copy executable path for ArpCommand."); | ||
1117 | |||
1118 | for (int i = 1; i < argc; ++i) | ||
1119 | { | ||
1120 | hr = AppAppendCommandLineArgument(psczArguments, argv[i]); | ||
1121 | ExitOnFailure(hr, "Failed to append argument for ArpCommand."); | ||
1122 | } | ||
1123 | |||
1124 | LExit: | ||
1125 | if (argv) | ||
1126 | { | ||
1127 | AppFreeCommandLineArgs(argv); | ||
1128 | } | ||
1129 | |||
1130 | return hr; | ||
1131 | } | ||
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h index 3ec77baf..85f34de5 100644 --- a/src/burn/engine/package.h +++ b/src/burn/engine/package.h | |||
@@ -16,6 +16,13 @@ typedef _BURN_PACKAGE BURN_PACKAGE; | |||
16 | 16 | ||
17 | const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000; | 17 | const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000; |
18 | 18 | ||
19 | enum BURN_EXE_DETECTION_TYPE | ||
20 | { | ||
21 | BURN_EXE_DETECTION_TYPE_NONE, | ||
22 | BURN_EXE_DETECTION_TYPE_CONDITION, | ||
23 | BURN_EXE_DETECTION_TYPE_ARP, | ||
24 | }; | ||
25 | |||
19 | enum BURN_EXE_EXIT_CODE_TYPE | 26 | enum BURN_EXE_EXIT_CODE_TYPE |
20 | { | 27 | { |
21 | BURN_EXE_EXIT_CODE_TYPE_NONE, | 28 | BURN_EXE_EXIT_CODE_TYPE_NONE, |
@@ -338,6 +345,12 @@ typedef struct _BURN_PACKAGE | |||
338 | } Bundle; | 345 | } Bundle; |
339 | struct | 346 | struct |
340 | { | 347 | { |
348 | BURN_EXE_DETECTION_TYPE detectionType; | ||
349 | |||
350 | BOOL fArpWin64; | ||
351 | LPWSTR sczArpKeyPath; | ||
352 | VERUTIL_VERSION* pArpDisplayVersion; | ||
353 | |||
341 | LPWSTR sczDetectCondition; | 354 | LPWSTR sczDetectCondition; |
342 | LPWSTR sczInstallArguments; | 355 | LPWSTR sczInstallArguments; |
343 | LPWSTR sczRepairArguments; | 356 | LPWSTR sczRepairArguments; |
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index 52bf6298..419d3272 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp | |||
@@ -2798,7 +2798,8 @@ static BOOL NeedsCache( | |||
2798 | { | 2798 | { |
2799 | BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback; | 2799 | BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback; |
2800 | // TODO: bundles could theoretically use package cache | 2800 | // TODO: bundles could theoretically use package cache |
2801 | if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || BURN_PACKAGE_TYPE_EXE == pPackage->type) // Bundle and Exe packages require the package for all operations (even uninstall). | 2801 | if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || // Bundle and Exe packages require the package for all operations (even uninstall). |
2802 | BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_DETECTION_TYPE_ARP != pPackage->Exe.detectionType) | ||
2802 | { | 2803 | { |
2803 | return BOOTSTRAPPER_ACTION_STATE_NONE != action; | 2804 | return BOOTSTRAPPER_ACTION_STATE_NONE != action; |
2804 | } | 2805 | } |