// 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" const DWORD BURN_TIMEOUT = 5 * 60 * 1000; // TODO: is 5 minutes good? typedef enum _BURN_ELEVATION_MESSAGE_TYPE { BURN_ELEVATION_MESSAGE_TYPE_UNKNOWN, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE, BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE, BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN, BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE, BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD, 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_BUNDLE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_EMBEDDED_CHILD, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_BEGIN, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE, BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN, BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE, BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS, BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_FAILURE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE, } BURN_ELEVATION_MESSAGE_TYPE; // struct typedef struct _BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT { BURN_USER_EXPERIENCE* pBA; BOOL fPauseCompleteNeeded; BOOL fSrpCompleteNeeded; } BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT; typedef struct _BURN_ELEVATION_CACHE_MESSAGE_CONTEXT { PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler; LPPROGRESS_ROUTINE pfnProgress; LPVOID pvContext; } BURN_ELEVATION_CACHE_MESSAGE_CONTEXT; typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT { PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler; LPVOID pvContext; BOOTSTRAPPER_APPLY_RESTART restart; } BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT; typedef struct _BURN_ELEVATION_MSI_MESSAGE_CONTEXT { PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler; LPVOID pvContext; BOOTSTRAPPER_APPLY_RESTART restart; } BURN_ELEVATION_MSI_MESSAGE_CONTEXT; typedef struct _BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT { DWORD dwProcessId; } BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT; typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT { HANDLE hPipe; HANDLE* phLock; BOOL* pfDisabledAutomaticUpdates; BOOL* pfApplying; BURN_APPROVED_EXES* pApprovedExes; BURN_CACHE* pCache; BURN_CONTAINERS* pContainers; BURN_PACKAGES* pPackages; BURN_PAYLOADS* pPayloads; BURN_VARIABLES* pVariables; BURN_REGISTRATION* pRegistration; BURN_USER_EXPERIENCE* pUserExperience; } BURN_ELEVATION_CHILD_MESSAGE_CONTEXT; // internal function declarations /******************************************************************* LaunchElevatedProcess - Called from the per-user process to create the per-machine process and set up the communication pipe. *******************************************************************/ static HRESULT LaunchElevatedProcess( __in BURN_ENGINE_STATE* pEngineState, __in_opt HWND hwndParent ); static DWORD WINAPI ElevatedChildCacheThreadProc( __in LPVOID lpThreadParameter ); static HRESULT WaitForElevatedChildCacheThread( __in HANDLE hCacheThread, __in DWORD dwExpectedExitCode ); static HRESULT ProcessApplyInitializeMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessBurnCacheMessages( __in PIPE_MESSAGE* pMsg, __in LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessGenericExecuteMessages( __in PIPE_MESSAGE* pMsg, __in LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessMsiPackageMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessLaunchApprovedExeMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessProgressRoutineMessage( __in PIPE_MESSAGE* pMsg, __in LPPROGRESS_ROUTINE pfnProgress, __in LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessElevatedChildMessage( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessElevatedChildCacheMessage( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ); static HRESULT ProcessExecuteActionCompleteMessage( __in BYTE* pbData, __in DWORD cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart, __out DWORD* pdwResult ); static HRESULT OnApplyInitialize( __in HANDLE hPipe, __in BURN_VARIABLES* pVariables, __in BURN_REGISTRATION* pRegistration, __in BURN_PACKAGES* pPackages, __in HANDLE* phLock, __in BOOL* pfDisabledWindowsUpdate, __in BOOL* pfApplying, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT ElevatedProcessDetect( __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BURN_PACKAGES* pPackages ); static HRESULT OnApplyUninitialize( __in HANDLE* phLock, __in BOOL* pfApplying, __in BOOL* pfDisabledAutomaticUpdates ); static HRESULT OnSessionBegin( __in BURN_CACHE* pCache, __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnSessionEnd( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnSaveState( __in BURN_REGISTRATION* pRegistration, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnCachePreparePackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnCacheCompletePayload( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_PAYLOADS* pPayloads, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnCacheVerifyPayload( __in HANDLE hPipe, __in BURN_PACKAGES* pPackages, __in BURN_PAYLOADS* pPayloads, __in BYTE* pbData, __in SIZE_T cbData ); static void OnCacheCleanup( __in BURN_CACHE* pCache ); static HRESULT OnProcessDependentRegistration( __in const BURN_REGISTRATION* pRegistration, __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, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnExecuteBundlePackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); 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, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnExecuteMsiPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnExecuteMspPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnExecuteMsuPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnUninstallMsiCompatiblePackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ); static HRESULT OnExecutePackageProviderAction( __in BURN_PACKAGES* pPackages, __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnExecutePackageDependencyAction( __in BURN_PACKAGES* pPackages, __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT CALLBACK BurnCacheMessageHandler( __in BURN_CACHE_MESSAGE* pMessage, __in LPVOID pvContext ); static DWORD CALLBACK ElevatedProgressRoutine( __in LARGE_INTEGER TotalFileSize, __in LARGE_INTEGER TotalBytesTransferred, __in LARGE_INTEGER StreamSize, __in LARGE_INTEGER StreamBytesTransferred, __in DWORD dwStreamNumber, __in DWORD dwCallbackReason, __in HANDLE hSourceFile, __in HANDLE hDestinationFile, __in_opt LPVOID lpData ); static int GenericExecuteMessageHandler( __in GENERIC_EXECUTE_MESSAGE* pMessage, __in LPVOID pvContext ); static int MsiExecuteMessageHandler( __in WIU_MSI_EXECUTE_MESSAGE* pMessage, __in_opt LPVOID pvContext ); static HRESULT OnCleanCompatiblePackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnCleanPackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnLaunchApprovedExe( __in HANDLE hPipe, __in BURN_APPROVED_EXES* pApprovedExes, __in BURN_CACHE* pCache, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnMsiBeginTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ); static HRESULT OnMsiCommitTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART *pRestart ); static HRESULT OnMsiRollbackTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART *pRestart ); static HRESULT ElevatedOnPauseAUBegin( __in HANDLE hPipe ); static HRESULT ElevatedOnPauseAUComplete( __in HANDLE hPipe, __in HRESULT hrStatus ); static HRESULT ElevatedOnSystemRestorePointBegin( __in HANDLE hPipe ); static HRESULT ElevatedOnSystemRestorePointComplete( __in HANDLE hPipe, __in HRESULT hrStatus ); static HRESULT ElevatedOnExecuteActionComplete( __in HANDLE hPipe, __in BOOTSTRAPPER_APPLY_RESTART restart ); // function definitions extern "C" HRESULT ElevationElevate( __in BURN_ENGINE_STATE* pEngineState, __in WM_BURN reason, __in_opt HWND hwndParent ) { Assert(BURN_MODE_ELEVATED != pEngineState->internalCommand.mode); Assert(!pEngineState->companionConnection.sczName); Assert(!pEngineState->companionConnection.sczSecret); Assert(!pEngineState->companionConnection.hProcess); Assert(!pEngineState->companionConnection.dwProcessId); Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe); Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hCachePipe); Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hLoggingPipe); HRESULT hr = S_OK; int nResult = IDOK; hr = BACallbackOnElevateBegin(&pEngineState->userExperience); ExitOnRootFailure(hr, "BA aborted elevation requirement."); hr = BurnPipeCreateNameAndSecret(&pEngineState->companionConnection.sczName, &pEngineState->companionConnection.sczSecret); ExitOnFailure(hr, "Failed to create pipe name and client token."); hr = BurnPipeCreatePipes(&pEngineState->companionConnection, TRUE); ExitOnFailure(hr, "Failed to create pipe and cache pipe."); LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_STARTING); do { nResult = IDOK; // Create the elevated process and if successful, wait for it to connect. hr = LaunchElevatedProcess(pEngineState, hwndParent); if (SUCCEEDED(hr)) { LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_SUCCESS); hr = BurnPipeWaitForChildConnect(&pEngineState->companionConnection); if (HRESULT_FROM_WIN32(ERROR_NO_DATA) == hr) { hr = E_SUSPECTED_AV_INTERFERENCE; } ExitOnFailure(hr, "Failed to connect to elevated child process."); LogId(REPORT_STANDARD, MSG_CONNECT_TO_ELEVATED_ENGINE_SUCCESS); } else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) { // The user clicked "Cancel" on the elevation prompt or the elevation prompt timed out, provide the notification with the option to retry. if (WM_BURN_APPLY == reason) { hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); } nResult = BootstrapperApplicationSendError(&pEngineState->userExperience, BOOTSTRAPPER_ERROR_TYPE_ELEVATE, NULL, hr, NULL, MB_ICONERROR | MB_RETRYCANCEL, IDNOACTION); } } while (IDRETRY == nResult); ExitOnFailure(hr, "Failed to elevate."); LExit: if (FAILED(hr)) { BurnPipeConnectionUninitialize(&pEngineState->companionConnection); } BACallbackOnElevateComplete(&pEngineState->userExperience, hr); return hr; } extern "C" HRESULT ElevationApplyInitialize( __in HANDLE hPipe, __in BURN_USER_EXPERIENCE* pBA, __in BURN_VARIABLES* pVariables, __in BURN_PLAN* pPlan ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT context = { }; context.pBA = pBA; // serialize message data hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pPlan->action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pPlan->pInternalCommand->automaticUpdates); ExitOnFailure(hr, "Failed to write update action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)!pPlan->pInternalCommand->fDisableSystemRestore); ExitOnFailure(hr, "Failed to write system restore point action to message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE, pbData, cbData, ProcessApplyInitializeMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send message to per-machine process."); hr = (HRESULT)dwResult; // Best effort to keep the sequence of BA events sane. if (context.fPauseCompleteNeeded) { BACallbackOnPauseAUComplete(pBA, hr); } if (context.fSrpCompleteNeeded) { BACallbackOnSystemRestorePointComplete(pBA, hr); } LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationApplyUninitialize( __in HANDLE hPipe ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationSessionBegin - *******************************************************************/ extern "C" HRESULT ElevationSessionBegin( __in HANDLE hPipe, __in_z LPCWSTR wzEngineWorkingPath, __in_z LPCWSTR wzResumeCommandLine, __in BOOL fDisableResume, __in BURN_VARIABLES* pVariables, __in DWORD dwRegistrationOperations, __in BOOL fDetectedForeignProviderKeyBundleCode, __in DWORD64 qwEstimatedSize, __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // serialize message data hr = BuffWriteString(&pbData, &cbData, wzEngineWorkingPath); ExitOnFailure(hr, "Failed to write engine working path to message buffer."); hr = BuffWriteString(&pbData, &cbData, wzResumeCommandLine); ExitOnFailure(hr, "Failed to write resume command line to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, fDisableResume); ExitOnFailure(hr, "Failed to write resume flag."); hr = BuffWriteNumber(&pbData, &cbData, dwRegistrationOperations); ExitOnFailure(hr, "Failed to write registration operations to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fDetectedForeignProviderKeyBundleCode); ExitOnFailure(hr, "Failed to write dependency registration action to message buffer."); hr = BuffWriteNumber64(&pbData, &cbData, qwEstimatedSize); ExitOnFailure(hr, "Failed to write estimated size to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)registrationType); ExitOnFailure(hr, "Failed to write registration type to message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationSessionEnd - *******************************************************************/ extern "C" HRESULT ElevationSessionEnd( __in HANDLE hPipe, __in BURN_RESUME_MODE resumeMode, __in BOOTSTRAPPER_APPLY_RESTART restart, __in BOOL fDetectedForeignProviderKeyBundleCode, __in DWORD64 qwEstimatedSize, __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // serialize message data hr = BuffWriteNumber(&pbData, &cbData, (DWORD)resumeMode); ExitOnFailure(hr, "Failed to write resume mode to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)restart); ExitOnFailure(hr, "Failed to write restart enum to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fDetectedForeignProviderKeyBundleCode); ExitOnFailure(hr, "Failed to write dependency registration action to message buffer."); hr = BuffWriteNumber64(&pbData, &cbData, qwEstimatedSize); ExitOnFailure(hr, "Failed to write estimated size to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)registrationType); ExitOnFailure(hr, "Failed to write registration type to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationSaveState - *******************************************************************/ HRESULT ElevationSaveState( __in HANDLE hPipe, __in_bcount(cbBuffer) BYTE* pbBuffer, __in SIZE_T cbBuffer ) { HRESULT hr = S_OK; DWORD dwResult = 0; // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE, pbBuffer, cbBuffer, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send message to per-machine process."); hr = (HRESULT)dwResult; LExit: return hr; } extern "C" HRESULT ElevationCachePreparePackage( __in HANDLE hPipe, __in BURN_PACKAGE* pPackage ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // Serialize message data. hr = BuffWriteString(&pbData, &cbData, pPackage ? pPackage->sczId : NULL); ExitOnFailure(hr, "Failed to write package id to message buffer."); // Send message. hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationCacheCompletePayload - *******************************************************************/ extern "C" HRESULT ElevationCacheCompletePayload( __in HANDLE hPipe, __in BURN_PACKAGE* pPackage, __in BURN_PAYLOAD* pPayload, __in_z LPCWSTR wzUnverifiedPath, __in BOOL fMove, __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler, __in LPPROGRESS_ROUTINE pfnProgress, __in LPVOID pContext ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; BURN_ELEVATION_CACHE_MESSAGE_CONTEXT context = { }; context.pfnCacheMessageHandler = pfnCacheMessageHandler; context.pfnProgress = pfnProgress; context.pvContext = pContext; // serialize message data hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pPayload->sczKey); ExitOnFailure(hr, "Failed to write payload id to message buffer."); hr = BuffWriteString(&pbData, &cbData, wzUnverifiedPath); ExitOnFailure(hr, "Failed to write unverified path to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fMove); ExitOnFailure(hr, "Failed to write move flag to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD, pbData, cbData, ProcessBurnCacheMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationCacheVerifyPayload( __in HANDLE hPipe, __in BURN_PACKAGE* pPackage, __in BURN_PAYLOAD* pPayload, __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler, __in LPPROGRESS_ROUTINE pfnProgress, __in LPVOID pContext ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; BURN_ELEVATION_CACHE_MESSAGE_CONTEXT context = { }; context.pfnCacheMessageHandler = pfnCacheMessageHandler; context.pfnProgress = pfnProgress; context.pvContext = pContext; // serialize message data hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pPayload->sczKey); ExitOnFailure(hr, "Failed to write payload id to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD, pbData, cbData, ProcessBurnCacheMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationCacheCleanup - *******************************************************************/ extern "C" HRESULT ElevationCacheCleanup( __in HANDLE hPipe ) { HRESULT hr = S_OK; DWORD dwResult = 0; // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, NULL, 0, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP message to per-machine process."); hr = (HRESULT)dwResult; LExit: return hr; } extern "C" HRESULT ElevationProcessDependentRegistration( __in HANDLE hPipe, __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pAction->type); ExitOnFailure(hr, "Failed to write action type to message buffer."); hr = BuffWriteString(&pbData, &cbData, pAction->sczBundleCode); ExitOnFailure(hr, "Failed to write bundle code to message buffer."); hr = BuffWriteString(&pbData, &cbData, pAction->sczDependentProviderKey); ExitOnFailure(hr, "Failed to write dependent provider key to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationExecuteRelatedBundle - *******************************************************************/ extern "C" 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 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->relatedBundle.pRelatedBundle->package.sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.pRelatedBundle->planRelationType); ExitOnFailure(hr, "Failed to write planRelationType to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, fRollback); ExitOnFailure(hr, "Failed to write rollback."); 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->relatedBundle.sczAncestors); ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); 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); ExitOnFailure(hr, "Failed to write variables."); // send message context.pfnGenericMessageHandler = pfnGenericMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(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 = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationExecuteBundlePackage - *******************************************************************/ extern "C" HRESULT ElevationExecuteBundlePackage( __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->bundlePackage.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->bundlePackage.action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, fRollback); ExitOnFailure(hr, "Failed to write rollback."); hr = BuffWriteNumber(&pbData, &cbData, SUCCEEDED(pExecuteAction->bundlePackage.pPackage->hrCacheResult)); ExitOnFailure(hr, "Failed to write fCacheAvailable."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczParent); ExitOnFailure(hr, "Failed to write the parent to the message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczIgnoreDependencies); ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczAncestors); ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->bundlePackage.sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message context.pfnGenericMessageHandler = pfnGenericMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(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 = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message context.pfnGenericMessageHandler = pfnGenericMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(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."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationMsiBeginTransaction( __in HANDLE hPipe, __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = ERROR_SUCCESS; // serialize message data hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczId); ExitOnFailure(hr, "Failed to write transaction name to message buffer."); hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczLogPath); ExitOnFailure(hr, "Failed to write transaction log path to message buffer."); hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION message to per-machine process."); hr = static_cast(dwResult); LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationMsiCommitTransaction( __in HANDLE hPipe, __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary, __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; DWORD dwResult = ERROR_SUCCESS; // serialize message data hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczId); ExitOnFailure(hr, "Failed to write transaction name to message buffer."); hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczLogPath); ExitOnFailure(hr, "Failed to write transaction log path to message buffer."); // send message context.pfnMessageHandler = pfnMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationMsiRollbackTransaction( __in HANDLE hPipe, __in BURN_ROLLBACK_BOUNDARY* pRollbackBoundary, __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; DWORD dwResult = ERROR_SUCCESS; // serialize message data hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczId); ExitOnFailure(hr, "Failed to write transaction name to message buffer."); hr = BuffWriteString(&pbData, &cbData, pRollbackBoundary->sczLogPath); ExitOnFailure(hr, "Failed to write transaction log path to message buffer."); // send message context.pfnMessageHandler = pfnMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationExecuteMsiPackage - *******************************************************************/ extern "C" HRESULT ElevationExecuteMsiPackage( __in HANDLE hPipe, __in_opt HWND hwndParent, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_VARIABLES* pVariables, __in BOOL fRollback, __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; DWORD dwResult = 0; // serialize message data hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msiPackage.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWritePointer(&pbData, &cbData, (DWORD_PTR)hwndParent); ExitOnFailure(hr, "Failed to write parent hwnd to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msiPackage.sczLogPath); ExitOnFailure(hr, "Failed to write package log to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.actionMsiProperty); ExitOnFailure(hr, "Failed to write actionMsiProperty to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.uiLevel); ExitOnFailure(hr, "Failed to write UI level to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.fDisableExternalUiHandler); ExitOnFailure(hr, "Failed to write fDisableExternalUiHandler to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.fileVersioning); ExitOnFailure(hr, "Failed to write fileVersioning to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.action); ExitOnFailure(hr, "Failed to write action to message buffer."); // Feature actions. for (DWORD i = 0; i < pExecuteAction->msiPackage.pPackage->Msi.cFeatures; ++i) { hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msiPackage.rgFeatures[i]); ExitOnFailure(hr, "Failed to write feature action to message buffer."); } // Slipstream patches actions. for (DWORD i = 0; i < pExecuteAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++i) { BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pExecuteAction->msiPackage.pPackage->Msi.rgSlipstreamMsps + i; BOOTSTRAPPER_ACTION_STATE* pAction = fRollback ? &pSlipstreamMsp->rollback : &pSlipstreamMsp->execute; hr = BuffWriteNumber(&pbData, &cbData, (DWORD)*pAction); ExitOnFailure(hr, "Failed to write slipstream patch action to message buffer."); } hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message context.pfnMessageHandler = pfnMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationExecuteMspPackage - *******************************************************************/ extern "C" HRESULT ElevationExecuteMspPackage( __in HANDLE hPipe, __in_opt HWND hwndParent, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_VARIABLES* pVariables, __in BOOL fRollback, __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; DWORD dwResult = 0; // serialize message data hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWritePointer(&pbData, &cbData, (DWORD_PTR)hwndParent); ExitOnFailure(hr, "Failed to write parent hwnd to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.sczTargetProductCode); ExitOnFailure(hr, "Failed to write target product code to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.sczLogPath); ExitOnFailure(hr, "Failed to write package log to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.actionMsiProperty); ExitOnFailure(hr, "Failed to write actionMsiProperty to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.uiLevel); ExitOnFailure(hr, "Failed to write UI level to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.fDisableExternalUiHandler); ExitOnFailure(hr, "Failed to write fDisableExternalUiHandler to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.fileVersioning); ExitOnFailure(hr, "Failed to write fileVersioning to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->mspTarget.action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, pExecuteAction->mspTarget.cOrderedPatches); ExitOnFailure(hr, "Failed to write count of ordered patches to message buffer."); for (DWORD i = 0; i < pExecuteAction->mspTarget.cOrderedPatches; ++i) { hr = BuffWriteString(&pbData, &cbData, pExecuteAction->mspTarget.rgOrderedPatches[i].pPackage->sczId); ExitOnFailure(hr, "Failed to write ordered patch id to message buffer."); } hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); // send message context.pfnMessageHandler = pfnMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationExecuteMsuPackage - *******************************************************************/ extern "C" HRESULT ElevationExecuteMsuPackage( __in HANDLE hPipe, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BOOL fRollback, __in BOOL fStopWusaService, __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->msuPackage.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->msuPackage.sczLogPath); ExitOnFailure(hr, "Failed to write package log to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->msuPackage.action); ExitOnFailure(hr, "Failed to write action to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, fRollback); ExitOnFailure(hr, "Failed to write rollback."); hr = BuffWriteNumber(&pbData, &cbData, fStopWusaService); ExitOnFailure(hr, "Failed to write StopWusaService."); // send message context.pfnGenericMessageHandler = pfnGenericMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationUninstallMsiCompatiblePackage( __in HANDLE hPipe, __in_opt HWND hwndParent, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BURN_VARIABLES* pVariables, __in BOOL fRollback, __in PFN_MSIEXECUTEMESSAGEHANDLER pfnMessageHandler, __in LPVOID pvContext, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; BURN_ELEVATION_MSI_MESSAGE_CONTEXT context = { }; DWORD dwResult = 0; // serialize message data hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->uninstallMsiCompatiblePackage.pParentPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->uninstallMsiCompatiblePackage.pParentPackage->compatiblePackage.compatibleEntry.sczId); ExitOnFailure(hr, "Failed to write compatible package id to message buffer."); hr = BuffWritePointer(&pbData, &cbData, (DWORD_PTR)hwndParent); ExitOnFailure(hr, "Failed to write parent hwnd to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath); ExitOnFailure(hr, "Failed to write package log to message buffer."); hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); ExitOnFailure(hr, "Failed to write variables."); // send message context.pfnMessageHandler = pfnMessageHandler; context.pvContext = pvContext; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE, pbData, cbData, ProcessMsiPackageMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE message to per-machine process."); hr = static_cast(dwResult); *pRestart = context.restart; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationExecutePackageProviderAction( __in HANDLE hPipe, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BOOL fRollback ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // Serialize the message data. hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageProvider.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); // Provider actions. for (DWORD i = 0; i < pExecuteAction->packageProvider.pPackage->cDependencyProviders; ++i) { BURN_DEPENDENCY_PROVIDER* pProvider = pExecuteAction->packageProvider.pPackage->rgDependencyProviders + i; BURN_DEPENDENCY_ACTION* pAction = fRollback ? &pProvider->providerRollback : &pProvider->providerExecute; hr = BuffWriteNumber(&pbData, &cbData, (DWORD)*pAction); ExitOnFailure(hr, "Failed to write provider action to message buffer."); } // Send the message. hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER message to per-machine process."); LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationExecutePackageDependencyAction( __in HANDLE hPipe, __in BURN_EXECUTE_ACTION* pExecuteAction, __in BOOL fRollback ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // Serialize the message data. hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.pPackage->sczId); ExitOnFailure(hr, "Failed to write package id to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRollback); ExitOnFailure(hr, "Failed to write rollback flag to message buffer."); hr = BuffWriteString(&pbData, &cbData, pExecuteAction->packageDependency.sczBundleProviderKey); ExitOnFailure(hr, "Failed to write bundle dependency key to message buffer."); // Dependent actions. for (DWORD i = 0; i < pExecuteAction->packageProvider.pPackage->cDependencyProviders; ++i) { BURN_DEPENDENCY_PROVIDER* pProvider = pExecuteAction->packageProvider.pPackage->rgDependencyProviders + i; BURN_DEPENDENCY_ACTION* pAction = fRollback ? &pProvider->dependentRollback : &pProvider->dependentExecute; hr = BuffWriteNumber(&pbData, &cbData, (DWORD)*pAction); ExitOnFailure(hr, "Failed to write dependent action to message buffer."); } // Send the message. hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY message to per-machine process."); LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationCleanCompatiblePackage( __in HANDLE hPipe, __in BURN_PACKAGE* pPackage ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // serialize message data hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); ExitOnFailure(hr, "Failed to write clean package id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pPackage->compatiblePackage.compatibleEntry.sczId); ExitOnFailure(hr, "Failed to write compatible package id to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationCleanPackage - *******************************************************************/ extern "C" HRESULT ElevationCleanPackage( __in HANDLE hPipe, __in BURN_PACKAGE* pPackage ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; // serialize message data hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); ExitOnFailure(hr, "Failed to write clean package id to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE message to per-machine process."); hr = (HRESULT)dwResult; LExit: ReleaseMem(pbData); return hr; } extern "C" HRESULT ElevationLaunchApprovedExe( __in HANDLE hPipe, __in BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe, __out DWORD* pdwProcessId ) { HRESULT hr = S_OK; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwResult = 0; BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT context = { }; // Serialize message data. hr = BuffWriteString(&pbData, &cbData, pLaunchApprovedExe->sczId); ExitOnFailure(hr, "Failed to write approved exe id to message buffer."); hr = BuffWriteString(&pbData, &cbData, pLaunchApprovedExe->sczArguments); ExitOnFailure(hr, "Failed to write approved exe arguments to message buffer."); hr = BuffWriteNumber(&pbData, &cbData, pLaunchApprovedExe->dwWaitForInputIdleTimeout); ExitOnFailure(hr, "Failed to write approved exe WaitForInputIdle timeout to message buffer."); // Send the message. hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE, pbData, cbData, ProcessLaunchApprovedExeMessages, &context, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE message to per-machine process."); hr = (HRESULT)dwResult; *pdwProcessId = context.dwProcessId; LExit: ReleaseMem(pbData); return hr; } /******************************************************************* ElevationChildPumpMessages - *******************************************************************/ extern "C" HRESULT ElevationChildPumpMessages( __in HANDLE hPipe, __in HANDLE hCachePipe, __in BURN_APPROVED_EXES* pApprovedExes, __in BURN_CACHE* pCache, __in BURN_CONTAINERS* pContainers, __in BURN_PACKAGES* pPackages, __in BURN_PAYLOADS* pPayloads, __in BURN_VARIABLES* pVariables, __in BURN_REGISTRATION* pRegistration, __in BURN_USER_EXPERIENCE* pUserExperience, __out HANDLE* phLock, __out DWORD* pdwChildExitCode, __out BOOL* pfRestart, __out BOOL* pfApplying ) { HRESULT hr = S_OK; BURN_ELEVATION_CHILD_MESSAGE_CONTEXT cacheContext = { }; BURN_ELEVATION_CHILD_MESSAGE_CONTEXT context = { }; HANDLE hCacheThread = NULL; BURN_PIPE_RESULT result = { }; BOOL fDisabledAutomaticUpdates = FALSE; cacheContext.hPipe = hCachePipe; cacheContext.pCache = pCache; cacheContext.pContainers = pContainers; cacheContext.pPackages = pPackages; cacheContext.pPayloads = pPayloads; cacheContext.pVariables = pVariables; cacheContext.pRegistration = pRegistration; cacheContext.pUserExperience = pUserExperience; context.hPipe = hPipe; context.phLock = phLock; context.pfDisabledAutomaticUpdates = &fDisabledAutomaticUpdates; context.pfApplying = pfApplying; context.pApprovedExes = pApprovedExes; context.pCache = pCache; context.pContainers = pContainers; context.pPackages = pPackages; context.pPayloads = pPayloads; context.pVariables = pVariables; context.pRegistration = pRegistration; context.pUserExperience = pUserExperience; hCacheThread = ::CreateThread(NULL, 0, ElevatedChildCacheThreadProc, &cacheContext, 0, NULL); ExitOnNullWithLastError(hCacheThread, hr, "Failed to create elevated cache thread."); hr = BurnPipePumpMessages(hPipe, ProcessElevatedChildMessage, &context, &result); ExitOnFailure(hr, "Failed to pump messages in child process."); // Wait for the cache thread and verify it gets the right result but don't fail if things // don't work out. WaitForElevatedChildCacheThread(hCacheThread, result.dwResult); *pdwChildExitCode = result.dwResult; *pfRestart = result.fRestart; LExit: ReleaseHandle(hCacheThread); if (fDisabledAutomaticUpdates) { ElevationChildResumeAutomaticUpdates(); } return hr; } extern "C" HRESULT ElevationChildResumeAutomaticUpdates() { HRESULT hr = S_OK; LogId(REPORT_STANDARD, MSG_RESUME_AU_STARTING); hr = WuaResumeAutomaticUpdates(); ExitOnFailure(hr, "Failed to resume automatic updates after pausing them, continuing..."); LogId(REPORT_STANDARD, MSG_RESUME_AU_SUCCEEDED); LExit: return hr; } // internal function definitions static HRESULT LaunchElevatedProcess( __in BURN_ENGINE_STATE* pEngineState, __in_opt HWND hwndParent ) { HRESULT hr = S_OK; DWORD dwCurrentProcessId = ::GetCurrentProcessId(); LPWSTR sczParameters = NULL; HANDLE hProcess = NULL; BURN_PIPE_CONNECTION* pConnection = &pEngineState->companionConnection; hr = StrAllocFormatted(&sczParameters, L"-q -%ls %ls %ls %u", BURN_COMMANDLINE_SWITCH_ELEVATED, pConnection->sczName, pConnection->sczSecret, dwCurrentProcessId); ExitOnFailure(hr, "Failed to allocate parameters for elevated process."); if (BURN_LOGGING_ATTRIBUTE_EXTRADEBUG & pEngineState->internalCommand.dwLoggingAttributes) { hr = StrAllocConcatFormatted(&sczParameters, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_LOG_MODE, L"x"); ExitOnFailure(hr, "Failed to set log mode in elevated process command-line."); } // Since ShellExecuteEx doesn't support passing inherited handles, don't bother with CoreAppendFileHandleSelfToCommandLine. // We could fallback to using ::DuplicateHandle to inject the file handle later if necessary. hr = ShelExec(pEngineState->cache.sczBundleEngineWorkingPath, sczParameters, L"runas", NULL, SW_SHOWNA, hwndParent, &hProcess); ExitOnFailure(hr, "Failed to launch elevated child process: %ls", pEngineState->cache.sczBundleEngineWorkingPath); pConnection->dwProcessId = ::GetProcessId(hProcess); pConnection->hProcess = hProcess; hProcess = NULL; LExit: ReleaseHandle(hProcess); ReleaseStr(sczParameters); return hr; } static DWORD WINAPI ElevatedChildCacheThreadProc( __in LPVOID lpThreadParameter ) { HRESULT hr = S_OK; BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = reinterpret_cast(lpThreadParameter); BOOL fComInitialized = FALSE; BURN_PIPE_RESULT result = { }; // initialize COM hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); ExitOnFailure(hr, "Failed to initialize COM."); fComInitialized = TRUE; hr = BurnPipePumpMessages(pContext->hPipe, ProcessElevatedChildCacheMessage, pContext, &result); ExitOnFailure(hr, "Failed to pump messages in child process."); hr = (HRESULT)result.dwResult; LExit: if (fComInitialized) { ::CoUninitialize(); } return (DWORD)hr; } static HRESULT WaitForElevatedChildCacheThread( __in HANDLE hCacheThread, __in DWORD dwExpectedExitCode ) { UNREFERENCED_PARAMETER(dwExpectedExitCode); HRESULT hr = S_OK; DWORD dwExitCode = ERROR_SUCCESS; hr = ThrdWaitForCompletion(hCacheThread, BURN_TIMEOUT, &dwExitCode); ExitOnFailure(hr, "Failed to wait for cache thread to complete."); AssertSz(dwExitCode == dwExpectedExitCode, "Cache thread should have exited with the expected exit code."); LExit: return hr; } static HRESULT ProcessApplyInitializeMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT* pContext = static_cast(pvContext); BYTE* pbData = (BYTE*)pMsg->pvData; SIZE_T iData = 0; HRESULT hrStatus = S_OK; HRESULT hrBA = S_OK; // Process the message. switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_BEGIN: pContext->fPauseCompleteNeeded = TRUE; hrBA = BACallbackOnPauseAUBegin(pContext->pBA); break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE: // read hrStatus hr = BuffReadNumber(pbData, pMsg->cbData, &iData, reinterpret_cast(&hrStatus)); ExitOnFailure(hr, "Failed to read pause AU hrStatus."); pContext->fPauseCompleteNeeded = FALSE; hrBA = BACallbackOnPauseAUComplete(pContext->pBA, hrStatus); break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN: if (pContext->fPauseCompleteNeeded) { pContext->fPauseCompleteNeeded = FALSE; hrBA = BACallbackOnPauseAUComplete(pContext->pBA, E_INVALIDSTATE); } pContext->fSrpCompleteNeeded = TRUE; hrBA = BACallbackOnSystemRestorePointBegin(pContext->pBA); break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE: // read hrStatus hr = BuffReadNumber(pbData, pMsg->cbData, &iData, reinterpret_cast(&hrStatus)); ExitOnFailure(hr, "Failed to read system restore point hrStatus."); pContext->fSrpCompleteNeeded = FALSE; hrBA = BACallbackOnSystemRestorePointComplete(pContext->pBA, hrStatus); break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid apply initialize message."); break; } *pdwResult = static_cast(hrBA); LExit: return hr; } static HRESULT ProcessBurnCacheMessages( __in PIPE_MESSAGE* pMsg, __in LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; BURN_ELEVATION_CACHE_MESSAGE_CONTEXT* pContext = static_cast(pvContext); BURN_CACHE_MESSAGE message = { }; BOOL fProgressRoutine = FALSE; // Process the message. switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN: // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast(&message.begin.cacheStep)); ExitOnFailure(hr, "Failed to read begin cache step."); message.type = BURN_CACHE_MESSAGE_BEGIN; break; case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE: // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast(&message.complete.hrStatus)); ExitOnFailure(hr, "Failed to read complete hresult."); message.type = BURN_CACHE_MESSAGE_COMPLETE; break; case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS: // read message parameters hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.success.qwFileSize); ExitOnFailure(hr, "Failed to read success file size."); message.type = BURN_CACHE_MESSAGE_SUCCESS; break; case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_FAILURE: // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast(&message.failure.cacheStep)); ExitOnFailure(hr, "Failed to read failure cache step."); message.type = BURN_CACHE_MESSAGE_FAILURE; break; case BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE: fProgressRoutine = TRUE; break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid burn cache message."); break; } if (fProgressRoutine) { hr = ProcessProgressRoutineMessage(pMsg, pContext->pfnProgress, pContext->pvContext, pdwResult); } else { hr = pContext->pfnCacheMessageHandler(&message, pContext->pvContext); *pdwResult = static_cast(hr); } LExit: return hr; } static HRESULT ProcessGenericExecuteMessages( __in PIPE_MESSAGE* pMsg, __in LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT* pContext = static_cast(pvContext); LPWSTR sczMessage = NULL; DWORD cFiles = 0; LPWSTR* rgwzFiles = NULL; GENERIC_EXECUTE_MESSAGE message = { }; if (BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE == pMsg->dwMessageType) { hr = ProcessExecuteActionCompleteMessage((BYTE*)pMsg->pvData, pMsg->cbData, &pContext->restart, pdwResult); ExitOnFailure(hr, "Failed to process BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message."); ExitFunction(); } hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint); ExitOnFailure(hr, "Failed to allowed results."); // Process the message. switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS: message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS; // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); ExitOnFailure(hr, "Failed to read progress."); break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL: message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL; hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.processCancel.dwProcessId); ExitOnFailure(hr, "Failed to read processId."); break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED: message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED: message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: message.type = GENERIC_EXECUTE_MESSAGE_ERROR; // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.error.dwErrorCode); ExitOnFailure(hr, "Failed to read error code."); hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); ExitOnFailure(hr, "Failed to read error message."); message.error.wzMessage = sczMessage; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE: message.type = GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE; // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cFiles); ExitOnFailure(hr, "Failed to read file count."); rgwzFiles = (LPWSTR*)MemAlloc(sizeof(LPWSTR*) * cFiles, TRUE); ExitOnNull(rgwzFiles, hr, E_OUTOFMEMORY, "Failed to allocate buffer for files in use."); for (DWORD i = 0; i < cFiles; ++i) { hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &rgwzFiles[i]); ExitOnFailure(hr, "Failed to read file name: %u", i); } message.filesInUse.cFiles = cFiles; message.filesInUse.rgwzFiles = (LPCWSTR*)rgwzFiles; break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid package message."); break; } // send message *pdwResult = (DWORD)pContext->pfnGenericMessageHandler(&message, pContext->pvContext); LExit: ReleaseStr(sczMessage); if (rgwzFiles) { for (DWORD i = 0; i < cFiles; ++i) { ReleaseStr(rgwzFiles[i]); } MemFree(rgwzFiles); } return hr; } static HRESULT ProcessMsiPackageMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; WIU_MSI_EXECUTE_MESSAGE message = { }; DWORD cMsiData = 0; LPWSTR* rgwzMsiData = NULL; BURN_ELEVATION_MSI_MESSAGE_CONTEXT* pContext = static_cast(pvContext); LPWSTR sczMessage = NULL; BOOL fRestartManager = FALSE; if (BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE == pMsg->dwMessageType) { hr = ProcessExecuteActionCompleteMessage((BYTE*)pMsg->pvData, pMsg->cbData, &pContext->restart, pdwResult); ExitOnFailure(hr, "Failed to process BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message."); ExitFunction(); } // Read MSI extended message data. hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &cMsiData); ExitOnFailure(hr, "Failed to read MSI data count."); if (cMsiData) { rgwzMsiData = (LPWSTR*)MemAlloc(sizeof(LPWSTR*) * cMsiData, TRUE); ExitOnNull(rgwzMsiData, hr, E_OUTOFMEMORY, "Failed to allocate buffer to read MSI data."); for (DWORD i = 0; i < cMsiData; ++i) { hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &rgwzMsiData[i]); ExitOnFailure(hr, "Failed to read MSI data: %u", i); } message.cData = cMsiData; message.rgwzData = (LPCWSTR*)rgwzMsiData; } hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.dwUIHint); ExitOnFailure(hr, "Failed to read UI flags."); // Process the rest of the message. switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS: // read message parameters message.type = WIU_MSI_EXECUTE_MESSAGE_PROGRESS; hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.progress.dwPercentage); ExitOnFailure(hr, "Failed to read progress."); break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR: // read message parameters message.type = WIU_MSI_EXECUTE_MESSAGE_ERROR; hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.error.dwErrorCode); ExitOnFailure(hr, "Failed to read error code."); hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); ExitOnFailure(hr, "Failed to read MSI execute error message."); message.error.wzMessage = sczMessage; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE: // read message parameters message.type = WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE; hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, (DWORD*)&message.msiMessage.mt); ExitOnFailure(hr, "Failed to read MSI execute message type."); hr = BuffReadString((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &sczMessage); ExitOnFailure(hr, "Failed to read MSI execute message."); message.msiMessage.wzMessage = sczMessage; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE: hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, (DWORD*)&fRestartManager); ExitOnFailure(hr, "Failed to read fRestartManager."); message.type = fRestartManager ? WIU_MSI_EXECUTE_MESSAGE_MSI_RM_FILES_IN_USE : WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE; message.msiFilesInUse.cFiles = cMsiData; message.msiFilesInUse.rgwzFiles = (LPCWSTR*)rgwzMsiData; break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid package message."); break; } // send message *pdwResult = (DWORD)pContext->pfnMessageHandler(&message, pContext->pvContext); LExit: ReleaseStr(sczMessage); if (rgwzMsiData) { for (DWORD i = 0; i < cMsiData; ++i) { ReleaseStr(rgwzMsiData[i]); } MemFree(rgwzMsiData); } return hr; } static HRESULT ProcessLaunchApprovedExeMessages( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT* pContext = static_cast(pvContext); DWORD dwProcessId = 0; // Process the message. switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID: // read message parameters hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &dwProcessId); ExitOnFailure(hr, "Failed to read approved exe process id."); pContext->dwProcessId = dwProcessId; break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid launch approved exe message."); break; } *pdwResult = static_cast(hr); LExit: return hr; } static HRESULT ProcessProgressRoutineMessage( __in PIPE_MESSAGE* pMsg, __in LPPROGRESS_ROUTINE pfnProgress, __in LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; LARGE_INTEGER liTotalFileSize = { }; LARGE_INTEGER liTotalBytesTransferred = { }; LARGE_INTEGER liStreamSize = { }; LARGE_INTEGER liStreamBytesTransferred = { }; DWORD dwStreamNumber = 0; DWORD dwCallbackReason = CALLBACK_CHUNK_FINISHED; HANDLE hSourceFile = INVALID_HANDLE_VALUE; HANDLE hDestinationFile = INVALID_HANDLE_VALUE; hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast(&liTotalFileSize.QuadPart)); ExitOnFailure(hr, "Failed to read total file size for progress."); hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast(&liTotalBytesTransferred.QuadPart)); ExitOnFailure(hr, "Failed to read total bytes transferred for progress."); *pdwResult = pfnProgress(liTotalFileSize, liTotalBytesTransferred, liStreamSize, liStreamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, pvContext); LExit: return hr; } static HRESULT ProcessElevatedChildMessage( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast(pvContext); HRESULT hrResult = S_OK; BOOTSTRAPPER_APPLY_RESTART restart = BOOTSTRAPPER_APPLY_RESTART_NONE; BOOL fSendRestart = FALSE; switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_BEGIN_MSI_TRANSACTION: hrResult = OnMsiBeginTransaction(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_COMMIT_MSI_TRANSACTION: hrResult = OnMsiCommitTransaction(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_ROLLBACK_MSI_TRANSACTION: hrResult = OnMsiRollbackTransaction(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE: hrResult = OnApplyInitialize(pContext->hPipe, pContext->pVariables, pContext->pRegistration, pContext->pPackages, pContext->phLock, pContext->pfDisabledAutomaticUpdates, pContext->pfApplying, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_APPLY_UNINITIALIZE: hrResult = OnApplyUninitialize(pContext->phLock, pContext->pfApplying, pContext->pfDisabledAutomaticUpdates); break; case BURN_ELEVATION_MESSAGE_TYPE_SESSION_BEGIN: hrResult = OnSessionBegin(pContext->pCache, pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_SESSION_END: hrResult = OnSessionEnd(pContext->pCache, pContext->pPackages, pContext->pRegistration, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE: hrResult = OnSaveState(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION: 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, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_BUNDLE_PACKAGE: hrResult = OnExecuteBundlePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE: hrResult = OnExecuteMsiPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE: hrResult = OnExecuteMspPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSU_PACKAGE: hrResult = OnExecuteMsuPackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_PROVIDER: hrResult = OnExecutePackageProviderAction(pContext->pPackages, &pContext->pRegistration->relatedBundles, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PACKAGE_DEPENDENCY: hrResult = OnExecutePackageDependencyAction(pContext->pPackages, &pContext->pRegistration->relatedBundles, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE: hrResult = OnCleanPackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE: hrResult = OnLaunchApprovedExe(pContext->hPipe, pContext->pApprovedExes, pContext->pCache, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE: hrResult = OnUninstallMsiCompatiblePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData, &restart); fSendRestart = TRUE; break; case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_COMPATIBLE_PACKAGE: hrResult = OnCleanCompatiblePackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); break; default: ExitWithRootFailure(hr, E_INVALIDARG, "Unexpected elevated message sent to child process, msg: %u", pMsg->dwMessageType); } if (fSendRestart) { hr = ElevatedOnExecuteActionComplete(pContext->hPipe, restart); ExitOnFailure(hr, "ElevatedOnExecuteActionComplete failed."); } *pdwResult = (DWORD)hrResult; LExit: return hr; } static HRESULT ProcessElevatedChildCacheMessage( __in PIPE_MESSAGE* pMsg, __in_opt LPVOID pvContext, __out DWORD* pdwResult ) { HRESULT hr = S_OK; BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast(pvContext); HRESULT hrResult = S_OK; switch (pMsg->dwMessageType) { case BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE: hrResult = OnCachePreparePackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD: hrResult = OnCacheCompletePayload(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD: hrResult = OnCacheVerifyPayload(pContext->hPipe, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); break; case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP: OnCacheCleanup(pContext->pCache); hrResult = S_OK; break; case BURN_ELEVATION_MESSAGE_TYPE_CLEAN_PACKAGE: hrResult = OnCleanPackage(pContext->pCache, pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData); break; default: hr = E_INVALIDARG; ExitOnRootFailure(hr, "Unexpected elevated cache message sent to child process, msg: %u", pMsg->dwMessageType); } *pdwResult = (DWORD)hrResult; LExit: return hr; } static HRESULT ProcessExecuteActionCompleteMessage( __in BYTE* pbData, __in DWORD cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart, __out DWORD* pdwResult ) { HRESULT hr = S_OK; SIZE_T iData = 0; hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast(pRestart)); ExitOnFailure(hr, "Failed to read execute action restart result."); *pdwResult = (DWORD)hr; LExit: return hr; } static HRESULT OnApplyInitialize( __in HANDLE hPipe, __in BURN_VARIABLES* pVariables, __in BURN_REGISTRATION* pRegistration, __in BURN_PACKAGES* pPackages, __in HANDLE* phLock, __in BOOL* pfDisabledWindowsUpdate, __in BOOL* pfApplying, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; DWORD dwAction = 0; DWORD dwAUAction = 0; DWORD dwTakeSystemRestorePoint = 0; LPWSTR sczBundleName = NULL; HRESULT hrStatus = S_OK; // Deserialize message data. hr = BuffReadNumber(pbData, cbData, &iData, &dwAction); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, &dwAUAction); ExitOnFailure(hr, "Failed to read update action."); hr = BuffReadNumber(pbData, cbData, &iData, &dwTakeSystemRestorePoint); ExitOnFailure(hr, "Failed to read system restore point action."); hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); // Initialize. hr = ApplyLock(TRUE, phLock); ExitOnFailure(hr, "Failed to acquire lock due to setup in other session."); *pfApplying = TRUE; // Detect. hr = ElevatedProcessDetect(pRegistration, pVariables, pPackages); ExitOnFailure(hr, "Failed to run detection in elevated process."); // Attempt to pause AU with best effort. if (BURN_AU_PAUSE_ACTION_IFELEVATED == dwAUAction || BURN_AU_PAUSE_ACTION_IFELEVATED_NORESUME == dwAUAction) { hr = ElevatedOnPauseAUBegin(hPipe); ExitOnFailure(hr, "ElevatedOnPauseAUBegin failed."); LogId(REPORT_STANDARD, MSG_PAUSE_AU_STARTING); hrStatus = hr = WuaPauseAutomaticUpdates(); if (FAILED(hr)) { LogId(REPORT_STANDARD, MSG_FAILED_PAUSE_AU, hr); hr = S_OK; } else { LogId(REPORT_STANDARD, MSG_PAUSE_AU_SUCCEEDED); if (BURN_AU_PAUSE_ACTION_IFELEVATED == dwAUAction) { *pfDisabledWindowsUpdate = TRUE; } } hr = ElevatedOnPauseAUComplete(hPipe, hrStatus); ExitOnFailure(hr, "ElevatedOnPauseAUComplete failed."); } if (dwTakeSystemRestorePoint) { hr = VariableGetString(pVariables, BURN_BUNDLE_NAME, &sczBundleName); if (FAILED(hr)) { hr = S_OK; ExitFunction(); } hr = ElevatedOnSystemRestorePointBegin(hPipe); ExitOnFailure(hr, "ElevatedOnSystemRestorePointBegin failed."); LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_STARTING); SRP_ACTION restoreAction = SRP_ACTION_UNKNOWN; switch (static_cast(dwAction)) { case BOOTSTRAPPER_ACTION_INSTALL: restoreAction = SRP_ACTION_INSTALL; break; case BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL: __fallthrough; case BOOTSTRAPPER_ACTION_UNINSTALL: restoreAction = SRP_ACTION_UNINSTALL; break; default: restoreAction = SRP_ACTION_MODIFY; break; } hrStatus = hr = SrpCreateRestorePoint(sczBundleName, restoreAction); if (SUCCEEDED(hr)) { LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_SUCCEEDED); } else if (E_NOTIMPL == hr) { LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_DISABLED); hr = S_OK; } else { LogId(REPORT_STANDARD, MSG_SYSTEM_RESTORE_POINT_FAILED, hr); hr = S_OK; } hr = ElevatedOnSystemRestorePointComplete(hPipe, hrStatus); ExitOnFailure(hr, "ElevatedOnSystemRestorePointComplete failed."); } LExit: ReleaseStr(sczBundleName); return hr; } static HRESULT ElevatedProcessDetect( __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BURN_PACKAGES* pPackages ) { HRESULT hr = S_OK; DetectReset(pRegistration, pPackages); hr = RegistrationSetDynamicVariables(pRegistration, pVariables); ExitOnFailure(hr, "Failed to reset the dynamic registration variables during elevated detect."); hr = RelatedBundlesInitializeForScope(TRUE, pRegistration, &pRegistration->relatedBundles); ExitOnFailure(hr, "Failed to initialize per-machine related bundles."); for (DWORD i = 0; i < pPackages->cPackages; ++i) { BURN_PACKAGE* pPackage = pPackages->rgPackages + i; hr = DependencyDetectCompatibleEntry(pPackage, pRegistration); ExitOnFailure(hr, "Failed to detect per-machine compatible entry for package: %ls", pPackage->sczId); switch (pPackage->type) { case BURN_PACKAGE_TYPE_MSI: hr = MsiEngineDetectCompatiblePackage(pPackage); ExitOnFailure(hr, "Failed to detect per-machine compatible package for package: %ls", pPackage->sczId); break; } } LExit: return hr; } static HRESULT OnApplyUninitialize( __in HANDLE* phLock, __in BOOL* pfApplying, __in BOOL* pfDisabledAutomaticUpdates ) { Assert(phLock); // TODO: end system restore point. *pfApplying = FALSE; if (*pfDisabledAutomaticUpdates) { *pfDisabledAutomaticUpdates = FALSE; ElevationChildResumeAutomaticUpdates(); } if (*phLock) { ::ReleaseMutex(*phLock); ::CloseHandle(*phLock); *phLock = NULL; } return S_OK; } static HRESULT OnSessionBegin( __in BURN_CACHE* pCache, __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczEngineWorkingPath = NULL; DWORD dwRegistrationOperations = 0; DWORD64 qwEstimatedSize = 0; DWORD dwRegistrationType = 0; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingPath); ExitOnFailure(hr, "Failed to read engine working path."); hr = BuffReadString(pbData, cbData, &iData, &pRegistration->sczResumeCommandLine); ExitOnFailure(hr, "Failed to read resume command line."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDisableResume); ExitOnFailure(hr, "Failed to read resume flag."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationOperations); ExitOnFailure(hr, "Failed to read registration operations."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDetectedForeignProviderKeyBundleCode); ExitOnFailure(hr, "Failed to read dependency registration action."); hr = BuffReadNumber64(pbData, cbData, &iData, &qwEstimatedSize); ExitOnFailure(hr, "Failed to read estimated size."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationType); ExitOnFailure(hr, "Failed to read dependency registration action."); hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); // Begin session in per-machine process. hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pCache, pVariables, dwRegistrationOperations, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType); ExitOnFailure(hr, "Failed to begin registration session."); LExit: ReleaseStr(sczEngineWorkingPath); return hr; } static HRESULT OnSessionEnd( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_REGISTRATION* pRegistration, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; DWORD dwResumeMode = 0; DWORD dwRestart = 0; DWORD64 qwEstimatedSize = 0; DWORD dwRegistrationType = 0; // Deserialize message data. hr = BuffReadNumber(pbData, cbData, &iData, &dwResumeMode); ExitOnFailure(hr, "Failed to read resume mode enum."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRestart); ExitOnFailure(hr, "Failed to read restart enum."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDetectedForeignProviderKeyBundleCode); ExitOnFailure(hr, "Failed to read dependency registration action."); hr = BuffReadNumber64(pbData, cbData, &iData, &qwEstimatedSize); ExitOnFailure(hr, "Failed to read estimated size."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationType); ExitOnFailure(hr, "Failed to read dependency registration action."); // suspend session in per-machine process hr = RegistrationSessionEnd(pRegistration, pCache, pVariables, pPackages, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType); ExitOnFailure(hr, "Failed to suspend registration session."); LExit: return hr; } static HRESULT OnSaveState( __in BURN_REGISTRATION* pRegistration, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; // save state in per-machine process hr = RegistrationSaveState(pRegistration, pbData, cbData); ExitOnFailure(hr, "Failed to save state."); LExit: return hr; } static HRESULT OnCachePreparePackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR scz = NULL; BURN_PACKAGE* pPackage = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &scz); ExitOnFailure(hr, "Failed to read package id."); if (scz && *scz) { hr = PackageFindById(pPackages, scz, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", scz); } else { hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid data passed to cache prepare package."); } hr = CachePreparePackage(pCache, pPackage); ExitOnFailure(hr, "Failed to prepare cache package."); LExit: ReleaseStr(scz); return hr; } static HRESULT OnCacheCompletePayload( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_PAYLOADS* pPayloads, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR scz = NULL; BURN_PACKAGE* pPackage = NULL; BURN_PAYLOAD* pPayload = NULL; LPWSTR sczUnverifiedPath = NULL; BOOL fMove = FALSE; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &scz); ExitOnFailure(hr, "Failed to read package id."); if (scz && *scz) { hr = PackageFindById(pPackages, scz, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", scz); } hr = BuffReadString(pbData, cbData, &iData, &scz); ExitOnFailure(hr, "Failed to read payload id."); if (scz && *scz) { hr = PayloadFindById(pPayloads, scz, &pPayload); ExitOnFailure(hr, "Failed to find payload: %ls", scz); } hr = BuffReadString(pbData, cbData, &iData, &sczUnverifiedPath); ExitOnFailure(hr, "Failed to read unverified path."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fMove); ExitOnFailure(hr, "Failed to read move flag."); if (pPackage && pPayload) // complete payload. { hr = CacheCompletePayload(pCache, pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe); ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey); } else { hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid data passed to cache complete payload."); } LExit: ReleaseStr(sczUnverifiedPath); ReleaseStr(scz); return hr; } static HRESULT OnCacheVerifyPayload( __in HANDLE hPipe, __in BURN_PACKAGES* pPackages, __in BURN_PAYLOADS* pPayloads, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR scz = NULL; BURN_PACKAGE* pPackage = NULL; BURN_PAYLOAD* pPayload = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &scz); ExitOnFailure(hr, "Failed to read package id."); if (scz && *scz) { hr = PackageFindById(pPackages, scz, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", scz); } hr = BuffReadString(pbData, cbData, &iData, &scz); ExitOnFailure(hr, "Failed to read payload id."); if (scz && *scz) { hr = PayloadFindById(pPayloads, scz, &pPayload); ExitOnFailure(hr, "Failed to find payload: %ls", scz); } if (pPackage && pPayload) { if (!pPackage->sczCacheFolder) { hr = E_INVALIDSTATE; ExitOnRootFailure(hr, "Cache verify payload called without starting its package."); } hr = CacheVerifyPayload(pPayload, pPackage->sczCacheFolder, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe); } else { hr = E_INVALIDARG; ExitOnRootFailure(hr, "Invalid data passed to cache verify payload."); } // Nothing should be logged on failure. LExit: ReleaseStr(scz); return hr; } static void OnCacheCleanup( __in BURN_CACHE* pCache ) { CacheCleanup(TRUE, pCache); } static HRESULT OnProcessDependentRegistration( __in const BURN_REGISTRATION* pRegistration, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; BURN_DEPENDENT_REGISTRATION_ACTION action = { }; // Deserialize message data. hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&action.type); ExitOnFailure(hr, "Failed to read action type."); hr = BuffReadString(pbData, cbData, &iData, &action.sczBundleCode); ExitOnFailure(hr, "Failed to read bundle code."); hr = BuffReadString(pbData, cbData, &iData, &action.sczDependentProviderKey); ExitOnFailure(hr, "Failed to read dependent provider key."); // Execute the registration action. hr = DependencyProcessDependentRegistration(pRegistration, &action); ExitOnFailure(hr, "Failed to execute dependent registration action for provider key: %ls", action.sczDependentProviderKey); LExit: // TODO: do the right thing here. //DependencyUninitializeRegistrationAction(&action); ReleaseStr(action.sczDependentProviderKey); ReleaseStr(action.sczBundleCode) return hr; } 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, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; DWORD dwPlanRelationType = 0; DWORD dwRollback = 0; BURN_EXECUTE_ACTION executeAction = { }; LPWSTR sczIgnoreDependencies = NULL; LPWSTR sczAncestors = NULL; LPWSTR sczEngineWorkingDirectory = NULL; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read related bundle code."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, &dwPlanRelationType); ExitOnFailure(hr, "Failed to read planRelationType."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); ExitOnFailure(hr, "Failed to read rollback."); hr = BuffReadString(pbData, cbData, &iData, &sczIgnoreDependencies); ExitOnFailure(hr, "Failed to read the list of dependencies to ignore."); hr = BuffReadString(pbData, cbData, &iData, &sczAncestors); ExitOnFailure(hr, "Failed to read the list of ancestors."); hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to read the custom working directory."); hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle); ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage); executeAction.relatedBundle.pRelatedBundle->planRelationType = (BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE)dwPlanRelationType; // Pass the list of dependencies to ignore, if any, to the related bundle. if (sczIgnoreDependencies && *sczIgnoreDependencies) { 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.relatedBundle.sczAncestors, sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) { hr = StrAllocString(&executeAction.relatedBundle.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); ExitOnFailure(hr, "Failed to allocate the custom working directory."); } // Execute related bundle. hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast(dwRollback), GenericExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute related bundle."); LExit: ReleaseStr(sczEngineWorkingDirectory); ReleaseStr(sczAncestors); ReleaseStr(sczIgnoreDependencies); ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecuteBundlePackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; BOOL fRollback = FALSE; BOOL fCacheAvailable = FALSE; BURN_EXECUTE_ACTION executeAction = { }; LPWSTR sczIgnoreDependencies = NULL; LPWSTR sczAncestors = NULL; LPWSTR sczEngineWorkingDirectory = NULL; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_BUNDLE_PACKAGE; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read BUNDLE package id."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.bundlePackage.action); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fCacheAvailable); ExitOnFailure(hr, "Failed to read fCacheAvailable."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.bundlePackage.sczParent); ExitOnFailure(hr, "Failed to read the parent."); hr = BuffReadString(pbData, cbData, &iData, &sczIgnoreDependencies); ExitOnFailure(hr, "Failed to read the list of dependencies to ignore."); hr = BuffReadString(pbData, cbData, &iData, &sczAncestors); ExitOnFailure(hr, "Failed to read the list of ancestors."); hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to read the custom working directory."); hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); hr = PackageFindById(pPackages, sczPackage, &executeAction.bundlePackage.pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); if (BURN_PACKAGE_TYPE_BUNDLE != executeAction.bundlePackage.pPackage->type) { ExitWithRootFailure(hr, E_INVALIDARG, "Package is not a BUNDLE package: %ls", sczPackage); } // Pass the list of dependencies to ignore, if any, to the related bundle. if (sczIgnoreDependencies && *sczIgnoreDependencies) { hr = StrAllocString(&executeAction.bundlePackage.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.bundlePackage.sczAncestors, sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) { hr = StrAllocString(&executeAction.bundlePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); ExitOnFailure(hr, "Failed to allocate the custom working directory."); } // Execute BUNDLE package. hr = BundlePackageEngineExecutePackage(&executeAction, pCache, pVariables, fRollback, fCacheAvailable, GenericExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute BUNDLE package."); LExit: ReleaseStr(sczEngineWorkingDirectory); ReleaseStr(sczAncestors); ReleaseStr(sczIgnoreDependencies); ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); 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, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; DWORD dwRollback = 0; BURN_EXECUTE_ACTION executeAction = { }; LPWSTR sczAncestors = NULL; LPWSTR sczEngineWorkingDirectory = NULL; *pRestart = 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 = BuffReadString(pbData, cbData, &iData, &sczAncestors); ExitOnFailure(hr, "Failed to read the list of ancestors."); hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingDirectory); ExitOnFailure(hr, "Failed to read the custom working directory."); 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); if (BURN_PACKAGE_TYPE_EXE != executeAction.exePackage.pPackage->type) { ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage); } // Pass the list of ancestors, if any, to the related bundle. if (sczAncestors && *sczAncestors) { hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0); ExitOnFailure(hr, "Failed to allocate the list of ancestors."); } if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) { hr = StrAllocString(&executeAction.exePackage.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, pRestart); ExitOnFailure(hr, "Failed to execute EXE package."); LExit: ReleaseStr(sczEngineWorkingDirectory); ReleaseStr(sczAncestors); ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecuteMsiPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; HWND hwndParent = NULL; BOOL fRollback = FALSE; BURN_EXECUTE_ACTION executeAction = { }; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE; // Deserialize message data. hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback flag."); hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read MSI package id."); hr = PackageFindById(pPackages, sczPackage, &executeAction.msiPackage.pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent); ExitOnFailure(hr, "Failed to read parent hwnd."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.msiPackage.sczLogPath); ExitOnFailure(hr, "Failed to read package log."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.actionMsiProperty); ExitOnFailure(hr, "Failed to read actionMsiProperty."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.uiLevel); ExitOnFailure(hr, "Failed to read UI level."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.fDisableExternalUiHandler); ExitOnFailure(hr, "Failed to read fDisableExternalUiHandler."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.fileVersioning); ExitOnFailure(hr, "Failed to read fileVersioning."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.action); ExitOnFailure(hr, "Failed to read action."); // Read feature actions. if (executeAction.msiPackage.pPackage->Msi.cFeatures) { executeAction.msiPackage.rgFeatures = (BOOTSTRAPPER_FEATURE_ACTION*)MemAlloc(executeAction.msiPackage.pPackage->Msi.cFeatures * sizeof(BOOTSTRAPPER_FEATURE_ACTION), TRUE); ExitOnNull(executeAction.msiPackage.rgFeatures, hr, E_OUTOFMEMORY, "Failed to allocate memory for feature actions."); for (DWORD i = 0; i < executeAction.msiPackage.pPackage->Msi.cFeatures; ++i) { hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.msiPackage.rgFeatures[i]); ExitOnFailure(hr, "Failed to read feature action."); } } // Read slipstream patches actions. if (executeAction.msiPackage.pPackage->Msi.cSlipstreamMspPackages) { for (DWORD i = 0; i < executeAction.msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++i) { BURN_SLIPSTREAM_MSP* pSlipstreamMsp = executeAction.msiPackage.pPackage->Msi.rgSlipstreamMsps + i; BOOTSTRAPPER_ACTION_STATE* pAction = fRollback ? &pSlipstreamMsp->rollback : &pSlipstreamMsp->execute; hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)pAction); ExitOnFailure(hr, "Failed to read slipstream action."); } } hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); if (BURN_PACKAGE_TYPE_MSI != executeAction.msiPackage.pPackage->type) { ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an MSI package: %ls", sczPackage); } // Execute MSI package. hr = MsiEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute MSI package."); LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecuteMspPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; HWND hwndParent = NULL; BOOL fRollback = FALSE; BURN_EXECUTE_ACTION executeAction = { }; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSP_TARGET; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read MSP package id."); hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent); ExitOnFailure(hr, "Failed to read parent hwnd."); executeAction.mspTarget.fPerMachineTarget = TRUE; // we're in the elevated process, clearly we're targeting a per-machine product. hr = BuffReadString(pbData, cbData, &iData, &executeAction.mspTarget.sczTargetProductCode); ExitOnFailure(hr, "Failed to read target product code."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.mspTarget.sczLogPath); ExitOnFailure(hr, "Failed to read package log."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.actionMsiProperty); ExitOnFailure(hr, "Failed to read actionMsiProperty."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.uiLevel); ExitOnFailure(hr, "Failed to read UI level."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.fDisableExternalUiHandler); ExitOnFailure(hr, "Failed to read fDisableExternalUiHandler."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.fileVersioning); ExitOnFailure(hr, "Failed to read fileVersioning."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.action); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.mspTarget.cOrderedPatches); ExitOnFailure(hr, "Failed to read count of ordered patches."); if (executeAction.mspTarget.cOrderedPatches) { executeAction.mspTarget.rgOrderedPatches = (BURN_ORDERED_PATCHES*)MemAlloc(executeAction.mspTarget.cOrderedPatches * sizeof(BURN_ORDERED_PATCHES), TRUE); ExitOnNull(executeAction.mspTarget.rgOrderedPatches, hr, E_OUTOFMEMORY, "Failed to allocate memory for ordered patches."); for (DWORD i = 0; i < executeAction.mspTarget.cOrderedPatches; ++i) { hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read ordered patch package id."); hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.rgOrderedPatches[i].pPackage); ExitOnFailure(hr, "Failed to find ordered patch package: %ls", sczPackage); } } hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback flag."); if (BURN_PACKAGE_TYPE_MSP != executeAction.mspTarget.pPackage->type) { ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an MSP package: %ls", sczPackage); } // Execute MSP package. hr = MspEngineExecutePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute MSP package."); LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecuteMsuPackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; DWORD dwRollback = 0; DWORD dwStopWusaService = 0; BURN_EXECUTE_ACTION executeAction = { }; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read MSU package id."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.msuPackage.sczLogPath); ExitOnFailure(hr, "Failed to read package log."); hr = BuffReadNumber(pbData, cbData, &iData, reinterpret_cast(&executeAction.msuPackage.action)); ExitOnFailure(hr, "Failed to read action."); hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); ExitOnFailure(hr, "Failed to read rollback."); hr = BuffReadNumber(pbData, cbData, &iData, &dwStopWusaService); ExitOnFailure(hr, "Failed to read StopWusaService."); hr = PackageFindById(pPackages, sczPackage, &executeAction.msuPackage.pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); if (BURN_PACKAGE_TYPE_MSU != executeAction.msuPackage.pPackage->type) { ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an MSU package: %ls", sczPackage); } // execute MSU package hr = MsuEngineExecutePackage(&executeAction, pCache, pVariables, static_cast(dwRollback), static_cast(dwStopWusaService), GenericExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute MSU package."); LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnUninstallMsiCompatiblePackage( __in HANDLE hPipe, __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART* pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackageId = NULL; LPWSTR sczCompatiblePackageId = NULL; HWND hwndParent = NULL; BOOL fRollback = FALSE; BURN_EXECUTE_ACTION executeAction = { }; BURN_PACKAGE* pPackage = NULL; BURN_COMPATIBLE_PACKAGE* pCompatiblePackage = NULL; *pRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; executeAction.type = BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE; // Deserialize message data. hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback flag."); hr = BuffReadString(pbData, cbData, &iData, &sczPackageId); ExitOnFailure(hr, "Failed to read MSI package id."); hr = BuffReadString(pbData, cbData, &iData, &sczCompatiblePackageId); ExitOnFailure(hr, "Failed to read MSI compatible package id."); hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent); ExitOnFailure(hr, "Failed to read parent hwnd."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.uninstallMsiCompatiblePackage.sczLogPath); ExitOnFailure(hr, "Failed to read package log."); hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); ExitOnFailure(hr, "Failed to read variables."); hr = PackageFindById(pPackages, sczPackageId, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId); executeAction.uninstallMsiCompatiblePackage.pParentPackage = pPackage; pCompatiblePackage = &pPackage->compatiblePackage; if (!pCompatiblePackage->fDetected || BURN_PACKAGE_TYPE_MSI != pCompatiblePackage->type || !pCompatiblePackage->compatibleEntry.sczId) { ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible MSI package", sczPackageId); } if (!sczCompatiblePackageId || !*sczCompatiblePackageId || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1)) { ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId); } // Uninstall MSI compatible package. hr = MsiEngineUninstallCompatiblePackage(hwndParent, &executeAction, pCache, pVariables, fRollback, MsiExecuteMessageHandler, hPipe, pRestart); ExitOnFailure(hr, "Failed to execute compatible MSI package."); LExit: ReleaseStr(sczPackageId); ReleaseStr(sczCompatiblePackageId); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecutePackageProviderAction( __in BURN_PACKAGES* pPackages, __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; BOOL fRollback = FALSE; BURN_EXECUTE_ACTION executeAction = { }; executeAction.type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_PROVIDER; // Deserialize the message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read package id from message buffer."); // Find the package again. hr = PackageFindById(pPackages, sczPackage, &executeAction.packageProvider.pPackage); if (E_NOTFOUND == hr) { hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.packageProvider.pPackage); } ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback flag."); // Read provider actions. for (DWORD i = 0; i < executeAction.packageProvider.pPackage->cDependencyProviders; ++i) { BURN_DEPENDENCY_PROVIDER* pProvider = executeAction.packageProvider.pPackage->rgDependencyProviders + i; BURN_DEPENDENCY_ACTION* pAction = fRollback ? &pProvider->providerRollback : &pProvider->providerExecute; hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)pAction); ExitOnFailure(hr, "Failed to read provider action."); } if (!executeAction.packageProvider.pPackage->fPerMachine) { ExitWithRootFailure(hr, E_INVALIDARG, "ExecutePackageProviderAction called for per-user package."); } // Execute the package provider action. hr = DependencyExecutePackageProviderAction(&executeAction, fRollback); ExitOnFailure(hr, "Failed to execute package provider action."); LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT OnExecutePackageDependencyAction( __in BURN_PACKAGES* pPackages, __in BURN_RELATED_BUNDLES* pRelatedBundles, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; BOOL fRollback = FALSE; BURN_EXECUTE_ACTION executeAction = { }; executeAction.type = BURN_EXECUTE_ACTION_TYPE_PACKAGE_DEPENDENCY; // Deserialize the message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read package id from message buffer."); // Find the package again. hr = PackageFindById(pPackages, sczPackage, &executeAction.packageDependency.pPackage); if (E_NOTFOUND == hr) { hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.packageDependency.pPackage); } ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); ExitOnFailure(hr, "Failed to read rollback flag."); hr = BuffReadString(pbData, cbData, &iData, &executeAction.packageDependency.sczBundleProviderKey); ExitOnFailure(hr, "Failed to read bundle dependency key from message buffer."); // Read dependent actions. for (DWORD i = 0; i < executeAction.packageProvider.pPackage->cDependencyProviders; ++i) { BURN_DEPENDENCY_PROVIDER* pProvider = executeAction.packageProvider.pPackage->rgDependencyProviders + i; BURN_DEPENDENCY_ACTION* pAction = fRollback ? &pProvider->dependentRollback : &pProvider->dependentExecute; hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)pAction); ExitOnFailure(hr, "Failed to read dependent action."); } // Execute the package dependency action. hr = DependencyExecutePackageDependencyAction(TRUE, &executeAction, fRollback); ExitOnFailure(hr, "Failed to execute package dependency action."); LExit: ReleaseStr(sczPackage); PlanUninitializeExecuteAction(&executeAction); return hr; } static HRESULT CALLBACK BurnCacheMessageHandler( __in BURN_CACHE_MESSAGE* pMessage, __in LPVOID pvContext ) { HRESULT hr = S_OK; DWORD dwResult = 0; HANDLE hPipe = (HANDLE)pvContext; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwMessage = 0; switch (pMessage->type) { case BURN_CACHE_MESSAGE_BEGIN: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->begin.cacheStep); ExitOnFailure(hr, "Failed to write cache step to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN; break; case BURN_CACHE_MESSAGE_COMPLETE: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->complete.hrStatus); ExitOnFailure(hr, "Failed to write error code to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE; break; case BURN_CACHE_MESSAGE_SUCCESS: hr = BuffWriteNumber64(&pbData, &cbData, pMessage->success.qwFileSize); ExitOnFailure(hr, "Failed to write file size to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS; break; case BURN_CACHE_MESSAGE_FAILURE: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->failure.cacheStep); ExitOnFailure(hr, "Failed to write cache step to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_FAILURE; break; } // send message hr = BurnPipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send burn cache message to per-user process."); hr = dwResult; LExit: ReleaseMem(pbData); return hr; } static DWORD CALLBACK ElevatedProgressRoutine( __in LARGE_INTEGER TotalFileSize, __in LARGE_INTEGER TotalBytesTransferred, __in LARGE_INTEGER /*StreamSize*/, __in LARGE_INTEGER /*StreamBytesTransferred*/, __in DWORD /*dwStreamNumber*/, __in DWORD /*dwCallbackReason*/, __in HANDLE /*hSourceFile*/, __in HANDLE /*hDestinationFile*/, __in_opt LPVOID lpData ) { HRESULT hr = S_OK; DWORD dwResult = 0; HANDLE hPipe = (HANDLE)lpData; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwMessage = BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE; hr = BuffWriteNumber64(&pbData, &cbData, TotalFileSize.QuadPart); ExitOnFailure(hr, "Failed to write total file size progress to message buffer."); hr = BuffWriteNumber64(&pbData, &cbData, TotalBytesTransferred.QuadPart); ExitOnFailure(hr, "Failed to write total bytes transferred progress to message buffer."); // send message hr = BurnPipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send progress routine message to per-user process."); LExit: ReleaseMem(pbData); return dwResult; } static int GenericExecuteMessageHandler( __in GENERIC_EXECUTE_MESSAGE* pMessage, __in LPVOID pvContext ) { HRESULT hr = S_OK; int nResult = IDOK; HANDLE hPipe = (HANDLE)pvContext; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwMessage = 0; hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwUIHint); ExitOnFailure(hr, "Failed to write UI flags."); switch(pMessage->type) { case GENERIC_EXECUTE_MESSAGE_PROGRESS: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->progress.dwPercentage); ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; break; case GENERIC_EXECUTE_MESSAGE_PROCESS_CANCEL: hr = BuffWriteNumber(&pbData, &cbData, pMessage->processCancel.dwProcessId); ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_CANCEL; break; case GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED: dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_STARTED; break; case GENERIC_EXECUTE_MESSAGE_PROCESS_COMPLETED: dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROCESS_COMPLETED; break; case GENERIC_EXECUTE_MESSAGE_ERROR: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); ExitOnFailure(hr, "Failed to write error code to message buffer."); hr = BuffWriteString(&pbData, &cbData, pMessage->error.wzMessage); ExitOnFailure(hr, "Failed to write message to message buffer."); dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR; break; case GENERIC_EXECUTE_MESSAGE_NETFX_FILES_IN_USE: hr = BuffWriteNumber(&pbData, &cbData, pMessage->filesInUse.cFiles); ExitOnFailure(hr, "Failed to count of files in use to message buffer."); for (DWORD i = 0; i < pMessage->filesInUse.cFiles; ++i) { hr = BuffWriteString(&pbData, &cbData, pMessage->filesInUse.rgwzFiles[i]); ExitOnFailure(hr, "Failed to write file in use to message buffer."); } dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_NETFX_FILES_IN_USE; break; } // send message hr = BurnPipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, reinterpret_cast(&nResult)); ExitOnFailure(hr, "Failed to send message to per-user process."); LExit: ReleaseMem(pbData); return nResult; } static int MsiExecuteMessageHandler( __in WIU_MSI_EXECUTE_MESSAGE* pMessage, __in_opt LPVOID pvContext ) { HRESULT hr = S_OK; int nResult = IDOK; HANDLE hPipe = (HANDLE)pvContext; BYTE* pbData = NULL; SIZE_T cbData = 0; DWORD dwMessage = 0; BOOL fRestartManager = FALSE; // Always send any extra data via the struct first. hr = BuffWriteNumber(&pbData, &cbData, pMessage->cData); ExitOnFailure(hr, "Failed to write MSI data count to message buffer."); for (DWORD i = 0; i < pMessage->cData; ++i) { hr = BuffWriteString(&pbData, &cbData, pMessage->rgwzData[i]); ExitOnFailure(hr, "Failed to write MSI data to message buffer."); } hr = BuffWriteNumber(&pbData, &cbData, pMessage->dwUIHint); ExitOnFailure(hr, "Failed to write UI flags."); switch (pMessage->type) { case WIU_MSI_EXECUTE_MESSAGE_PROGRESS: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->progress.dwPercentage); ExitOnFailure(hr, "Failed to write progress percentage to message buffer."); // set message id dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS; break; case WIU_MSI_EXECUTE_MESSAGE_ERROR: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, pMessage->error.dwErrorCode); ExitOnFailure(hr, "Failed to write error code to message buffer."); hr = BuffWriteString(&pbData, &cbData, pMessage->error.wzMessage); ExitOnFailure(hr, "Failed to write message to message buffer."); // set message id dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR; break; case WIU_MSI_EXECUTE_MESSAGE_MSI_MESSAGE: // serialize message data hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pMessage->msiMessage.mt); ExitOnFailure(hr, "Failed to write MSI message type to message buffer."); hr = BuffWriteString(&pbData, &cbData, pMessage->msiMessage.wzMessage); ExitOnFailure(hr, "Failed to write message to message buffer."); // set message id dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE; break; case WIU_MSI_EXECUTE_MESSAGE_MSI_RM_FILES_IN_USE: fRestartManager = TRUE; __fallthrough; case WIU_MSI_EXECUTE_MESSAGE_MSI_FILES_IN_USE: hr = BuffWriteNumber(&pbData, &cbData, (DWORD)fRestartManager); ExitOnFailure(hr, "Failed to write fRestartManager to message buffer."); // set message id dwMessage = BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_FILES_IN_USE; break; default: hr = E_UNEXPECTED; ExitOnFailure(hr, "Invalid MSI execute message type: %d", pMessage->type); } // send message hr = BurnPipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, (DWORD*)&nResult); ExitOnFailure(hr, "Failed to send msi message to per-user process."); LExit: ReleaseMem(pbData); return nResult; } static HRESULT OnCleanCompatiblePackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackageId = NULL; LPWSTR sczCompatiblePackageId = NULL; BURN_PACKAGE* pPackage = NULL; BURN_COMPATIBLE_PACKAGE* pCompatiblePackage = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackageId); ExitOnFailure(hr, "Failed to read package id."); hr = BuffReadString(pbData, cbData, &iData, &sczCompatiblePackageId); ExitOnFailure(hr, "Failed to read compatible package id."); hr = PackageFindById(pPackages, sczPackageId, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId); pCompatiblePackage = &pPackage->compatiblePackage; if (!pCompatiblePackage->fDetected || !pCompatiblePackage->compatibleEntry.sczId || !pCompatiblePackage->sczCacheId || !*pCompatiblePackage->sczCacheId) { ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package to clean.", sczPackageId); } if (!sczCompatiblePackageId || !*sczCompatiblePackageId || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pCompatiblePackage->compatibleEntry.sczId, -1, sczCompatiblePackageId, -1)) { ExitWithRootFailure(hr, E_INVALIDARG, "Package '%ls' has no compatible package with id: %ls", sczPackageId, sczCompatiblePackageId); } // Remove the package from the cache. hr = CacheRemovePackage(pCache, TRUE, pCompatiblePackage->compatibleEntry.sczId, pCompatiblePackage->sczCacheId); ExitOnFailure(hr, "Failed to remove from cache compatible package: %ls", pCompatiblePackage->compatibleEntry.sczId); LExit: ReleaseStr(sczPackageId); ReleaseStr(sczCompatiblePackageId); return hr; } static HRESULT OnCleanPackage( __in BURN_CACHE* pCache, __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczPackage = NULL; BURN_PACKAGE* pPackage = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczPackage); ExitOnFailure(hr, "Failed to read package id."); hr = PackageFindById(pPackages, sczPackage, &pPackage); ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); // Remove the package from the cache. hr = CacheRemovePackage(pCache, TRUE, pPackage->sczId, pPackage->sczCacheId); ExitOnFailure(hr, "Failed to remove from cache package: %ls", pPackage->sczId); LExit: ReleaseStr(sczPackage); return hr; } static HRESULT OnLaunchApprovedExe( __in HANDLE hPipe, __in BURN_APPROVED_EXES* pApprovedExes, __in BURN_CACHE* pCache, __in BURN_VARIABLES* pVariables, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; BURN_LAUNCH_APPROVED_EXE launchApprovedExe = { }; BURN_LAUNCH_APPROVED_EXE* pLaunchApprovedExe = &launchApprovedExe; BURN_APPROVED_EXE* pApprovedExe = NULL; HKEY hKey = NULL; DWORD dwProcessId = 0; BYTE* pbSendData = NULL; SIZE_T cbSendData = 0; DWORD dwResult = 0; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczId); ExitOnFailure(hr, "Failed to read approved exe id."); hr = BuffReadString(pbData, cbData, &iData, &pLaunchApprovedExe->sczArguments); ExitOnFailure(hr, "Failed to read approved exe arguments."); hr = BuffReadNumber(pbData, cbData, &iData, &pLaunchApprovedExe->dwWaitForInputIdleTimeout); ExitOnFailure(hr, "Failed to read approved exe WaitForInputIdle timeout."); hr = ApprovedExesFindById(pApprovedExes, pLaunchApprovedExe->sczId, &pApprovedExe); ExitOnFailure(hr, "The per-user process requested unknown approved exe with id: %ls", pLaunchApprovedExe->sczId); LogId(REPORT_STANDARD, MSG_LAUNCH_APPROVED_EXE_SEARCH, pApprovedExe->sczKey, pApprovedExe->sczValueName ? pApprovedExe->sczValueName : L"", pApprovedExe->fWin64 ? L"yes" : L"no"); hr = RegOpenEx(HKEY_LOCAL_MACHINE, pApprovedExe->sczKey, KEY_QUERY_VALUE, pApprovedExe->fWin64 ? REG_KEY_64BIT : REG_KEY_32BIT, &hKey); ExitOnFailure(hr, "Failed to open the registry key for the approved exe path."); hr = RegReadString(hKey, pApprovedExe->sczValueName, &pLaunchApprovedExe->sczExecutablePath); ExitOnFailure(hr, "Failed to read the value for the approved exe path."); hr = ApprovedExesVerifySecureLocation(pCache, pVariables, pLaunchApprovedExe->sczExecutablePath); ExitOnFailure(hr, "Failed to verify the executable path is in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); if (S_FALSE == hr) { LogStringLine(REPORT_STANDARD, "The executable path is not in a secure location: %ls", pLaunchApprovedExe->sczExecutablePath); ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)); } hr = ApprovedExesLaunch(pVariables, pLaunchApprovedExe, &dwProcessId); ExitOnFailure(hr, "Failed to launch approved exe: %ls", pLaunchApprovedExe->sczExecutablePath); //send process id over pipe hr = BuffWriteNumber(&pbSendData, &cbSendData, dwProcessId); ExitOnFailure(hr, "Failed to write the approved exe process id to message buffer."); hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, pbSendData, cbSendData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID message to per-user process."); LExit: ReleaseMem(pbSendData); ApprovedExesUninitializeLaunch(pLaunchApprovedExe); return hr; } static HRESULT OnMsiBeginTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczId = NULL; LPWSTR sczLogPath = NULL; BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczId); ExitOnFailure(hr, "Failed to read rollback boundary id."); hr = BuffReadString(pbData, cbData, &iData, &sczLogPath); ExitOnFailure(hr, "Failed to read transaction log path."); hr = PackageFindRollbackBoundaryById(pPackages, sczId, &pRollbackBoundary); ExitOnFailure(hr, "Failed to find rollback boundary: %ls", sczId); if (sczLogPath && *sczLogPath) { pRollbackBoundary->sczLogPath = sczLogPath; } hr = MsiEngineBeginTransaction(pRollbackBoundary); LExit: ReleaseStr(sczId); ReleaseStr(sczLogPath); if (pRollbackBoundary) { pRollbackBoundary->sczLogPath = NULL; } return hr; } static HRESULT OnMsiCommitTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART *pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczId = NULL; LPWSTR sczLogPath = NULL; BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczId); ExitOnFailure(hr, "Failed to read rollback boundary id."); hr = BuffReadString(pbData, cbData, &iData, &sczLogPath); ExitOnFailure(hr, "Failed to read transaction log path."); hr = PackageFindRollbackBoundaryById(pPackages, sczId, &pRollbackBoundary); ExitOnFailure(hr, "Failed to find rollback boundary: %ls", sczId); if (sczLogPath && *sczLogPath) { pRollbackBoundary->sczLogPath = sczLogPath; } hr = MsiEngineCommitTransaction(pRollbackBoundary, pRestart); LExit: ReleaseStr(sczId); ReleaseStr(sczLogPath); if (pRollbackBoundary) { pRollbackBoundary->sczLogPath = NULL; } return hr; } static HRESULT OnMsiRollbackTransaction( __in BURN_PACKAGES* pPackages, __in BYTE* pbData, __in SIZE_T cbData, __out BOOTSTRAPPER_APPLY_RESTART *pRestart ) { HRESULT hr = S_OK; SIZE_T iData = 0; LPWSTR sczId = NULL; LPWSTR sczLogPath = NULL; BURN_ROLLBACK_BOUNDARY* pRollbackBoundary = NULL; // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &sczId); ExitOnFailure(hr, "Failed to read rollback boundary id."); hr = BuffReadString(pbData, cbData, &iData, &sczLogPath); ExitOnFailure(hr, "Failed to read transaction log path."); hr = PackageFindRollbackBoundaryById(pPackages, sczId, &pRollbackBoundary); ExitOnFailure(hr, "Failed to find rollback boundary: %ls", sczId); if (sczLogPath && *sczLogPath) { pRollbackBoundary->sczLogPath = sczLogPath; } hr = MsiEngineRollbackTransaction(pRollbackBoundary, pRestart); LExit: ReleaseStr(sczId); ReleaseStr(sczLogPath); if (pRollbackBoundary) { pRollbackBoundary->sczLogPath = NULL; } return hr; } static HRESULT ElevatedOnPauseAUBegin( __in HANDLE hPipe ) { HRESULT hr = S_OK; DWORD dwResult = 0; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_BEGIN, NULL, 0, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_BEGIN message to per-user process."); LExit: return hr; } static HRESULT ElevatedOnPauseAUComplete( __in HANDLE hPipe, __in HRESULT hrStatus ) { HRESULT hr = S_OK; BYTE* pbSendData = NULL; SIZE_T cbSendData = 0; DWORD dwResult = 0; hr = BuffWriteNumber(&pbSendData, &cbSendData, hrStatus); ExitOnFailure(hr, "Failed to write the pause au status to message buffer."); hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE, pbSendData, cbSendData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE message to per-user process."); LExit: ReleaseMem(pbSendData); return hr; } static HRESULT ElevatedOnSystemRestorePointBegin( __in HANDLE hPipe ) { HRESULT hr = S_OK; DWORD dwResult = 0; hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN, NULL, 0, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN message to per-user process."); LExit: return hr; } static HRESULT ElevatedOnSystemRestorePointComplete( __in HANDLE hPipe, __in HRESULT hrStatus ) { HRESULT hr = S_OK; BYTE* pbSendData = NULL; SIZE_T cbSendData = 0; DWORD dwResult = 0; hr = BuffWriteNumber(&pbSendData, &cbSendData, hrStatus); ExitOnFailure(hr, "Failed to write the system restore point status to message buffer."); hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE, pbSendData, cbSendData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE message to per-user process."); LExit: ReleaseMem(pbSendData); return hr; } static HRESULT ElevatedOnExecuteActionComplete( __in HANDLE hPipe, __in BOOTSTRAPPER_APPLY_RESTART restart ) { HRESULT hr = S_OK; BYTE* pbSendData = NULL; SIZE_T cbSendData = 0; DWORD dwResult = 0; hr = BuffWriteNumber(&pbSendData, &cbSendData, restart); ExitOnFailure(hr, "Failed to write the restart type to message buffer."); hr = BurnPipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE, pbSendData, cbSendData, NULL, NULL, &dwResult); ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ACTION_COMPLETE message to per-user process."); LExit: ReleaseMem(pbSendData); return hr; }