summaryrefslogtreecommitdiff
path: root/src/burn/engine/plan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/plan.cpp')
-rw-r--r--src/burn/engine/plan.cpp143
1 files changed, 130 insertions, 13 deletions
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index f850d49c..f1fb87b8 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -103,6 +103,10 @@ static HRESULT AppendCleanAction(
103 __in BURN_PLAN* pPlan, 103 __in BURN_PLAN* pPlan,
104 __out BURN_CLEAN_ACTION** ppCleanAction 104 __out BURN_CLEAN_ACTION** ppCleanAction
105 ); 105 );
106static HRESULT AppendRestoreRelatedBundleAction(
107 __in BURN_PLAN* pPlan,
108 __out BURN_EXECUTE_ACTION** ppExecuteAction
109 );
106static HRESULT ProcessPayloadGroup( 110static HRESULT ProcessPayloadGroup(
107 __in BURN_PLAN* pPlan, 111 __in BURN_PLAN* pPlan,
108 __in BURN_PAYLOAD_GROUP* pPayloadGroup 112 __in BURN_PAYLOAD_GROUP* pPayloadGroup
@@ -196,6 +200,15 @@ extern "C" void PlanReset(
196 MemFree(pPlan->rgRollbackActions); 200 MemFree(pPlan->rgRollbackActions);
197 } 201 }
198 202
203 if (pPlan->rgRestoreRelatedBundleActions)
204 {
205 for (DWORD i = 0; i < pPlan->cRestoreRelatedBundleActions; ++i)
206 {
207 PlanUninitializeExecuteAction(&pPlan->rgRestoreRelatedBundleActions[i]);
208 }
209 MemFree(pPlan->rgRestoreRelatedBundleActions);
210 }
211
199 if (pPlan->rgCleanActions) 212 if (pPlan->rgCleanActions)
200 { 213 {
201 // Nothing needs to be freed inside clean actions today. 214 // Nothing needs to be freed inside clean actions today.
@@ -1276,6 +1289,9 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1276 continue; 1289 continue;
1277 } 1290 }
1278 1291
1292 pRelatedBundle->defaultRequestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1293 pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_NONE;
1294 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE;
1279 pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1295 pRelatedBundle->package.defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1280 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1296 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1281 1297
@@ -1312,12 +1328,6 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1312 hr = UserExperienceOnPlanRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->package.requested); 1328 hr = UserExperienceOnPlanRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->package.requested);
1313 ExitOnRootFailure(hr, "BA aborted plan related bundle."); 1329 ExitOnRootFailure(hr, "BA aborted plan related bundle.");
1314 1330
1315 // Log when the BA changed the bundle state so the engine doesn't get blamed for planning the wrong thing.
1316 if (pRelatedBundle->package.requested != pRelatedBundle->package.defaultRequested)
1317 {
1318 LogId(REPORT_STANDARD, MSG_PLANNED_BUNDLE_UX_CHANGED_REQUEST, pRelatedBundle->package.sczId, LoggingRequestStateToString(pRelatedBundle->package.requested), LoggingRequestStateToString(pRelatedBundle->package.defaultRequested));
1319 }
1320
1321 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting. 1331 // If uninstalling and the dependent related bundle may be executed, ignore its provider key to allow for downgrades with ref-counting.
1322 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) 1332 if (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action && BOOTSTRAPPER_RELATION_DEPENDENT == pRelatedBundle->relationType && BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1323 { 1333 {
@@ -1340,6 +1350,7 @@ LExit:
1340} 1350}
1341 1351
1342extern "C" HRESULT PlanRelatedBundlesComplete( 1352extern "C" HRESULT PlanRelatedBundlesComplete(
1353 __in BURN_USER_EXPERIENCE* pUserExperience,
1343 __in BURN_REGISTRATION* pRegistration, 1354 __in BURN_REGISTRATION* pRegistration,
1344 __in BURN_PLAN* pPlan, 1355 __in BURN_PLAN* pPlan,
1345 __in BURN_LOGGING* pLog, 1356 __in BURN_LOGGING* pLog,
@@ -1359,16 +1370,19 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1359 ExitOnFailure(hr, "Failed to create dictionary for planned packages."); 1370 ExitOnFailure(hr, "Failed to create dictionary for planned packages.");
1360 1371
1361 BOOL fExecutingAnyPackage = FALSE; 1372 BOOL fExecutingAnyPackage = FALSE;
1373 BOOL fInstallingAnyPackage = FALSE;
1362 1374
1363 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) 1375 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1364 { 1376 {
1377 BOOTSTRAPPER_ACTION_STATE packageAction = BOOTSTRAPPER_ACTION_STATE_NONE;
1378
1365 switch (pPlan->rgExecuteActions[i].type) 1379 switch (pPlan->rgExecuteActions[i].type)
1366 { 1380 {
1367 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: 1381 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1368 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action) 1382 packageAction = pPlan->rgExecuteActions[i].relatedBundle.action;
1369 {
1370 fExecutingAnyPackage = TRUE;
1371 1383
1384 if (BOOTSTRAPPER_ACTION_STATE_NONE != packageAction)
1385 {
1372 BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package; 1386 BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1373 if (pPackage->cDependencyProviders) 1387 if (pPackage->cDependencyProviders)
1374 { 1388 {
@@ -1380,21 +1394,24 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1380 break; 1394 break;
1381 1395
1382 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 1396 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1383 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action); 1397 packageAction = pPlan->rgExecuteActions[i].exePackage.action;
1384 break; 1398 break;
1385 1399
1386 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 1400 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1387 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action); 1401 packageAction = pPlan->rgExecuteActions[i].msiPackage.action;
1388 break; 1402 break;
1389 1403
1390 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 1404 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1391 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action); 1405 packageAction = pPlan->rgExecuteActions[i].mspTarget.action;
1392 break; 1406 break;
1393 1407
1394 case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: 1408 case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1395 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action); 1409 packageAction = pPlan->rgExecuteActions[i].msuPackage.action;
1396 break; 1410 break;
1397 } 1411 }
1412
1413 fExecutingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_NONE != packageAction;
1414 fInstallingAnyPackage |= BOOTSTRAPPER_ACTION_STATE_INSTALL == packageAction || BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE == packageAction;
1398 } 1415 }
1399 1416
1400 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i) 1417 for (DWORD i = 0; i < pRegistration->relatedBundles.cRelatedBundles; ++i)
@@ -1492,6 +1509,62 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1492 hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan); 1509 hr = DependencyPlanPackageComplete(&pRelatedBundle->package, pPlan);
1493 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId); 1510 ExitOnFailure(hr, "Failed to complete plan dependency actions for related bundle package: %ls", pRelatedBundle->package.sczId);
1494 } 1511 }
1512
1513 if (fInstallingAnyPackage && BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType)
1514 {
1515 BURN_EXECUTE_ACTION* pAction = NULL;
1516
1517 pRelatedBundle->defaultRequestedRestore = pRelatedBundle->requestedRestore = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
1518
1519 hr = UserExperienceOnPlanRestoreRelatedBundle(pUserExperience, pRelatedBundle->package.sczId, &pRelatedBundle->requestedRestore);
1520 ExitOnRootFailure(hr, "BA aborted plan restore related bundle.");
1521
1522 switch (pRelatedBundle->requestedRestore)
1523 {
1524 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
1525 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_REPAIR;
1526 break;
1527 case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough;
1528 case BOOTSTRAPPER_REQUEST_STATE_CACHE: __fallthrough;
1529 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
1530 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
1531 break;
1532 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
1533 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_INSTALL;
1534 break;
1535 default:
1536 pRelatedBundle->restore = BOOTSTRAPPER_ACTION_STATE_NONE;
1537 break;
1538 }
1539
1540 if (BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->restore)
1541 {
1542 hr = AppendRestoreRelatedBundleAction(pPlan, &pAction);
1543 ExitOnFailure(hr, "Failed to append restore related bundle action to plan.");
1544
1545 pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
1546 pAction->relatedBundle.pRelatedBundle = pRelatedBundle;
1547 pAction->relatedBundle.action = pRelatedBundle->restore;
1548
1549 if (pRelatedBundle->package.Bundle.sczIgnoreDependencies)
1550 {
1551 hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pRelatedBundle->package.Bundle.sczIgnoreDependencies, 0);
1552 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
1553 }
1554
1555 if (pRelatedBundle->package.Bundle.wzAncestors)
1556 {
1557 hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pRelatedBundle->package.Bundle.wzAncestors, 0);
1558 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
1559 }
1560
1561 if (pRelatedBundle->package.Bundle.wzEngineWorkingDirectory)
1562 {
1563 hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pRelatedBundle->package.Bundle.wzEngineWorkingDirectory, 0);
1564 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
1565 }
1566 }
1567 }
1495 } 1568 }
1496 1569
1497LExit: 1570LExit:
@@ -2269,6 +2342,23 @@ LExit:
2269 return hr; 2342 return hr;
2270} 2343}
2271 2344
2345static HRESULT AppendRestoreRelatedBundleAction(
2346 __in BURN_PLAN* pPlan,
2347 __out BURN_EXECUTE_ACTION** ppExecuteAction
2348 )
2349{
2350 HRESULT hr = S_OK;
2351
2352 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(&pPlan->rgRestoreRelatedBundleActions), pPlan->cRestoreRelatedBundleActions, 1, sizeof(BURN_EXECUTE_ACTION), 5);
2353 ExitOnFailure(hr, "Failed to grow plan's array of restore related bundle actions.");
2354
2355 *ppExecuteAction = pPlan->rgRestoreRelatedBundleActions + pPlan->cRestoreRelatedBundleActions;
2356 ++pPlan->cRestoreRelatedBundleActions;
2357
2358LExit:
2359 return hr;
2360}
2361
2272static HRESULT ProcessPayloadGroup( 2362static HRESULT ProcessPayloadGroup(
2273 __in BURN_PLAN* pPlan, 2363 __in BURN_PLAN* pPlan,
2274 __in BURN_PAYLOAD_GROUP* pPayloadGroup 2364 __in BURN_PAYLOAD_GROUP* pPayloadGroup
@@ -2725,6 +2815,28 @@ static void ExecuteActionLog(
2725 } 2815 }
2726} 2816}
2727 2817
2818static void RestoreRelatedBundleActionLog(
2819 __in DWORD iAction,
2820 __in BURN_EXECUTE_ACTION* pAction
2821 )
2822{
2823 switch (pAction->type)
2824 {
2825 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2826 LogStringLine(PlanDumpLevel, "Restore action[%u]: RELATED_BUNDLE package id: %ls, action: %hs, ignore dependencies: %ls", iAction, pAction->relatedBundle.pRelatedBundle->package.sczId, LoggingActionStateToString(pAction->relatedBundle.action), pAction->relatedBundle.sczIgnoreDependencies);
2827 break;
2828
2829 default:
2830 AssertSz(FALSE, "Unknown execute action type.");
2831 break;
2832 }
2833
2834 if (pAction->fDeleted)
2835 {
2836 LogStringLine(PlanDumpLevel, " (deleted action)");
2837 }
2838}
2839
2728static void CleanActionLog( 2840static void CleanActionLog(
2729 __in DWORD iAction, 2841 __in DWORD iAction,
2730 __in BURN_CLEAN_ACTION* pAction 2842 __in BURN_CLEAN_ACTION* pAction
@@ -2784,6 +2896,11 @@ extern "C" void PlanDump(
2784 ExecuteActionLog(i, pPlan->rgRollbackActions + i, TRUE); 2896 ExecuteActionLog(i, pPlan->rgRollbackActions + i, TRUE);
2785 } 2897 }
2786 2898
2899 for (DWORD i = 0; i < pPlan->cRestoreRelatedBundleActions; ++i)
2900 {
2901 RestoreRelatedBundleActionLog(i, pPlan->rgRestoreRelatedBundleActions + i);
2902 }
2903
2787 for (DWORD i = 0; i < pPlan->cCleanActions; ++i) 2904 for (DWORD i = 0; i < pPlan->cCleanActions; ++i)
2788 { 2905 {
2789 CleanActionLog(i, pPlan->rgCleanActions + i); 2906 CleanActionLog(i, pPlan->rgCleanActions + i);