From 0d3d54992104288e9ee0c834d0b96e8502fd2d42 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Thu, 11 Jan 2024 18:26:20 -0800 Subject: Move the BootstrapperApplication out of proc --- src/burn/engine/baengine.cpp | 1532 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1532 insertions(+) create mode 100644 src/burn/engine/baengine.cpp (limited to 'src/burn/engine/baengine.cpp') diff --git a/src/burn/engine/baengine.cpp b/src/burn/engine/baengine.cpp new file mode 100644 index 00000000..e63836f4 --- /dev/null +++ b/src/burn/engine/baengine.cpp @@ -0,0 +1,1532 @@ +// 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" + + +static DWORD WINAPI BAEngineMessagePumpThreadProc( + __in LPVOID lpThreadParameter +); +static void CALLBACK FreeQueueItem( + __in void* pvValue, + __in void* /*pvContext*/ +); + + +extern "C" HRESULT BAEngineCreateContext( + __in BURN_ENGINE_STATE *pEngineState, + __inout BAENGINE_CONTEXT** ppContext +) +{ + HRESULT hr = S_OK; + BAENGINE_CONTEXT* pContext = NULL; + + pContext = static_cast(MemAlloc(sizeof(BAENGINE_CONTEXT), TRUE)); + ExitOnNull(pContext, hr, E_OUTOFMEMORY, "Failed to allocate bootstrapper application engine context."); + + ::InitializeCriticalSection(&pContext->csQueue); + + pContext->hQueueSemaphore = ::CreateSemaphoreW(NULL, 0, LONG_MAX, NULL); + ExitOnNullWithLastError(pContext->hQueueSemaphore, hr, "Failed to create semaphore for queue."); + + hr = QueCreate(&pContext->hQueue); + ExitOnFailure(hr, "Failed to create queue for bootstrapper engine."); + + pContext->pEngineState = pEngineState; + + *ppContext = pContext; + pContext = NULL; + +LExit: + if (pContext) + { + BAEngineFreeContext(pContext); + pContext = NULL; + } + + return hr; +} + +extern "C" void BAEngineFreeContext( + __in BAENGINE_CONTEXT* pContext +) +{ + PipeRpcUninitiailize(&pContext->hRpcPipe); + ReleaseQueue(pContext->hQueue, FreeQueueItem, pContext); + ReleaseHandle(pContext->hQueueSemaphore); + ::DeleteCriticalSection(&pContext->csQueue); +} + +extern "C" void DAPI BAEngineFreeAction( + __in BAENGINE_ACTION * pAction +) +{ + switch (pAction->dwMessage) + { + case WM_BURN_LAUNCH_APPROVED_EXE: + ApprovedExesUninitializeLaunch(&pAction->launchApprovedExe); + break; + } + + MemFree(pAction); +} + +extern "C" HRESULT BAEngineStartListening( + __in BAENGINE_CONTEXT *pContext, + __in HANDLE hBAEnginePipe +) +{ + HRESULT hr = S_OK; + + if (PipeRpcInitialized(&pContext->hRpcPipe)) + { + ExitWithRootFailure(hr, E_INVALIDARG, "Bootstrapper application engine already listening on a pipe."); + } + + PipeRpcInitialize(&pContext->hRpcPipe, hBAEnginePipe, TRUE); + + pContext->hThread = ::CreateThread(NULL, 0, BAEngineMessagePumpThreadProc, pContext, 0, NULL); + ExitOnNullWithLastError(pContext->hThread, hr, "Failed to create bootstrapper application engine thread."); + +LExit: + return hr; +} + +extern "C" HRESULT BAEngineStopListening( + __in BAENGINE_CONTEXT * pContext +) +{ + HRESULT hr = S_OK; + + // If the pipe was open, this should cause the bootstrapper application engine pipe thread to stop pumping messages and exit. + if (PipeRpcInitialized(&pContext->hRpcPipe)) + { + PipeWriteDisconnect(pContext->hRpcPipe.hPipe); + + PipeRpcUninitiailize(&pContext->hRpcPipe); + } + + if (pContext->hThread) + { + hr = AppWaitForSingleObject(pContext->hThread, INFINITE); + + ReleaseHandle(pContext->hThread); // always release the thread, no matter if we were able to wait for it to join or not. + + ExitOnFailure(hr, "Failed to wait for bootstrapper application engine pipe thread."); + } + +LExit: + return hr; +} + +static void CALLBACK FreeQueueItem( + __in void* pvValue, + __in void* /*pvContext*/ +) +{ + BAENGINE_ACTION* pAction = reinterpret_cast(pvValue); + + LogId(REPORT_WARNING, MSG_IGNORE_OPERATION_AFTER_QUIT, LoggingBurnMessageToString(pAction->dwMessage)); + + BAEngineFreeAction(pAction); + MemFree(pAction); +} + +static HRESULT BAEngineGetPackageCount( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_GETPACKAGECOUNT_ARGS args = { }; + BAENGINE_GETPACKAGECOUNT_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetPackageCount args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetPackageCount results."); + + // Execute. + ExternalEngineGetPackageCount(pContext->pEngineState, &results.cPackages); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineGetPackageCount struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cPackages); + ExitOnFailure(hr, "Failed to write length of value of BAEngineGetPackageCount struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineGetVariableNumeric( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_GETVARIABLENUMERIC_ARGS args = { }; + BAENGINE_GETVARIABLENUMERIC_RESULTS results = { }; + LPWSTR sczVariable = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableNumeric args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable name of BAEngineGetVariableNumeric args."); + + args.wzVariable = sczVariable; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableNumeric results."); + + // Execute. + hr = ExternalEngineGetVariableNumeric(pContext->pEngineState, args.wzVariable, &results.llValue); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineGetVariableNumeric struct."); + + hr = BuffWriteNumber64ToBuffer(pBuffer, (DWORD64)results.llValue); + ExitOnFailure(hr, "Failed to write length of value of BAEngineGetVariableNumeric struct."); + +LExit: + ReleaseStr(sczVariable); + return hr; +} + +static HRESULT BAEngineGetVariableString( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_GETVARIABLESTRING_ARGS args = { }; + BAENGINE_GETVARIABLESTRING_RESULTS results = { }; + LPWSTR sczVariable = NULL; + LPWSTR sczValue = NULL; + DWORD cchValue = 0; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableString args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable name of BAEngineGetVariableString args."); + + args.wzVariable = sczVariable; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableString results."); + + hr = BuffReaderReadNumber(pReaderResults, &cchValue); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableString results."); + + results.cchValue = cchValue; + + // Execute. + hr = VariableGetString(&pContext->pEngineState->variables, args.wzVariable, &sczValue); + if (E_NOTFOUND == hr) + { + ExitFunction(); + } + ExitOnFailure(hr, "Failed to get string variable: %ls", sczVariable); + + results.cchValue = lstrlenW(sczValue); + results.wzValue = sczValue; + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineGetVariableString struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cchValue); + ExitOnFailure(hr, "Failed to write length of value of BAEngineGetVariableString struct."); + + hr = BuffWriteStringToBuffer(pBuffer, results.wzValue); + ExitOnFailure(hr, "Failed to write value of BAEngineGetVariableString struct."); + +LExit: + ReleaseStr(sczValue); + ReleaseStr(sczVariable); + + return hr; +} + +static HRESULT BAEngineGetVariableVersion( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_GETVARIABLEVERSION_ARGS args = { }; + BAENGINE_GETVARIABLEVERSION_RESULTS results = { }; + LPWSTR sczVariable = NULL; + VERUTIL_VERSION* pVersion = NULL; + DWORD cchValue = 0; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableVersion args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable name of BAEngineGetVariableVersion args."); + + args.wzVariable = sczVariable; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableVersion results."); + + hr = BuffReaderReadNumber(pReaderResults, &cchValue); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetVariableVersion results."); + + results.cchValue = cchValue; + + // Execute. + hr = VariableGetVersion(&pContext->pEngineState->variables, args.wzVariable, &pVersion); + ExitOnFailure(hr, "Failed to get version variable: %ls", sczVariable); + + results.cchValue = lstrlenW(pVersion->sczVersion); + results.wzValue = pVersion->sczVersion; + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineGetVariableVersion struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cchValue); + ExitOnFailure(hr, "Failed to write length of value of BAEngineGetVariableVersion struct."); + + hr = BuffWriteStringToBuffer(pBuffer, results.wzValue); + ExitOnFailure(hr, "Failed to write value of BAEngineGetVariableVersion struct."); + +LExit: + ReleaseVerutilVersion(pVersion); + ReleaseStr(sczVariable); + + return hr; +} + +static HRESULT BAEngineGetRelatedBundleVariable( + __in BAENGINE_CONTEXT* /* pContext */, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_GETRELATEDBUNDLEVARIABLE_ARGS args = { }; + BAENGINE_GETRELATEDBUNDLEVARIABLE_RESULTS results = { }; + LPWSTR sczBundleId = NULL; + LPWSTR sczVariable = NULL; + LPWSTR sczValue = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetRelatedBundleVariable args."); + + hr = BuffReaderReadString(pReaderArgs, &sczBundleId); + ExitOnFailure(hr, "Failed to read bundle id of BAEngineGetRelatedBundleVariable args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable name of BAEngineGetRelatedBundleVariable args."); + + args.wzBundleId = sczBundleId; + args.wzVariable = sczVariable; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineGetRelatedBundleVariable results."); + + hr = BuffReaderReadNumber(pReaderResults, &results.cchValue); // ignored, overwritten below. + ExitOnFailure(hr, "Failed to read API version of BAEngineGetRelatedBundleVariable results."); + + // Execute. + hr = BundleGetBundleVariable(args.wzBundleId, args.wzVariable, &sczValue); + ExitOnFailure(hr, "Failed to get related bundle variable: %ls", sczVariable); + + results.cchValue = lstrlenW(sczValue); + results.wzValue = sczValue; + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineGetRelatedBundleVariable struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cchValue); + ExitOnFailure(hr, "Failed to write length of value of BAEngineGetRelatedBundleVariable struct."); + + hr = BuffWriteStringToBuffer(pBuffer, results.wzValue); + ExitOnFailure(hr, "Failed to write value of BAEngineGetRelatedBundleVariable struct."); + +LExit: + ReleaseStr(sczValue); + ReleaseStr(sczVariable); + ReleaseStr(sczBundleId); + + return hr; +} + +static HRESULT BAEngineFormatString( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_FORMATSTRING_ARGS args = { }; + BAENGINE_FORMATSTRING_RESULTS results = { }; + LPWSTR sczIn = NULL; + LPWSTR sczOut = NULL; + SIZE_T cchOut = 0; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineFormatString args."); + + hr = BuffReaderReadString(pReaderArgs, &sczIn); + ExitOnFailure(hr, "Failed to read string to format of BAEngineFormatString args."); + + args.wzIn = sczIn; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineFormatString results."); + + hr = BuffReaderReadNumber(pReaderResults, &results.cchOut); // ignored, overwritten below. + ExitOnFailure(hr, "Failed to read allowed length of formatted string of BAEngineFormatString results."); + + // Execute. + hr = VariableFormatString(&pContext->pEngineState->variables, args.wzIn, &sczOut, &cchOut); + ExitOnFailure(hr, "Failed to format string"); + + results.cchOut = (cchOut > DWORD_MAX) ? DWORD_MAX : static_cast(cchOut); + results.wzOut = sczOut; + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineFormatString struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cchOut); + ExitOnFailure(hr, "Failed to write length of formatted string of BAEngineFormatString struct."); + + hr = BuffWriteStringToBuffer(pBuffer, results.wzOut); + ExitOnFailure(hr, "Failed to write formatted string of BAEngineFormatString struct."); + +LExit: + ReleaseStr(sczOut); + ReleaseStr(sczIn); + + return hr; +} + +static HRESULT BAEngineEscapeString( + __in BAENGINE_CONTEXT* /* pContext */, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_ESCAPESTRING_ARGS args = { }; + BAENGINE_ESCAPESTRING_RESULTS results = { }; + LPWSTR sczIn = NULL; + LPWSTR sczOut = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineEscapeString args."); + + hr = BuffReaderReadString(pReaderArgs, &sczIn); + ExitOnFailure(hr, "Failed to read string to escape of BAEngineEscapeString args."); + + args.wzIn = sczIn; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineEscapeString results."); + + hr = BuffReaderReadNumber(pReaderResults, &results.cchOut); // ignored, overwritten below. + ExitOnFailure(hr, "Failed to read allowed length of escaped string of BAEngineEscapeString results."); + + // Execute. + hr = VariableEscapeString(args.wzIn, &sczOut); + ExitOnFailure(hr, "Failed to format string"); + + results.cchOut = lstrlenW(sczOut); + results.wzOut = sczOut; + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineEscapeString struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.cchOut); + ExitOnFailure(hr, "Failed to write length of formatted string of BAEngineEscapeString struct."); + + hr = BuffWriteStringToBuffer(pBuffer, results.wzOut); + ExitOnFailure(hr, "Failed to write formatted string of BAEngineEscapeString struct."); + +LExit: + ReleaseStr(sczOut); + ReleaseStr(sczIn); + + return hr; +} + +static HRESULT BAEngineEvaluateCondition( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_EVALUATECONDITION_ARGS args = { }; + BAENGINE_EVALUATECONDITION_RESULTS results = { }; + LPWSTR sczCondition = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineEvaluateCondition args."); + + hr = BuffReaderReadString(pReaderArgs, &sczCondition); + ExitOnFailure(hr, "Failed to read condition of BAEngineEvaluateCondition args."); + + args.wzCondition = sczCondition; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineEvaluateCondition results."); + + // Execute. + hr = ConditionEvaluate(&pContext->pEngineState->variables, args.wzCondition, &results.f); + ExitOnFailure(hr, "Failed to evalute condition."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineEvaluateCondition struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.f); + ExitOnFailure(hr, "Failed to result of BAEngineEvaluateCondition struct."); + +LExit: + ReleaseStr(sczCondition); + + return hr; +} + +static HRESULT BAEngineLog( + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_LOG_ARGS args = { }; + BAENGINE_LOG_RESULTS results = { }; + LPWSTR sczMessage = NULL; + REPORT_LEVEL rl = REPORT_NONE; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineLog args."); + + hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast(&args.level)); + ExitOnFailure(hr, "Failed to read API version of BAEngineLog args."); + + hr = BuffReaderReadString(pReaderArgs, &sczMessage); + ExitOnFailure(hr, "Failed to read variable name of BAEngineLog args."); + + switch (args.level) + { + case BOOTSTRAPPER_LOG_LEVEL_STANDARD: + rl = REPORT_STANDARD; + break; + + case BOOTSTRAPPER_LOG_LEVEL_VERBOSE: + rl = REPORT_VERBOSE; + break; + + case BOOTSTRAPPER_LOG_LEVEL_DEBUG: + rl = REPORT_DEBUG; + break; + + case BOOTSTRAPPER_LOG_LEVEL_ERROR: + rl = REPORT_ERROR; + break; + + default: + ExitFunction1(hr = E_INVALIDARG); + } + + args.wzMessage = sczMessage; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineLog results."); + + // Execute. + hr = ExternalEngineLog(rl, args.wzMessage); + ExitOnFailure(hr, "Failed to log BA message."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineLog struct."); + +LExit: + ReleaseStr(sczMessage); + return hr; +} + +static HRESULT BAEngineSendEmbeddedError( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SENDEMBEDDEDERROR_ARGS args = { }; + BAENGINE_SENDEMBEDDEDERROR_RESULTS results = { }; + LPWSTR sczMessage = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSendEmbeddedError args."); + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwErrorCode); + ExitOnFailure(hr, "Failed to read error code of BAEngineSendEmbeddedError args."); + + hr = BuffReaderReadString(pReaderArgs, &sczMessage); + ExitOnFailure(hr, "Failed to read condition of BAEngineSendEmbeddedError args."); + + args.wzMessage = sczMessage; + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwUIHint); + ExitOnFailure(hr, "Failed to read UI hint of BAEngineSendEmbeddedError args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSendEmbeddedError results."); + + // Execute. + hr = ExternalEngineSendEmbeddedError(pContext->pEngineState, args.dwErrorCode, args.wzMessage, args.dwUIHint, &results.nResult); + ExitOnFailure(hr, "Failed to send embedded error."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSendEmbeddedError struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.nResult); + ExitOnFailure(hr, "Failed to result of BAEngineSendEmbeddedError struct."); + +LExit: + ReleaseStr(sczMessage); + return hr; +} + +static HRESULT BAEngineSendEmbeddedProgress( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SENDEMBEDDEDPROGRESS_ARGS args = { }; + BAENGINE_SENDEMBEDDEDPROGRESS_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSendEmbeddedProgress args."); + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwProgressPercentage); + ExitOnFailure(hr, "Failed to read progress of BAEngineSendEmbeddedProgress args."); + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwOverallProgressPercentage); + ExitOnFailure(hr, "Failed to read overall progress of BAEngineSendEmbeddedProgress args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSendEmbeddedProgress results."); + + // Execute. + hr = ExternalEngineSendEmbeddedProgress(pContext->pEngineState, args.dwProgressPercentage, args.dwOverallProgressPercentage, &results.nResult); + ExitOnFailure(hr, "Failed to send embedded error."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSendEmbeddedProgress struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.nResult); + ExitOnFailure(hr, "Failed to result of BAEngineSendEmbeddedProgress struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineSetUpdate( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETUPDATE_ARGS args = { }; + BAENGINE_SETUPDATE_RESULTS results = { }; + LPWSTR sczLocalSource = NULL; + LPWSTR sczDownloadSource = NULL; + LPWSTR sczHash = NULL; + LPWSTR sczUpdatePackageId = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetUpdate args."); + + hr = BuffReaderReadString(pReaderArgs, &sczLocalSource); + ExitOnFailure(hr, "Failed to read local source of BAEngineSetUpdate args."); + + args.wzLocalSource = sczLocalSource; + + hr = BuffReaderReadString(pReaderArgs, &sczDownloadSource); + ExitOnFailure(hr, "Failed to read download source of BAEngineSetUpdate args."); + + args.wzDownloadSource = sczDownloadSource; + + hr = BuffReaderReadNumber64(pReaderArgs, &args.qwSize); + ExitOnFailure(hr, "Failed to read update size of BAEngineSetUpdate args."); + + hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast(&args.hashType)); + ExitOnFailure(hr, "Failed to read hash type of BAEngineSetUpdate args."); + + hr = BuffReaderReadString(pReaderArgs, &sczHash); + ExitOnFailure(hr, "Failed to read hash of BAEngineSetUpdate args."); + + args.wzHash = sczHash; + + hr = BuffReaderReadString(pReaderArgs, &sczUpdatePackageId); + ExitOnFailure(hr, "Failed to read update package id of BAEngineSetUpdate args."); + + args.wzUpdatePackageId = sczUpdatePackageId; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetUpdate results."); + + // Execute. + hr = ExternalEngineSetUpdate(pContext->pEngineState, args.wzLocalSource, args.wzDownloadSource, args.qwSize, args.hashType, args.wzHash, args.wzUpdatePackageId); + ExitOnFailure(hr, "Failed to set update."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetUpdate struct."); + +LExit: + ReleaseStr(sczUpdatePackageId); + ReleaseStr(sczHash); + ReleaseStr(sczDownloadSource); + ReleaseStr(sczLocalSource); + return hr; +} + +static HRESULT BAEngineSetLocalSource( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETLOCALSOURCE_ARGS args = { }; + BAENGINE_SETLOCALSOURCE_RESULTS results = { }; + LPWSTR sczPackageOrContainerId = NULL; + LPWSTR sczPayloadId = NULL; + LPWSTR sczPath = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetLocalSource args."); + + hr = BuffReaderReadString(pReaderArgs, &sczPackageOrContainerId); + ExitOnFailure(hr, "Failed to read package or container id of BAEngineSetLocalSource args."); + + args.wzPackageOrContainerId = sczPackageOrContainerId; + + hr = BuffReaderReadString(pReaderArgs, &sczPayloadId); + ExitOnFailure(hr, "Failed to read payload id of BAEngineSetLocalSource args."); + + args.wzPayloadId = sczPayloadId; + + hr = BuffReaderReadString(pReaderArgs, &sczPath); + ExitOnFailure(hr, "Failed to read path of BAEngineSetLocalSource args."); + + args.wzPath = sczPath; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetLocalSource results."); + + // Execute. + hr = ExternalEngineSetLocalSource(pContext->pEngineState, args.wzPackageOrContainerId, args.wzPayloadId, args.wzPath); + ExitOnFailure(hr, "Failed to set local source."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetLocalSource struct."); + +LExit: + ReleaseStr(sczPath); + ReleaseStr(sczPayloadId); + ReleaseStr(sczPackageOrContainerId); + return hr; +} + +static HRESULT BAEngineSetDownloadSource( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETDOWNLOADSOURCE_ARGS args = { }; + BAENGINE_SETDOWNLOADSOURCE_RESULTS results = { }; + LPWSTR sczPackageOrContainerId = NULL; + LPWSTR sczPayloadId = NULL; + LPWSTR sczUrl = NULL; + LPWSTR sczUser = NULL; + LPWSTR sczPassword = NULL; + LPWSTR sczAuthorizationHeader = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetDownloadSource args."); + + hr = BuffReaderReadString(pReaderArgs, &sczPackageOrContainerId); + ExitOnFailure(hr, "Failed to read package or container id of BAEngineSetDownloadSource args."); + + args.wzPackageOrContainerId = sczPackageOrContainerId; + + hr = BuffReaderReadString(pReaderArgs, &sczPayloadId); + ExitOnFailure(hr, "Failed to read payload id of BAEngineSetDownloadSource args."); + + args.wzPayloadId = sczPayloadId; + + hr = BuffReaderReadString(pReaderArgs, &sczUrl); + ExitOnFailure(hr, "Failed to read url of BAEngineSetDownloadSource args."); + + args.wzUrl = sczUrl; + + hr = BuffReaderReadString(pReaderArgs, &sczUser); + ExitOnFailure(hr, "Failed to read user of BAEngineSetDownloadSource args."); + + args.wzUser = sczUser; + + hr = BuffReaderReadString(pReaderArgs, &sczPassword); + ExitOnFailure(hr, "Failed to read password of BAEngineSetDownloadSource args."); + + args.wzPassword = sczPassword; + + hr = BuffReaderReadString(pReaderArgs, &sczAuthorizationHeader); + ExitOnFailure(hr, "Failed to read authorization header of BAEngineSetDownloadSource args."); + + args.wzAuthorizationHeader = sczAuthorizationHeader; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetDownloadSource results."); + + // Execute. + hr = ExternalEngineSetDownloadSource(pContext->pEngineState, args.wzPackageOrContainerId, args.wzPayloadId, args.wzUrl, args.wzUser, args.wzPassword, args.wzAuthorizationHeader); + ExitOnFailure(hr, "Failed to set download source."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetDownloadSource struct."); + +LExit: + ReleaseStr(sczAuthorizationHeader); + ReleaseStr(sczPassword); + ReleaseStr(sczUser); + ReleaseStr(sczUrl); + ReleaseStr(sczPayloadId); + ReleaseStr(sczPackageOrContainerId); + return hr; +} + + +static HRESULT BAEngineSetVariableNumeric( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETVARIABLENUMERIC_ARGS args = { }; + BAENGINE_SETVARIABLENUMERIC_RESULTS results = { }; + LPWSTR sczVariable = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableNumeric args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable of BAEngineSetVariableNumeric args."); + + args.wzVariable = sczVariable; + + hr = BuffReaderReadNumber64(pReaderArgs, reinterpret_cast(&args.llValue)); + ExitOnFailure(hr, "Failed to read formatted flag of BAEngineSetVariableNumeric results."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableNumeric results."); + + // Execute. + hr = ExternalEngineSetVariableNumeric(pContext->pEngineState, args.wzVariable, args.llValue); + ExitOnFailure(hr, "Failed to set numeric variable."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetVariableNumeric struct."); + +LExit: + ReleaseStr(sczVariable); + return hr; +} + +static HRESULT BAEngineSetVariableString( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETVARIABLESTRING_ARGS args = { }; + BAENGINE_SETVARIABLESTRING_RESULTS results = { }; + LPWSTR sczVariable = NULL; + LPWSTR sczValue = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableString args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable of BAEngineSetVariableString args."); + + args.wzVariable = sczVariable; + + hr = BuffReaderReadString(pReaderArgs, &sczValue); + ExitOnFailure(hr, "Failed to read value of BAEngineSetVariableString args."); + + args.wzValue = sczValue; + + hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast(&args.fFormatted)); + ExitOnFailure(hr, "Failed to read formatted flag of BAEngineSetVariableString results."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableString results."); + + // Execute. + hr = ExternalEngineSetVariableString(pContext->pEngineState, args.wzVariable, args.wzValue, args.fFormatted); + ExitOnFailure(hr, "Failed to set string variable."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetVariableString struct."); + +LExit: + ReleaseStr(sczValue); + ReleaseStr(sczVariable); + return hr; +} + +static HRESULT BAEngineSetVariableVersion( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETVARIABLEVERSION_ARGS args = { }; + BAENGINE_SETVARIABLEVERSION_RESULTS results = { }; + LPWSTR sczVariable = NULL; + LPWSTR sczValue = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableVersion args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVariable); + ExitOnFailure(hr, "Failed to read variable of BAEngineSetVariableVersion args."); + + args.wzVariable = sczVariable; + + hr = BuffReaderReadString(pReaderArgs, &sczValue); + ExitOnFailure(hr, "Failed to read value of BAEngineSetVariableVersion args."); + + args.wzValue = sczValue; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetVariableVersion results."); + + // Execute. + hr = ExternalEngineSetVariableVersion(pContext->pEngineState, args.wzVariable, args.wzValue); + ExitOnFailure(hr, "Failed to set variable version."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetVariableVersion struct."); + +LExit: + ReleaseStr(sczValue); + ReleaseStr(sczVariable); + return hr; +} + +static HRESULT BAEngineCloseSplashScreen( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_CLOSESPLASHSCREEN_ARGS args = { }; + BAENGINE_CLOSESPLASHSCREEN_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineCloseSplashScreen args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineCloseSplashScreen results."); + + // Execute. + ExternalEngineCloseSplashScreen(pContext->pEngineState); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineCloseSplashScreen struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineCompareVersions( + __in BAENGINE_CONTEXT* /* pContext */, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_COMPAREVERSIONS_ARGS args = { }; + BAENGINE_COMPAREVERSIONS_RESULTS results = { }; + LPWSTR sczVersion1 = NULL; + LPWSTR sczVersion2 = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineCompareVersions args."); + + hr = BuffReaderReadString(pReaderArgs, &sczVersion1); + ExitOnFailure(hr, "Failed to read first input of BAEngineCompareVersions args."); + + args.wzVersion1 = sczVersion1; + + hr = BuffReaderReadString(pReaderArgs, &sczVersion2); + ExitOnFailure(hr, "Failed to read second input of BAEngineCompareVersions args."); + + args.wzVersion2 = sczVersion2; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineCompareVersions results."); + + // Execute. + hr = ExternalEngineCompareVersions(args.wzVersion1, args.wzVersion2, &results.nResult); + ExitOnFailure(hr, "Failed to compare versions."); + + // Write results. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineCompareVersions struct."); + + hr = BuffWriteNumberToBuffer(pBuffer, results.nResult); + ExitOnFailure(hr, "Failed to result of BAEngineCompareVersions struct."); + +LExit: + ReleaseStr(sczVersion2); + ReleaseStr(sczVersion1); + + return hr; +} + +static HRESULT BAEngineDetect( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_DETECT_ARGS args = { }; + BAENGINE_DETECT_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineDetect args."); + + hr = BuffReaderReadNumber64(pReaderArgs, &args.hwndParent); + ExitOnFailure(hr, "Failed to read parent window of BAEngineDetect args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineDetect results."); + + // Execute. + hr = ExternalEngineDetect(pContext, reinterpret_cast(args.hwndParent)); + ExitOnFailure(hr, "Failed to detect in the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineDetect struct."); + +LExit: + return hr; +} + +static HRESULT BAEnginePlan( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_PLAN_ARGS args = { }; + BAENGINE_PLAN_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEnginePlan args."); + + hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast(&args.action)); + ExitOnFailure(hr, "Failed to read plan action of BAEnginePlan args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEnginePlan results."); + + // Execute. + hr = ExternalEnginePlan(pContext, args.action); + ExitOnFailure(hr, "Failed to plan in the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEnginePlan struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineElevate( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_ELEVATE_ARGS args = { }; + BAENGINE_ELEVATE_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineElevate args."); + + hr = BuffReaderReadNumber64(pReaderArgs, &args.hwndParent); + ExitOnFailure(hr, "Failed to read parent window of BAEngineElevate args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineElevate results."); + + // Execute. + hr = ExternalEngineElevate(pContext, reinterpret_cast(args.hwndParent)); + ExitOnFailure(hr, "Failed to detect in the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineElevate struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineApply( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_APPLY_ARGS args = { }; + BAENGINE_APPLY_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineApply args."); + + hr = BuffReaderReadNumber64(pReaderArgs, &args.hwndParent); + ExitOnFailure(hr, "Failed to read parent window of BAEngineApply args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineApply results."); + + // Execute. + hr = ExternalEngineApply(pContext, reinterpret_cast(args.hwndParent)); + ExitOnFailure(hr, "Failed to detect in the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineApply struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineQuit( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_QUIT_ARGS args = { }; + BAENGINE_QUIT_RESULTS results = { }; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineQuit args."); + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwExitCode); + ExitOnFailure(hr, "Failed to read API version of BAEngineQuit args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineQuit results."); + + // Execute. + hr = ExternalEngineQuit(pContext, args.dwExitCode); + ExitOnFailure(hr, "Failed to quit the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineQuit struct."); + +LExit: + return hr; +} + +static HRESULT BAEngineLaunchApprovedExe( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_LAUNCHAPPROVEDEXE_ARGS args = { }; + BAENGINE_LAUNCHAPPROVEDEXE_RESULTS results = { }; + LPWSTR sczApprovedExeForElevationId = NULL; + LPWSTR sczArguments = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineLaunchApprovedExe args."); + + hr = BuffReaderReadNumber64(pReaderArgs, &args.hwndParent); + ExitOnFailure(hr, "Failed to read parent window of BAEngineLaunchApprovedExe args."); + + hr = BuffReaderReadString(pReaderArgs, &sczApprovedExeForElevationId); + ExitOnFailure(hr, "Failed to read approved exe elevation id of BAEngineLaunchApprovedExe args."); + + args.wzApprovedExeForElevationId = sczApprovedExeForElevationId; + + hr = BuffReaderReadString(pReaderArgs, &sczArguments); + ExitOnFailure(hr, "Failed to read arguments of BAEngineLaunchApprovedExe args."); + + args.wzArguments = sczArguments; + + hr = BuffReaderReadNumber(pReaderArgs, &args.dwWaitForInputIdleTimeout); + ExitOnFailure(hr, "Failed to read wait for idle input timeout of BAEngineLaunchApprovedExe args."); + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineLaunchApprovedExe results."); + + // Execute. + hr = ExternalEngineLaunchApprovedExe(pContext, reinterpret_cast(args.hwndParent), args.wzApprovedExeForElevationId, args.wzArguments, args.dwWaitForInputIdleTimeout); + ExitOnFailure(hr, "Failed to quit the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineLaunchApprovedExe struct."); + +LExit: + ReleaseStr(sczArguments); + ReleaseStr(sczApprovedExeForElevationId); + return hr; +} + +static HRESULT BAEngineSetUpdateSource( + __in BAENGINE_CONTEXT* pContext, + __in BUFF_READER* pReaderArgs, + __in BUFF_READER* pReaderResults, + __in BUFF_BUFFER* pBuffer + ) +{ + HRESULT hr = S_OK; + BAENGINE_SETUPDATESOURCE_ARGS args = { }; + BAENGINE_SETUPDATESOURCE_RESULTS results = { }; + LPWSTR sczUrl = NULL; + LPWSTR sczAuthorizationHeader = NULL; + + // Read args. + hr = BuffReaderReadNumber(pReaderArgs, &args.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetUpdateSource args."); + + hr = BuffReaderReadString(pReaderArgs, &sczUrl); + ExitOnFailure(hr, "Failed to read url of BAEngineSetUpdateSource args."); + + args.wzUrl = sczUrl; + + hr = BuffReaderReadString(pReaderArgs, &sczAuthorizationHeader); + ExitOnFailure(hr, "Failed to read authorization header of BAEngineSetUpdateSource args."); + + args.wzAuthorizationHeader = sczAuthorizationHeader; + + // Read results. + hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); + ExitOnFailure(hr, "Failed to read API version of BAEngineSetUpdateSource results."); + + // Execute. + hr = ExternalEngineSetUpdateSource(pContext->pEngineState, args.wzUrl, args.wzAuthorizationHeader); + ExitOnFailure(hr, "Failed to set update source in the engine."); + + // Pack result. + hr = BuffWriteNumberToBuffer(pBuffer, sizeof(results)); + ExitOnFailure(hr, "Failed to write size of BAEngineSetUpdateSource struct."); + +LExit: + ReleaseStr(sczAuthorizationHeader); + ReleaseStr(sczUrl); + + return hr; +} + +static HRESULT ParseArgsAndResults( + __in_bcount(cbData) LPCBYTE pbData, + __in SIZE_T cbData, + __in BUFF_READER* pBufferArgs, + __in BUFF_READER* pBufferResults +) +{ + HRESULT hr = S_OK; + SIZE_T iData = 0; + DWORD dw = 0; + + // Get the args reader size and point to the data just after the size. + hr = BuffReadNumber(pbData, cbData, &iData, &dw); + ExitOnFailure(hr, "Failed to parse size of args"); + + pBufferArgs->pbData = pbData + iData; + pBufferArgs->cbData = dw; + pBufferArgs->iBuffer = 0; + + // Get the results reader size and point to the data just after the size. + hr = ::SIZETAdd(iData, dw, &iData); + ExitOnFailure(hr, "Failed to advance index beyond args"); + + hr = BuffReadNumber(pbData, cbData, &iData, &dw); + ExitOnFailure(hr, "Failed to parse size of results"); + + pBufferResults->pbData = pbData + iData; + pBufferResults->cbData = dw; + pBufferResults->iBuffer = 0; + +LExit: + return hr; +} + +HRESULT WINAPI EngineForApplicationProc( + __in BAENGINE_CONTEXT* pContext, + __in BOOTSTRAPPER_ENGINE_MESSAGE message, + __in_bcount(cbData) LPCBYTE pbData, + __in SIZE_T cbData + ) +{ + HRESULT hr = S_OK; + BUFF_READER readerArgs = { }; + BUFF_READER readerResults = { }; + BUFF_BUFFER bufferResponse = { }; + + hr = ParseArgsAndResults(pbData, cbData, &readerArgs, &readerResults); + if (SUCCEEDED(hr)) + { + switch (message) + { + case BOOTSTRAPPER_ENGINE_MESSAGE_GETPACKAGECOUNT: + hr = BAEngineGetPackageCount(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_GETVARIABLENUMERIC: + hr = BAEngineGetVariableNumeric(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_GETVARIABLESTRING: + hr = BAEngineGetVariableString(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_GETVARIABLEVERSION: + hr = BAEngineGetVariableVersion(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_FORMATSTRING: + hr = BAEngineFormatString(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_ESCAPESTRING: + hr = BAEngineEscapeString(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_EVALUATECONDITION: + hr = BAEngineEvaluateCondition(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_LOG: + hr = BAEngineLog(&readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SENDEMBEDDEDERROR: + hr = BAEngineSendEmbeddedError(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SENDEMBEDDEDPROGRESS: + hr = BAEngineSendEmbeddedProgress(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETUPDATE: + hr = BAEngineSetUpdate(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETLOCALSOURCE: + hr = BAEngineSetLocalSource(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETDOWNLOADSOURCE: + hr = BAEngineSetDownloadSource(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETVARIABLENUMERIC: + hr = BAEngineSetVariableNumeric(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETVARIABLESTRING: + hr = BAEngineSetVariableString(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETVARIABLEVERSION: + hr = BAEngineSetVariableVersion(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_CLOSESPLASHSCREEN: + hr = BAEngineCloseSplashScreen(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_DETECT: + hr = BAEngineDetect(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_PLAN: + hr = BAEnginePlan(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_ELEVATE: + hr = BAEngineElevate(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_APPLY: + hr = BAEngineApply(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_QUIT: + hr = BAEngineQuit(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_LAUNCHAPPROVEDEXE: + hr = BAEngineLaunchApprovedExe(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_SETUPDATESOURCE: + hr = BAEngineSetUpdateSource(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_COMPAREVERSIONS: + hr = BAEngineCompareVersions(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + case BOOTSTRAPPER_ENGINE_MESSAGE_GETRELATEDBUNDLEVARIABLE: + hr = BAEngineGetRelatedBundleVariable(pContext, &readerArgs, &readerResults, &bufferResponse); + break; + default: + hr = E_NOTIMPL; + break; + } + } + + hr = PipeRpcResponse(&pContext->hRpcPipe, message, hr, bufferResponse.pbData, bufferResponse.cbData); + ExitOnFailure(hr, "Failed to send engine result to bootstrapper application."); + +LExit: + ReleaseBuffer(bufferResponse); + return hr; +} + +static DWORD WINAPI BAEngineMessagePumpThreadProc( + __in LPVOID lpThreadParameter +) +{ + HRESULT hr = S_OK; + BOOL fComInitialized = FALSE; + BAENGINE_CONTEXT* pContext = reinterpret_cast(lpThreadParameter); + PIPE_MESSAGE msg = { }; + + // initialize COM + hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + ExitOnFailure(hr, "Failed to initialize COM."); + fComInitialized = TRUE; + + // Pump messages from bootstrapper application for engine messages until the pipe is closed. + while (S_OK == (hr = PipeRpcReadMessage(&pContext->hRpcPipe, &msg))) + { + EngineForApplicationProc(pContext, static_cast(msg.dwMessageType), reinterpret_cast(msg.pvData), msg.cbData); + + ReleasePipeMessage(&msg); + } + ExitOnFailure(hr, "Failed to get message over bootstrapper application pipe"); + + if (S_FALSE == hr) + { + hr = S_OK; + } + +LExit: + ReleasePipeMessage(&msg); + + if (fComInitialized) + { + ::CoUninitialize(); + } + + return (DWORD)hr; +} -- cgit v1.2.3-55-g6feb