aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/shellexecca.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Util/ca/shellexecca.cpp')
-rw-r--r--src/ext/Util/ca/shellexecca.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/ext/Util/ca/shellexecca.cpp b/src/ext/Util/ca/shellexecca.cpp
new file mode 100644
index 00000000..ea21d3bd
--- /dev/null
+++ b/src/ext/Util/ca/shellexecca.cpp
@@ -0,0 +1,271 @@
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
5HRESULT ShellExec(
6 __in LPCWSTR wzTarget,
7 __in BOOL fUnelevated
8 )
9{
10 HRESULT hr = S_OK;
11 LPWSTR sczWorkingDirectory = NULL;
12
13 // a reasonable working directory (not the system32 default from MSI) is the directory where the target lives
14 hr = PathGetDirectory(wzTarget, &sczWorkingDirectory);
15 ExitOnFailure(hr, "failed to get directory for target: %ls", wzTarget);
16
17 if (!DirExists(sczWorkingDirectory, NULL))
18 {
19 ReleaseNullStr(sczWorkingDirectory);
20 }
21
22 if (fUnelevated)
23 {
24 hr = ShelExecUnelevated(wzTarget, NULL, NULL, sczWorkingDirectory, SW_SHOWDEFAULT);
25 ExitOnFailure(hr, "ShelExecUnelevated failed with target %ls", wzTarget);
26 }
27 else
28 {
29 HINSTANCE hinst = ::ShellExecuteW(NULL, NULL, wzTarget, NULL, sczWorkingDirectory, SW_SHOWDEFAULT);
30 if (hinst <= HINSTANCE(32))
31 {
32 LONG64 code = reinterpret_cast<LONG64>(hinst);
33 switch (code)
34 {
35 case ERROR_FILE_NOT_FOUND:
36 hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
37 break;
38 case ERROR_PATH_NOT_FOUND:
39 hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
40 break;
41 case ERROR_BAD_FORMAT:
42 hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
43 break;
44 case SE_ERR_ASSOCINCOMPLETE:
45 case SE_ERR_NOASSOC:
46 hr = HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
47 break;
48 case SE_ERR_DDEBUSY:
49 case SE_ERR_DDEFAIL:
50 case SE_ERR_DDETIMEOUT:
51 hr = HRESULT_FROM_WIN32(ERROR_DDE_FAIL);
52 break;
53 case SE_ERR_DLLNOTFOUND:
54 hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
55 break;
56 case SE_ERR_OOM:
57 hr = E_OUTOFMEMORY;
58 break;
59 case SE_ERR_ACCESSDENIED:
60 hr = E_ACCESSDENIED;
61 break;
62 default:
63 hr = E_FAIL;
64 }
65
66 ExitOnFailure(hr, "ShellExec failed with return code %llu.", code);
67 }
68 }
69
70
71LExit:
72 ReleaseStr(sczWorkingDirectory);
73 return hr;
74}
75
76extern "C" UINT __stdcall WixShellExec(
77 __in MSIHANDLE hInstall
78 )
79{
80 Assert(hInstall);
81 HRESULT hr = S_OK;
82 UINT er = ERROR_SUCCESS;
83 LPWSTR pwzTarget = NULL;
84
85 hr = WcaInitialize(hInstall, "WixShellExec");
86 ExitOnFailure(hr, "failed to initialize");
87
88 hr = WcaGetFormattedProperty(L"WixShellExecTarget", &pwzTarget);
89 ExitOnFailure(hr, "failed to get WixShellExecTarget");
90
91 WcaLog(LOGMSG_VERBOSE, "WixShellExecTarget is %ls", pwzTarget);
92
93 if (!pwzTarget || !*pwzTarget)
94 {
95 hr = E_INVALIDARG;
96 ExitOnFailure(hr, "failed to get WixShellExecTarget");
97 }
98
99 hr = ShellExec(pwzTarget, FALSE);
100 ExitOnFailure(hr, "failed to launch target");
101
102LExit:
103 ReleaseStr(pwzTarget);
104
105 if (FAILED(hr))
106 {
107 er = ERROR_INSTALL_FAILURE;
108 }
109 return WcaFinalize(er);
110}
111
112extern "C" UINT __stdcall WixUnelevatedShellExec(
113 __in MSIHANDLE hInstall
114 )
115{
116 Assert(hInstall);
117 HRESULT hr = S_OK;
118 UINT er = ERROR_SUCCESS;
119 LPWSTR pwzTarget = NULL;
120
121 hr = WcaInitialize(hInstall, "WixUnelevatedShellExec");
122 ExitOnFailure(hr, "failed to initialize");
123
124 hr = WcaGetFormattedProperty(L"WixUnelevatedShellExecTarget", &pwzTarget);
125 ExitOnFailure(hr, "failed to get WixUnelevatedShellExecTarget");
126
127 WcaLog(LOGMSG_VERBOSE, "WixUnelevatedShellExecTarget is %ls", pwzTarget);
128
129 if (!pwzTarget || !*pwzTarget)
130 {
131 hr = E_INVALIDARG;
132 ExitOnFailure(hr, "failed to get WixShellExecTarget");
133 }
134
135 hr = ShellExec(pwzTarget, TRUE);
136 ExitOnFailure(hr, "failed to launch target");
137
138LExit:
139 ReleaseStr(pwzTarget);
140
141 if (FAILED(hr))
142 {
143 er = ERROR_INSTALL_FAILURE;
144 }
145 return WcaFinalize(er);
146}
147
148//
149// ExtractBinary extracts the data from the Binary table row with the given ID into a file.
150//
151HRESULT ExtractBinary(
152 __in LPCWSTR wzBinaryId,
153 __out BYTE** pbData,
154 __out DWORD* pcbData
155 )
156{
157 HRESULT hr = S_OK;
158 LPWSTR pwzSql = NULL;
159 PMSIHANDLE hView;
160 PMSIHANDLE hRec;
161
162 // make sure we're not horked from the get-go
163 hr = WcaTableExists(L"Binary");
164 if (S_OK != hr)
165 {
166 if (SUCCEEDED(hr))
167 {
168 hr = E_UNEXPECTED;
169 }
170 ExitOnFailure(hr, "There is no Binary table.");
171 }
172
173 ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null");
174 ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string");
175
176 hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId);
177 ExitOnFailure(hr, "Failed to allocate Binary table query.");
178
179 hr = WcaOpenExecuteView(pwzSql, &hView);
180 ExitOnFailure(hr, "Failed to open view on Binary table");
181
182 hr = WcaFetchSingleRecord(hView, &hRec);
183 ExitOnFailure(hr, "Failed to retrieve request from Binary table");
184
185 hr = WcaGetRecordStream(hRec, 1, pbData, pcbData);
186 ExitOnFailure(hr, "Failed to read Binary.Data.");
187
188LExit:
189 ReleaseStr(pwzSql);
190
191 return hr;
192}
193
194extern "C" UINT __stdcall WixShellExecBinary(
195 __in MSIHANDLE hInstall
196 )
197{
198 Assert(hInstall);
199 HRESULT hr = S_OK;
200 UINT er = ERROR_SUCCESS;
201 LPWSTR pwzBinary = NULL;
202 LPWSTR pwzFilename = NULL;
203 BYTE* pbData = NULL;
204 DWORD cbData = 0;
205 HANDLE hFile = INVALID_HANDLE_VALUE;
206
207#if 0
208 ::MessageBoxA(0, "WixShellExecBinary", "-->> ATTACH HERE", MB_OK);
209#endif
210
211 hr = WcaInitialize(hInstall, "WixShellExecBinary");
212 ExitOnFailure(hr, "failed to initialize");
213
214 hr = WcaGetFormattedProperty(L"WixShellExecBinaryId", &pwzBinary);
215 ExitOnFailure(hr, "failed to get WixShellExecBinaryId");
216
217 WcaLog(LOGMSG_VERBOSE, "WixShellExecBinaryId is %ls", pwzBinary);
218
219 if (!pwzBinary || !*pwzBinary)
220 {
221 hr = E_INVALIDARG;
222 ExitOnFailure(hr, "failed to get WixShellExecBinaryId");
223 }
224
225 // get temporary path for extracted file
226 StrAlloc(&pwzFilename, MAX_PATH);
227 ExitOnFailure(hr, "Failed to allocate temporary path");
228 ::GetTempPathW(MAX_PATH, pwzFilename);
229 hr = ::StringCchCatW(pwzFilename, MAX_PATH, pwzBinary);
230 ExitOnFailure(hr, "Failed to append filename.");
231
232 // grab the bits
233 hr = ExtractBinary(pwzBinary, &pbData, &cbData);
234 ExitOnFailure(hr, "failed to extract binary data");
235
236 // write 'em to the temp file
237 hFile = ::CreateFileW(pwzFilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
238 if (INVALID_HANDLE_VALUE == hFile)
239 {
240 ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFilename);
241 }
242
243 DWORD cbWritten = 0;
244 if (!::WriteFile(hFile, pbData, cbData, &cbWritten, NULL))
245 {
246 ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFilename);
247 }
248
249 // close it
250 ::CloseHandle(hFile);
251 hFile = INVALID_HANDLE_VALUE;
252
253 // and run it
254 hr = ShellExec(pwzFilename, FALSE);
255 ExitOnFailure(hr, "failed to launch target: %ls", pwzFilename);
256
257LExit:
258 ReleaseStr(pwzBinary);
259 ReleaseStr(pwzFilename);
260 ReleaseMem(pbData);
261 if (INVALID_HANDLE_VALUE != hFile)
262 {
263 ::CloseHandle(hFile);
264 }
265
266 if (FAILED(hr))
267 {
268 er = ERROR_INSTALL_FAILURE;
269 }
270 return WcaFinalize(er);
271}