extern "C" HRESULT DependencyPlanPackage( __in_opt DWORD *pdwInsertSequence, __in const BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan ) { HRESULT hr = S_OK; BURN_EXECUTE_ACTION* pAction = NULL; // If the dependency execution action is to unregister, add the dependency actions to the plan // *before* the provider key is potentially removed. if (BURN_DEPENDENCY_ACTION_UNREGISTER == pPackage->dependencyExecute) { hr = AddPackageDependencyActions(pdwInsertSequence, pPackage, pPlan, pPackage->dependencyExecute, pPackage->dependencyRollback); ExitOnFailure1(hr, "Failed to plan the dependency actions for package: %ls", pPackage->sczId); } // Add the provider rollback plan. if (BURN_DEPENDENCY_ACTION_NONE != pPackage->providerRollback) { hr = PlanAppendRollbackAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append provider rollback action."); pAction->type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER; pAction->packageProvider.pPackage = const_cast<BURN_PACKAGE*>(pPackage); pAction->packageProvider.action = pPackage->providerRollback; // Put a checkpoint before the execute action so that rollback happens // if execute fails. hr = PlanExecuteCheckpoint(pPlan); ExitOnFailure(hr, "Failed to plan provider checkpoint action."); } // Add the provider execute plan. This comes after rollback so if something goes wrong // rollback will try to clean up after us. if (BURN_DEPENDENCY_ACTION_NONE != pPackage->providerExecute) { if (NULL != pdwInsertSequence) { hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction); ExitOnFailure(hr, "Failed to insert provider execute action."); // Always move the sequence after this dependency action so the provider registration // stays in front of the inserted actions. ++(*pdwInsertSequence); } else { hr = PlanAppendExecuteAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append provider execute action."); } pAction->type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER; pAction->packageProvider.pPackage = const_cast<BURN_PACKAGE*>(pPackage); pAction->packageProvider.action = pPackage->providerExecute; } LExit: return hr; }
// // PlanAdd - adds the calculated execute and rollback actions for the package. // extern "C" HRESULT MsuEnginePlanAddPackage( __in_opt DWORD *pdwInsertSequence, __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, __in HANDLE hCacheEvent, __in BOOL fPlanPackageCacheRollback ) { HRESULT hr = S_OK; BURN_EXECUTE_ACTION* pAction = NULL; // add wait for cache if (hCacheEvent) { hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); ExitOnFailure(hr, "Failed to plan package cache syncpoint"); } // add execute action if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) { if (NULL != pdwInsertSequence) { hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction); ExitOnFailure(hr, "Failed to insert execute action."); } else { hr = PlanAppendExecuteAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append execute action."); } pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; pAction->msuPackage.pPackage = pPackage; pAction->msuPackage.action = pPackage->execute; LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors. } // add rollback action if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback) { hr = PlanAppendRollbackAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append rollback action."); pAction->type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; pAction->msuPackage.pPackage = pPackage; pAction->msuPackage.action = pPackage->rollback; LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, &pAction->msuPackage.sczLogPath); // ignore errors. } LExit: return hr; }
// // PlanAdd - adds the calculated execute and rollback actions for the package. // extern "C" HRESULT ExeEnginePlanAddPackage( __in_opt DWORD *pdwInsertSequence, __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, __in_opt HANDLE hCacheEvent, __in BOOL fPlanPackageCacheRollback ) { HRESULT hr = S_OK; BURN_EXECUTE_ACTION* pAction = NULL; // add wait for cache if (hCacheEvent) { hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage, hCacheEvent, fPlanPackageCacheRollback); ExitOnFailure(hr, "Failed to plan package cache syncpoint"); } hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); ExitOnFailure(hr, "Failed to plan package dependency actions."); // add execute action if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) { if (NULL != pdwInsertSequence) { hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction); ExitOnFailure(hr, "Failed to insert execute action."); } else { hr = PlanAppendExecuteAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append execute action."); } pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; pAction->exePackage.pPackage = pPackage; pAction->exePackage.fFireAndForget = (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action); pAction->exePackage.action = pPackage->execute; if (pPackage->Exe.sczIgnoreDependencies) { hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0); ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); } if (pPackage->Exe.sczAncestors) { hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. } // add rollback action if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback) { hr = PlanAppendRollbackAction(pPlan, &pAction); ExitOnFailure(hr, "Failed to append rollback action."); pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; pAction->exePackage.pPackage = pPackage; pAction->exePackage.action = pPackage->rollback; if (pPackage->Exe.sczIgnoreDependencies) { hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0); ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); } if (pPackage->Exe.sczAncestors) { hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. } LExit: return hr; }
static HRESULT PlanTargetProduct( __in BOOTSTRAPPER_DISPLAY display, __in BOOL fRollback, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, __in BOOTSTRAPPER_ACTION_STATE actionState, __in BURN_PACKAGE* pPackage, __in BURN_MSPTARGETPRODUCT* pTargetProduct ) { HRESULT hr = S_OK; BURN_EXECUTE_ACTION* rgActions = fRollback ? pPlan->rgRollbackActions : pPlan->rgExecuteActions; DWORD cActions = fRollback ? pPlan->cRollbackActions : pPlan->cExecuteActions; BURN_EXECUTE_ACTION* pAction = NULL; // Try to find another MSP action with the exact same action (install or uninstall) targeting // the same product in the same machine context (per-user or per-machine). for (DWORD i = 0; i < cActions; ++i) { pAction = rgActions + i; if (BURN_EXECUTE_ACTION_TYPE_MSP_TARGET == pAction->type && pAction->mspTarget.action == actionState && pAction->mspTarget.fPerMachineTarget == (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context) && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pAction->mspTarget.sczTargetProductCode, -1, pTargetProduct->wzTargetProductCode, -1)) { break; } pAction = NULL; } // If we didn't find an MSP target action already updating the product, create a new action. if (!pAction) { if (fRollback) { hr = PlanAppendRollbackAction(pPlan, &pAction); } else { hr = PlanAppendExecuteAction(pPlan, &pAction); } ExitOnFailure(hr, "Failed to plan action for target product."); pAction->type = BURN_EXECUTE_ACTION_TYPE_MSP_TARGET; pAction->mspTarget.action = actionState; pAction->mspTarget.pPackage = pPackage; pAction->mspTarget.fPerMachineTarget = (MSIINSTALLCONTEXT_MACHINE == pTargetProduct->context); pAction->mspTarget.uiLevel = MsiEngineCalculateInstallLevel(pPackage->Msp.fDisplayInternalUI, display); pAction->mspTarget.pChainedTargetPackage = pTargetProduct->pChainedTargetPackage; pAction->mspTarget.fSlipstream = pTargetProduct->fSlipstream; hr = StrAllocString(&pAction->mspTarget.sczTargetProductCode, pTargetProduct->wzTargetProductCode, 0); ExitOnFailure(hr, "Failed to copy target product code."); // If this is a per-machine target product, then the plan needs to be per-machine as well. if (pAction->mspTarget.fPerMachineTarget) { pPlan->fPerMachine = TRUE; } LoggingSetPackageVariable(pPackage, pAction->mspTarget.sczTargetProductCode, fRollback, pLog, pVariables, &pAction->mspTarget.sczLogPath); // ignore errors. } // Add our target product to the array and sort based on their order determined during detection. hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pAction->mspTarget.rgOrderedPatches), pAction->mspTarget.cOrderedPatches + 1, sizeof(BURN_ORDERED_PATCHES), 2); ExitOnFailure(hr, "Failed grow array of ordered patches."); pAction->mspTarget.rgOrderedPatches[pAction->mspTarget.cOrderedPatches].dwOrder = pTargetProduct->dwOrder; pAction->mspTarget.rgOrderedPatches[pAction->mspTarget.cOrderedPatches].pPackage = pPackage; ++pAction->mspTarget.cOrderedPatches; // Insertion sort to keep the patches ordered. for (DWORD i = pAction->mspTarget.cOrderedPatches - 1; i > 0; --i) { if (pAction->mspTarget.rgOrderedPatches[i].dwOrder < pAction->mspTarget.rgOrderedPatches[i - 1].dwOrder) { BURN_ORDERED_PATCHES temp = pAction->mspTarget.rgOrderedPatches[i - 1]; pAction->mspTarget.rgOrderedPatches[i - 1] = pAction->mspTarget.rgOrderedPatches[i]; pAction->mspTarget.rgOrderedPatches[i] = temp; } else // no swap necessary, we're done. { break; } } LExit: return hr; }