Mercurial > trustbridge
comparison packaging/desktopshellrun.cpp @ 1118:fd85a02d771d
(issue54) Implement a privilege drop to execute the program after installation.
This commit is extremly ugly as I accidentally worked in a
working tree that was partially merged with default.
To review the real change please check the commit that will
merge this branch into default.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 16 Sep 2014 19:45:19 +0200 |
parents | |
children | 4a17c9f977d0 |
comparison
equal
deleted
inserted
replaced
1117:5b6203f78b4e | 1118:fd85a02d771d |
---|---|
1 /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik | |
2 * Software engineering by Intevation GmbH | |
3 * | |
4 * This file is Free Software under the GNU GPL (v>=2) | |
5 * and comes with ABSOLUTELY NO WARRANTY! | |
6 * See LICENSE.txt for details. | |
7 */ | |
8 | |
9 /** | |
10 * @file tasksched_run_as.cpp | |
11 * @brief Run a command with the Task Scheduler API | |
12 * | |
13 * This effectively starts a program as the user regardles of the current | |
14 * process token. | |
15 */ | |
16 #include <windows.h> | |
17 #include "logging.h" | |
18 #include "strhelp.h" | |
19 | |
20 #ifndef INITGUID | |
21 #define INITGUID | |
22 #endif | |
23 | |
24 #include <initguid.h> | |
25 #include <mstask.h> | |
26 #include <wchar.h> | |
27 #include <ole2.h> | |
28 #include <shldisp.h> | |
29 #include <shobjidl.h> | |
30 #include <exdisp.h> | |
31 #include <shlguid.h> | |
32 | |
33 /* Some declarations missing in mingw-w64 3.1.0 taken from msdn */ | |
34 | |
35 __CRT_UUID_DECL(IShellWindows, 0x85CB6900, 0x4D95, 0x11CF, | |
36 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); | |
37 | |
38 DEFINE_GUID(IID_IShellWindows, | |
39 0x85CB6900, 0x4D95, 0x11CF, | |
40 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); | |
41 DEFINE_GUID(CLSID_ShellWindows, | |
42 0x9BA05972, 0xF6A8, 0x11CF, | |
43 0xA4, 0x42, 0x00, 0xA0, 0xC9, 0x0A, 0x8F, 0x39); | |
44 | |
45 | |
46 __CRT_UUID_DECL(IShellDispatch2, 0xA4C6892C, 0x3BA9, 0x11d2, | |
47 0x9D, 0xEA, 0x00, 0xC0, 0x4F, 0xB1, 0x61, 0x62); | |
48 __CRT_UUID_DECL(IShellFolderViewDual, 0xe7a1af80, 0x4d96, | |
49 0x11cf, 0x96, 0x0c, 0x00, 0x80, 0xc7, 0xf4, 0xee, 0x85); | |
50 | |
51 #ifndef SWC_DESKTOP /* Will probably be addedd in future mingw */ | |
52 #define SWC_DESKTOP 0x00000008 | |
53 /* from http://msdn.microsoft.com/en-us/library/windows/desktop/cc836581%28v=vs.85%29.aspx */ | |
54 #endif | |
55 | |
56 #undef INITGUID | |
57 | |
58 #ifdef DO_RELEASE_BUILD | |
59 bool g_debug = false; | |
60 #else | |
61 bool g_debug = true; | |
62 #endif | |
63 | |
64 typedef struct _stack_t | |
65 { | |
66 struct _stack_t *next; | |
67 char text[1]; /* This should be the length of string_size. */ | |
68 } stack_t; | |
69 | |
70 static HINSTANCE g_hInstance; /* Our Instance. */ | |
71 | |
72 #define UNUSED(x) (void)(x) | |
73 | |
74 /** @brief the actual execuation call on the shell dispatcher | |
75 * | |
76 * @param[in] disp The shell dispatcher to use for shell execute. | |
77 * @param[in] fName The file that should be exectued. | |
78 * | |
79 * @returns true on success. | |
80 */ | |
81 static bool | |
82 shellexecute(IShellDispatch2 *disp, wchar_t *fName) | |
83 { | |
84 BSTR bName = NULL, | |
85 bParam = NULL, | |
86 bDir = NULL, | |
87 bOp = NULL; | |
88 VARIANT vParams[4]; | |
89 HRESULT hr; | |
90 | |
91 if (!fName || !disp) | |
92 { | |
93 ERRORPRINTF ("Invalid call to shellexecute."); | |
94 return false; | |
95 } | |
96 | |
97 bName = SysAllocString(fName); | |
98 bParam = SysAllocString(L""); | |
99 bDir = SysAllocString(L""); | |
100 bOp = SysAllocString(L""); | |
101 | |
102 if (!bName || !bParam || !bDir || !bOp) | |
103 { | |
104 /* Out of memory */ | |
105 ERRORPRINTF ("Failed to allocate bstr values "); | |
106 return false; | |
107 } | |
108 | |
109 vParams[0].vt = VT_BSTR; | |
110 vParams[0].bstrVal = bParam; | |
111 vParams[1].vt = VT_BSTR; | |
112 vParams[1].bstrVal = bDir; | |
113 vParams[2].vt = VT_BSTR; | |
114 vParams[2].bstrVal = bOp; | |
115 vParams[3].vt = VT_INT; | |
116 vParams[3].intVal = SW_SHOWNORMAL; | |
117 | |
118 hr = disp->ShellExecute(bName, vParams[0], vParams[1], vParams[2], vParams[3]); | |
119 | |
120 SysFreeString(bName); | |
121 SysFreeString(bParam); | |
122 SysFreeString(bOp); | |
123 SysFreeString(bDir); | |
124 | |
125 if (FAILED(hr)) | |
126 { | |
127 ERRORPRINTF ("Failed to execute."); | |
128 return false; | |
129 } | |
130 return true; | |
131 } | |
132 | |
133 #ifdef __cplusplus | |
134 extern "C" { | |
135 #endif | |
136 | |
137 /* Standard entry point for DLLs. */ | |
138 int WINAPI | |
139 DllMain (HANDLE hinst, DWORD reason, LPVOID reserved) | |
140 { | |
141 UNUSED(reserved); | |
142 if (reason == DLL_PROCESS_ATTACH) | |
143 g_hInstance = (HINSTANCE)hinst; | |
144 return TRUE; | |
145 } | |
146 | |
147 /** @brief Execute a command with the current running shell. | |
148 * | |
149 * This function is intended to be called when you want to | |
150 * make sure that your application is not executed with higher | |
151 * privileges then the normal desktop session. | |
152 * | |
153 * The code is based on the idea: | |
154 * http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx | |
155 * | |
156 * The function signature is explained by NSIS. | |
157 */ | |
158 void __declspec(dllexport) __cdecl Exec(HWND hwndParent, | |
159 int string_size, | |
160 char *variables, | |
161 stack_t **stacktop) | |
162 { | |
163 UNUSED(hwndParent); | |
164 UNUSED(string_size); | |
165 HRESULT hr; | |
166 wchar_t *wbuf = NULL; | |
167 IShellWindows *shellWindows = NULL; | |
168 IShellBrowser *shellBrowser = NULL; | |
169 IShellView *shellView = NULL; | |
170 IShellFolderViewDual *folderView = NULL; | |
171 IShellDispatch2 *shellDispatch = NULL; | |
172 IServiceProvider *serviceProv = NULL; | |
173 HWND hwnd; | |
174 IDispatch *disp = NULL, | |
175 *bgDisp = NULL, | |
176 *sDisp = NULL; | |
177 VARIANT vEmpty = {}; | |
178 | |
179 | |
180 if (!stacktop || !*stacktop || !(*stacktop)->text) | |
181 { | |
182 ERRORPRINTF ("Invalid call to exec :"); | |
183 return; | |
184 } | |
185 | |
186 /* Initialize com ctx */ | |
187 hr = CoInitialize(NULL); | |
188 if(FAILED(hr)) | |
189 { | |
190 ERRORPRINTF ("CoInitializeEx failed. error = 0x%lx.", hr); | |
191 return; | |
192 } | |
193 | |
194 /* Get the shell interface */ | |
195 hr = CoCreateInstance(CLSID_ShellWindows, | |
196 NULL, CLSCTX_LOCAL_SERVER, | |
197 IID_PPV_ARGS(&shellWindows)); | |
198 if (FAILED(hr)) | |
199 { | |
200 ERRORPRINTF ("Failed to get shell interface."); | |
201 goto done; | |
202 } | |
203 | |
204 /* Get the desktop shell window */ | |
205 hr = shellWindows->FindWindowSW(&vEmpty, | |
206 &vEmpty, | |
207 SWC_DESKTOP, | |
208 (long*)&hwnd, | |
209 SWFO_NEEDDISPATCH, | |
210 &disp); | |
211 if (FAILED(hr)) | |
212 { | |
213 ERRORPRINTF ("Failed to find the desktop dispatcher."); | |
214 goto done; | |
215 } | |
216 | |
217 hr = disp->QueryInterface(IID_PPV_ARGS(&serviceProv)); | |
218 | |
219 if (FAILED(hr)) | |
220 { | |
221 ERRORPRINTF ("Failed to get the service provider."); | |
222 goto done; | |
223 } | |
224 | |
225 /* Get the shell browser */ | |
226 hr = serviceProv->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&shellBrowser)); | |
227 if (FAILED(hr)) | |
228 { | |
229 ERRORPRINTF ("Failed to find the top level browser."); | |
230 goto done; | |
231 } | |
232 | |
233 hr = shellBrowser->QueryActiveShellView(&shellView); | |
234 | |
235 if (FAILED(hr)) | |
236 { | |
237 ERRORPRINTF ("Failed to find the active view."); | |
238 goto done; | |
239 } | |
240 | |
241 hr = shellView->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&bgDisp)); | |
242 | |
243 if (FAILED(hr)) | |
244 { | |
245 ERRORPRINTF ("Failed to get the views background."); | |
246 goto done; | |
247 } | |
248 | |
249 hr = bgDisp->QueryInterface(IID_PPV_ARGS(&folderView)); | |
250 | |
251 if (FAILED(hr)) | |
252 { | |
253 ERRORPRINTF ("Failed to get the folder view."); | |
254 goto done; | |
255 } | |
256 | |
257 | |
258 hr = folderView->get_Application(&sDisp); | |
259 | |
260 if (FAILED(hr)) | |
261 { | |
262 ERRORPRINTF ("Failed to get the shell dispatch."); | |
263 goto done; | |
264 } | |
265 | |
266 hr = sDisp->QueryInterface(IID_PPV_ARGS(&shellDispatch)); | |
267 | |
268 if (FAILED(hr)) | |
269 { | |
270 ERRORPRINTF ("Failed to get the shell dispatch interface."); | |
271 goto done; | |
272 } | |
273 | |
274 wbuf = utf8_to_wchar((*stacktop)->text, strlen((*stacktop)->text)); | |
275 if (!wbuf) | |
276 { | |
277 ERRORPRINTF ("Failed to convert argument to wchar. error = 0x%lx.", hr); | |
278 goto done; | |
279 } | |
280 | |
281 if (!shellexecute(shellDispatch, wbuf)) | |
282 { | |
283 ERRORPRINTF ("Failed to execute."); | |
284 } | |
285 xfree (wbuf); | |
286 done: | |
287 if (folderView) | |
288 { | |
289 folderView->Release(); | |
290 } | |
291 if (disp) | |
292 { | |
293 disp->Release(); | |
294 } | |
295 if (shellBrowser) | |
296 { | |
297 shellBrowser->Release(); | |
298 } | |
299 if (shellWindows) | |
300 { | |
301 shellWindows->Release(); | |
302 } | |
303 if (shellView) | |
304 { | |
305 shellView->Release(); | |
306 } | |
307 if (sDisp) | |
308 { | |
309 sDisp->Release(); | |
310 } | |
311 if (shellDispatch) | |
312 { | |
313 shellDispatch->Release(); | |
314 } | |
315 if (serviceProv) | |
316 { | |
317 serviceProv->Release(); | |
318 } | |
319 CoUninitialize(); | |
320 return; | |
321 } | |
322 #ifdef __cplusplus | |
323 } | |
324 #endif | |
325 | |
326 |