diff options
author | Rob Mensching <rob@firegiant.com> | 2021-04-22 17:06:54 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-04-29 16:36:06 -0700 |
commit | af10c45d7b3a44af0b461a557847fe03263dcc10 (patch) | |
tree | 6a5c1532304782c36ffe4200b38f3afb76789a43 /src/burn/test/BurnUnitTest/ElevationTest.cpp | |
parent | 9c2aed97299fb96aeee3f1471ce40225437aaecf (diff) | |
download | wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.gz wix-af10c45d7b3a44af0b461a557847fe03263dcc10.tar.bz2 wix-af10c45d7b3a44af0b461a557847fe03263dcc10.zip |
Move burn into burn
Diffstat (limited to 'src/burn/test/BurnUnitTest/ElevationTest.cpp')
-rw-r--r-- | src/burn/test/BurnUnitTest/ElevationTest.cpp | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/burn/test/BurnUnitTest/ElevationTest.cpp b/src/burn/test/BurnUnitTest/ElevationTest.cpp new file mode 100644 index 00000000..3d144128 --- /dev/null +++ b/src/burn/test/BurnUnitTest/ElevationTest.cpp | |||
@@ -0,0 +1,221 @@ | |||
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 | |||
6 | const DWORD TEST_CHILD_SENT_MESSAGE_ID = 0xFFFE; | ||
7 | const DWORD TEST_PARENT_SENT_MESSAGE_ID = 0xFFFF; | ||
8 | const HRESULT S_TEST_SUCCEEDED = 0x3133; | ||
9 | const char TEST_MESSAGE_DATA[] = "{94949868-7EAE-4ac5-BEAC-AFCA2821DE01}"; | ||
10 | |||
11 | |||
12 | static BOOL STDAPICALLTYPE ElevateTest_ShellExecuteExW( | ||
13 | __inout LPSHELLEXECUTEINFOW lpExecInfo | ||
14 | ); | ||
15 | static DWORD CALLBACK ElevateTest_ThreadProc( | ||
16 | __in LPVOID lpThreadParameter | ||
17 | ); | ||
18 | static HRESULT ProcessParentMessages( | ||
19 | __in BURN_PIPE_MESSAGE* pMsg, | ||
20 | __in_opt LPVOID pvContext, | ||
21 | __out DWORD* pdwResult | ||
22 | ); | ||
23 | static HRESULT ProcessChildMessages( | ||
24 | __in BURN_PIPE_MESSAGE* pMsg, | ||
25 | __in_opt LPVOID pvContext, | ||
26 | __out DWORD* pdwResult | ||
27 | ); | ||
28 | |||
29 | namespace Microsoft | ||
30 | { | ||
31 | namespace Tools | ||
32 | { | ||
33 | namespace WindowsInstallerXml | ||
34 | { | ||
35 | namespace Test | ||
36 | { | ||
37 | namespace Bootstrapper | ||
38 | { | ||
39 | using namespace System; | ||
40 | using namespace System::IO; | ||
41 | using namespace System::Threading; | ||
42 | using namespace Xunit; | ||
43 | |||
44 | public ref class ElevationTest : BurnUnitTest | ||
45 | { | ||
46 | public: | ||
47 | ElevationTest(BurnTestFixture^ fixture) : BurnUnitTest(fixture) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | [Fact] | ||
52 | void ElevateTest() | ||
53 | { | ||
54 | HRESULT hr = S_OK; | ||
55 | BURN_PIPE_CONNECTION connection = { }; | ||
56 | HANDLE hEvent = NULL; | ||
57 | DWORD dwResult = S_OK; | ||
58 | try | ||
59 | { | ||
60 | ShelFunctionOverride(ElevateTest_ShellExecuteExW); | ||
61 | |||
62 | PipeConnectionInitialize(&connection); | ||
63 | |||
64 | // | ||
65 | // per-user side setup | ||
66 | // | ||
67 | hr = PipeCreateNameAndSecret(&connection.sczName, &connection.sczSecret); | ||
68 | TestThrowOnFailure(hr, L"Failed to create connection name and secret."); | ||
69 | |||
70 | hr = PipeCreatePipes(&connection, TRUE, &hEvent); | ||
71 | TestThrowOnFailure(hr, L"Failed to create pipes."); | ||
72 | |||
73 | hr = PipeLaunchChildProcess(L"tests\\ignore\\this\\path\\to\\burn.exe", &connection, TRUE, NULL); | ||
74 | TestThrowOnFailure(hr, L"Failed to create elevated process."); | ||
75 | |||
76 | hr = PipeWaitForChildConnect(&connection); | ||
77 | TestThrowOnFailure(hr, L"Failed to wait for child process to connect."); | ||
78 | |||
79 | // post execute message | ||
80 | hr = PipeSendMessage(connection.hPipe, TEST_PARENT_SENT_MESSAGE_ID, NULL, 0, ProcessParentMessages, NULL, &dwResult); | ||
81 | TestThrowOnFailure(hr, "Failed to post execute message to per-machine process."); | ||
82 | |||
83 | // | ||
84 | // initiate termination | ||
85 | // | ||
86 | hr = PipeTerminateChildProcess(&connection, 666, FALSE); | ||
87 | TestThrowOnFailure(hr, L"Failed to terminate elevated process."); | ||
88 | |||
89 | // check flags | ||
90 | Assert::Equal(S_TEST_SUCCEEDED, (HRESULT)dwResult); | ||
91 | } | ||
92 | finally | ||
93 | { | ||
94 | PipeConnectionUninitialize(&connection); | ||
95 | ReleaseHandle(hEvent); | ||
96 | } | ||
97 | } | ||
98 | }; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | |||
106 | static BOOL STDAPICALLTYPE ElevateTest_ShellExecuteExW( | ||
107 | __inout LPSHELLEXECUTEINFOW lpExecInfo | ||
108 | ) | ||
109 | { | ||
110 | HRESULT hr = S_OK; | ||
111 | LPWSTR scz = NULL; | ||
112 | |||
113 | hr = StrAllocString(&scz, lpExecInfo->lpParameters, 0); | ||
114 | ExitOnFailure(hr, "Failed to copy arguments."); | ||
115 | |||
116 | // Pretend this thread is the elevated process. | ||
117 | lpExecInfo->hProcess = ::CreateThread(NULL, 0, ElevateTest_ThreadProc, scz, 0, NULL); | ||
118 | ExitOnNullWithLastError(lpExecInfo->hProcess, hr, "Failed to create thread."); | ||
119 | scz = NULL; | ||
120 | |||
121 | LExit: | ||
122 | ReleaseStr(scz); | ||
123 | |||
124 | return SUCCEEDED(hr); | ||
125 | } | ||
126 | |||
127 | static DWORD CALLBACK ElevateTest_ThreadProc( | ||
128 | __in LPVOID lpThreadParameter | ||
129 | ) | ||
130 | { | ||
131 | HRESULT hr = S_OK; | ||
132 | LPWSTR sczArguments = (LPWSTR)lpThreadParameter; | ||
133 | BURN_PIPE_CONNECTION connection = { }; | ||
134 | BURN_PIPE_RESULT result = { }; | ||
135 | |||
136 | PipeConnectionInitialize(&connection); | ||
137 | |||
138 | StrAlloc(&connection.sczName, MAX_PATH); | ||
139 | StrAlloc(&connection.sczSecret, MAX_PATH); | ||
140 | |||
141 | // parse command line arguments | ||
142 | if (3 != swscanf_s(sczArguments, L"-q -burn.elevated %s %s %u", connection.sczName, MAX_PATH, connection.sczSecret, MAX_PATH, &connection.dwProcessId)) | ||
143 | { | ||
144 | hr = E_INVALIDARG; | ||
145 | ExitOnFailure(hr, "Failed to parse argument string."); | ||
146 | } | ||
147 | |||
148 | // set up connection with per-user process | ||
149 | hr = PipeChildConnect(&connection, TRUE); | ||
150 | ExitOnFailure(hr, "Failed to connect to per-user process."); | ||
151 | |||
152 | // pump messages | ||
153 | hr = PipePumpMessages(connection.hPipe, ProcessChildMessages, static_cast<LPVOID>(connection.hPipe), &result); | ||
154 | ExitOnFailure(hr, "Failed while pumping messages in child 'process'."); | ||
155 | |||
156 | LExit: | ||
157 | PipeConnectionUninitialize(&connection); | ||
158 | ReleaseStr(sczArguments); | ||
159 | |||
160 | return FAILED(hr) ? (DWORD)hr : result.dwResult; | ||
161 | } | ||
162 | |||
163 | static HRESULT ProcessParentMessages( | ||
164 | __in BURN_PIPE_MESSAGE* pMsg, | ||
165 | __in_opt LPVOID /*pvContext*/, | ||
166 | __out DWORD* pdwResult | ||
167 | ) | ||
168 | { | ||
169 | HRESULT hr = S_OK; | ||
170 | HRESULT hrResult = E_INVALIDDATA; | ||
171 | |||
172 | // Process the message. | ||
173 | switch (pMsg->dwMessage) | ||
174 | { | ||
175 | case TEST_CHILD_SENT_MESSAGE_ID: | ||
176 | if (sizeof(TEST_MESSAGE_DATA) == pMsg->cbData && 0 == memcmp(TEST_MESSAGE_DATA, pMsg->pvData, sizeof(TEST_MESSAGE_DATA))) | ||
177 | { | ||
178 | hrResult = S_TEST_SUCCEEDED; | ||
179 | } | ||
180 | break; | ||
181 | |||
182 | default: | ||
183 | hr = E_INVALIDARG; | ||
184 | ExitOnRootFailure(hr, "Unexpected elevated message sent to parent process, msg: %u", pMsg->dwMessage); | ||
185 | } | ||
186 | |||
187 | *pdwResult = static_cast<DWORD>(hrResult); | ||
188 | |||
189 | LExit: | ||
190 | return hr; | ||
191 | } | ||
192 | |||
193 | static HRESULT ProcessChildMessages( | ||
194 | __in BURN_PIPE_MESSAGE* pMsg, | ||
195 | __in_opt LPVOID pvContext, | ||
196 | __out DWORD* pdwResult | ||
197 | ) | ||
198 | { | ||
199 | HRESULT hr = S_OK; | ||
200 | HANDLE hPipe = static_cast<HANDLE>(pvContext); | ||
201 | DWORD dwResult = 0; | ||
202 | |||
203 | // Process the message. | ||
204 | switch (pMsg->dwMessage) | ||
205 | { | ||
206 | case TEST_PARENT_SENT_MESSAGE_ID: | ||
207 | // send test message | ||
208 | hr = PipeSendMessage(hPipe, TEST_CHILD_SENT_MESSAGE_ID, (LPVOID)TEST_MESSAGE_DATA, sizeof(TEST_MESSAGE_DATA), NULL, NULL, &dwResult); | ||
209 | ExitOnFailure(hr, "Failed to send message to per-machine process."); | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | hr = E_INVALIDARG; | ||
214 | ExitOnRootFailure(hr, "Unexpected elevated message sent to child process, msg: %u", pMsg->dwMessage); | ||
215 | } | ||
216 | |||
217 | *pdwResult = dwResult; | ||
218 | |||
219 | LExit: | ||
220 | return hr; | ||
221 | } | ||