Mercurial > trustbridge
view packaging/desktopshellrun.cpp @ 1310:60e481aa75ca
(issue152) Do not return CryptUIDlgViewContext's return value
The return value is false if the user cancels the dialog.
But as the certificate has been shown this is not really an
error.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 13 Oct 2014 14:13:05 +0200 |
parents | ffdc8cba139a |
children | 12ed0b72e9f5 |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ /** * @file tasksched_run_as.cpp * @brief Run a command with the Task Scheduler API * * This effectively starts a program as the user regardles of the current * process token. */ #include <windows.h> #include "logging.h" #include "strhelp.h" #ifndef INITGUID #define INITGUID #endif #include <initguid.h> #include <mstask.h> #include <wchar.h> #include <ole2.h> #include <shldisp.h> #include <shobjidl.h> #include <exdisp.h> #include <shlguid.h> /* Some declarations missing in mingw-w64 3.1.0 taken from msdn */ __CRT_UUID_DECL(IShellWindows, 0x85CB6900, 0x4D95, 0x11CF, 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); DEFINE_GUID(IID_IShellWindows, 0x85CB6900, 0x4D95, 0x11CF, 0x96, 0x0C, 0x00, 0x80, 0xC7, 0xF4, 0xEE, 0x85); DEFINE_GUID(CLSID_ShellWindows, 0x9BA05972, 0xF6A8, 0x11CF, 0xA4, 0x42, 0x00, 0xA0, 0xC9, 0x0A, 0x8F, 0x39); __CRT_UUID_DECL(IShellDispatch2, 0xA4C6892C, 0x3BA9, 0x11d2, 0x9D, 0xEA, 0x00, 0xC0, 0x4F, 0xB1, 0x61, 0x62); __CRT_UUID_DECL(IShellFolderViewDual, 0xe7a1af80, 0x4d96, 0x11cf, 0x96, 0x0c, 0x00, 0x80, 0xc7, 0xf4, 0xee, 0x85); #ifndef SWC_DESKTOP /* Will probably be addedd in future mingw */ #define SWC_DESKTOP 0x00000008 /* from http://msdn.microsoft.com/en-us/library/windows/desktop/cc836581%28v=vs.85%29.aspx */ #endif #undef INITGUID #ifdef DO_RELEASE_BUILD bool g_debug = false; #else bool g_debug = true; #endif typedef struct _stack_t { struct _stack_t *next; char text[1]; /* This should be the length of string_size. */ } stack_t; static HINSTANCE g_hInstance; /* Our Instance. */ #define UNUSED(x) (void)(x) /** @brief the actual execuation call on the shell dispatcher * * @param[in] disp The shell dispatcher to use for shell execute. * @param[in] fName The file that should be exectued. * @param[in] param Optinal parameters to add. * * @returns true on success. */ static bool shellexecute(IShellDispatch2 *disp, wchar_t *fName, wchar_t *param) { BSTR bName = NULL, bParam = NULL, bDir = NULL, bOp = NULL; VARIANT vParams[4]; HRESULT hr; if (!fName || !disp) { ERRORPRINTF ("Invalid call to shellexecute."); return false; } bName = SysAllocString(fName); bParam = SysAllocString(param ? param : L""); bDir = SysAllocString(L""); bOp = SysAllocString(L""); if (!bName || !bParam || !bDir || !bOp) { /* Out of memory */ ERRORPRINTF ("Failed to allocate bstr values "); return false; } vParams[0].vt = VT_BSTR; vParams[0].bstrVal = bParam; vParams[1].vt = VT_BSTR; vParams[1].bstrVal = bDir; vParams[2].vt = VT_BSTR; vParams[2].bstrVal = bOp; vParams[3].vt = VT_INT; vParams[3].intVal = SW_SHOWNORMAL; hr = disp->ShellExecute(bName, vParams[0], vParams[1], vParams[2], vParams[3]); SysFreeString(bName); SysFreeString(bParam); SysFreeString(bOp); SysFreeString(bDir); if (FAILED(hr)) { ERRORPRINTF ("Failed to execute."); return false; } return true; } #ifdef __cplusplus extern "C" { #endif /* Standard entry point for DLLs. */ int WINAPI DllMain (HANDLE hinst, DWORD reason, LPVOID reserved) { UNUSED(reserved); if (reason == DLL_PROCESS_ATTACH) g_hInstance = (HINSTANCE)hinst; return TRUE; } /** @brief Execute a command with the current running shell. * * This function is intended to be called when you want to * make sure that your application is not executed with higher * privileges then the normal desktop session. * * The code is based on the idea: * http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx * * The function signature is explained by NSIS. */ void __declspec(dllexport) __cdecl Exec(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { UNUSED(hwndParent); UNUSED(string_size); HRESULT hr; wchar_t *wbuf = NULL, *params = NULL; IShellWindows *shellWindows = NULL; IShellBrowser *shellBrowser = NULL; IShellView *shellView = NULL; IShellFolderViewDual *folderView = NULL; IShellDispatch2 *shellDispatch = NULL; IServiceProvider *serviceProv = NULL; HWND hwnd; IDispatch *disp = NULL, *bgDisp = NULL, *sDisp = NULL; VARIANT vEmpty = {}; if (!stacktop || !*stacktop || !(*stacktop)->text) { ERRORPRINTF ("Invalid call to exec :"); return; } /* Initialize com ctx */ hr = CoInitialize(NULL); if(FAILED(hr)) { ERRORPRINTF ("CoInitializeEx failed. error = 0x%lx.", hr); return; } /* Get the shell interface */ hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&shellWindows)); if (FAILED(hr)) { ERRORPRINTF ("Failed to get shell interface."); goto done; } /* Get the desktop shell window */ hr = shellWindows->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &disp); if (FAILED(hr)) { ERRORPRINTF ("Failed to find the desktop dispatcher."); goto done; } hr = disp->QueryInterface(IID_PPV_ARGS(&serviceProv)); if (FAILED(hr)) { ERRORPRINTF ("Failed to get the service provider."); goto done; } /* Get the shell browser */ hr = serviceProv->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&shellBrowser)); if (FAILED(hr)) { ERRORPRINTF ("Failed to find the top level browser."); goto done; } hr = shellBrowser->QueryActiveShellView(&shellView); if (FAILED(hr)) { ERRORPRINTF ("Failed to find the active view."); goto done; } hr = shellView->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&bgDisp)); if (FAILED(hr)) { ERRORPRINTF ("Failed to get the views background."); goto done; } hr = bgDisp->QueryInterface(IID_PPV_ARGS(&folderView)); if (FAILED(hr)) { ERRORPRINTF ("Failed to get the folder view."); goto done; } hr = folderView->get_Application(&sDisp); if (FAILED(hr)) { ERRORPRINTF ("Failed to get the shell dispatch."); goto done; } hr = sDisp->QueryInterface(IID_PPV_ARGS(&shellDispatch)); if (FAILED(hr)) { ERRORPRINTF ("Failed to get the shell dispatch interface."); goto done; } /* For unicodensis this has to be utf8 to wchar */ wbuf = acp_to_wchar((*stacktop)->text, strlen((*stacktop)->text)); if (!wbuf) { ERRORPRINTF ("Failed to convert argument to wchar. error = 0x%lx.", hr); goto done; } if ((*stacktop)->next && (*stacktop)->next->text) { params = acp_to_wchar((*stacktop)->next->text, strlen((*stacktop)->next->text)); } if (!shellexecute(shellDispatch, wbuf, params)) { ERRORPRINTF ("Failed to execute."); } xfree (wbuf); xfree (params); done: if (folderView) { folderView->Release(); } if (disp) { disp->Release(); } if (shellBrowser) { shellBrowser->Release(); } if (shellWindows) { shellWindows->Release(); } if (shellView) { shellView->Release(); } if (sDisp) { sDisp->Release(); } if (shellDispatch) { shellDispatch->Release(); } if (serviceProv) { serviceProv->Release(); } CoUninitialize(); return; } #ifdef __cplusplus } #endif