From ec413164bd0285d1e9b9d36538974641a109b579 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Wed, 29 Jun 2022 10:29:14 -0500 Subject: Add embedded test. --- src/burn/test/BurnUnitTest/EmbeddedTest.cpp | 175 ++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 src/burn/test/BurnUnitTest/EmbeddedTest.cpp (limited to 'src/burn/test/BurnUnitTest/EmbeddedTest.cpp') diff --git a/src/burn/test/BurnUnitTest/EmbeddedTest.cpp b/src/burn/test/BurnUnitTest/EmbeddedTest.cpp new file mode 100644 index 00000000..cac1ba81 --- /dev/null +++ b/src/burn/test/BurnUnitTest/EmbeddedTest.cpp @@ -0,0 +1,175 @@ +// 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 HRESULT S_TEST_SUCCEEDED = 0x3133; +const DWORD TEST_EXIT_CODE = 666; + +struct BUNDLE_RUNNER_CONTEXT +{ + DWORD dwResult; +}; + + +static BOOL STDAPICALLTYPE EmbeddedTest_CreateProcessW( + __in_opt LPCWSTR lpApplicationName, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, + __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, + __in BOOL bInheritHandles, + __in DWORD dwCreationFlags, + __in_opt LPVOID lpEnvironment, + __in_opt LPCWSTR lpCurrentDirectory, + __in LPSTARTUPINFOW lpStartupInfo, + __out LPPROCESS_INFORMATION lpProcessInformation + ); +static DWORD CALLBACK EmbeddedTest_ThreadProc( + __in LPVOID lpThreadParameter + ); +static int EmbeddedTest_GenericMessageHandler( + __in GENERIC_EXECUTE_MESSAGE* pMessage, + __in LPVOID pvContext + ); + +namespace Microsoft +{ +namespace Tools +{ +namespace WindowsInstallerXml +{ +namespace Test +{ +namespace Bootstrapper +{ + using namespace System; + using namespace System::IO; + using namespace System::Threading; + using namespace Xunit; + + public ref class EmbeddedTest : BurnUnitTest + { + public: + EmbeddedTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture) + { + } + + [Fact] + void EmbeddedProtocolTest() + { + HRESULT hr = S_OK; + BUNDLE_RUNNER_CONTEXT bundleRunnerContext = { }; + DWORD dwExitCode = 0; + + try + { + CoreFunctionOverride(EmbeddedTest_CreateProcessW, ThrdWaitForCompletion); + + // + // bundle runner setup + // + hr = EmbeddedRunBundle(L"C:\\ignored\\target.exe", L"\"C:\\ignored\\target.exe\"", NULL, EmbeddedTest_GenericMessageHandler, &bundleRunnerContext, &dwExitCode); + TestThrowOnFailure(hr, L"Failed to run embedded bundle."); + + // check results + Assert::Equal(S_TEST_SUCCEEDED, (HRESULT)bundleRunnerContext.dwResult); + Assert::Equal(TEST_EXIT_CODE, dwExitCode); + } + finally + { + } + } + }; +} +} +} +} +} + + +static BOOL STDAPICALLTYPE EmbeddedTest_CreateProcessW( + __in_opt LPCWSTR /*lpApplicationName*/, + __inout_opt LPWSTR lpCommandLine, + __in_opt LPSECURITY_ATTRIBUTES /*lpProcessAttributes*/, + __in_opt LPSECURITY_ATTRIBUTES /*lpThreadAttributes*/, + __in BOOL /*bInheritHandles*/, + __in DWORD /*dwCreationFlags*/, + __in_opt LPVOID /*lpEnvironment*/, + __in_opt LPCWSTR /*lpCurrentDirectory*/, + __in LPSTARTUPINFOW /*lpStartupInfo*/, + __out LPPROCESS_INFORMATION lpProcessInformation + ) +{ + HRESULT hr = S_OK; + LPWSTR scz = NULL; + LPCWSTR wzArgs = lpCommandLine + 24; //skip '"C:\ignored\target.exe" ' + + hr = StrAllocString(&scz, wzArgs, 0); + ExitOnFailure(hr, "Failed to copy arguments."); + + // Pretend this thread is the embedded process. + lpProcessInformation->hProcess = ::CreateThread(NULL, 0, EmbeddedTest_ThreadProc, scz, 0, NULL); + ExitOnNullWithLastError(lpProcessInformation->hProcess, hr, "Failed to create thread."); + + scz = NULL; + +LExit: + ReleaseStr(scz); + + return SUCCEEDED(hr); +} + +static DWORD CALLBACK EmbeddedTest_ThreadProc( + __in LPVOID lpThreadParameter + ) +{ + HRESULT hr = S_OK; + LPWSTR sczArguments = (LPWSTR)lpThreadParameter; + BURN_ENGINE_STATE engineState = { }; + BURN_PIPE_CONNECTION* pConnection = &engineState.embeddedConnection; + DWORD dwResult = 0; + + engineState.internalCommand.mode = BURN_MODE_EMBEDDED; + + PipeConnectionInitialize(pConnection); + + StrAlloc(&pConnection->sczName, MAX_PATH); + StrAlloc(&pConnection->sczSecret, MAX_PATH); + + // parse command line arguments + if (3 != swscanf_s(sczArguments, L"-burn.embedded %s %s %u", pConnection->sczName, MAX_PATH, pConnection->sczSecret, MAX_PATH, &pConnection->dwProcessId)) + { + ExitWithRootFailure(hr, E_INVALIDARG, "Failed to parse argument string."); + } + + // set up connection with parent bundle runner + hr = PipeChildConnect(pConnection, FALSE); + ExitOnFailure(hr, "Failed to connect to parent bundle runner."); + + // post known message + hr = ExternalEngineSendEmbeddedError(&engineState, S_TEST_SUCCEEDED, NULL, 0, reinterpret_cast(&dwResult)); + ExitOnFailure(hr, "Failed to post known message to parent bundle runner."); + +LExit: + PipeConnectionUninitialize(pConnection); + ReleaseStr(sczArguments); + + return FAILED(hr) ? (DWORD)hr : dwResult; +} + +static int EmbeddedTest_GenericMessageHandler( + __in GENERIC_EXECUTE_MESSAGE* pMessage, + __in LPVOID pvContext + ) +{ + BUNDLE_RUNNER_CONTEXT* pContext = reinterpret_cast(pvContext); + DWORD dwResult = 0; + + if (GENERIC_EXECUTE_MESSAGE_ERROR == pMessage->type) + { + pContext->dwResult = pMessage->error.dwErrorCode; + dwResult = TEST_EXIT_CODE; + } + + return dwResult; +} -- cgit v1.2.3-55-g6feb