From 1f5314302b3c8bc1977aed79df1d05c52608f382 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Mon, 3 Jan 2022 15:35:14 -0600 Subject: Don't assume Exe packages with Burn protocol are bundles. Related to #3693 --- src/burn/engine/apply.cpp | 94 +++++++ src/burn/engine/bundlepackageengine.cpp | 460 ++++++++++++++++++++++++++++++++ src/burn/engine/bundlepackageengine.h | 38 +++ src/burn/engine/core.cpp | 14 +- src/burn/engine/elevation.cpp | 166 ++++++++++-- src/burn/engine/elevation.h | 9 + src/burn/engine/engine.vcxproj | 2 + src/burn/engine/exeengine.cpp | 177 ++++-------- src/burn/engine/exeengine.h | 20 +- src/burn/engine/package.cpp | 22 +- src/burn/engine/package.h | 22 +- src/burn/engine/plan.cpp | 128 ++++----- src/burn/engine/plan.h | 22 +- src/burn/engine/precomp.h | 1 + src/burn/engine/pseudobundle.cpp | 153 ++--------- src/burn/engine/pseudobundle.h | 15 +- src/burn/engine/relatedbundle.cpp | 47 +++- src/burn/engine/relatedbundle.h | 5 + src/burn/test/BurnUnitTest/PlanTest.cpp | 33 ++- 19 files changed, 1018 insertions(+), 410 deletions(-) create mode 100644 src/burn/engine/bundlepackageengine.cpp create mode 100644 src/burn/engine/bundlepackageengine.h (limited to 'src/burn') diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp index e2939f40..99884234 100644 --- a/src/burn/engine/apply.cpp +++ b/src/burn/engine/apply.cpp @@ -201,6 +201,15 @@ static HRESULT DoRollbackActions( __in DWORD dwCheckpoint, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); +static HRESULT ExecuteRelatedBundle( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fRollback, + __out BOOL* pfRetry, + __out BOOL* pfSuspend, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ); static HRESULT ExecuteExePackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, @@ -686,6 +695,9 @@ extern "C" HRESULT ApplyExecute( LPCWSTR wzId = NULL; switch (pExecuteAction->type) { + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId; + break; case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: wzId = pExecuteAction->exePackage.pPackage->sczId; break; @@ -2285,6 +2297,11 @@ static HRESULT DoExecuteAction( } break; + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + hr = ExecuteRelatedBundle(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); + ExitOnFailure(hr, "Failed to execute related bundle."); + break; + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); ExitOnFailure(hr, "Failed to execute EXE package."); @@ -2399,6 +2416,11 @@ static HRESULT DoRollbackActions( case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: break; + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + hr = ExecuteRelatedBundle(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); + ExitOnFailure(hr, "Failed to execute related bundle."); + break; + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); IgnoreRollbackError(hr, "Failed to rollback EXE package."); @@ -2462,6 +2484,78 @@ LExit: return hr; } +static HRESULT ExecuteRelatedBundle( + __in BURN_ENGINE_STATE* pEngineState, + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_EXECUTE_CONTEXT* pContext, + __in BOOL fRollback, + __out BOOL* pfRetry, + __out BOOL* pfSuspend, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ) +{ + HRESULT hr = S_OK; + HRESULT hrExecute = S_OK; + GENERIC_EXECUTE_MESSAGE message = { }; + int nResult = 0; + BOOL fBeginCalled = FALSE; + BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle; + BURN_PACKAGE* pPackage = &pRelatedBundle->package; + + if (FAILED(pPackage->hrCacheResult)) + { + LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); + ExitFunction1(hr = S_OK); + } + + Assert(pContext->fRollback == fRollback); + pContext->pExecutingPackage = pPackage; + fBeginCalled = TRUE; + + // Send package execute begin to BA. + hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->relatedBundle.action, INSTALLUILEVEL_NOCHANGE, FALSE); + ExitOnRootFailure(hr, "BA aborted execute related bundle begin."); + + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; + message.dwUIHint = MB_OKCANCEL; + message.progress.dwPercentage = fRollback ? 100 : 0; + nResult = GenericExecuteMessageHandler(&message, pContext); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); + ExitOnRootFailure(hr, "BA aborted related bundle progress."); + + // Execute package. + if (pPackage->fPerMachine) + { + hrExecute = ElevationExecuteRelatedBundle(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart); + ExitOnFailure(hrExecute, "Failed to configure per-machine related bundle."); + } + else + { + hrExecute = BundlePackageEngineExecuteRelatedBundle(pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart); + ExitOnFailure(hrExecute, "Failed to configure per-user related bundle."); + } + + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; + message.dwUIHint = MB_OKCANCEL; + message.progress.dwPercentage = fRollback ? 0 : 100; + nResult = GenericExecuteMessageHandler(&message, pContext); + hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult); + ExitOnRootFailure(hr, "BA aborted related bundle progress."); + + pContext->cExecutedPackages += fRollback ? -1 : 1; + + hr = ReportOverallProgressTicks(&pEngineState->userExperience, fRollback, pEngineState->plan.cOverallProgressTicksTotal, pContext->pApplyContext); + ExitOnRootFailure(hr, "BA aborted related bundle execute progress."); + +LExit: + if (fBeginCalled) + { + hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend); + } + + return hr; +} + static HRESULT ExecuteExePackage( __in BURN_ENGINE_STATE* pEngineState, __in BURN_EXECUTE_ACTION* pExecuteAction, diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp new file mode 100644 index 00000000..10022b6a --- /dev/null +++ b/src/burn/engine/bundlepackageengine.cpp @@ -0,0 +1,460 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" + + + +// function definitions + +extern "C" void BundlePackageEnginePackageUninitialize( + __in BURN_PACKAGE* pPackage + ) +{ + ReleaseStr(pPackage->Bundle.sczInstallArguments); + ReleaseStr(pPackage->Bundle.sczRepairArguments); + ReleaseStr(pPackage->Bundle.sczUninstallArguments); + ReleaseStr(pPackage->Bundle.sczIgnoreDependencies); + ReleaseMem(pPackage->Bundle.rgExitCodes); + + // free command-line arguments + if (pPackage->Bundle.rgCommandLineArguments) + { + for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i) + { + ExeEngineCommandLineArgumentUninitialize(pPackage->Bundle.rgCommandLineArguments + i); + } + MemFree(pPackage->Bundle.rgCommandLineArguments); + } + + // clear struct + memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle)); +} + +// +// PlanCalculate - calculates the execute and rollback state for the requested package state. +// +extern "C" HRESULT BundlePackageEnginePlanCalculatePackage( + __in BURN_PACKAGE* pPackage + ) +{ + HRESULT hr = S_OK; + BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE; + BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE; + + // execute action + switch (pPackage->currentState) + { + case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: + switch (pPackage->requested) + { + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: + execute = pPackage->Bundle.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; + break; + case BOOTSTRAPPER_REQUEST_STATE_REPAIR: + execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE; + break; + case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_CACHE: + execute = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; + break; + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: + execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; + break; + default: + execute = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + } + break; + + case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: + switch (pPackage->requested) + { + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_REPAIR: + execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; + break; + default: + execute = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + } + break; + + default: + hr = E_INVALIDARG; + ExitOnRootFailure(hr, "Invalid package current state: %d.", pPackage->currentState); + } + + // Calculate the rollback action if there is an execute action. + if (BOOTSTRAPPER_ACTION_STATE_NONE != execute) + { + switch (pPackage->currentState) + { + case BOOTSTRAPPER_PACKAGE_STATE_PRESENT: + switch (pPackage->requested) + { + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_REPAIR: + rollback = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_ABSENT: + rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL; + break; + default: + rollback = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + } + break; + + case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: + switch (pPackage->requested) + { + case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_REPAIR: + rollback = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; + break; + case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough; + case BOOTSTRAPPER_REQUEST_STATE_ABSENT: + rollback = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + default: + rollback = BOOTSTRAPPER_ACTION_STATE_NONE; + break; + } + break; + + default: + hr = E_INVALIDARG; + ExitOnRootFailure(hr, "Invalid package expected state."); + } + } + + // return values + pPackage->execute = execute; + pPackage->rollback = rollback; + +LExit: + return hr; +} + +// +// PlanAdd - adds the calculated execute and rollback actions for the package. +// +extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle( + __in_opt DWORD *pdwInsertSequence, + __in BURN_RELATED_BUNDLE* pRelatedBundle, + __in BURN_PLAN* pPlan, + __in BURN_LOGGING* pLog, + __in BURN_VARIABLES* pVariables + ) +{ + HRESULT hr = S_OK; + BURN_EXECUTE_ACTION* pAction = NULL; + BURN_PACKAGE* pPackage = &pRelatedBundle->package; + + hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); + ExitOnFailure(hr, "Failed to plan package dependency actions."); + + // add execute action + if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) + { + if (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_RELATED_BUNDLE; + pAction->relatedBundle.pRelatedBundle = pRelatedBundle; + pAction->relatedBundle.action = pPackage->execute; + + if (pPackage->Bundle.sczIgnoreDependencies) + { + hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0); + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); + } + + if (pPackage->Bundle.wzAncestors) + { + hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0); + ExitOnFailure(hr, "Failed to allocate the list of ancestors."); + } + + if (pPackage->Bundle.wzEngineWorkingDirectory) + { + hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0); + ExitOnFailure(hr, "Failed to allocate the custom working directory."); + } + + 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_RELATED_BUNDLE; + pAction->relatedBundle.pRelatedBundle = pRelatedBundle; + pAction->relatedBundle.action = pPackage->rollback; + + if (pPackage->Bundle.sczIgnoreDependencies) + { + hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0); + ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); + } + + if (pPackage->Bundle.wzAncestors) + { + hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0); + ExitOnFailure(hr, "Failed to allocate the list of ancestors."); + } + + if (pPackage->Bundle.wzEngineWorkingDirectory) + { + hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0); + ExitOnFailure(hr, "Failed to allocate the custom working directory."); + } + + LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. + } + +LExit: + return hr; +} + +extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle( + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_CACHE* pCache, + __in BURN_VARIABLES* pVariables, + __in BOOL fRollback, + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, + __in LPVOID pvContext, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ) +{ + HRESULT hr = S_OK; + int nResult = IDNOACTION; + LPCWSTR wzArguments = NULL; + LPWSTR sczArguments = NULL; + LPWSTR sczArgumentsFormatted = NULL; + LPWSTR sczArgumentsObfuscated = NULL; + LPWSTR sczCachedDirectory = NULL; + LPWSTR sczExecutablePath = NULL; + LPWSTR sczCommand = NULL; + LPWSTR sczCommandObfuscated = NULL; + HANDLE hExecutableFile = INVALID_HANDLE_VALUE; + STARTUPINFOW si = { }; + PROCESS_INFORMATION pi = { }; + DWORD dwExitCode = 0; + GENERIC_EXECUTE_MESSAGE message = { }; + BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action; + BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle; + BOOTSTRAPPER_RELATION_TYPE relationType = pRelatedBundle->relationType; + BURN_PACKAGE* pPackage = &pRelatedBundle->package; + BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload; + LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); + LPCWSTR wzOperationCommandLine = NULL; + BOOL fRunEmbedded = pPackage->Bundle.fSupportsBurnProtocol; + + // get cached executable path + hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory); + ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId); + + // Best effort to set the execute package cache folder and action variables. + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE); + VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, action, TRUE); + + hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath); + ExitOnFailure(hr, "Failed to build executable path."); + + // pick arguments + switch (action) + { + case BOOTSTRAPPER_ACTION_STATE_INSTALL: + wzArguments = pPackage->Bundle.sczInstallArguments; + break; + + case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: + wzOperationCommandLine = L"-uninstall"; + wzArguments = pPackage->Bundle.sczUninstallArguments; + break; + + case BOOTSTRAPPER_ACTION_STATE_REPAIR: + wzOperationCommandLine = L"-repair"; + wzArguments = pPackage->Bundle.sczRepairArguments; + break; + + default: + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid Bundle package action: %d.", action); + } + + // now add optional arguments + if (wzArguments && *wzArguments) + { + hr = StrAllocString(&sczArguments, wzArguments, 0); + ExitOnFailure(hr, "Failed to copy package arguments."); + } + + for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i) + { + BURN_EXE_COMMAND_LINE_ARGUMENT* commandLineArgument = &pPackage->Bundle.rgCommandLineArguments[i]; + BOOL fCondition = FALSE; + + hr = ConditionEvaluate(pVariables, commandLineArgument->sczCondition, &fCondition); + ExitOnFailure(hr, "Failed to evaluate bundle package command-line condition."); + + if (fCondition) + { + if (sczArguments) + { + hr = StrAllocConcat(&sczArguments, L" ", 0); + ExitOnFailure(hr, "Failed to separate command-line arguments."); + } + + switch (action) + { + case BOOTSTRAPPER_ACTION_STATE_INSTALL: + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0); + ExitOnFailure(hr, "Failed to get command-line argument for install."); + break; + + case BOOTSTRAPPER_ACTION_STATE_UNINSTALL: + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0); + ExitOnFailure(hr, "Failed to get command-line argument for uninstall."); + break; + + case BOOTSTRAPPER_ACTION_STATE_REPAIR: + hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0); + ExitOnFailure(hr, "Failed to get command-line argument for repair."); + break; + + default: + hr = E_INVALIDARG; + ExitOnFailure(hr, "Invalid Bundle package action: %d.", action); + } + } + } + + // build command + AppAppendCommandLineArgument(&sczCommand, sczExecutablePath); + ExitOnFailure(hr, "Failed to create executable command."); + + if (!fRunEmbedded) + { + hr = StrAllocConcat(&sczCommand, L" -quiet", 0); + ExitOnFailure(hr, "Failed to append quiet argument."); + } + + if (wzOperationCommandLine) + { + hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine); + ExitOnFailure(hr, "Failed to append operation argument."); + } + + if (wzRelationTypeCommandLine) + { + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine); + ExitOnFailure(hr, "Failed to append relation type argument."); + } + + // Add the list of dependencies to ignore, if any, to the burn command line. + if (pExecuteAction->relatedBundle.sczIgnoreDependencies) + { + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies); + ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); + } + + // Add the list of ancestors, if any, to the burn command line. + if (pExecuteAction->relatedBundle.sczAncestors) + { + hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors); + ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); + } + + hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczCommand, NULL); + ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line."); + + hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL); + ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); + + // Always add user supplied arguments last. + if (sczArguments && *sczArguments) + { + hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); + ExitOnFailure(hr, "Failed to format argument string."); + + hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); + ExitOnFailure(hr, "Failed to format obfuscated argument string."); + + hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated); + ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments."); + + hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted); + ExitOnFailure(hr, "Failed to copy formatted arguments."); + } + + // Log before we add the secret pipe name and client token for embedded processes. + LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated); + + if (fRunEmbedded) + { + hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); + ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); + } + else // create and wait for the executable process while sending fake progress to allow cancel. + { + // Make the cache location of the executable the current directory to help those executables + // that expect stuff to be relative to them. + si.cb = sizeof(si); + if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, sczCachedDirectory, &si, &pi)) + { + ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath); + } + + do + { + message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; + message.dwUIHint = MB_OKCANCEL; + message.progress.dwPercentage = 50; + nResult = pfnGenericMessageHandler(&message, pvContext); + hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE); + ExitOnRootFailure(hr, "Bootstrapper application aborted during BUNDLE progress."); + + hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode); + if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr) + { + ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath); + } + } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); + } + + hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart); + ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); + +LExit: + StrSecureZeroFreeString(sczArguments); + StrSecureZeroFreeString(sczArgumentsFormatted); + ReleaseStr(sczArgumentsObfuscated); + ReleaseStr(sczCachedDirectory); + ReleaseStr(sczExecutablePath); + StrSecureZeroFreeString(sczCommand); + ReleaseStr(sczCommandObfuscated); + + ReleaseHandle(pi.hThread); + ReleaseHandle(pi.hProcess); + ReleaseFileHandle(hExecutableFile); + + // Best effort to clear the execute package cache folder and action variables. + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, NULL, TRUE, FALSE); + VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, NULL, TRUE, FALSE); + + return hr; +} diff --git a/src/burn/engine/bundlepackageengine.h b/src/burn/engine/bundlepackageengine.h new file mode 100644 index 00000000..0d59907d --- /dev/null +++ b/src/burn/engine/bundlepackageengine.h @@ -0,0 +1,38 @@ +#pragma once +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + + +#if defined(__cplusplus) +extern "C" { +#endif + + +// function declarations + +void BundlePackageEnginePackageUninitialize( + __in BURN_PACKAGE* pPackage + ); +HRESULT BundlePackageEnginePlanCalculatePackage( + __in BURN_PACKAGE* pPackage + ); +HRESULT BundlePackageEnginePlanAddRelatedBundle( + __in_opt DWORD *pdwInsertSequence, + __in BURN_RELATED_BUNDLE* pRelatedBundle, + __in BURN_PLAN* pPlan, + __in BURN_LOGGING* pLog, + __in BURN_VARIABLES* pVariables + ); +HRESULT BundlePackageEngineExecuteRelatedBundle( + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_CACHE* pCache, + __in BURN_VARIABLES* pVariables, + __in BOOL fRollback, + __in PFN_GENERICMESSAGEHANDLER pfnGenericExecuteProgress, + __in LPVOID pvContext, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ); + + +#if defined(__cplusplus) +} +#endif diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp index 30c64b01..8a181e7c 100644 --- a/src/burn/engine/core.cpp +++ b/src/burn/engine/core.cpp @@ -228,11 +228,11 @@ extern "C" HRESULT CoreInitializeConstants( { BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; - if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) // TODO: Don't assume exePackages with burn protocol are bundles. + if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type) { // Pass along any ancestors and ourself to prevent infinite loops. - pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; - pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory; + pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors; + pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory; } } @@ -518,7 +518,7 @@ extern "C" HRESULT CorePlan( ExitOnFailure(hr, "Failed to plan the layout of the bundle."); // Plan the packages' layout. - hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables); ExitOnFailure(hr, "Failed to plan packages."); } else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) @@ -527,7 +527,7 @@ extern "C" HRESULT CorePlan( pUpgradeBundlePackage = &pEngineState->update.package; - hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); + hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables); ExitOnFailure(hr, "Failed to plan update."); } else @@ -541,7 +541,7 @@ extern "C" HRESULT CorePlan( pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle; - hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); + hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables); ExitOnFailure(hr, "Failed to plan passthrough."); } else // doing an action that modifies the machine state. @@ -562,7 +562,7 @@ extern "C" HRESULT CorePlan( hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); ExitOnFailure(hr, "Failed to plan related bundles."); - hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType); + hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables); ExitOnFailure(hr, "Failed to plan packages."); // Schedule the update of related bundles last. diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp index 6c4a775f..355b4a34 100644 --- a/src/burn/engine/elevation.cpp +++ b/src/burn/engine/elevation.cpp @@ -19,6 +19,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD, BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, + BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, @@ -230,11 +231,18 @@ static HRESULT OnProcessDependentRegistration( __in BYTE* pbData, __in SIZE_T cbData ); +static HRESULT OnExecuteRelatedBundle( + __in HANDLE hPipe, + __in BURN_CACHE* pCache, + __in BURN_RELATED_BUNDLES* pRelatedBundles, + __in BURN_VARIABLES* pVariables, + __in BYTE* pbData, + __in SIZE_T cbData + ); static HRESULT OnExecuteExePackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, - __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData @@ -818,10 +826,10 @@ LExit: } /******************************************************************* - ElevationExecuteExePackage - + ElevationExecuteRelatedBundle - *******************************************************************/ -extern "C" HRESULT ElevationExecuteExePackage( +extern "C" HRESULT ElevationExecuteRelatedBundle( __in HANDLE hPipe, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_VARIABLES* pVariables, @@ -838,22 +846,22 @@ extern "C" HRESULT ElevationExecuteExePackage( DWORD dwResult = 0; // serialize message data - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId); + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.pRelatedBundle->package.sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); - hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action); + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, fRollback); ExitOnFailure(hr, "Failed to write rollback."); - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies); + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczIgnoreDependencies); ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer."); - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczAncestors); ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); - hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory); + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); @@ -863,6 +871,54 @@ extern "C" HRESULT ElevationExecuteExePackage( context.pfnGenericMessageHandler = pfnGenericMessageHandler; context.pvContext = pvContext; + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE message to per-machine process."); + + hr = ProcessResult(dwResult, pRestart); + +LExit: + ReleaseBuffer(pbData); + + return hr; +} + +/******************************************************************* + ElevationExecuteExePackage - + +*******************************************************************/ +extern "C" HRESULT ElevationExecuteExePackage( + __in HANDLE hPipe, + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_VARIABLES* pVariables, + __in BOOL fRollback, + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, + __in LPVOID pvContext, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ) +{ + HRESULT hr = S_OK; + BYTE* pbData = NULL; + SIZE_T cbData = 0; + BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { }; + DWORD dwResult = 0; + + // serialize message data + hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId); + ExitOnFailure(hr, "Failed to write package id to message buffer."); + + hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action); + ExitOnFailure(hr, "Failed to write action to message buffer."); + + hr = BuffWriteNumber(&pbData, &cbData, fRollback); + ExitOnFailure(hr, "Failed to write rollback."); + + hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); + ExitOnFailure(hr, "Failed to write variables."); + + // send message + context.pfnGenericMessageHandler = pfnGenericMessageHandler; + context.pvContext = pvContext; + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process."); @@ -1911,8 +1967,12 @@ static HRESULT ProcessElevatedChildMessage( hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); break; + case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE: + hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); + break; + case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: - hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); + hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE: @@ -2473,10 +2533,9 @@ LExit: return hr; } -static HRESULT OnExecuteExePackage( +static HRESULT OnExecuteRelatedBundle( __in HANDLE hPipe, __in BURN_CACHE* pCache, - __in BURN_PACKAGES* pPackages, __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, @@ -2491,15 +2550,15 @@ static HRESULT OnExecuteExePackage( LPWSTR sczIgnoreDependencies = NULL; LPWSTR sczAncestors = NULL; LPWSTR sczEngineWorkingDirectory = NULL; - BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; + BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; - executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; + executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); - ExitOnFailure(hr, "Failed to read EXE package id."); + ExitOnFailure(hr, "Failed to read related bundle id."); - hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action); + hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); @@ -2517,36 +2576,32 @@ static HRESULT OnExecuteExePackage( hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); - hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); - if (E_NOTFOUND == hr) - { - hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.exePackage.pPackage); - } - ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); + hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle); + ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage); // Pass the list of dependencies to ignore, if any, to the related bundle. if (sczIgnoreDependencies && *sczIgnoreDependencies) { - hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0); + hr = StrAllocString(&executeAction.relatedBundle.sczIgnoreDependencies, sczIgnoreDependencies, 0); ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); } // Pass the list of ancestors, if any, to the related bundle. if (sczAncestors && *sczAncestors) { - hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0); + hr = StrAllocString(&executeAction.relatedBundle.sczAncestors, sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) { - hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); + hr = StrAllocString(&executeAction.relatedBundle.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); ExitOnFailure(hr, "Failed to allocate the custom working directory."); } - // Execute EXE package. - hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); - ExitOnFailure(hr, "Failed to execute EXE package."); + // Execute related bundle. + hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart); + ExitOnFailure(hr, "Failed to execute related bundle."); LExit: ReleaseStr(sczEngineWorkingDirectory); @@ -2555,6 +2610,63 @@ LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); + if (SUCCEEDED(hr)) + { + if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart) + { + hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); + } + else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart) + { + hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED); + } + } + + return hr; +} + +static HRESULT OnExecuteExePackage( + __in HANDLE hPipe, + __in BURN_CACHE* pCache, + __in BURN_PACKAGES* pPackages, + __in BURN_VARIABLES* pVariables, + __in BYTE* pbData, + __in SIZE_T cbData + ) +{ + HRESULT hr = S_OK; + SIZE_T iData = 0; + LPWSTR sczPackage = NULL; + DWORD dwRollback = 0; + BURN_EXECUTE_ACTION executeAction = { }; + BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; + + executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; + + // Deserialize message data. + hr = BuffReadString(pbData, cbData, &iData, &sczPackage); + ExitOnFailure(hr, "Failed to read EXE package id."); + + hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action); + ExitOnFailure(hr, "Failed to read action."); + + hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); + ExitOnFailure(hr, "Failed to read rollback."); + + hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); + ExitOnFailure(hr, "Failed to read variables."); + + hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); + ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); + + // Execute EXE package. + hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); + ExitOnFailure(hr, "Failed to execute EXE package."); + +LExit: + ReleaseStr(sczPackage); + PlanUninitializeExecuteAction(&executeAction); + if (SUCCEEDED(hr)) { if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart) diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h index ad1141bb..0e63c687 100644 --- a/src/burn/engine/elevation.h +++ b/src/burn/engine/elevation.h @@ -80,6 +80,15 @@ HRESULT ElevationProcessDependentRegistration( __in HANDLE hPipe, __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction ); +HRESULT ElevationExecuteRelatedBundle( + __in HANDLE hPipe, + __in BURN_EXECUTE_ACTION* pExecuteAction, + __in BURN_VARIABLES* pVariables, + __in BOOL fRollback, + __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler, + __in LPVOID pvContext, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ); HRESULT ElevationExecuteExePackage( __in HANDLE hPipe, __in BURN_EXECUTE_ACTION* pExecuteAction, diff --git a/src/burn/engine/engine.vcxproj b/src/burn/engine/engine.vcxproj index 3d6ed181..5c4860f1 100644 --- a/src/burn/engine/engine.vcxproj +++ b/src/burn/engine/engine.vcxproj @@ -52,6 +52,7 @@ + @@ -101,6 +102,7 @@ + diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp index b728f599..45349ed0 100644 --- a/src/burn/engine/exeengine.cpp +++ b/src/burn/engine/exeengine.cpp @@ -3,23 +3,6 @@ #include "precomp.h" -// internal function declarations - -static HRESULT HandleExitCode( - __in BURN_PACKAGE* pPackage, - __in DWORD dwExitCode, - __out BOOTSTRAPPER_APPLY_RESTART* pRestart - ); -static HRESULT ParseCommandLineArgumentsFromXml( - __in IXMLDOMNode* pixnExePackage, - __in BURN_PACKAGE* pPackage - ); -static HRESULT ParseExitCodesFromXml( - __in IXMLDOMNode* pixnExePackage, - __in BURN_PACKAGE* pPackage - ); - - // function definitions extern "C" HRESULT ExeEngineParsePackageFromXml( @@ -82,10 +65,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml( ExitOnFailure(hr, "Failed to get @Protocol."); } - hr = ParseExitCodesFromXml(pixnExePackage, pPackage); + hr = ExeEngineParseExitCodesFromXml(pixnExePackage, &pPackage->Exe.rgExitCodes, &pPackage->Exe.cExitCodes); ExitOnFailure(hr, "Failed to parse exit codes."); - hr = ParseCommandLineArgumentsFromXml(pixnExePackage, pPackage); + hr = ExeEngineParseCommandLineArgumentsFromXml(pixnExePackage, &pPackage->Exe.rgCommandLineArguments, &pPackage->Exe.cCommandLineArguments); ExitOnFailure(hr, "Failed to parse command lines."); LExit: @@ -104,8 +87,6 @@ extern "C" void ExeEnginePackageUninitialize( ReleaseStr(pPackage->Exe.sczInstallArguments); ReleaseStr(pPackage->Exe.sczRepairArguments); ReleaseStr(pPackage->Exe.sczUninstallArguments); - ReleaseStr(pPackage->Exe.sczIgnoreDependencies); - //ReleaseStr(pPackage->Exe.sczProgressSwitch); ReleaseMem(pPackage->Exe.rgExitCodes); // free command-line arguments @@ -113,11 +94,7 @@ extern "C" void ExeEnginePackageUninitialize( { for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) { - BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i]; - ReleaseStr(pCommandLineArgument->sczInstallArgument); - ReleaseStr(pCommandLineArgument->sczUninstallArgument); - ReleaseStr(pCommandLineArgument->sczRepairArgument); - ReleaseStr(pCommandLineArgument->sczCondition); + ExeEngineCommandLineArgumentUninitialize(pPackage->Exe.rgCommandLineArguments + i); } MemFree(pPackage->Exe.rgCommandLineArguments); } @@ -126,6 +103,16 @@ extern "C" void ExeEnginePackageUninitialize( memset(&pPackage->Exe, 0, sizeof(pPackage->Exe)); } +extern "C" void ExeEngineCommandLineArgumentUninitialize( + __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument + ) +{ + ReleaseStr(pCommandLineArgument->sczInstallArgument); + ReleaseStr(pCommandLineArgument->sczUninstallArgument); + ReleaseStr(pCommandLineArgument->sczRepairArgument); + ReleaseStr(pCommandLineArgument->sczCondition); +} + extern "C" HRESULT ExeEngineDetectPackage( __in BURN_PACKAGE* pPackage, __in BURN_VARIABLES* pVariables @@ -264,7 +251,6 @@ LExit: // 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, @@ -274,46 +260,19 @@ extern "C" HRESULT ExeEnginePlanAddPackage( HRESULT hr = S_OK; BURN_EXECUTE_ACTION* pAction = NULL; - hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); + hr = DependencyPlanPackage(NULL, 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."); - } + 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.wzAncestors) - { - hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0); - ExitOnFailure(hr, "Failed to allocate the list of ancestors."); - } - - if (pPackage->Exe.wzEngineWorkingDirectory) - { - hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0); - ExitOnFailure(hr, "Failed to allocate the custom working directory."); - } - LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. } @@ -327,18 +286,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage( 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.wzAncestors) - { - hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0); - ExitOnFailure(hr, "Failed to allocate the list of ancestors."); - } - LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. } @@ -452,13 +399,13 @@ extern "C" HRESULT ExeEngineExecutePackage( hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); ExitOnFailure(hr, "Failed to format argument string."); - hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted); + hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted); ExitOnFailure(hr, "Failed to create executable command."); hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); ExitOnFailure(hr, "Failed to format obfuscated argument string."); - hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated); + hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated); } else { @@ -469,47 +416,15 @@ extern "C" HRESULT ExeEngineExecutePackage( } ExitOnFailure(hr, "Failed to create obfuscated executable command."); - if (pPackage->Exe.fSupportsAncestors) - { - // Add the list of dependencies to ignore, if any, to the burn command line. - if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) - { - hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); - ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line."); - - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies); - ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the obfuscated command line."); - } - - // Add the list of ancestors, if any, to the burn command line. - if (pExecuteAction->exePackage.sczAncestors) - { - hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); - ExitOnFailure(hr, "Failed to append the list of ancestors to the command line."); - - hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors); - ExitOnFailure(hr, "Failed to append the list of ancestors to the obfuscated command line."); - } - } - - if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) - { - hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, &sczCommandObfuscated); - ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line."); - - hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated); - ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF); - } - // Log before we add the secret pipe name and client token for embedded processes. LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); - if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) + if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) { hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); - ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath); + ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath); } - else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) + else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol) { hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); @@ -524,7 +439,7 @@ extern "C" HRESULT ExeEngineExecutePackage( ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath); } - if (pExecuteAction->exePackage.fFireAndForget) + if (pPackage->Exe.fFireAndForget) { ::WaitForInputIdle(pi.hProcess, 5000); ExitFunction(); @@ -547,7 +462,7 @@ extern "C" HRESULT ExeEngineExecutePackage( } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); } - hr = HandleExitCode(pPackage, dwExitCode, pRestart); + hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart); ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); LExit: @@ -595,12 +510,10 @@ LExit: return; } - -// internal helper functions - -static HRESULT ParseExitCodesFromXml( - __in IXMLDOMNode* pixnExePackage, - __in BURN_PACKAGE* pPackage +extern "C" HRESULT ExeEngineParseExitCodesFromXml( + __in IXMLDOMNode* pixnPackage, + __inout BURN_EXE_EXIT_CODE** prgExitCodes, + __inout DWORD* pcExitCodes ) { HRESULT hr = S_OK; @@ -610,7 +523,7 @@ static HRESULT ParseExitCodesFromXml( LPWSTR scz = NULL; // select exit code nodes - hr = XmlSelectNodes(pixnExePackage, L"ExitCode", &pixnNodes); + hr = XmlSelectNodes(pixnPackage, L"ExitCode", &pixnNodes); ExitOnFailure(hr, "Failed to select exit code nodes."); // get exit code node count @@ -620,15 +533,15 @@ static HRESULT ParseExitCodesFromXml( if (cNodes) { // allocate memory for exit codes - pPackage->Exe.rgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE); - ExitOnNull(pPackage->Exe.rgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs."); + *prgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE); + ExitOnNull(*prgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs."); - pPackage->Exe.cExitCodes = cNodes; + *pcExitCodes = cNodes; // parse package elements for (DWORD i = 0; i < cNodes; ++i) { - BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i]; + BURN_EXE_EXIT_CODE* pExitCode = *prgExitCodes + i; hr = XmlNextElement(pixnNodes, &pixnNode, NULL); ExitOnFailure(hr, "Failed to get next node."); @@ -666,9 +579,10 @@ LExit: return hr; } -static HRESULT ParseCommandLineArgumentsFromXml( - __in IXMLDOMNode* pixnExePackage, - __in BURN_PACKAGE* pPackage +extern "C" HRESULT ExeEngineParseCommandLineArgumentsFromXml( + __in IXMLDOMNode* pixnPackage, + __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments, + __inout DWORD* pcCommandLineArguments ) { HRESULT hr = S_OK; @@ -678,7 +592,7 @@ static HRESULT ParseCommandLineArgumentsFromXml( LPWSTR scz = NULL; // Select command-line argument nodes. - hr = XmlSelectNodes(pixnExePackage, L"CommandLine", &pixnNodes); + hr = XmlSelectNodes(pixnPackage, L"CommandLine", &pixnNodes); ExitOnFailure(hr, "Failed to select command-line argument nodes."); // Get command-line argument node count. @@ -687,15 +601,15 @@ static HRESULT ParseCommandLineArgumentsFromXml( if (cNodes) { - pPackage->Exe.rgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE); - ExitOnNull(pPackage->Exe.rgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs."); + *prgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE); + ExitOnNull(*prgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs."); - pPackage->Exe.cCommandLineArguments = cNodes; + *pcCommandLineArguments = cNodes; // Parse command-line argument elements. for (DWORD i = 0; i < cNodes; ++i) { - BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i]; + BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = *prgCommandLineArguments + i; hr = XmlNextElement(pixnNodes, &pixnNode, NULL); ExitOnFailure(hr, "Failed to get next command-line argument node."); @@ -731,8 +645,9 @@ LExit: return hr; } -static HRESULT HandleExitCode( - __in BURN_PACKAGE* pPackage, +extern "C" HRESULT ExeEngineHandleExitCode( + __in BURN_EXE_EXIT_CODE* rgCustomExitCodes, + __in DWORD cCustomExitCodes, __in DWORD dwExitCode, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) @@ -740,9 +655,9 @@ static HRESULT HandleExitCode( HRESULT hr = S_OK; BURN_EXE_EXIT_CODE_TYPE typeCode = BURN_EXE_EXIT_CODE_TYPE_NONE; - for (DWORD i = 0; i < pPackage->Exe.cExitCodes; ++i) + for (DWORD i = 0; i < cCustomExitCodes; ++i) { - BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i]; + BURN_EXE_EXIT_CODE* pExitCode = rgCustomExitCodes + i; // If this is a wildcard, use the last one we come across. if (pExitCode->fWildcard) diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h index 877968cd..bd5d7ea9 100644 --- a/src/burn/engine/exeengine.h +++ b/src/burn/engine/exeengine.h @@ -16,6 +16,9 @@ HRESULT ExeEngineParsePackageFromXml( void ExeEnginePackageUninitialize( __in BURN_PACKAGE* pPackage ); +void ExeEngineCommandLineArgumentUninitialize( + __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument + ); HRESULT ExeEngineDetectPackage( __in BURN_PACKAGE* pPackage, __in BURN_VARIABLES* pVariables @@ -24,7 +27,6 @@ HRESULT ExeEnginePlanCalculatePackage( __in BURN_PACKAGE* pPackage ); HRESULT ExeEnginePlanAddPackage( - __in_opt DWORD *pdwInsertSequence, __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, @@ -43,6 +45,22 @@ void ExeEngineUpdateInstallRegistrationState( __in BURN_EXECUTE_ACTION* pAction, __in HRESULT hrExecute ); +HRESULT ExeEngineParseExitCodesFromXml( + __in IXMLDOMNode* pixnPackage, + __inout BURN_EXE_EXIT_CODE** prgExitCodes, + __inout DWORD* pcExitCodes + ); +HRESULT ExeEngineParseCommandLineArgumentsFromXml( + __in IXMLDOMNode* pixnPackage, + __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments, + __inout DWORD* pcCommandLineArguments + ); +HRESULT ExeEngineHandleExitCode( + __in BURN_EXE_EXIT_CODE* rgCustomExitCodes, + __in DWORD cCustomExitCodes, + __in DWORD dwExitCode, + __out BOOTSTRAPPER_APPLY_RESTART* pRestart + ); #if defined(__cplusplus) diff --git a/src/burn/engine/package.cpp b/src/burn/engine/package.cpp index bea48cb5..d9087f79 100644 --- a/src/burn/engine/package.cpp +++ b/src/burn/engine/package.cpp @@ -350,6 +350,9 @@ extern "C" void PackageUninitialize( switch (pPackage->type) { + case BURN_PACKAGE_TYPE_BUNDLE: + BundlePackageEnginePackageUninitialize(pPackage); + break; case BURN_PACKAGE_TYPE_EXE: ExeEnginePackageUninitialize(pPackage); // TODO: Modularization break; @@ -439,22 +442,11 @@ extern "C" HRESULT PackageFindRelatedById( ) { HRESULT hr = S_OK; - BURN_PACKAGE* pPackage = NULL; - - for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) - { - pPackage = &pRelatedBundles->rgRelatedBundles[i].package; - - if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1)) - { - *ppPackage = pPackage; - ExitFunction1(hr = S_OK); - } - } + BURN_RELATED_BUNDLE* pRelatedBundle = NULL; + + hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle); + *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package; - hr = E_NOTFOUND; - -LExit: return hr; } diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h index f2a1c304..10b5f33c 100644 --- a/src/burn/engine/package.h +++ b/src/burn/engine/package.h @@ -35,6 +35,7 @@ enum BURN_EXE_PROTOCOL_TYPE enum BURN_PACKAGE_TYPE { BURN_PACKAGE_TYPE_NONE, + BURN_PACKAGE_TYPE_BUNDLE, BURN_PACKAGE_TYPE_EXE, BURN_PACKAGE_TYPE_MSI, BURN_PACKAGE_TYPE_MSP, @@ -263,21 +264,36 @@ typedef struct _BURN_PACKAGE { struct { - LPWSTR sczDetectCondition; LPWSTR sczInstallArguments; LPWSTR sczRepairArguments; LPWSTR sczUninstallArguments; + LPWSTR sczIgnoreDependencies; LPCWSTR wzAncestors; // points directly into engine state. LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. BOOL fPseudoBundle; + BOOL fRepairable; + BOOL fSupportsBurnProtocol; + BURN_EXE_EXIT_CODE* rgExitCodes; + DWORD cExitCodes; + + BURN_EXE_COMMAND_LINE_ARGUMENT* rgCommandLineArguments; + DWORD cCommandLineArguments; + } Bundle; + struct + { + LPWSTR sczDetectCondition; + LPWSTR sczInstallArguments; + LPWSTR sczRepairArguments; + LPWSTR sczUninstallArguments; + + BOOL fPseudoBundle; + BOOL fFireAndForget; BOOL fRepairable; BURN_EXE_PROTOCOL_TYPE protocol; - BOOL fSupportsAncestors; - BURN_EXE_EXIT_CODE* rgExitCodes; DWORD cExitCodes; diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp index 0f63a945..e0e9a82b 100644 --- a/src/burn/engine/plan.cpp +++ b/src/burn/engine/plan.cpp @@ -36,16 +36,13 @@ static HRESULT PlanPackagesHelper( __in BURN_USER_EXPERIENCE* pUX, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ); static HRESULT InitializePackage( __in BURN_PLAN* pPlan, __in BURN_USER_EXPERIENCE* pUX, __in BURN_VARIABLES* pVariables, - __in BURN_PACKAGE* pPackage, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_PACKAGE* pPackage ); static HRESULT ProcessPackage( __in BOOL fBundlePerMachine, @@ -54,7 +51,6 @@ static HRESULT ProcessPackage( __in BURN_PACKAGE* pPackage, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary ); static HRESULT ProcessPackageRollbackBoundary( @@ -266,10 +262,10 @@ extern "C" void PlanUninitializeExecuteAction( { switch (pExecuteAction->type) { - case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: - ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies); - ReleaseStr(pExecuteAction->exePackage.sczAncestors); - ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory); + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + ReleaseStr(pExecuteAction->relatedBundle.sczIgnoreDependencies); + ReleaseStr(pExecuteAction->relatedBundle.sczAncestors); + ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory); break; case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: @@ -500,14 +496,12 @@ extern "C" HRESULT PlanPackages( __in BURN_PACKAGES* pPackages, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ) { HRESULT hr = S_OK; - hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables, display, relationType); + hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables); return hr; } @@ -712,15 +706,13 @@ extern "C" HRESULT PlanPassThroughBundle( __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ) { HRESULT hr = S_OK; // Plan passthrough package. - hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType); + hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables); ExitOnFailure(hr, "Failed to process passthrough package."); LExit: @@ -732,15 +724,17 @@ extern "C" HRESULT PlanUpdateBundle( __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ) { HRESULT hr = S_OK; + Assert(!pPackage->fPerMachine); + Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type); + pPackage->Exe.fFireAndForget = BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action; + // Plan update package. - hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType); + hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables); ExitOnFailure(hr, "Failed to process update package."); LExit: @@ -753,9 +747,7 @@ static HRESULT PlanPackagesHelper( __in BURN_USER_EXPERIENCE* pUX, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ) { HRESULT hr = S_OK; @@ -768,7 +760,7 @@ static HRESULT PlanPackagesHelper( DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; BURN_PACKAGE* pPackage = rgPackages + iPackage; - hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType); + hr = InitializePackage(pPlan, pUX, pVariables, pPackage); ExitOnFailure(hr, "Failed to initialize package."); } @@ -791,7 +783,7 @@ static HRESULT PlanPackagesHelper( DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; BURN_PACKAGE* pPackage = rgPackages + iPackage; - hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &pRollbackBoundary); + hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary); ExitOnFailure(hr, "Failed to process package."); } @@ -841,14 +833,24 @@ static HRESULT InitializePackage( __in BURN_PLAN* pPlan, __in BURN_USER_EXPERIENCE* pUX, __in BURN_VARIABLES* pVariables, - __in BURN_PACKAGE* pPackage, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_PACKAGE* pPackage ) { HRESULT hr = S_OK; BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition = BOOTSTRAPPER_PACKAGE_CONDITION_DEFAULT; BOOL fInstallCondition = FALSE; BOOL fBeginCalled = FALSE; + BOOTSTRAPPER_RELATION_TYPE relationType = pPlan->pCommand->relationType; + + if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fPseudoBundle) + { + // Exe pseudo bundles are not configurable. + // The BA already requested this package to be executed + // * by the overall plan action for UpdateReplace + // * by enabling the forward compatible bundle for Passthrough + pPackage->defaultRequested = pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_PRESENT; + ExitFunction(); + } if (pPackage->fCanAffectRegistration) { @@ -896,7 +898,6 @@ static HRESULT ProcessPackage( __in BURN_PACKAGE* pPackage, __in BURN_LOGGING* pLog, __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary ) { @@ -920,7 +921,7 @@ static HRESULT ProcessPackage( if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) { // If the package is in a requested state, plan it. - hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables); + hr = PlanExecutePackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables); ExitOnFailure(hr, "Failed to plan execute package."); } else @@ -1064,7 +1065,6 @@ LExit: extern "C" HRESULT PlanExecutePackage( __in BOOL fPerMachine, - __in BOOTSTRAPPER_DISPLAY display, __in BURN_USER_EXPERIENCE* pUserExperience, __in BURN_PLAN* pPlan, __in BURN_PACKAGE* pPackage, @@ -1073,6 +1073,7 @@ extern "C" HRESULT PlanExecutePackage( ) { HRESULT hr = S_OK; + BOOTSTRAPPER_DISPLAY display = pPlan->pCommand->display; BOOL fRequestedCache = BOOTSTRAPPER_CACHE_TYPE_REMOVE < pPackage->cacheType && (BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested || ForceCache(pPlan, pPackage)); hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary); @@ -1124,7 +1125,7 @@ extern "C" HRESULT PlanExecutePackage( switch (pPackage->type) { case BURN_PACKAGE_TYPE_EXE: - hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables); + hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables); break; case BURN_PACKAGE_TYPE_MSI: @@ -1288,8 +1289,8 @@ extern "C" HRESULT PlanRelatedBundlesBegin( } // Pass along any ancestors and ourself to prevent infinite loops. - pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; - pRelatedBundle->package.Exe.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory; + pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors; + pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory; hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested); ExitOnFailure(hr, "Failed to get default request state for related bundle."); @@ -1349,37 +1350,38 @@ extern "C" HRESULT PlanRelatedBundlesComplete( for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) { - if (BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE == pPlan->rgExecuteActions[i].type && BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action) + switch (pPlan->rgExecuteActions[i].type) { - fExecutingAnyPackage = TRUE; - - BURN_PACKAGE* pPackage = pPlan->rgExecuteActions[i].packageProvider.pPackage; - if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action) { - if (0 < pPackage->cDependencyProviders) + fExecutingAnyPackage = TRUE; + + BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package; + if (pPackage->cDependencyProviders) { // Bundles only support a single provider key. const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders; DictAddKey(sdProviderKeys, pProvider->sczKey); } } - } - else - { - switch (pPlan->rgExecuteActions[i].type) - { - case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action); - break; + break; - case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action); - break; + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action); + break; - case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: - fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action); - break; - } + case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action); + break; + + case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action); + break; + + case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: + fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action); + break; } } @@ -1422,7 +1424,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete( if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) { // Addon and patch bundles will be passed a list of dependencies to ignore for planning. - hr = StrAllocString(&pRelatedBundle->package.Exe.sczIgnoreDependencies, sczIgnoreDependencies, 0); + hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0); ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore."); // Uninstall addons and patches early in the chain, before other packages are uninstalled. @@ -1434,8 +1436,8 @@ extern "C" HRESULT PlanRelatedBundlesComplete( if (BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) { - hr = ExeEnginePlanCalculatePackage(&pRelatedBundle->package); - ExitOnFailure(hr, "Failed to calcuate plan for related bundle: %ls", pRelatedBundle->package.sczId); + hr = BundlePackageEnginePlanCalculatePackage(&pRelatedBundle->package); + ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId); // Calculate package states based on reference count for addon and patch related bundles. if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) @@ -1450,7 +1452,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete( } } - hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables); + hr = BundlePackageEnginePlanAddRelatedBundle(pdwInsertIndex, pRelatedBundle, pPlan, pLog, pVariables); ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId); // Calculate package states based on reference count for addon and patch related bundles. @@ -2603,8 +2605,12 @@ static void ExecuteActionLog( LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE_DEPENDENCY package id: %ls, bundle provider key: %ls, action: %hs", wzBase, iAction, pAction->packageDependency.pPackage->sczId, pAction->packageDependency.sczBundleProviderKey, LoggingDependencyActionToString(pAction->packageDependency.action)); break; + case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE: + LogStringLine(PlanDumpLevel, "%ls action[%u]: RELATED_BUNDLE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->relatedBundle.pRelatedBundle->package.sczId, LoggingActionStateToString(pAction->relatedBundle.action), pAction->relatedBundle.sczIgnoreDependencies); + break; + case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: - LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action), pAction->exePackage.sczIgnoreDependencies); + LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action)); break; case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h index f0560e6e..6be19a10 100644 --- a/src/burn/engine/plan.h +++ b/src/burn/engine/plan.h @@ -50,6 +50,7 @@ enum BURN_EXECUTE_ACTION_TYPE BURN_EXECUTE_ACTION_TYPE_CHECKPOINT, BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE, BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE, + BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, BURN_EXECUTE_ACTION_TYPE_MSP_TARGET, @@ -160,12 +161,16 @@ typedef struct _BURN_EXECUTE_ACTION } uncachePackage; struct { - BURN_PACKAGE* pPackage; - BOOL fFireAndForget; + BURN_RELATED_BUNDLE* pRelatedBundle; BOOTSTRAPPER_ACTION_STATE action; LPWSTR sczIgnoreDependencies; LPWSTR sczAncestors; LPWSTR sczEngineWorkingDirectory; + } relatedBundle; + struct + { + BURN_PACKAGE* pPackage; + BOOTSTRAPPER_ACTION_STATE action; } exePackage; struct { @@ -339,9 +344,7 @@ HRESULT PlanPackages( __in BURN_PACKAGES* pPackages, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ); HRESULT PlanRegistration( __in BURN_PLAN* pPlan, @@ -356,18 +359,14 @@ HRESULT PlanPassThroughBundle( __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ); HRESULT PlanUpdateBundle( __in BURN_USER_EXPERIENCE* pUX, __in BURN_PACKAGE* pPackage, __in BURN_PLAN* pPlan, __in BURN_LOGGING* pLog, - __in BURN_VARIABLES* pVariables, - __in BOOTSTRAPPER_DISPLAY display, - __in BOOTSTRAPPER_RELATION_TYPE relationType + __in BURN_VARIABLES* pVariables ); HRESULT PlanLayoutContainer( __in BURN_PLAN* pPlan, @@ -379,7 +378,6 @@ HRESULT PlanLayoutPackage( ); HRESULT PlanExecutePackage( __in BOOL fPerMachine, - __in BOOTSTRAPPER_DISPLAY display, __in BURN_USER_EXPERIENCE* pUserExperience, __in BURN_PLAN* pPlan, __in BURN_PACKAGE* pPackage, diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h index 3b4d989b..26adf44c 100644 --- a/src/burn/engine/precomp.h +++ b/src/burn/engine/precomp.h @@ -86,6 +86,7 @@ #include "dependency.h" #include "core.h" #include "apply.h" +#include "bundlepackageengine.h" #include "exeengine.h" #include "msiengine.h" #include "mspengine.h" diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp index 14dd2b77..7b670035 100644 --- a/src/burn/engine/pseudobundle.cpp +++ b/src/burn/engine/pseudobundle.cpp @@ -3,36 +3,24 @@ #include "precomp.h" -extern "C" HRESULT PseudoBundleInitialize( +extern "C" HRESULT PseudoBundleInitializeRelated( __in BURN_PACKAGE* pPackage, __in BOOL fSupportsBurnProtocol, __in BOOL fPerMachine, __in_z LPCWSTR wzId, +#ifdef DEBUG __in BOOTSTRAPPER_RELATION_TYPE relationType, - __in BOOTSTRAPPER_PACKAGE_STATE state, +#endif __in BOOL fCached, __in_z LPCWSTR wzFilePath, - __in_z LPCWSTR wzLocalSource, - __in_z_opt LPCWSTR wzDownloadSource, __in DWORD64 qwSize, - __in BOOL fVital, - __in_z_opt LPCWSTR wzInstallArguments, - __in_z_opt LPCWSTR wzRepairArguments, - __in_z_opt LPCWSTR wzUninstallArguments, - __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider, - __in_opt const BYTE* pbHash, - __in const DWORD cbHash + __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider ) { HRESULT hr = S_OK; - LPWSTR sczRelationTypeCommandLineSwitch = NULL; BURN_PAYLOAD* pPayload = NULL; - LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); - if (wzRelationTypeCommandLine) - { - hr = StrAllocFormatted(&sczRelationTypeCommandLineSwitch, L" -%ls", wzRelationTypeCommandLine); - } + AssertSz(BOOTSTRAPPER_RELATION_UPDATE != relationType, "Update pseudo bundles must use PseudoBundleInitializeUpdateBundle instead."); // Initialize the single payload, and fill out all the necessary fields pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE); @@ -51,41 +39,21 @@ extern "C" HRESULT PseudoBundleInitialize( hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0); ExitOnFailure(hr, "Failed to copy filename for pseudo bundle."); - hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0); + hr = StrAllocString(&pPayload->sczSourcePath, wzFilePath, 0); ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle."); - if (wzDownloadSource && *wzDownloadSource) - { - hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0); - ExitOnFailure(hr, "Failed to copy download source for pseudo bundle."); - } - - if (pbHash) - { - pPayload->pbHash = static_cast(MemAlloc(cbHash, FALSE)); - ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash."); - - pPayload->cbHash = cbHash; - memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash); - } - - if (BOOTSTRAPPER_RELATION_UPDATE == relationType) - { - pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE; - } - - pPackage->Exe.fPseudoBundle = TRUE; - - pPackage->type = BURN_PACKAGE_TYPE_EXE; + pPackage->type = BURN_PACKAGE_TYPE_BUNDLE; pPackage->fPerMachine = fPerMachine; - pPackage->currentState = state; + pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT; pPackage->fCached = fCached; pPackage->qwInstallSize = qwSize; pPackage->qwSize = qwSize; - pPackage->fVital = fVital; + pPackage->fVital = FALSE; - pPackage->Exe.protocol = fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; - pPackage->Exe.fSupportsAncestors = TRUE; + pPackage->fUninstallable = TRUE; + pPackage->Bundle.fPseudoBundle = TRUE; + pPackage->Bundle.fRepairable = TRUE; + pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol; hr = StrAllocString(&pPackage->sczId, wzId, 0); ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); @@ -93,47 +61,6 @@ extern "C" HRESULT PseudoBundleInitialize( hr = StrAllocString(&pPackage->sczCacheId, wzId, 0); ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle."); - // If we are a self updating bundle, we don't have to have Install arguments. - if (wzInstallArguments) - { - hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0); - ExitOnFailure(hr, "Failed to copy install arguments for related bundle package"); - } - - if (sczRelationTypeCommandLineSwitch) - { - hr = StrAllocConcat(&pPackage->Exe.sczInstallArguments, sczRelationTypeCommandLineSwitch, 0); - ExitOnFailure(hr, "Failed to append relation type to install arguments for related bundle package"); - } - - if (wzRepairArguments) - { - hr = StrAllocString(&pPackage->Exe.sczRepairArguments, wzRepairArguments, 0); - ExitOnFailure(hr, "Failed to copy repair arguments for related bundle package"); - - if (sczRelationTypeCommandLineSwitch) - { - hr = StrAllocConcat(&pPackage->Exe.sczRepairArguments, sczRelationTypeCommandLineSwitch, 0); - ExitOnFailure(hr, "Failed to append relation type to repair arguments for related bundle package"); - } - - pPackage->Exe.fRepairable = TRUE; - } - - if (wzUninstallArguments) - { - hr = StrAllocString(&pPackage->Exe.sczUninstallArguments, wzUninstallArguments, 0); - ExitOnFailure(hr, "Failed to copy uninstall arguments for related bundle package"); - - if (sczRelationTypeCommandLineSwitch) - { - hr = StrAllocConcat(&pPackage->Exe.sczUninstallArguments, sczRelationTypeCommandLineSwitch, 0); - ExitOnFailure(hr, "Failed to append relation type to uninstall arguments for related bundle package"); - } - - pPackage->fUninstallable = TRUE; - } - if (pDependencyProvider) { pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE); @@ -153,8 +80,6 @@ extern "C" HRESULT PseudoBundleInitialize( } LExit: - ReleaseStr(sczRelationTypeCommandLineSwitch); - return hr; } @@ -165,7 +90,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough( __in BURN_PACKAGE* pPackage ) { - Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type); + Assert(BURN_PACKAGE_TYPE_BUNDLE == pPackage->type); HRESULT hr = S_OK; LPWSTR sczArguments = NULL; @@ -180,59 +105,29 @@ extern "C" HRESULT PseudoBundleInitializePassthrough( pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload; } - pPassthroughPackage->Exe.fPseudoBundle = TRUE; - pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user. - pPassthroughPackage->type = pPackage->type; + pPassthroughPackage->type = BURN_PACKAGE_TYPE_EXE; pPassthroughPackage->currentState = pPackage->currentState; pPassthroughPackage->fCached = pPackage->fCached; pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize; pPassthroughPackage->qwSize = pPackage->qwSize; pPassthroughPackage->fVital = pPackage->fVital; + pPassthroughPackage->Exe.fPseudoBundle = TRUE; + pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; + hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0); ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle."); hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0); ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle."); - pPassthroughPackage->Exe.protocol = pPackage->Exe.protocol; - hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand); ExitOnFailure(hr, "Failed to create command-line arguments."); hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0); ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package"); - hr = StrAllocString(&pPassthroughPackage->Exe.sczRepairArguments, sczArguments, 0); - ExitOnFailure(hr, "Failed to copy related arguments for passthrough bundle package"); - - pPassthroughPackage->Exe.fRepairable = TRUE; - - hr = StrAllocString(&pPassthroughPackage->Exe.sczUninstallArguments, sczArguments, 0); - ExitOnFailure(hr, "Failed to copy uninstall arguments for passthrough bundle package"); - - pPassthroughPackage->fUninstallable = TRUE; - - // TODO: consider bringing this back in the near future. - //if (pDependencyProvider) - //{ - // pPassthroughPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE); - // ExitOnNull(pPassthroughPackage->rgDependencyProviders, hr, E_OUTOFMEMORY, "Failed to allocate memory for dependency providers."); - // pPassthroughPackage->cDependencyProviders = 1; - - // pPassthroughPackage->rgDependencyProviders[0].fImported = pDependencyProvider->fImported; - - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczKey, pDependencyProvider->sczKey, 0); - // ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); - - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczVersion, pDependencyProvider->sczVersion, 0); - // ExitOnFailure(hr, "Failed to copy version for pseudo bundle."); - - // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczDisplayName, pDependencyProvider->sczDisplayName, 0); - // ExitOnFailure(hr, "Failed to copy display name for pseudo bundle."); - //} - LExit: ReleaseStr(sczArguments); return hr; @@ -290,14 +185,16 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle( memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash); } - pPackage->Exe.fPseudoBundle = TRUE; - pPackage->type = BURN_PACKAGE_TYPE_EXE; pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; pPackage->qwInstallSize = qwSize; pPackage->qwSize = qwSize; pPackage->fVital = TRUE; + // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate. + pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; + pPackage->Exe.fPseudoBundle = TRUE; + hr = StrAllocString(&pPackage->sczId, wzId, 0); ExitOnFailure(hr, "Failed to copy id for update bundle."); @@ -307,10 +204,6 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle( hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0); ExitOnFailure(hr, "Failed to copy install arguments for update bundle package"); - // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate. - pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; - pPackage->Exe.fSupportsAncestors = TRUE; - LExit: return hr; -} \ No newline at end of file +} diff --git a/src/burn/engine/pseudobundle.h b/src/burn/engine/pseudobundle.h index 22132c5e..78a681df 100644 --- a/src/burn/engine/pseudobundle.h +++ b/src/burn/engine/pseudobundle.h @@ -6,25 +6,18 @@ extern "C" { #endif -HRESULT PseudoBundleInitialize( +HRESULT PseudoBundleInitializeRelated( __in BURN_PACKAGE* pPackage, __in BOOL fSupportsBurnProtocol, __in BOOL fPerMachine, __in_z LPCWSTR wzId, +#ifdef DEBUG __in BOOTSTRAPPER_RELATION_TYPE relationType, - __in BOOTSTRAPPER_PACKAGE_STATE state, +#endif __in BOOL fCached, __in_z LPCWSTR wzFilePath, - __in_z LPCWSTR wzLocalSource, - __in_z_opt LPCWSTR wzDownloadSource, __in DWORD64 qwSize, - __in BOOL fVital, - __in_z_opt LPCWSTR wzInstallArguments, - __in_z_opt LPCWSTR wzRepairArguments, - __in_z_opt LPCWSTR wzUninstallArguments, - __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider, - __in_opt const BYTE* pbHash, - __in const DWORD cbHash + __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider ); HRESULT PseudoBundleInitializePassthrough( __in BURN_PACKAGE* pPassthroughPackage, diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp index 4a694ef6..e2380aab 100644 --- a/src/burn/engine/relatedbundle.cpp +++ b/src/burn/engine/relatedbundle.cpp @@ -98,6 +98,37 @@ extern "C" void RelatedBundlesUninitialize( } +extern "C" HRESULT RelatedBundleFindById( + __in BURN_RELATED_BUNDLES* pRelatedBundles, + __in_z LPCWSTR wzId, + __out BURN_RELATED_BUNDLE** ppRelatedBundle + ) +{ + HRESULT hr = S_OK; + BURN_RELATED_BUNDLE* pRelatedBundle = NULL; + BURN_PACKAGE* pPackage = NULL; + + *ppRelatedBundle = NULL; + + for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) + { + pRelatedBundle = pRelatedBundles->rgRelatedBundles + i; + pPackage = &pRelatedBundle->package; + + if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1)) + { + *ppRelatedBundle = pRelatedBundle; + ExitFunction1(hr = S_OK); + } + } + + hr = E_NOTFOUND; + +LExit: + return hr; +} + + // internal helper functions static HRESULT LoadIfRelatedBundle( @@ -410,6 +441,7 @@ static HRESULT LoadRelatedBundleFromKey( BOOL fCached = FALSE; DWORD64 qwFileSize = 0; BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; + BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL; // Only support progress from engines that are compatible. hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion); @@ -458,6 +490,11 @@ static HRESULT LoadRelatedBundleFromKey( if (E_FILENOTFOUND != hr) { ExitOnFailure(hr, "Failed to read provider key from registry for bundle: %ls", wzRelatedBundleId); + } + + if (dependencyProvider.sczKey && *dependencyProvider.sczKey) + { + pBundleDependencyProvider = &dependencyProvider; dependencyProvider.fImported = TRUE; @@ -480,11 +517,11 @@ static HRESULT LoadRelatedBundleFromKey( pRelatedBundle->relationType = relationType; - hr = PseudoBundleInitialize(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, - BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, - L"-quiet", L"-repair -quiet", L"-uninstall -quiet", - (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, - NULL, 0); + hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, +#ifdef DEBUG + pRelatedBundle->relationType, +#endif + fCached, sczCachePath, qwFileSize, pBundleDependencyProvider); ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId); LExit: diff --git a/src/burn/engine/relatedbundle.h b/src/burn/engine/relatedbundle.h index 01691c25..0113c8ee 100644 --- a/src/burn/engine/relatedbundle.h +++ b/src/burn/engine/relatedbundle.h @@ -14,6 +14,11 @@ HRESULT RelatedBundlesInitializeForScope( void RelatedBundlesUninitialize( __in BURN_RELATED_BUNDLES* pRelatedBundles ); +HRESULT RelatedBundleFindById( + __in BURN_RELATED_BUNDLES* pRelatedBundles, + __in_z LPCWSTR wzId, + __out BURN_RELATED_BUNDLE** ppRelatedBundle + ); #if defined(__cplusplus) } diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp index 35ddb22f..7e704c23 100644 --- a/src/burn/test/BurnUnitTest/PlanTest.cpp +++ b/src/burn/test/BurnUnitTest/PlanTest.cpp @@ -117,7 +117,7 @@ namespace Bootstrapper ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); Assert::Equal(dwIndex, pPlan->cExecuteActions); fRollback = TRUE; @@ -155,7 +155,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); Assert::Equal(dwIndex, pPlan->cRollbackActions); Assert::Equal(4ul, pPlan->cExecutePackagesTotal); @@ -496,7 +496,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL); Assert::Equal(dwIndex, pPlan->cExecuteActions); fRollback = TRUE; @@ -514,7 +514,7 @@ namespace Bootstrapper ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); - ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); + ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL); Assert::Equal(dwIndex, pPlan->cRollbackActions); Assert::Equal(2ul, pPlan->cExecutePackagesTotal); @@ -1154,7 +1154,11 @@ namespace Bootstrapper pRelatedBundle->fPlannable = TRUE; pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; - hr = PseudoBundleInitialize(&pRelatedBundle->package, TRUE, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, wzFilePath, wzFilePath, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0); + hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId, +#ifdef DEBUG + pRelatedBundle->relationType, +#endif + TRUE, wzFilePath, 0, &dependencyProvider); NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); ++pRelatedBundles->cRelatedBundles; @@ -1310,7 +1314,7 @@ namespace Bootstrapper Assert::Equal(FALSE, pAction->fDeleted); } - void ValidateExecuteExePackage( + void ValidateExecuteRelatedBundle( __in BURN_PLAN* pPlan, __in BOOL fRollback, __in DWORD dwIndex, @@ -1318,12 +1322,27 @@ namespace Bootstrapper __in BOOTSTRAPPER_ACTION_STATE action, __in LPCWSTR wzIgnoreDependencies ) + { + BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); + Assert::Equal(BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, pAction->type); + NativeAssert::StringEqual(wzPackageId, pAction->relatedBundle.pRelatedBundle->package.sczId); + Assert::Equal(action, pAction->relatedBundle.action); + NativeAssert::StringEqual(wzIgnoreDependencies, pAction->relatedBundle.sczIgnoreDependencies); + Assert::Equal(FALSE, pAction->fDeleted); + } + + void ValidateExecuteExePackage( + __in BURN_PLAN* pPlan, + __in BOOL fRollback, + __in DWORD dwIndex, + __in LPCWSTR wzPackageId, + __in BOOTSTRAPPER_ACTION_STATE action + ) { BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); Assert::Equal(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type); NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId); Assert::Equal(action, pAction->exePackage.action); - NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies); Assert::Equal(FALSE, pAction->fDeleted); } -- cgit v1.2.3-55-g6feb