aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-06-29 10:29:14 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-06-29 15:08:37 -0500
commitec413164bd0285d1e9b9d36538974641a109b579 (patch)
treea8c38c1c1c883eee7897efa179ce1379384871c8 /src/burn
parent7cca75c8e95f129a21c33f1f4568e90e9e397f9d (diff)
downloadwix-ec413164bd0285d1e9b9d36538974641a109b579.tar.gz
wix-ec413164bd0285d1e9b9d36538974641a109b579.tar.bz2
wix-ec413164bd0285d1e9b9d36538974641a109b579.zip
Add embedded test.
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/core.cpp35
-rw-r--r--src/burn/engine/core.h23
-rw-r--r--src/burn/engine/embedded.cpp9
-rw-r--r--src/burn/engine/engine.cpp9
-rw-r--r--src/burn/engine/exeengine.cpp15
-rw-r--r--src/burn/engine/netfxchainer.cpp8
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj1
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters3
-rw-r--r--src/burn/test/BurnUnitTest/ElevationTest.cpp2
-rw-r--r--src/burn/test/BurnUnitTest/EmbeddedTest.cpp175
-rw-r--r--src/burn/test/BurnUnitTest/precomp.h1
11 files changed, 248 insertions, 33 deletions
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 716e5af1..90bbc8f6 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -12,6 +12,7 @@ struct BURN_CACHE_THREAD_CONTEXT
12}; 12};
13 13
14 14
15static PFN_CREATEPROCESSW vpfnCreateProcessW = ::CreateProcessW;
15static PFN_PROCWAITFORCOMPLETION vpfnProcWaitForCompletion = ProcWaitForCompletion; 16static PFN_PROCWAITFORCOMPLETION vpfnProcWaitForCompletion = ProcWaitForCompletion;
16 17
17 18
@@ -1947,12 +1948,46 @@ LExit:
1947} 1948}
1948 1949
1949extern "C" void CoreFunctionOverride( 1950extern "C" void CoreFunctionOverride(
1951 __in_opt PFN_CREATEPROCESSW pfnCreateProcessW,
1950 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion 1952 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion
1951 ) 1953 )
1952{ 1954{
1955 vpfnCreateProcessW = pfnCreateProcessW;
1953 vpfnProcWaitForCompletion = pfnProcWaitForCompletion; 1956 vpfnProcWaitForCompletion = pfnProcWaitForCompletion;
1954} 1957}
1955 1958
1959extern "C" HRESULT CoreCreateProcess(
1960 __in_opt LPCWSTR wzApplicationName,
1961 __inout_opt LPWSTR sczCommandLine,
1962 __in BOOL fInheritHandles,
1963 __in DWORD dwCreationFlags,
1964 __in_opt LPCWSTR wzCurrentDirectory,
1965 __in WORD wShowWindow,
1966 __out LPPROCESS_INFORMATION pProcessInformation
1967 )
1968{
1969 HRESULT hr = S_OK;
1970 STARTUPINFOW si = { };
1971 size_t cchCurrentDirectory = 0;
1972
1973 // CreateProcessW has undocumented MAX_PATH restriction for lpCurrentDirectory even when long path support is enabled.
1974 if (wzCurrentDirectory && FAILED(::StringCchLengthW(wzCurrentDirectory, MAX_PATH - 1, &cchCurrentDirectory)))
1975 {
1976 wzCurrentDirectory = NULL;
1977 }
1978
1979 si.cb = sizeof(si);
1980 si.wShowWindow = wShowWindow;
1981
1982 if (!vpfnCreateProcessW(wzApplicationName, sczCommandLine, NULL, NULL, fInheritHandles, dwCreationFlags, NULL, wzCurrentDirectory, &si, pProcessInformation))
1983 {
1984 ExitWithLastError(hr, "CreateProcessW failed with return code: %d", Dutil_er);
1985 }
1986
1987LExit:
1988 return hr;
1989}
1990
1956extern "C" HRESULT DAPI CoreWaitForProcCompletion( 1991extern "C" HRESULT DAPI CoreWaitForProcCompletion(
1957 __in HANDLE hProcess, 1992 __in HANDLE hProcess,
1958 __in DWORD dwTimeout, 1993 __in DWORD dwTimeout,
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 14dbabcc..31f63ed4 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -174,6 +174,19 @@ typedef struct _BURN_APPLY_CONTEXT
174 DWORD dwCacheCheckpoint; 174 DWORD dwCacheCheckpoint;
175} BURN_APPLY_CONTEXT; 175} BURN_APPLY_CONTEXT;
176 176
177typedef BOOL (STDAPICALLTYPE *PFN_CREATEPROCESSW)(
178 __in_opt LPCWSTR lpApplicationName,
179 __inout_opt LPWSTR lpCommandLine,
180 __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
181 __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
182 __in BOOL bInheritHandles,
183 __in DWORD dwCreationFlags,
184 __in_opt LPVOID lpEnvironment,
185 __in_opt LPCWSTR lpCurrentDirectory,
186 __in LPSTARTUPINFOW lpStartupInfo,
187 __out LPPROCESS_INFORMATION lpProcessInformation
188 );
189
177typedef HRESULT (DAPI *PFN_PROCWAITFORCOMPLETION)( 190typedef HRESULT (DAPI *PFN_PROCWAITFORCOMPLETION)(
178 __in HANDLE hProcess, 191 __in HANDLE hProcess,
179 __in DWORD dwTimeout, 192 __in DWORD dwTimeout,
@@ -287,8 +300,18 @@ HRESULT CoreParseCommandLine(
287 __inout HANDLE* phSourceEngineFile 300 __inout HANDLE* phSourceEngineFile
288 ); 301 );
289void CoreFunctionOverride( 302void CoreFunctionOverride(
303 __in_opt PFN_CREATEPROCESSW pfnCreateProcessW,
290 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion 304 __in_opt PFN_PROCWAITFORCOMPLETION pfnProcWaitForCompletion
291 ); 305 );
306HRESULT CoreCreateProcess(
307 __in_opt LPCWSTR wzApplicationName,
308 __inout_opt LPWSTR sczCommandLine,
309 __in BOOL fInheritHandles,
310 __in DWORD dwCreationFlags,
311 __in_opt LPCWSTR wzCurrentDirectory,
312 __in WORD wShowWindow,
313 __out LPPROCESS_INFORMATION pProcessInformation
314 );
292HRESULT DAPI CoreWaitForProcCompletion( 315HRESULT DAPI CoreWaitForProcCompletion(
293 __in HANDLE hProcess, 316 __in HANDLE hProcess,
294 __in DWORD dwTimeout, 317 __in DWORD dwTimeout,
diff --git a/src/burn/engine/embedded.cpp b/src/burn/engine/embedded.cpp
index 58af5574..4c3de98e 100644
--- a/src/burn/engine/embedded.cpp
+++ b/src/burn/engine/embedded.cpp
@@ -52,7 +52,6 @@ extern "C" HRESULT EmbeddedRunBundle(
52 DWORD dwCurrentProcessId = ::GetCurrentProcessId(); 52 DWORD dwCurrentProcessId = ::GetCurrentProcessId();
53 HANDLE hCreatedPipesEvent = NULL; 53 HANDLE hCreatedPipesEvent = NULL;
54 LPWSTR sczCommand = NULL; 54 LPWSTR sczCommand = NULL;
55 STARTUPINFOW si = { };
56 PROCESS_INFORMATION pi = { }; 55 PROCESS_INFORMATION pi = { };
57 BURN_PIPE_RESULT result = { }; 56 BURN_PIPE_RESULT result = { };
58 57
@@ -79,10 +78,8 @@ extern "C" HRESULT EmbeddedRunBundle(
79 ExitOnFailure(hr, "Failed to append user args."); 78 ExitOnFailure(hr, "Failed to append user args.");
80 } 79 }
81 80
82 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 81 hr = CoreCreateProcess(wzExecutablePath, sczCommand, TRUE, CREATE_NO_WINDOW, NULL, 0, &pi);
83 { 82 ExitOnFailure(hr, "Failed to create embedded process at path: %ls", wzExecutablePath);
84 ExitWithLastError(hr, "Failed to create embedded process at path: %ls", wzExecutablePath);
85 }
86 83
87 connection.dwProcessId = ::GetProcessId(pi.hProcess); 84 connection.dwProcessId = ::GetProcessId(pi.hProcess);
88 connection.hProcess = pi.hProcess; 85 connection.hProcess = pi.hProcess;
@@ -95,7 +92,7 @@ extern "C" HRESULT EmbeddedRunBundle(
95 ExitOnFailure(hr, "Failed to process messages from embedded message."); 92 ExitOnFailure(hr, "Failed to process messages from embedded message.");
96 93
97 // Get the return code from the embedded process. 94 // Get the return code from the embedded process.
98 hr = ProcWaitForCompletion(connection.hProcess, INFINITE, pdwExitCode); 95 hr = CoreWaitForProcCompletion(connection.hProcess, INFINITE, pdwExitCode);
99 ExitOnFailure(hr, "Failed to wait for embedded executable: %ls", wzExecutablePath); 96 ExitOnFailure(hr, "Failed to wait for embedded executable: %ls", wzExecutablePath);
100 97
101LExit: 98LExit:
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 13075497..413db69b 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -445,7 +445,6 @@ static HRESULT RunUntrusted(
445 LPWSTR sczCachedCleanRoomBundlePath = NULL; 445 LPWSTR sczCachedCleanRoomBundlePath = NULL;
446 LPWSTR sczParameters = NULL; 446 LPWSTR sczParameters = NULL;
447 LPWSTR sczFullCommandLine = NULL; 447 LPWSTR sczFullCommandLine = NULL;
448 STARTUPINFOW si = { };
449 PROCESS_INFORMATION pi = { }; 448 PROCESS_INFORMATION pi = { };
450 HANDLE hFileAttached = NULL; 449 HANDLE hFileAttached = NULL;
451 HANDLE hFileSelf = NULL; 450 HANDLE hFileSelf = NULL;
@@ -484,12 +483,8 @@ static HRESULT RunUntrusted(
484 hr = StrAllocFormattedSecure(&sczFullCommandLine, L"\"%ls\" %ls", wzCleanRoomBundlePath, sczParameters); 483 hr = StrAllocFormattedSecure(&sczFullCommandLine, L"\"%ls\" %ls", wzCleanRoomBundlePath, sczParameters);
485 ExitOnFailure(hr, "Failed to allocate full command-line."); 484 ExitOnFailure(hr, "Failed to allocate full command-line.");
486 485
487 si.cb = sizeof(si); 486 hr = CoreCreateProcess(wzCleanRoomBundlePath, sczFullCommandLine, TRUE, 0, NULL, static_cast<WORD>(pEngineState->command.nCmdShow), &pi);
488 si.wShowWindow = static_cast<WORD>(pEngineState->command.nCmdShow); 487 ExitOnFailure(hr, "Failed to launch clean room process: %ls", sczFullCommandLine);
489 if (!::CreateProcessW(wzCleanRoomBundlePath, sczFullCommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
490 {
491 ExitWithLastError(hr, "Failed to launch clean room process: %ls", sczFullCommandLine);
492 }
493 488
494 hProcess = pi.hProcess; 489 hProcess = pi.hProcess;
495 pi.hProcess = NULL; 490 pi.hProcess = NULL;
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index 701adb74..1168f5ea 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -687,7 +687,6 @@ extern "C" HRESULT ExeEngineRunProcess(
687{ 687{
688 HRESULT hr = S_OK; 688 HRESULT hr = S_OK;
689 LPWSTR sczCommand = NULL; 689 LPWSTR sczCommand = NULL;
690 STARTUPINFOW si = { };
691 PROCESS_INFORMATION pi = { }; 690 PROCESS_INFORMATION pi = { };
692 GENERIC_EXECUTE_MESSAGE message = { }; 691 GENERIC_EXECUTE_MESSAGE message = { };
693 int nResult = IDNOACTION; 692 int nResult = IDNOACTION;
@@ -695,7 +694,6 @@ extern "C" HRESULT ExeEngineRunProcess(
695 BOOL fDelayedCancel = FALSE; 694 BOOL fDelayedCancel = FALSE;
696 BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget; 695 BOOL fFireAndForget = BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fFireAndForget;
697 BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type; 696 BOOL fInheritHandles = BURN_PACKAGE_TYPE_BUNDLE == pPackage->type;
698 size_t cchCachedDirectory = 0;
699 697
700 // Always add user supplied arguments last. 698 // Always add user supplied arguments last.
701 if (wzUserArgs) 699 if (wzUserArgs)
@@ -704,19 +702,10 @@ extern "C" HRESULT ExeEngineRunProcess(
704 ExitOnFailure(hr, "Failed to append user args."); 702 ExitOnFailure(hr, "Failed to append user args.");
705 } 703 }
706 704
707 // CreateProcessW has undocumented MAX_PATH restriction for lpCurrentDirectory even when long path support is enabled.
708 if (wzCachedDirectory && FAILED(::StringCchLengthW(wzCachedDirectory, MAX_PATH - 1, &cchCachedDirectory)))
709 {
710 wzCachedDirectory = NULL;
711 }
712
713 // Make the cache location of the executable the current directory to help those executables 705 // Make the cache location of the executable the current directory to help those executables
714 // that expect stuff to be relative to them. 706 // that expect stuff to be relative to them.
715 si.cb = sizeof(si); 707 hr = CoreCreateProcess(wzExecutablePath, sczCommand ? sczCommand : sczBaseCommand, fInheritHandles, CREATE_NO_WINDOW, wzCachedDirectory, 0, &pi);
716 if (!::CreateProcessW(wzExecutablePath, sczCommand ? sczCommand : sczBaseCommand, NULL, NULL, fInheritHandles, CREATE_NO_WINDOW, NULL, wzCachedDirectory, &si, &pi)) 708 ExitOnFailure(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
717 {
718 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
719 }
720 709
721 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED; 710 message.type = GENERIC_EXECUTE_MESSAGE_PROCESS_STARTED;
722 message.dwUIHint = MB_OK; 711 message.dwUIHint = MB_OK;
diff --git a/src/burn/engine/netfxchainer.cpp b/src/burn/engine/netfxchainer.cpp
index 68ddb093..86a06373 100644
--- a/src/burn/engine/netfxchainer.cpp
+++ b/src/burn/engine/netfxchainer.cpp
@@ -345,7 +345,6 @@ extern "C" HRESULT NetFxRunChainer(
345 LPWSTR sczSectionName = NULL; 345 LPWSTR sczSectionName = NULL;
346 LPWSTR sczCommand = NULL; 346 LPWSTR sczCommand = NULL;
347 NetFxChainer* pNetfxChainer = NULL; 347 NetFxChainer* pNetfxChainer = NULL;
348 STARTUPINFOW si = { };
349 PROCESS_INFORMATION pi = { }; 348 PROCESS_INFORMATION pi = { };
350 HRESULT hrInternalError = 0; 349 HRESULT hrInternalError = 0;
351 350
@@ -372,11 +371,8 @@ extern "C" HRESULT NetFxRunChainer(
372 ExitOnFailure(hr, "Failed to append user args."); 371 ExitOnFailure(hr, "Failed to append user args.");
373 } 372 }
374 373
375 si.cb = sizeof(si); 374 hr = CoreCreateProcess(wzExecutablePath, sczCommand, FALSE, CREATE_NO_WINDOW, NULL, 0, &pi);
376 if (!::CreateProcessW(wzExecutablePath, sczCommand, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 375 ExitOnFailure(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
377 {
378 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", wzExecutablePath);
379 }
380 376
381 HANDLE handles[2] = { pi.hProcess, pNetfxChainer->hEventChaineeSend }; 377 HANDLE handles[2] = { pi.hProcess, pNetfxChainer->hEventChaineeSend };
382 378
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
index f07418a7..5f8004b4 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -47,6 +47,7 @@
47 <ClCompile Include="AssemblyInfo.cpp" /> 47 <ClCompile Include="AssemblyInfo.cpp" />
48 <ClCompile Include="CacheTest.cpp" /> 48 <ClCompile Include="CacheTest.cpp" />
49 <ClCompile Include="ElevationTest.cpp" /> 49 <ClCompile Include="ElevationTest.cpp" />
50 <ClCompile Include="EmbeddedTest.cpp" />
50 <ClCompile Include="ManifestHelpers.cpp" /> 51 <ClCompile Include="ManifestHelpers.cpp" />
51 <ClCompile Include="ManifestTest.cpp" /> 52 <ClCompile Include="ManifestTest.cpp" />
52 <ClCompile Include="PlanTest.cpp" /> 53 <ClCompile Include="PlanTest.cpp" />
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
index 90290f52..9cfe9ee6 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj.filters
@@ -24,6 +24,9 @@
24 <ClCompile Include="ElevationTest.cpp"> 24 <ClCompile Include="ElevationTest.cpp">
25 <Filter>Source Files</Filter> 25 <Filter>Source Files</Filter>
26 </ClCompile> 26 </ClCompile>
27 <ClCompile Include="EmbeddedTest.cpp">
28 <Filter>Source Files</Filter>
29 </ClCompile>
27 <ClCompile Include="ManifestHelpers.cpp"> 30 <ClCompile Include="ManifestHelpers.cpp">
28 <Filter>Source Files</Filter> 31 <Filter>Source Files</Filter>
29 </ClCompile> 32 </ClCompile>
diff --git a/src/burn/test/BurnUnitTest/ElevationTest.cpp b/src/burn/test/BurnUnitTest/ElevationTest.cpp
index ce34b4b1..8d4cc7ff 100644
--- a/src/burn/test/BurnUnitTest/ElevationTest.cpp
+++ b/src/burn/test/BurnUnitTest/ElevationTest.cpp
@@ -61,7 +61,7 @@ namespace Bootstrapper
61 try 61 try
62 { 62 {
63 ShelFunctionOverride(ElevateTest_ShellExecuteExW); 63 ShelFunctionOverride(ElevateTest_ShellExecuteExW);
64 CoreFunctionOverride(ThrdWaitForCompletion); 64 CoreFunctionOverride(NULL, ThrdWaitForCompletion);
65 65
66 PipeConnectionInitialize(pConnection); 66 PipeConnectionInitialize(pConnection);
67 67
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 @@
1// 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.
2
3#include "precomp.h"
4
5
6const HRESULT S_TEST_SUCCEEDED = 0x3133;
7const DWORD TEST_EXIT_CODE = 666;
8
9struct BUNDLE_RUNNER_CONTEXT
10{
11 DWORD dwResult;
12};
13
14
15static BOOL STDAPICALLTYPE EmbeddedTest_CreateProcessW(
16 __in_opt LPCWSTR lpApplicationName,
17 __inout_opt LPWSTR lpCommandLine,
18 __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
19 __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
20 __in BOOL bInheritHandles,
21 __in DWORD dwCreationFlags,
22 __in_opt LPVOID lpEnvironment,
23 __in_opt LPCWSTR lpCurrentDirectory,
24 __in LPSTARTUPINFOW lpStartupInfo,
25 __out LPPROCESS_INFORMATION lpProcessInformation
26 );
27static DWORD CALLBACK EmbeddedTest_ThreadProc(
28 __in LPVOID lpThreadParameter
29 );
30static int EmbeddedTest_GenericMessageHandler(
31 __in GENERIC_EXECUTE_MESSAGE* pMessage,
32 __in LPVOID pvContext
33 );
34
35namespace Microsoft
36{
37namespace Tools
38{
39namespace WindowsInstallerXml
40{
41namespace Test
42{
43namespace Bootstrapper
44{
45 using namespace System;
46 using namespace System::IO;
47 using namespace System::Threading;
48 using namespace Xunit;
49
50 public ref class EmbeddedTest : BurnUnitTest
51 {
52 public:
53 EmbeddedTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture)
54 {
55 }
56
57 [Fact]
58 void EmbeddedProtocolTest()
59 {
60 HRESULT hr = S_OK;
61 BUNDLE_RUNNER_CONTEXT bundleRunnerContext = { };
62 DWORD dwExitCode = 0;
63
64 try
65 {
66 CoreFunctionOverride(EmbeddedTest_CreateProcessW, ThrdWaitForCompletion);
67
68 //
69 // bundle runner setup
70 //
71 hr = EmbeddedRunBundle(L"C:\\ignored\\target.exe", L"\"C:\\ignored\\target.exe\"", NULL, EmbeddedTest_GenericMessageHandler, &bundleRunnerContext, &dwExitCode);
72 TestThrowOnFailure(hr, L"Failed to run embedded bundle.");
73
74 // check results
75 Assert::Equal<HRESULT>(S_TEST_SUCCEEDED, (HRESULT)bundleRunnerContext.dwResult);
76 Assert::Equal<DWORD>(TEST_EXIT_CODE, dwExitCode);
77 }
78 finally
79 {
80 }
81 }
82 };
83}
84}
85}
86}
87}
88
89
90static BOOL STDAPICALLTYPE EmbeddedTest_CreateProcessW(
91 __in_opt LPCWSTR /*lpApplicationName*/,
92 __inout_opt LPWSTR lpCommandLine,
93 __in_opt LPSECURITY_ATTRIBUTES /*lpProcessAttributes*/,
94 __in_opt LPSECURITY_ATTRIBUTES /*lpThreadAttributes*/,
95 __in BOOL /*bInheritHandles*/,
96 __in DWORD /*dwCreationFlags*/,
97 __in_opt LPVOID /*lpEnvironment*/,
98 __in_opt LPCWSTR /*lpCurrentDirectory*/,
99 __in LPSTARTUPINFOW /*lpStartupInfo*/,
100 __out LPPROCESS_INFORMATION lpProcessInformation
101 )
102{
103 HRESULT hr = S_OK;
104 LPWSTR scz = NULL;
105 LPCWSTR wzArgs = lpCommandLine + 24; //skip '"C:\ignored\target.exe" '
106
107 hr = StrAllocString(&scz, wzArgs, 0);
108 ExitOnFailure(hr, "Failed to copy arguments.");
109
110 // Pretend this thread is the embedded process.
111 lpProcessInformation->hProcess = ::CreateThread(NULL, 0, EmbeddedTest_ThreadProc, scz, 0, NULL);
112 ExitOnNullWithLastError(lpProcessInformation->hProcess, hr, "Failed to create thread.");
113
114 scz = NULL;
115
116LExit:
117 ReleaseStr(scz);
118
119 return SUCCEEDED(hr);
120}
121
122static DWORD CALLBACK EmbeddedTest_ThreadProc(
123 __in LPVOID lpThreadParameter
124 )
125{
126 HRESULT hr = S_OK;
127 LPWSTR sczArguments = (LPWSTR)lpThreadParameter;
128 BURN_ENGINE_STATE engineState = { };
129 BURN_PIPE_CONNECTION* pConnection = &engineState.embeddedConnection;
130 DWORD dwResult = 0;
131
132 engineState.internalCommand.mode = BURN_MODE_EMBEDDED;
133
134 PipeConnectionInitialize(pConnection);
135
136 StrAlloc(&pConnection->sczName, MAX_PATH);
137 StrAlloc(&pConnection->sczSecret, MAX_PATH);
138
139 // parse command line arguments
140 if (3 != swscanf_s(sczArguments, L"-burn.embedded %s %s %u", pConnection->sczName, MAX_PATH, pConnection->sczSecret, MAX_PATH, &pConnection->dwProcessId))
141 {
142 ExitWithRootFailure(hr, E_INVALIDARG, "Failed to parse argument string.");
143 }
144
145 // set up connection with parent bundle runner
146 hr = PipeChildConnect(pConnection, FALSE);
147 ExitOnFailure(hr, "Failed to connect to parent bundle runner.");
148
149 // post known message
150 hr = ExternalEngineSendEmbeddedError(&engineState, S_TEST_SUCCEEDED, NULL, 0, reinterpret_cast<int*>(&dwResult));
151 ExitOnFailure(hr, "Failed to post known message to parent bundle runner.");
152
153LExit:
154 PipeConnectionUninitialize(pConnection);
155 ReleaseStr(sczArguments);
156
157 return FAILED(hr) ? (DWORD)hr : dwResult;
158}
159
160static int EmbeddedTest_GenericMessageHandler(
161 __in GENERIC_EXECUTE_MESSAGE* pMessage,
162 __in LPVOID pvContext
163 )
164{
165 BUNDLE_RUNNER_CONTEXT* pContext = reinterpret_cast<BUNDLE_RUNNER_CONTEXT*>(pvContext);
166 DWORD dwResult = 0;
167
168 if (GENERIC_EXECUTE_MESSAGE_ERROR == pMessage->type)
169 {
170 pContext->dwResult = pMessage->error.dwErrorCode;
171 dwResult = TEST_EXIT_CODE;
172 }
173
174 return dwResult;
175}
diff --git a/src/burn/test/BurnUnitTest/precomp.h b/src/burn/test/BurnUnitTest/precomp.h
index 69c62cb2..84e989a4 100644
--- a/src/burn/test/BurnUnitTest/precomp.h
+++ b/src/burn/test/BurnUnitTest/precomp.h
@@ -73,6 +73,7 @@
73#include "manifest.h" 73#include "manifest.h"
74#include "splashscreen.h" 74#include "splashscreen.h"
75#include "detect.h" 75#include "detect.h"
76#include "externalengine.h"
76 77
77#include "engine.version.h" 78#include "engine.version.h"
78 79