diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h | 3 | ||||
-rw-r--r-- | src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs | 5 | ||||
-rw-r--r-- | src/burn/engine/apply.cpp | 13 | ||||
-rw-r--r-- | src/burn/engine/core.cpp | 28 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 17 | ||||
-rw-r--r-- | src/burn/engine/engine.mc | 21 | ||||
-rw-r--r-- | src/burn/engine/logging.cpp | 2 | ||||
-rw-r--r-- | src/burn/engine/msiengine.cpp | 2 | ||||
-rw-r--r-- | src/burn/engine/plan.cpp | 84 | ||||
-rw-r--r-- | src/burn/engine/plan.h | 1 | ||||
-rw-r--r-- | src/burn/engine/userexperience.cpp | 2 | ||||
-rw-r--r-- | src/burn/test/BurnUnitTest/PlanTest.cpp | 78 | ||||
-rw-r--r-- | src/test/burn/WixTestTools/BundleInstaller.cs | 30 | ||||
-rw-r--r-- | src/test/burn/WixTestTools/MSIExec.cs | 5 | ||||
-rw-r--r-- | src/test/burn/WixToolsetTest.BurnE2E/ForwardCompatibleBundleTests.cs | 46 |
15 files changed, 284 insertions, 53 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h index d45c7b2a..cdb01330 100644 --- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h +++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h | |||
@@ -15,13 +15,12 @@ extern "C" { | |||
15 | 15 | ||
16 | static const HRESULT E_SUSPECTED_AV_INTERFERENCE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 2000); | 16 | static const HRESULT E_SUSPECTED_AV_INTERFERENCE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 2000); |
17 | 17 | ||
18 | // Note that ordering of the enumeration values is important. | ||
19 | // Some code paths use < or > comparisions and simply reording values will break those comparisons. | ||
20 | enum BOOTSTRAPPER_ACTION | 18 | enum BOOTSTRAPPER_ACTION |
21 | { | 19 | { |
22 | BOOTSTRAPPER_ACTION_UNKNOWN, | 20 | BOOTSTRAPPER_ACTION_UNKNOWN, |
23 | BOOTSTRAPPER_ACTION_HELP, | 21 | BOOTSTRAPPER_ACTION_HELP, |
24 | BOOTSTRAPPER_ACTION_LAYOUT, | 22 | BOOTSTRAPPER_ACTION_LAYOUT, |
23 | BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL, | ||
25 | BOOTSTRAPPER_ACTION_UNINSTALL, | 24 | BOOTSTRAPPER_ACTION_UNINSTALL, |
26 | BOOTSTRAPPER_ACTION_CACHE, | 25 | BOOTSTRAPPER_ACTION_CACHE, |
27 | BOOTSTRAPPER_ACTION_INSTALL, | 26 | BOOTSTRAPPER_ACTION_INSTALL, |
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs index 8ead0919..ebea6c4f 100644 --- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs +++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs | |||
@@ -341,6 +341,11 @@ namespace WixToolset.Mba.Core | |||
341 | /// <summary> | 341 | /// <summary> |
342 | /// | 342 | /// |
343 | /// </summary> | 343 | /// </summary> |
344 | UnsafeUninstall, | ||
345 | |||
346 | /// <summary> | ||
347 | /// | ||
348 | /// </summary> | ||
344 | Uninstall, | 349 | Uninstall, |
345 | 350 | ||
346 | /// <summary> | 351 | /// <summary> |
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index 73f8fc72..4e652768 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp | |||
@@ -505,8 +505,7 @@ extern "C" HRESULT ApplyUnregister( | |||
505 | 505 | ||
506 | registrationType = defaultRegistrationType; | 506 | registrationType = defaultRegistrationType; |
507 | 507 | ||
508 | hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience, ®istrationType); | 508 | UserExperienceOnUnregisterBegin(&pEngineState->userExperience, ®istrationType); |
509 | ExitOnRootFailure(hr, "BA aborted unregister begin."); | ||
510 | 509 | ||
511 | // Barring the special cases, if it was determined that we should keep the registration then | 510 | // Barring the special cases, if it was determined that we should keep the registration then |
512 | // do that, otherwise the resume mode is NONE and registration will be removed. | 511 | // do that, otherwise the resume mode is NONE and registration will be removed. |
@@ -517,7 +516,7 @@ extern "C" HRESULT ApplyUnregister( | |||
517 | 516 | ||
518 | // If apply failed in any way and we're going to be keeping the bundle registered then | 517 | // If apply failed in any way and we're going to be keeping the bundle registered then |
519 | // execute any rollback dependency registration actions. | 518 | // execute any rollback dependency registration actions. |
520 | if (fFailed && BURN_RESUME_MODE_NONE < resumeMode) | 519 | if (fFailed && BURN_RESUME_MODE_NONE < resumeMode && !pEngineState->plan.fDisableRollback) |
521 | { | 520 | { |
522 | // Execute any rollback registration actions. | 521 | // Execute any rollback registration actions. |
523 | HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); | 522 | HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); |
@@ -526,6 +525,14 @@ extern "C" HRESULT ApplyUnregister( | |||
526 | 525 | ||
527 | LogId(REPORT_STANDARD, MSG_SESSION_END, pEngineState->registration.sczRegistrationKey, LoggingResumeModeToString(resumeMode), LoggingRestartToString(restart), LoggingBoolToString(pEngineState->registration.fDisableResume), LoggingRegistrationTypeToString(defaultRegistrationType), LoggingRegistrationTypeToString(registrationType)); | 526 | LogId(REPORT_STANDARD, MSG_SESSION_END, pEngineState->registration.sczRegistrationKey, LoggingResumeModeToString(resumeMode), LoggingRestartToString(restart), LoggingBoolToString(pEngineState->registration.fDisableResume), LoggingRegistrationTypeToString(defaultRegistrationType), LoggingRegistrationTypeToString(registrationType)); |
528 | 527 | ||
528 | if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action) | ||
529 | { | ||
530 | registrationType = BOOTSTRAPPER_REGISTRATION_TYPE_NONE; | ||
531 | resumeMode = BURN_RESUME_MODE_NONE; | ||
532 | |||
533 | LogId(REPORT_STANDARD, MSG_UNSAFE_SESSION_END); | ||
534 | } | ||
535 | |||
529 | if (pEngineState->registration.fPerMachine) | 536 | if (pEngineState->registration.fPerMachine) |
530 | { | 537 | { |
531 | hr = ElevationSessionEnd(pEngineState->companionConnection.hPipe, resumeMode, restart, pEngineState->registration.fDetectedForeignProviderKeyBundleId, registrationType); | 538 | hr = ElevationSessionEnd(pEngineState->companionConnection.hPipe, resumeMode, restart, pEngineState->registration.fDetectedForeignProviderKeyBundleId, registrationType); |
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 8fac7bd0..9d5364a4 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp | |||
@@ -488,7 +488,7 @@ extern "C" HRESULT CorePlan( | |||
488 | pEngineState->plan.pPayloads = &pEngineState->payloads; | 488 | pEngineState->plan.pPayloads = &pEngineState->payloads; |
489 | pEngineState->plan.wzBundleId = pEngineState->registration.sczId; | 489 | pEngineState->plan.wzBundleId = pEngineState->registration.sczId; |
490 | pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId; | 490 | pEngineState->plan.wzBundleProviderKey = pEngineState->registration.sczId; |
491 | pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback; | 491 | pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action; |
492 | pEngineState->plan.fBundleAlreadyRegistered = pEngineState->registration.fInstalled; | 492 | pEngineState->plan.fBundleAlreadyRegistered = pEngineState->registration.fInstalled; |
493 | 493 | ||
494 | hr = PlanSetVariables(action, &pEngineState->variables); | 494 | hr = PlanSetVariables(action, &pEngineState->variables); |
@@ -756,6 +756,14 @@ extern "C" HRESULT CoreApply( | |||
756 | } | 756 | } |
757 | } | 757 | } |
758 | 758 | ||
759 | if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action) | ||
760 | { | ||
761 | fSuspend = FALSE; | ||
762 | restart = BOOTSTRAPPER_APPLY_RESTART_NONE; | ||
763 | |||
764 | LogId(REPORT_STANDARD, MSG_UNSAFE_APPLY_COMPLETED); | ||
765 | } | ||
766 | |||
759 | if (fSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart) | 767 | if (fSuspend || BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart) |
760 | { | 768 | { |
761 | // Leave cache alone. | 769 | // Leave cache alone. |
@@ -773,7 +781,7 @@ extern "C" HRESULT CoreApply( | |||
773 | } | 781 | } |
774 | 782 | ||
775 | LExit: | 783 | LExit: |
776 | if (fRollbackCache) | 784 | if (fRollbackCache && !pEngineState->plan.fDisableRollback) |
777 | { | 785 | { |
778 | ApplyCacheRollback(&pEngineState->userExperience, &pEngineState->plan, pEngineState->companionConnection.hCachePipe, &applyContext); | 786 | ApplyCacheRollback(&pEngineState->userExperience, &pEngineState->plan, pEngineState->companionConnection.hCachePipe, &applyContext); |
779 | } | 787 | } |
@@ -978,6 +986,9 @@ static HRESULT CoreRecreateCommandLine( | |||
978 | case BOOTSTRAPPER_ACTION_UNINSTALL: | 986 | case BOOTSTRAPPER_ACTION_UNINSTALL: |
979 | hr = StrAllocConcat(psczCommandLine, L" /uninstall", 0); | 987 | hr = StrAllocConcat(psczCommandLine, L" /uninstall", 0); |
980 | break; | 988 | break; |
989 | case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: | ||
990 | hr = StrAllocConcat(psczCommandLine, L" /unsafeuninstall", 0); | ||
991 | break; | ||
981 | } | 992 | } |
982 | ExitOnFailure(hr, "Failed to append action state to command-line"); | 993 | ExitOnFailure(hr, "Failed to append action state to command-line"); |
983 | 994 | ||
@@ -1414,6 +1425,13 @@ extern "C" HRESULT CoreParseCommandLine( | |||
1414 | ExitOnFailure(hr, "Failed to copy path for layout directory."); | 1425 | ExitOnFailure(hr, "Failed to copy path for layout directory."); |
1415 | } | 1426 | } |
1416 | } | 1427 | } |
1428 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"unsafeuninstall", -1)) | ||
1429 | { | ||
1430 | if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) | ||
1431 | { | ||
1432 | pCommand->action = BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL; | ||
1433 | } | ||
1434 | } | ||
1417 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"uninstall", -1)) | 1435 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"uninstall", -1)) |
1418 | { | 1436 | { |
1419 | if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) | 1437 | if (BOOTSTRAPPER_ACTION_HELP != pCommand->action) |
@@ -2207,7 +2225,7 @@ static void LogPackages( | |||
2207 | __in const BOOTSTRAPPER_ACTION action | 2225 | __in const BOOTSTRAPPER_ACTION action |
2208 | ) | 2226 | ) |
2209 | { | 2227 | { |
2210 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action; | 2228 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action; |
2211 | 2229 | ||
2212 | if (pUpgradeBundlePackage) | 2230 | if (pUpgradeBundlePackage) |
2213 | { | 2231 | { |
@@ -2286,8 +2304,8 @@ static void LogPackages( | |||
2286 | } | 2304 | } |
2287 | } | 2305 | } |
2288 | 2306 | ||
2289 | // Display related bundles last if caching, installing, modifying, or repairing. | 2307 | // Display related bundles last if not uninstalling. |
2290 | if (BOOTSTRAPPER_ACTION_UNINSTALL < action) | 2308 | if (!fUninstalling) |
2291 | { | 2309 | { |
2292 | LogRelatedBundles(pRelatedBundles, FALSE); | 2310 | LogRelatedBundles(pRelatedBundles, FALSE); |
2293 | } | 2311 | } |
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 86b65cf9..d12a151a 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp | |||
@@ -2289,8 +2289,21 @@ static HRESULT OnApplyInitialize( | |||
2289 | 2289 | ||
2290 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_STARTING); | 2290 | LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_STARTING); |
2291 | 2291 | ||
2292 | BOOTSTRAPPER_ACTION action = static_cast<BOOTSTRAPPER_ACTION>(dwAction); | 2292 | SRP_ACTION restoreAction = SRP_ACTION_UNKNOWN; |
2293 | SRP_ACTION restoreAction = (BOOTSTRAPPER_ACTION_INSTALL == action) ? SRP_ACTION_INSTALL : (BOOTSTRAPPER_ACTION_UNINSTALL == action) ? SRP_ACTION_UNINSTALL : SRP_ACTION_MODIFY; | 2293 | switch (static_cast<BOOTSTRAPPER_ACTION>(dwAction)) |
2294 | { | ||
2295 | case BOOTSTRAPPER_ACTION_INSTALL: | ||
2296 | restoreAction = SRP_ACTION_INSTALL; | ||
2297 | break; | ||
2298 | case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: __fallthrough; | ||
2299 | case BOOTSTRAPPER_ACTION_UNINSTALL: | ||
2300 | restoreAction = SRP_ACTION_UNINSTALL; | ||
2301 | break; | ||
2302 | default: | ||
2303 | restoreAction = SRP_ACTION_MODIFY; | ||
2304 | break; | ||
2305 | } | ||
2306 | |||
2294 | hrStatus = hr = SrpCreateRestorePoint(sczBundleName, restoreAction); | 2307 | hrStatus = hr = SrpCreateRestorePoint(sczBundleName, restoreAction); |
2295 | if (SUCCEEDED(hr)) | 2308 | if (SUCCEEDED(hr)) |
2296 | { | 2309 | { |
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc index 675a5644..4425af12 100644 --- a/src/burn/engine/engine.mc +++ b/src/burn/engine/engine.mc | |||
@@ -492,6 +492,13 @@ Language=English | |||
492 | Planned rollback boundary: '%1!ls!', vital: %2!hs!, transaction: %3!hs! (default: %4!hs!) | 492 | Planned rollback boundary: '%1!ls!', vital: %2!hs!, transaction: %3!hs! (default: %4!hs!) |
493 | . | 493 | . |
494 | 494 | ||
495 | MessageId=223 | ||
496 | Severity=Success | ||
497 | SymbolicName=MSG_PLAN_NOT_SKIPPED_DUE_TO_DEPENDENTS | ||
498 | Language=English | ||
499 | Ignoring bundle dependents due to action UnsafeUninstall... | ||
500 | . | ||
501 | |||
495 | MessageId=299 | 502 | MessageId=299 |
496 | Severity=Success | 503 | Severity=Success |
497 | SymbolicName=MSG_PLAN_COMPLETE | 504 | SymbolicName=MSG_PLAN_COMPLETE |
@@ -947,6 +954,20 @@ Language=English | |||
947 | package: %1!ls!, install registration state: %2!hs!, cache registration state: %3!hs! | 954 | package: %1!ls!, install registration state: %2!hs!, cache registration state: %3!hs! |
948 | . | 955 | . |
949 | 956 | ||
957 | MessageId=375 | ||
958 | Severity=Success | ||
959 | SymbolicName=MSG_UNSAFE_APPLY_COMPLETED | ||
960 | Language=English | ||
961 | Ignoring suspend and restart values due to action UnsafeUninstall... | ||
962 | . | ||
963 | |||
964 | MessageId=376 | ||
965 | Severity=Success | ||
966 | SymbolicName=MSG_UNSAFE_SESSION_END | ||
967 | Language=English | ||
968 | Ignoring resume and registration values due to action UnsafeUninstall... | ||
969 | . | ||
970 | |||
950 | MessageId=380 | 971 | MessageId=380 |
951 | Severity=Warning | 972 | Severity=Warning |
952 | SymbolicName=MSG_APPLY_SKIPPED | 973 | SymbolicName=MSG_APPLY_SKIPPED |
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp index c5dd0ed8..07fc9ef3 100644 --- a/src/burn/engine/logging.cpp +++ b/src/burn/engine/logging.cpp | |||
@@ -354,6 +354,8 @@ extern "C" LPCSTR LoggingBurnActionToString( | |||
354 | return "Layout"; | 354 | return "Layout"; |
355 | case BOOTSTRAPPER_ACTION_CACHE: | 355 | case BOOTSTRAPPER_ACTION_CACHE: |
356 | return "Cache"; | 356 | return "Cache"; |
357 | case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: | ||
358 | return "UnsafeUninstall"; | ||
357 | case BOOTSTRAPPER_ACTION_UNINSTALL: | 359 | case BOOTSTRAPPER_ACTION_UNINSTALL: |
358 | return "Uninstall"; | 360 | return "Uninstall"; |
359 | case BOOTSTRAPPER_ACTION_INSTALL: | 361 | case BOOTSTRAPPER_ACTION_INSTALL: |
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp index c27dd8c2..d306f3e0 100644 --- a/src/burn/engine/msiengine.cpp +++ b/src/burn/engine/msiengine.cpp | |||
@@ -834,7 +834,7 @@ extern "C" HRESULT MsiEnginePlanInitializePackage( | |||
834 | { | 834 | { |
835 | Assert(BURN_PACKAGE_TYPE_MSI == pPackage->compatiblePackage.type); | 835 | Assert(BURN_PACKAGE_TYPE_MSI == pPackage->compatiblePackage.type); |
836 | 836 | ||
837 | pPackage->compatiblePackage.fDefaultRequested = BOOTSTRAPPER_ACTION_UNINSTALL == overallAction; | 837 | pPackage->compatiblePackage.fDefaultRequested = BOOTSTRAPPER_ACTION_UNINSTALL == overallAction || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == overallAction; |
838 | pPackage->compatiblePackage.fRequested = pPackage->compatiblePackage.fDefaultRequested; | 838 | pPackage->compatiblePackage.fRequested = pPackage->compatiblePackage.fDefaultRequested; |
839 | 839 | ||
840 | hr = UserExperienceOnPlanCompatibleMsiPackageBegin(pUserExperience, pPackage->sczId, pPackage->compatiblePackage.compatibleEntry.sczId, pPackage->compatiblePackage.Msi.pVersion, &pPackage->compatiblePackage.fRequested); | 840 | hr = UserExperienceOnPlanCompatibleMsiPackageBegin(pUserExperience, pPackage->sczId, pPackage->compatiblePackage.compatibleEntry.sczId, pPackage->compatiblePackage.Msi.pVersion, &pPackage->compatiblePackage.fRequested); |
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index f1fb87b8..49dd83f4 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp | |||
@@ -361,13 +361,15 @@ extern "C" HRESULT PlanDefaultPackageRequestState( | |||
361 | else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType) | 361 | else if (BOOTSTRAPPER_RELATION_PATCH == relationType && BURN_PACKAGE_TYPE_MSP == packageType) |
362 | { | 362 | { |
363 | // For patch related bundles, only install a patch if currently absent during install, modify, or repair. | 363 | // For patch related bundles, only install a patch if currently absent during install, modify, or repair. |
364 | if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT == currentState && BOOTSTRAPPER_ACTION_INSTALL <= action) | 364 | if (BOOTSTRAPPER_PACKAGE_STATE_ABSENT != currentState) |
365 | { | 365 | { |
366 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; | 366 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; |
367 | } | 367 | } |
368 | else | 368 | else if (BOOTSTRAPPER_ACTION_INSTALL == action || |
369 | BOOTSTRAPPER_ACTION_MODIFY == action || | ||
370 | BOOTSTRAPPER_ACTION_REPAIR == action) | ||
369 | { | 371 | { |
370 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE; | 372 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; |
371 | } | 373 | } |
372 | } | 374 | } |
373 | else // pick the best option for the action state and install condition. | 375 | else // pick the best option for the action state and install condition. |
@@ -375,7 +377,7 @@ extern "C" HRESULT PlanDefaultPackageRequestState( | |||
375 | hr = GetActionDefaultRequestState(action, currentState, &defaultRequestState); | 377 | hr = GetActionDefaultRequestState(action, currentState, &defaultRequestState); |
376 | ExitOnFailure(hr, "Failed to get default request state for action."); | 378 | ExitOnFailure(hr, "Failed to get default request state for action."); |
377 | 379 | ||
378 | if (BOOTSTRAPPER_ACTION_UNINSTALL != action) | 380 | if (BOOTSTRAPPER_ACTION_UNINSTALL != action && BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL != action) |
379 | { | 381 | { |
380 | // If we're not doing an uninstall, use the install condition | 382 | // If we're not doing an uninstall, use the install condition |
381 | // to determine whether to use the default request state or make the package absent. | 383 | // to determine whether to use the default request state or make the package absent. |
@@ -485,7 +487,8 @@ extern "C" HRESULT PlanForwardCompatibleBundles( | |||
485 | { | 487 | { |
486 | fRecommendIgnore = FALSE; | 488 | fRecommendIgnore = FALSE; |
487 | } | 489 | } |
488 | else if (BOOTSTRAPPER_ACTION_UNINSTALL == action || | 490 | else if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action || |
491 | BOOTSTRAPPER_ACTION_UNINSTALL == action || | ||
489 | BOOTSTRAPPER_ACTION_MODIFY == action || | 492 | BOOTSTRAPPER_ACTION_MODIFY == action || |
490 | BOOTSTRAPPER_ACTION_REPAIR == action) | 493 | BOOTSTRAPPER_ACTION_REPAIR == action) |
491 | { | 494 | { |
@@ -552,10 +555,10 @@ extern "C" HRESULT PlanRegistration( | |||
552 | HRESULT hr = S_OK; | 555 | HRESULT hr = S_OK; |
553 | STRINGDICT_HANDLE sdBundleDependents = NULL; | 556 | STRINGDICT_HANDLE sdBundleDependents = NULL; |
554 | STRINGDICT_HANDLE sdIgnoreDependents = NULL; | 557 | STRINGDICT_HANDLE sdIgnoreDependents = NULL; |
558 | BOOL fDependentBlocksUninstall = FALSE; | ||
555 | 559 | ||
556 | pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. | 560 | pPlan->fCanAffectMachineState = TRUE; // register the bundle since we're modifying machine state. |
557 | pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed | 561 | pPlan->fDisallowRemoval = FALSE; // by default the bundle can be planned to be removed |
558 | pPlan->fIgnoreAllDependents = pDependencies->fIgnoreAllDependents; | ||
559 | 562 | ||
560 | // Ensure the bundle is cached if not running from the cache. | 563 | // Ensure the bundle is cached if not running from the cache. |
561 | if (!CacheBundleRunningFromCache(pPlan->pCache)) | 564 | if (!CacheBundleRunningFromCache(pPlan->pCache)) |
@@ -563,7 +566,7 @@ extern "C" HRESULT PlanRegistration( | |||
563 | pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; | 566 | pPlan->dwRegistrationOperations |= BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE; |
564 | } | 567 | } |
565 | 568 | ||
566 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) | 569 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action) |
567 | { | 570 | { |
568 | // If our provider key was not owned by a different bundle, | 571 | // If our provider key was not owned by a different bundle, |
569 | // then plan to write our provider key registration to "fix it" if broken | 572 | // then plan to write our provider key registration to "fix it" if broken |
@@ -588,7 +591,7 @@ extern "C" HRESULT PlanRegistration( | |||
588 | ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); | 591 | ExitOnFailure(hr, "Failed to add self-dependent to ignore dependents."); |
589 | } | 592 | } |
590 | 593 | ||
591 | if (!pPlan->fIgnoreAllDependents) | 594 | if (!pDependencies->fIgnoreAllDependents) |
592 | { | 595 | { |
593 | // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. | 596 | // If we are not doing an upgrade, we check to see if there are still dependents on us and if so we skip planning. |
594 | // However, when being upgraded, we always execute our uninstall because a newer version of us is probably | 597 | // However, when being upgraded, we always execute our uninstall because a newer version of us is probably |
@@ -641,10 +644,9 @@ extern "C" HRESULT PlanRegistration( | |||
641 | hr = S_OK; | 644 | hr = S_OK; |
642 | 645 | ||
643 | // TODO: callback to the BA and let it have the option to ignore this dependent? | 646 | // TODO: callback to the BA and let it have the option to ignore this dependent? |
644 | if (!pPlan->fDisallowRemoval) | 647 | if (!fDependentBlocksUninstall) |
645 | { | 648 | { |
646 | pPlan->fDisallowRemoval = TRUE; // ensure the registration stays | 649 | fDependentBlocksUninstall = TRUE; |
647 | *pfContinuePlanning = FALSE; // skip the rest of planning. | ||
648 | 650 | ||
649 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); | 651 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DUE_TO_DEPENDENTS); |
650 | } | 652 | } |
@@ -653,6 +655,20 @@ extern "C" HRESULT PlanRegistration( | |||
653 | } | 655 | } |
654 | ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); | 656 | ExitOnFailure(hr, "Failed to check for remaining dependents during planning."); |
655 | } | 657 | } |
658 | |||
659 | if (fDependentBlocksUninstall) | ||
660 | { | ||
661 | if (BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action) | ||
662 | { | ||
663 | fDependentBlocksUninstall = FALSE; | ||
664 | LogId(REPORT_STANDARD, MSG_PLAN_NOT_SKIPPED_DUE_TO_DEPENDENTS); | ||
665 | } | ||
666 | else | ||
667 | { | ||
668 | pPlan->fDisallowRemoval = TRUE; // ensure the registration stays | ||
669 | *pfContinuePlanning = FALSE; // skip the rest of planning. | ||
670 | } | ||
671 | } | ||
656 | } | 672 | } |
657 | } | 673 | } |
658 | } | 674 | } |
@@ -776,11 +792,12 @@ static HRESULT PlanPackagesHelper( | |||
776 | HRESULT hr = S_OK; | 792 | HRESULT hr = S_OK; |
777 | BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. | 793 | BOOL fBundlePerMachine = pPlan->fPerMachine; // bundle is per-machine if plan starts per-machine. |
778 | BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; | 794 | BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; |
795 | BOOL fReverseOrder = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
779 | 796 | ||
780 | // Initialize the packages. | 797 | // Initialize the packages. |
781 | for (DWORD i = 0; i < cPackages; ++i) | 798 | for (DWORD i = 0; i < cPackages; ++i) |
782 | { | 799 | { |
783 | DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; | 800 | DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; |
784 | BURN_PACKAGE* pPackage = rgPackages + iPackage; | 801 | BURN_PACKAGE* pPackage = rgPackages + iPackage; |
785 | 802 | ||
786 | hr = InitializePackage(pPlan, pUX, pVariables, pPackage); | 803 | hr = InitializePackage(pPlan, pUX, pVariables, pPackage); |
@@ -790,7 +807,7 @@ static HRESULT PlanPackagesHelper( | |||
790 | // Initialize the patch targets after all packages, since they could rely on the requested state of packages that are after the patch's package in the chain. | 807 | // Initialize the patch targets after all packages, since they could rely on the requested state of packages that are after the patch's package in the chain. |
791 | for (DWORD i = 0; i < cPackages; ++i) | 808 | for (DWORD i = 0; i < cPackages; ++i) |
792 | { | 809 | { |
793 | DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; | 810 | DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; |
794 | BURN_PACKAGE* pPackage = rgPackages + iPackage; | 811 | BURN_PACKAGE* pPackage = rgPackages + iPackage; |
795 | 812 | ||
796 | if (BURN_PACKAGE_TYPE_MSP == pPackage->type) | 813 | if (BURN_PACKAGE_TYPE_MSP == pPackage->type) |
@@ -803,7 +820,7 @@ static HRESULT PlanPackagesHelper( | |||
803 | // Plan the packages. | 820 | // Plan the packages. |
804 | for (DWORD i = 0; i < cPackages; ++i) | 821 | for (DWORD i = 0; i < cPackages; ++i) |
805 | { | 822 | { |
806 | DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; | 823 | DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; |
807 | BURN_PACKAGE* pPackage = rgPackages + iPackage; | 824 | BURN_PACKAGE* pPackage = rgPackages + iPackage; |
808 | 825 | ||
809 | hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary); | 826 | hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary); |
@@ -825,7 +842,7 @@ static HRESULT PlanPackagesHelper( | |||
825 | // Plan clean up of packages. | 842 | // Plan clean up of packages. |
826 | for (DWORD i = 0; i < cPackages; ++i) | 843 | for (DWORD i = 0; i < cPackages; ++i) |
827 | { | 844 | { |
828 | DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; | 845 | DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; |
829 | BURN_PACKAGE* pPackage = rgPackages + iPackage; | 846 | BURN_PACKAGE* pPackage = rgPackages + iPackage; |
830 | 847 | ||
831 | hr = PlanCleanPackage(pPlan, pPackage); | 848 | hr = PlanCleanPackage(pPlan, pPackage); |
@@ -842,7 +859,7 @@ static HRESULT PlanPackagesHelper( | |||
842 | // Let the BA know the actions that were planned. | 859 | // Let the BA know the actions that were planned. |
843 | for (DWORD i = 0; i < cPackages; ++i) | 860 | for (DWORD i = 0; i < cPackages; ++i) |
844 | { | 861 | { |
845 | DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; | 862 | DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; |
846 | BURN_PACKAGE* pPackage = rgPackages + iPackage; | 863 | BURN_PACKAGE* pPackage = rgPackages + iPackage; |
847 | 864 | ||
848 | UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache); | 865 | UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache); |
@@ -931,8 +948,9 @@ static HRESULT ProcessPackage( | |||
931 | { | 948 | { |
932 | HRESULT hr = S_OK; | 949 | HRESULT hr = S_OK; |
933 | BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL; | 950 | BURN_ROLLBACK_BOUNDARY* pEffectiveRollbackBoundary = NULL; |
951 | BOOL fBackward = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
934 | 952 | ||
935 | pEffectiveRollbackBoundary = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward; | 953 | pEffectiveRollbackBoundary = fBackward ? pPackage->pRollbackBoundaryBackward : pPackage->pRollbackBoundaryForward; |
936 | hr = ProcessPackageRollbackBoundary(pPlan, pUX, pLog, pVariables, pEffectiveRollbackBoundary, ppRollbackBoundary); | 954 | hr = ProcessPackageRollbackBoundary(pPlan, pUX, pLog, pVariables, pEffectiveRollbackBoundary, ppRollbackBoundary); |
937 | ExitOnFailure(hr, "Failed to process package rollback boundary."); | 955 | ExitOnFailure(hr, "Failed to process package rollback boundary."); |
938 | 956 | ||
@@ -1205,6 +1223,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState( | |||
1205 | { | 1223 | { |
1206 | HRESULT hr = S_OK; | 1224 | HRESULT hr = S_OK; |
1207 | int nCompareResult = 0; | 1225 | int nCompareResult = 0; |
1226 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == action; | ||
1208 | 1227 | ||
1209 | // Never touch related bundles during Cache. | 1228 | // Never touch related bundles during Cache. |
1210 | if (BOOTSTRAPPER_ACTION_CACHE == action) | 1229 | if (BOOTSTRAPPER_ACTION_CACHE == action) |
@@ -1215,7 +1234,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState( | |||
1215 | switch (relatedBundleRelationType) | 1234 | switch (relatedBundleRelationType) |
1216 | { | 1235 | { |
1217 | case BOOTSTRAPPER_RELATION_UPGRADE: | 1236 | case BOOTSTRAPPER_RELATION_UPGRADE: |
1218 | if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && BOOTSTRAPPER_ACTION_UNINSTALL < action) | 1237 | if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && !fUninstalling) |
1219 | { | 1238 | { |
1220 | hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult); | 1239 | hr = VerCompareParsedVersions(pRegistrationVersion, pRelatedBundleVersion, &nCompareResult); |
1221 | ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion ? pRegistrationVersion->sczVersion : NULL, pRelatedBundleVersion ? pRelatedBundleVersion->sczVersion : NULL); | 1240 | ExitOnFailure(hr, "Failed to compare bundle version '%ls' to related bundle version '%ls'", pRegistrationVersion ? pRegistrationVersion->sczVersion : NULL, pRelatedBundleVersion ? pRelatedBundleVersion->sczVersion : NULL); |
@@ -1225,7 +1244,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState( | |||
1225 | break; | 1244 | break; |
1226 | case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; | 1245 | case BOOTSTRAPPER_RELATION_PATCH: __fallthrough; |
1227 | case BOOTSTRAPPER_RELATION_ADDON: | 1246 | case BOOTSTRAPPER_RELATION_ADDON: |
1228 | if (BOOTSTRAPPER_ACTION_UNINSTALL == action) | 1247 | if (fUninstalling) |
1229 | { | 1248 | { |
1230 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; | 1249 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; |
1231 | } | 1250 | } |
@@ -1242,7 +1261,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState( | |||
1242 | // Automatically repair dependent bundles to restore missing | 1261 | // Automatically repair dependent bundles to restore missing |
1243 | // packages after uninstall unless we're being upgraded with the | 1262 | // packages after uninstall unless we're being upgraded with the |
1244 | // assumption that upgrades are cumulative (as intended). | 1263 | // assumption that upgrades are cumulative (as intended). |
1245 | if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && BOOTSTRAPPER_ACTION_UNINSTALL == action) | 1264 | if (BOOTSTRAPPER_RELATION_UPGRADE != commandRelationType && fUninstalling) |
1246 | { | 1265 | { |
1247 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; | 1266 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; |
1248 | } | 1267 | } |
@@ -1270,6 +1289,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin( | |||
1270 | LPWSTR* rgsczAncestors = NULL; | 1289 | LPWSTR* rgsczAncestors = NULL; |
1271 | UINT cAncestors = 0; | 1290 | UINT cAncestors = 0; |
1272 | STRINGDICT_HANDLE sdAncestors = NULL; | 1291 | STRINGDICT_HANDLE sdAncestors = NULL; |
1292 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
1273 | 1293 | ||
1274 | if (pPlan->pInternalCommand->sczAncestors) | 1294 | if (pPlan->pInternalCommand->sczAncestors) |
1275 | { | 1295 | { |
@@ -1329,7 +1349,7 @@ extern "C" HRESULT PlanRelatedBundlesBegin( | |||
1329 | ExitOnRootFailure(hr, "BA aborted plan related bundle."); | 1349 | ExitOnRootFailure(hr, "BA aborted plan related bundle."); |
1330 | 1350 | ||
1331 | // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. | 1351 | // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. |
1332 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) | 1352 | if (fUninstalling && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) |
1333 | { | 1353 | { |
1334 | if (0 < pRelatedBundle->package.cDependencyProviders) | 1354 | if (0 < pRelatedBundle->package.cDependencyProviders) |
1335 | { | 1355 | { |
@@ -1361,6 +1381,9 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1361 | HRESULT hr = S_OK; | 1381 | HRESULT hr = S_OK; |
1362 | LPWSTR sczIgnoreDependencies = NULL; | 1382 | LPWSTR sczIgnoreDependencies = NULL; |
1363 | STRINGDICT_HANDLE sdProviderKeys = NULL; | 1383 | STRINGDICT_HANDLE sdProviderKeys = NULL; |
1384 | BOOL fExecutingAnyPackage = FALSE; | ||
1385 | BOOL fInstallingAnyPackage = FALSE; | ||
1386 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
1364 | 1387 | ||
1365 | // Get the list of dependencies to ignore to pass to related bundles. | 1388 | // Get the list of dependencies to ignore to pass to related bundles. |
1366 | hr = DependencyAllocIgnoreDependencies(pPlan, &sczIgnoreDependencies); | 1389 | hr = DependencyAllocIgnoreDependencies(pPlan, &sczIgnoreDependencies); |
@@ -1369,9 +1392,6 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1369 | hr = DictCreateStringList(&sdProviderKeys, pPlan->cExecuteActions, DICT_FLAG_CASEINSENSITIVE); | 1392 | hr = DictCreateStringList(&sdProviderKeys, pPlan->cExecuteActions, DICT_FLAG_CASEINSENSITIVE); |
1370 | ExitOnFailure(hr, "Failed to create dictionary for planned packages."); | 1393 | ExitOnFailure(hr, "Failed to create dictionary for planned packages."); |
1371 | 1394 | ||
1372 | BOOL fExecutingAnyPackage = FALSE; | ||
1373 | BOOL fInstallingAnyPackage = FALSE; | ||
1374 | |||
1375 | for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) | 1395 | for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) |
1376 | { | 1396 | { |
1377 | BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE; | 1397 | BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE; |
@@ -1444,7 +1464,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1444 | } | 1464 | } |
1445 | 1465 | ||
1446 | // For an uninstall, there is no need to repair dependent bundles if no packages are executing. | 1466 | // For an uninstall, there is no need to repair dependent bundles if no packages are executing. |
1447 | if (!fExecutingAnyPackage && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) | 1467 | if (!fExecutingAnyPackage && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_REPAIR == pRelatedBundle->package.requested && fUninstalling) |
1448 | { | 1468 | { |
1449 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; | 1469 | pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; |
1450 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType)); | 1470 | LogId(REPORT_STANDARD, MSG_PLAN_SKIPPED_DEPENDENT_BUNDLE_REPAIR, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType)); |
@@ -1457,7 +1477,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1457 | ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore."); | 1477 | ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore."); |
1458 | 1478 | ||
1459 | // Uninstall addons and patches early in the chain, before other packages are uninstalled. | 1479 | // Uninstall addons and patches early in the chain, before other packages are uninstalled. |
1460 | if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) | 1480 | if (fUninstalling) |
1461 | { | 1481 | { |
1462 | pdwInsertIndex = &dwExecuteActionEarlyIndex; | 1482 | pdwInsertIndex = &dwExecuteActionEarlyIndex; |
1463 | } | 1483 | } |
@@ -1475,7 +1495,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete( | |||
1475 | ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId); | 1495 | ExitOnFailure(hr, "Failed to begin plan dependency actions to package: %ls", pRelatedBundle->package.sczId); |
1476 | 1496 | ||
1477 | // If uninstalling a related bundle, make sure the bundle is uninstalled after removing registration. | 1497 | // If uninstalling a related bundle, make sure the bundle is uninstalled after removing registration. |
1478 | if (pdwInsertIndex && BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) | 1498 | if (pdwInsertIndex && fUninstalling) |
1479 | { | 1499 | { |
1480 | ++(*pdwInsertIndex); | 1500 | ++(*pdwInsertIndex); |
1481 | } | 1501 | } |
@@ -1599,9 +1619,10 @@ extern "C" HRESULT PlanCleanPackage( | |||
1599 | HRESULT hr = S_OK; | 1619 | HRESULT hr = S_OK; |
1600 | BOOL fPlanCleanPackage = FALSE; | 1620 | BOOL fPlanCleanPackage = FALSE; |
1601 | BURN_CLEAN_ACTION* pCleanAction = NULL; | 1621 | BURN_CLEAN_ACTION* pCleanAction = NULL; |
1622 | BOOL fUninstalling = BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pPlan->action; | ||
1602 | 1623 | ||
1603 | // The following is a complex set of logic that determines when a package should be cleaned from the cache. | 1624 | // The following is a complex set of logic that determines when a package should be cleaned from the cache. |
1604 | if (BOOTSTRAPPER_CACHE_TYPE_FORCE > pPackage->cacheType || BOOTSTRAPPER_ACTION_CACHE > pPlan->action) | 1625 | if (BOOTSTRAPPER_CACHE_TYPE_FORCE > pPackage->cacheType || fUninstalling) |
1605 | { | 1626 | { |
1606 | // The following are all different reasons why the package should be cleaned from the cache. | 1627 | // The following are all different reasons why the package should be cleaned from the cache. |
1607 | // The else-ifs are used to make the conditions easier to see (rather than have them combined | 1628 | // The else-ifs are used to make the conditions easier to see (rather than have them combined |
@@ -1624,7 +1645,7 @@ extern "C" HRESULT PlanCleanPackage( | |||
1624 | { | 1645 | { |
1625 | fPlanCleanPackage = TRUE; | 1646 | fPlanCleanPackage = TRUE; |
1626 | } | 1647 | } |
1627 | else if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && // uninstalling and | 1648 | else if (fUninstalling && // uninstalling and |
1628 | BOOTSTRAPPER_REQUEST_STATE_NONE == pPackage->requested && // requested do nothing (aka: default) and | 1649 | BOOTSTRAPPER_REQUEST_STATE_NONE == pPackage->requested && // requested do nothing (aka: default) and |
1629 | BOOTSTRAPPER_ACTION_STATE_NONE == pPackage->execute && // execute is still do nothing and | 1650 | BOOTSTRAPPER_ACTION_STATE_NONE == pPackage->execute && // execute is still do nothing and |
1630 | !pPackage->fDependencyManagerWasHere && // dependency manager didn't change execute and | 1651 | !pPackage->fDependencyManagerWasHere && // dependency manager didn't change execute and |
@@ -2091,6 +2112,7 @@ static HRESULT GetActionDefaultRequestState( | |||
2091 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; | 2112 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_REPAIR; |
2092 | break; | 2113 | break; |
2093 | 2114 | ||
2115 | case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: __fallthrough; | ||
2094 | case BOOTSTRAPPER_ACTION_UNINSTALL: | 2116 | case BOOTSTRAPPER_ACTION_UNINSTALL: |
2095 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; | 2117 | *pRequestState = BOOTSTRAPPER_REQUEST_STATE_ABSENT; |
2096 | break; | 2118 | break; |
@@ -2671,7 +2693,7 @@ static BOOL ForceCache( | |||
2671 | BOOTSTRAPPER_REQUEST_STATE_CACHE < pPackage->requested; | 2693 | BOOTSTRAPPER_REQUEST_STATE_CACHE < pPackage->requested; |
2672 | case BOOTSTRAPPER_CACHE_TYPE_FORCE: | 2694 | case BOOTSTRAPPER_CACHE_TYPE_FORCE: |
2673 | // All packages that have cacheType set to force should be cached if the bundle is going to be present. | 2695 | // All packages that have cacheType set to force should be cached if the bundle is going to be present. |
2674 | return BOOTSTRAPPER_ACTION_UNINSTALL < pPlan->action; | 2696 | return BOOTSTRAPPER_ACTION_UNINSTALL != pPlan->action && BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL != pPlan->action; |
2675 | default: | 2697 | default: |
2676 | return FALSE; | 2698 | return FALSE; |
2677 | } | 2699 | } |
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h index 3dce8e5d..c0936970 100644 --- a/src/burn/engine/plan.h +++ b/src/burn/engine/plan.h | |||
@@ -248,7 +248,6 @@ typedef struct _BURN_PLAN | |||
248 | BOOL fDisallowRemoval; | 248 | BOOL fDisallowRemoval; |
249 | BOOL fDisableRollback; | 249 | BOOL fDisableRollback; |
250 | BOOL fAffectedMachineState; | 250 | BOOL fAffectedMachineState; |
251 | BOOL fIgnoreAllDependents; | ||
252 | LPWSTR sczLayoutDirectory; | 251 | LPWSTR sczLayoutDirectory; |
253 | BOOL fBundleAlreadyRegistered; | 252 | BOOL fBundleAlreadyRegistered; |
254 | 253 | ||
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp index 59988bef..a2f33f80 100644 --- a/src/burn/engine/userexperience.cpp +++ b/src/burn/engine/userexperience.cpp | |||
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad( | |||
104 | args.pCommand = pCommand; | 104 | args.pCommand = pCommand; |
105 | args.pfnBootstrapperEngineProc = EngineForApplicationProc; | 105 | args.pfnBootstrapperEngineProc = EngineForApplicationProc; |
106 | args.pvBootstrapperEngineProcContext = pEngineContext; | 106 | args.pvBootstrapperEngineProcContext = pEngineContext; |
107 | args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 1, 10, 0); | 107 | args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 2, 22, 0); |
108 | 108 | ||
109 | results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); | 109 | results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); |
110 | 110 | ||
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp index 81484234..ba28713f 100644 --- a/src/burn/test/BurnUnitTest/PlanTest.cpp +++ b/src/burn/test/BurnUnitTest/PlanTest.cpp | |||
@@ -993,6 +993,84 @@ namespace Bootstrapper | |||
993 | } | 993 | } |
994 | 994 | ||
995 | [Fact] | 995 | [Fact] |
996 | void SingleMsiUnsafeUninstallTest() | ||
997 | { | ||
998 | HRESULT hr = S_OK; | ||
999 | BURN_ENGINE_STATE engineState = { }; | ||
1000 | BURN_ENGINE_STATE* pEngineState = &engineState; | ||
1001 | BURN_PLAN* pPlan = &engineState.plan; | ||
1002 | |||
1003 | InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState); | ||
1004 | DetectPackagesAsPresentAndCached(pEngineState); | ||
1005 | |||
1006 | hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL); | ||
1007 | NativeAssert::Succeeded(hr, "CorePlan failed"); | ||
1008 | |||
1009 | Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL, pPlan->action); | ||
1010 | Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine); | ||
1011 | Assert::Equal<BOOL>(TRUE, pPlan->fDisableRollback); | ||
1012 | |||
1013 | BOOL fRollback = FALSE; | ||
1014 | DWORD dwIndex = 0; | ||
1015 | Assert::Equal(dwIndex, pPlan->cCacheActions); | ||
1016 | |||
1017 | fRollback = TRUE; | ||
1018 | dwIndex = 0; | ||
1019 | Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); | ||
1020 | |||
1021 | Assert::Equal(0ull, pPlan->qwEstimatedSize); | ||
1022 | Assert::Equal(0ull, pPlan->qwCacheSizeTotal); | ||
1023 | |||
1024 | fRollback = FALSE; | ||
1025 | dwIndex = 0; | ||
1026 | DWORD dwExecuteCheckpointId = 1; | ||
1027 | ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); | ||
1028 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1029 | ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1); | ||
1030 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1031 | ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1); | ||
1032 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1033 | ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0); | ||
1034 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1035 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1036 | ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); | ||
1037 | Assert::Equal(dwIndex, pPlan->cExecuteActions); | ||
1038 | |||
1039 | fRollback = TRUE; | ||
1040 | dwIndex = 0; | ||
1041 | dwExecuteCheckpointId = 1; | ||
1042 | ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); | ||
1043 | ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1); | ||
1044 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1045 | ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); | ||
1046 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1047 | ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0); | ||
1048 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1049 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1050 | ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); | ||
1051 | ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); | ||
1052 | Assert::Equal(dwIndex, pPlan->cRollbackActions); | ||
1053 | |||
1054 | Assert::Equal(1ul, pPlan->cExecutePackagesTotal); | ||
1055 | Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); | ||
1056 | |||
1057 | dwIndex = 0; | ||
1058 | Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); | ||
1059 | |||
1060 | dwIndex = 0; | ||
1061 | ValidateCleanAction(pPlan, dwIndex++, L"PackageA"); | ||
1062 | Assert::Equal(dwIndex, pPlan->cCleanActions); | ||
1063 | |||
1064 | UINT uIndex = 0; | ||
1065 | ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL); | ||
1066 | ValidatePlannedProvider(pPlan, uIndex++, L"{64633047-D172-4BBB-B202-64337D15C952}", NULL); | ||
1067 | Assert::Equal(uIndex, pPlan->cPlannedProviders); | ||
1068 | |||
1069 | Assert::Equal(1ul, pEngineState->packages.cPackages); | ||
1070 | ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT); | ||
1071 | } | ||
1072 | |||
1073 | [Fact] | ||
996 | void SlipstreamInstallTest() | 1074 | void SlipstreamInstallTest() |
997 | { | 1075 | { |
998 | HRESULT hr = S_OK; | 1076 | HRESULT hr = S_OK; |
diff --git a/src/test/burn/WixTestTools/BundleInstaller.cs b/src/test/burn/WixTestTools/BundleInstaller.cs index a49c4024..2b449ebf 100644 --- a/src/test/burn/WixTestTools/BundleInstaller.cs +++ b/src/test/burn/WixTestTools/BundleInstaller.cs | |||
@@ -3,6 +3,7 @@ | |||
3 | namespace WixTestTools | 3 | namespace WixTestTools |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | ||
6 | using System.IO; | 7 | using System.IO; |
7 | using System.Text; | 8 | using System.Text; |
8 | 9 | ||
@@ -131,6 +132,35 @@ namespace WixTestTools | |||
131 | } | 132 | } |
132 | 133 | ||
133 | /// <summary> | 134 | /// <summary> |
135 | /// Uninstalls the bundle unsafely with optional arguments. | ||
136 | /// </summary> | ||
137 | /// <param name="expectedExitCode">Expected exit code, defaults to success.</param> | ||
138 | /// <param name="arguments">Optional arguments to pass to the tool.</param> | ||
139 | /// <returns>Path to the generated log file.</returns> | ||
140 | public string UnsafeUninstall(int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments) | ||
141 | { | ||
142 | var newArgumentList = new List<string>(); | ||
143 | newArgumentList.Add("-unsafeuninstall"); | ||
144 | newArgumentList.AddRange(arguments); | ||
145 | return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray()); | ||
146 | } | ||
147 | |||
148 | /// <summary> | ||
149 | /// Uninstalls the bundle unsafely at the given path with optional arguments. | ||
150 | /// </summary> | ||
151 | /// <param name="bundlePath">This should be the bundle in the package cache.</param> | ||
152 | /// <param name="expectedExitCode">Expected exit code, defaults to success.</param> | ||
153 | /// <param name="arguments">Optional arguments to pass to the tool.</param> | ||
154 | /// <returns>Path to the generated log file.</returns> | ||
155 | public string UnsafeUninstall(string bundlePath, int expectedExitCode = (int)MSIExec.MSIExecReturnCode.SUCCESS, params string[] arguments) | ||
156 | { | ||
157 | var newArgumentList = new List<string>(); | ||
158 | newArgumentList.Add("-unsafeuninstall"); | ||
159 | newArgumentList.AddRange(arguments); | ||
160 | return this.RunBundleWithArguments(expectedExitCode, MSIExec.MSIExecMode.Custom, newArgumentList.ToArray(), bundlePath: bundlePath); | ||
161 | } | ||
162 | |||
163 | /// <summary> | ||
134 | /// Executes the bundle with optional arguments. | 164 | /// Executes the bundle with optional arguments. |
135 | /// </summary> | 165 | /// </summary> |
136 | /// <param name="expectedExitCode">Expected exit code.</param> | 166 | /// <param name="expectedExitCode">Expected exit code.</param> |
diff --git a/src/test/burn/WixTestTools/MSIExec.cs b/src/test/burn/WixTestTools/MSIExec.cs index 8dce96cf..a10a48d6 100644 --- a/src/test/burn/WixTestTools/MSIExec.cs +++ b/src/test/burn/WixTestTools/MSIExec.cs | |||
@@ -697,6 +697,11 @@ namespace WixTestTools | |||
697 | /// Uninstalls the product as part of cleanup | 697 | /// Uninstalls the product as part of cleanup |
698 | /// </summary> | 698 | /// </summary> |
699 | Cleanup, | 699 | Cleanup, |
700 | |||
701 | /// <summary> | ||
702 | /// No action automatically added to arguments | ||
703 | /// </summary> | ||
704 | Custom, | ||
700 | } | 705 | } |
701 | 706 | ||
702 | /// <summary> | 707 | /// <summary> |
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/ForwardCompatibleBundleTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/ForwardCompatibleBundleTests.cs index eb649c86..357cf515 100644 --- a/src/test/burn/WixToolsetTest.BurnE2E/ForwardCompatibleBundleTests.cs +++ b/src/test/burn/WixToolsetTest.BurnE2E/ForwardCompatibleBundleTests.cs | |||
@@ -18,6 +18,38 @@ namespace WixToolsetTest.BurnE2E | |||
18 | private const string V200 = "2.0.0.0"; | 18 | private const string V200 = "2.0.0.0"; |
19 | 19 | ||
20 | [Fact] | 20 | [Fact] |
21 | public void CanIgnoreBundleDependentForUnsafeUninstall() | ||
22 | { | ||
23 | string providerId = BundleAProviderId; | ||
24 | string parent = "~BundleAv1"; | ||
25 | string parentSwitch = String.Concat("-parent ", parent); | ||
26 | |||
27 | var packageAv1 = this.CreatePackageInstaller("PackageAv1"); | ||
28 | var bundleAv1 = this.CreateBundleInstaller("BundleAv1"); | ||
29 | var testBAController = this.CreateTestBAController(); | ||
30 | |||
31 | packageAv1.VerifyInstalled(false); | ||
32 | |||
33 | // Install the v1 bundle with a parent. | ||
34 | bundleAv1.Install(arguments: parentSwitch); | ||
35 | bundleAv1.VerifyRegisteredAndInPackageCache(); | ||
36 | |||
37 | packageAv1.VerifyInstalled(true); | ||
38 | Assert.True(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out var actualProviderVersion)); | ||
39 | Assert.Equal(V100, actualProviderVersion); | ||
40 | Assert.True(BundleRegistration.DependencyDependentExists(providerId, parent)); | ||
41 | |||
42 | // Cancel package B right away. | ||
43 | testBAController.SetPackageCancelExecuteAtProgress("PackageA", 1); | ||
44 | |||
45 | bundleAv1.UnsafeUninstall((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_USEREXIT); | ||
46 | bundleAv1.VerifyUnregisteredAndRemovedFromPackageCache(); | ||
47 | |||
48 | packageAv1.VerifyInstalled(true); | ||
49 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); | ||
50 | } | ||
51 | |||
52 | [Fact] | ||
21 | public void CanTrack1ForwardCompatibleDependentThroughMajorUpgrade() | 53 | public void CanTrack1ForwardCompatibleDependentThroughMajorUpgrade() |
22 | { | 54 | { |
23 | string providerId = BundleAProviderId; | 55 | string providerId = BundleAProviderId; |
@@ -70,7 +102,7 @@ namespace WixToolsetTest.BurnE2E | |||
70 | 102 | ||
71 | packageAv1.VerifyInstalled(false); | 103 | packageAv1.VerifyInstalled(false); |
72 | packageAv2.VerifyInstalled(false); | 104 | packageAv2.VerifyInstalled(false); |
73 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 105 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
74 | } | 106 | } |
75 | 107 | ||
76 | [Fact] | 108 | [Fact] |
@@ -116,7 +148,7 @@ namespace WixToolsetTest.BurnE2E | |||
116 | 148 | ||
117 | packageAv1.VerifyInstalled(false); | 149 | packageAv1.VerifyInstalled(false); |
118 | packageAv2.VerifyInstalled(false); | 150 | packageAv2.VerifyInstalled(false); |
119 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 151 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
120 | } | 152 | } |
121 | 153 | ||
122 | [Fact] | 154 | [Fact] |
@@ -198,7 +230,7 @@ namespace WixToolsetTest.BurnE2E | |||
198 | 230 | ||
199 | packageAv1.VerifyInstalled(false); | 231 | packageAv1.VerifyInstalled(false); |
200 | packageAv2.VerifyInstalled(false); | 232 | packageAv2.VerifyInstalled(false); |
201 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 233 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
202 | } | 234 | } |
203 | 235 | ||
204 | [Fact] | 236 | [Fact] |
@@ -280,7 +312,7 @@ namespace WixToolsetTest.BurnE2E | |||
280 | 312 | ||
281 | packageCv1.VerifyInstalled(false); | 313 | packageCv1.VerifyInstalled(false); |
282 | packageCv2.VerifyInstalled(false); | 314 | packageCv2.VerifyInstalled(false); |
283 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 315 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
284 | } | 316 | } |
285 | 317 | ||
286 | [Fact] | 318 | [Fact] |
@@ -366,7 +398,7 @@ namespace WixToolsetTest.BurnE2E | |||
366 | 398 | ||
367 | packageAv1.VerifyInstalled(false); | 399 | packageAv1.VerifyInstalled(false); |
368 | packageAv2.VerifyInstalled(false); | 400 | packageAv2.VerifyInstalled(false); |
369 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 401 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
370 | } | 402 | } |
371 | 403 | ||
372 | [Fact] | 404 | [Fact] |
@@ -414,7 +446,7 @@ namespace WixToolsetTest.BurnE2E | |||
414 | 446 | ||
415 | packageAv1.VerifyInstalled(false); | 447 | packageAv1.VerifyInstalled(false); |
416 | packageAv2.VerifyInstalled(false); | 448 | packageAv2.VerifyInstalled(false); |
417 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 449 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
418 | } | 450 | } |
419 | 451 | ||
420 | [Fact] | 452 | [Fact] |
@@ -463,7 +495,7 @@ namespace WixToolsetTest.BurnE2E | |||
463 | 495 | ||
464 | packageAv1.VerifyInstalled(false); | 496 | packageAv1.VerifyInstalled(false); |
465 | packageAv2.VerifyInstalled(false); | 497 | packageAv2.VerifyInstalled(false); |
466 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out actualProviderVersion)); | 498 | Assert.False(BundleRegistration.TryGetDependencyProviderValue(providerId, "Version", out _)); |
467 | } | 499 | } |
468 | } | 500 | } |
469 | } | 501 | } |