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

http://wald.intevation.org/projects/trustbridge/