diff options
Diffstat (limited to 'src/burn/engine/exeengine.cpp')
| -rw-r--r-- | src/burn/engine/exeengine.cpp | 295 |
1 files changed, 265 insertions, 30 deletions
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 | } | ||
