diff --git a/src/desktopshellrun.cpp b/src/desktopshellrun.cpp index 69b6420b..b2c3fdc4 100644 --- a/src/desktopshellrun.cpp +++ b/src/desktopshellrun.cpp @@ -1,296 +1,296 @@ /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Copyright (C) 2016 Intevation GmbH * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! */ #include #include #include #include #include #include #include #include #include #include #include #include "exdll.h" #ifndef INITGUID #define INITGUID #endif /* Some declarations missing in mingw-w64 3.1.0 taken from msdn */ #if ! defined (__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 5 __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); #endif #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 #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 /** @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 DesktopShellRun(HWND hwndParent, int string_size, - char *variables, + LPTSTR variables, stack_t **stacktop) { UNUSED(hwndParent); UNUSED(string_size); HRESULT hr; wchar_t *wbuf = 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 = wcsdup ((*stacktop)->text); if (!wbuf) { ERRORPRINTF ("Failed to convert argument to wchar. error = 0x%lx.", hr); goto done; } if (!shellexecute(shellDispatch, wbuf, NULL)) { ERRORPRINTF ("Failed to execute."); } if (wbuf) free(wbuf); 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 diff --git a/src/exdll.c b/src/exdll.c index 4a800f1c..1f1839d7 100644 --- a/src/exdll.c +++ b/src/exdll.c @@ -1,286 +1,286 @@ #include "exdll.h" unsigned int g_stringsize; stack_t **g_stacktop; LPTSTR g_variables; // utility functions (not required but often useful) int NSISCALL popstring(LPTSTR str) { stack_t *th; if (!g_stacktop || !*g_stacktop) return 1; th=(*g_stacktop); if (str) lstrcpy(str,th->text); *g_stacktop = th->next; GlobalFree((HGLOBAL)th); return 0; } int NSISCALL popstringn(LPTSTR str, int maxlen) { stack_t *th; if (!g_stacktop || !*g_stacktop) return 1; th=(*g_stacktop); if (str) lstrcpyn(str,th->text,maxlen?maxlen:g_stringsize); *g_stacktop = th->next; GlobalFree((HGLOBAL)th); return 0; } void NSISCALL pushstring(LPCTSTR str) { stack_t *th; if (!g_stacktop) return; th=(stack_t*)GlobalAlloc(GPTR,(sizeof(stack_t)+(g_stringsize)*sizeof(*str))); lstrcpyn(th->text,str,g_stringsize); th->next=*g_stacktop; *g_stacktop=th; } LPTSTR NSISCALL getuservariable(const int varnum) { if (!isvalidnsisvarindex(varnum)) return NULL; - return g_variables+varnum*g_stringsize; + return (LPWSTR)((char*)g_variables+varnum*g_stringsize); } void NSISCALL setuservariable(const int varnum, LPCTSTR var) { if (var && isvalidnsisvarindex(varnum)) - lstrcpy(g_variables + varnum*g_stringsize, var); + lstrcpy((LPWSTR)((char*)g_variables + varnum*g_stringsize), var); } #ifdef UNICODE int NSISCALL PopStringA(LPSTR ansiStr) { LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR)); int rval = popstring(wideStr); WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); GlobalFree((HGLOBAL)wideStr); return rval; } int NSISCALL PopStringNA(LPSTR ansiStr, int maxlen) { int realLen = maxlen ? maxlen : g_stringsize; LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, realLen*sizeof(WCHAR)); int rval = popstringn(wideStr, realLen); WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, realLen, NULL, NULL); GlobalFree((HGLOBAL)wideStr); return rval; } void NSISCALL PushStringA(LPCSTR ansiStr) { LPWSTR wideStr = (LPWSTR) GlobalAlloc(GPTR, g_stringsize*sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); pushstring(wideStr); GlobalFree((HGLOBAL)wideStr); return; } void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr) { lstrcpyW(wideStr, getuservariable(varnum)); } void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr) { LPWSTR wideStr = getuservariable(varnum); WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); } void NSISCALL SetUserVariableA(const int varnum, LPCSTR ansiStr) { if (ansiStr && isvalidnsisvarindex(varnum)) { - LPWSTR wideStr = g_variables + varnum * g_stringsize; + LPWSTR wideStr = (LPWSTR)((char*)g_variables + varnum * g_stringsize); MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); } } #else // ANSI defs int NSISCALL PopStringW(LPWSTR wideStr) { LPSTR ansiStr = (LPSTR) GlobalAlloc(GPTR, g_stringsize); int rval = popstring(ansiStr); MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); GlobalFree((HGLOBAL)ansiStr); return rval; } int NSISCALL PopStringNW(LPWSTR wideStr, int maxlen) { int realLen = maxlen ? maxlen : g_stringsize; LPSTR ansiStr = (LPSTR) GlobalAlloc(GPTR, realLen); int rval = popstringn(ansiStr, realLen); MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, realLen); GlobalFree((HGLOBAL)ansiStr); return rval; } void NSISCALL PushStringW(LPWSTR wideStr) { LPSTR ansiStr = (LPSTR) GlobalAlloc(GPTR, g_stringsize); WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); pushstring(ansiStr); GlobalFree((HGLOBAL)ansiStr); } void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr) { LPSTR ansiStr = getuservariable(varnum); MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize); } void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr) { lstrcpyA(ansiStr, getuservariable(varnum)); } void NSISCALL SetUserVariableW(const int varnum, LPCWSTR wideStr) { if (wideStr && isvalidnsisvarindex(varnum)) { - LPSTR ansiStr = g_variables + varnum * g_stringsize; + LPSTR ansiStr = (char*)g_variables + varnum * g_stringsize; WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL); } } #endif // playing with integers INT_PTR NSISCALL nsishelper_str_to_ptr(LPCTSTR s) { INT_PTR v=0; if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) { s++; for (;;) { int c=*(++s); if (c >= _T('0') && c <= _T('9')) c-=_T('0'); else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; else break; v<<=4; v+=c; } } else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) { for (;;) { int c=*(++s); if (c >= _T('0') && c <= _T('7')) c-=_T('0'); else break; v<<=3; v+=c; } } else { int sign=0; if (*s == _T('-')) sign++; else s--; for (;;) { int c=*(++s) - _T('0'); if (c < 0 || c > 9) break; v*=10; v+=c; } if (sign) v = -v; } return v; } unsigned int NSISCALL myatou(LPCTSTR s) { unsigned int v=0; for (;;) { unsigned int c=*s++; if (c >= _T('0') && c <= _T('9')) c-=_T('0'); else break; v*=10; v+=c; } return v; } int NSISCALL myatoi_or(LPCTSTR s) { int v=0; if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X'))) { s++; for (;;) { int c=*(++s); if (c >= _T('0') && c <= _T('9')) c-=_T('0'); else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10; else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10; else break; v<<=4; v+=c; } } else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0')) { for (;;) { int c=*(++s); if (c >= _T('0') && c <= _T('7')) c-=_T('0'); else break; v<<=3; v+=c; } } else { int sign=0; if (*s == _T('-')) sign++; else s--; for (;;) { int c=*(++s) - _T('0'); if (c < 0 || c > 9) break; v*=10; v+=c; } if (sign) v = -v; } // Support for simple ORed expressions if (*s == _T('|')) { v |= myatoi_or(s+1); } return v; } INT_PTR NSISCALL popintptr() { TCHAR buf[128]; if (popstringn(buf,COUNTOF(buf))) return 0; return nsishelper_str_to_ptr(buf); } int NSISCALL popint_or() { TCHAR buf[128]; if (popstringn(buf,COUNTOF(buf))) return 0; return myatoi_or(buf); } void NSISCALL pushintptr(INT_PTR value) { TCHAR buffer[30]; wsprintf(buffer, sizeof(void*) > 4 ? _T("%Id") : _T("%d"), value); pushstring(buffer); } diff --git a/src/exdll.h b/src/exdll.h index 91e082f9..f419dc3f 100644 --- a/src/exdll.h +++ b/src/exdll.h @@ -1,162 +1,176 @@ #include #ifndef ___NSIS_PLUGIN__H___ #define ___NSIS_PLUGIN__H___ #ifdef __cplusplus extern "C" { #endif #ifndef NSISCALL # define NSISCALL __stdcall #endif #if !defined(_WIN32) && !defined(LPTSTR) # define LPTSTR TCHAR* #endif #ifndef NSISCALL # define NSISCALL WINAPI #endif #define EXDLL_INIT() { \ g_stringsize=string_size; \ g_stacktop=stacktop; \ g_variables=variables; } + +enum NSPIM +{ + NSPIM_UNLOAD, + NSPIM_GUIUNLOAD +}; + +typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM); + typedef struct _stack_t { struct _stack_t *next; #ifdef UNICODE WCHAR text[1]; // this should be the length of g_stringsize when allocating #else char text[1]; #endif } stack_t; typedef struct { int autoclose; int all_user_var; int exec_error; int abort; int exec_reboot; int reboot_called; int XXX_cur_insttype; /* deprecated */ - int XXX_insttype_changed; /* deprecated */ + int plugin_api_version; /* Used to be insttype_changed */ int silent; int instdir_error; int rtl; int errlvl; + int alter_reg_view; + int status_update; } exec_flags_t; typedef struct { exec_flags_t *exec_flags; int (__stdcall *ExecuteCodeSegment)(int, HWND); + void (__stdcall *validate_filename)(LPTSTR); + int (__stdcall *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); } extra_parameters_t; enum { INST_0, // $0 INST_1, // $1 INST_2, // $2 INST_3, // $3 INST_4, // $4 INST_5, // $5 INST_6, // $6 INST_7, // $7 INST_8, // $8 INST_9, // $9 INST_R0, // $R0 INST_R1, // $R1 INST_R2, // $R2 INST_R3, // $R3 INST_R4, // $R4 INST_R5, // $R5 INST_R6, // $R6 INST_R7, // $R7 INST_R8, // $R8 INST_R9, // $R9 INST_CMDLINE, // $CMDLINE INST_INSTDIR, // $INSTDIR INST_OUTDIR, // $OUTDIR INST_EXEDIR, // $EXEDIR INST_LANG, // $LANGUAGE __INST_LAST }; extern unsigned int g_stringsize; extern stack_t **g_stacktop; extern LPTSTR g_variables; void NSISCALL pushstring(LPCTSTR str); void NSISCALL pushintptr(INT_PTR value); #define pushint(v) pushintptr((INT_PTR)(v)) int NSISCALL popstring(LPTSTR str); // 0 on success, 1 on empty stack int NSISCALL popstringn(LPTSTR str, int maxlen); // with length limit, pass 0 for g_stringsize INT_PTR NSISCALL popintptr(); #define popint() ( (int) popintptr() ) int NSISCALL popint_or(); // with support for or'ing (2|4|8) INT_PTR NSISCALL nsishelper_str_to_ptr(LPCTSTR s); #define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer unsigned int NSISCALL myatou(LPCTSTR s); // converts a string to an unsigned integer, decimal only int NSISCALL myatoi_or(LPCTSTR s); // with support for or'ing (2|4|8) LPTSTR NSISCALL getuservariable(const int varnum); void NSISCALL setuservariable(const int varnum, LPCTSTR var); #ifdef UNICODE #define PopStringW(x) popstring(x) #define PushStringW(x) pushstring(x) #define SetUserVariableW(x,y) setuservariable(x,y) int NSISCALL PopStringA(LPSTR ansiStr); +int NSISCALL PopStringNA(LPSTR ansiStr, int maxlen); void NSISCALL PushStringA(LPCSTR ansiStr); void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr); void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr); void NSISCALL SetUserVariableA(const int varnum, LPCSTR ansiStr); #else // ANSI defs #define PopStringA(x) popstring(x) #define PushStringA(x) pushstring(x) #define SetUserVariableA(x,y) setuservariable(x,y) int NSISCALL PopStringW(LPWSTR wideStr); void NSISCALL PushStringW(LPWSTR wideStr); void NSISCALL GetUserVariableW(const int varnum, LPWSTR wideStr); void NSISCALL GetUserVariableA(const int varnum, LPSTR ansiStr); void NSISCALL SetUserVariableW(const int varnum, LPCWSTR wideStr); #endif #ifdef __cplusplus } #endif #endif//!___NSIS_PLUGIN__H___ #ifndef COUNTOF #define COUNTOF(a) (sizeof(a)/sizeof(a[0])) #endif // minimal tchar.h emulation #ifndef _T # define _T TEXT #endif #if !defined(TCHAR) && !defined(_TCHAR_DEFINED) # ifdef UNICODE # define TCHAR WCHAR # else # define TCHAR char # endif #endif #define isvalidnsisvarindex(varnum) ( ((unsigned int)(varnum)) < (__INST_LAST) ) #define ERRORPRINTF(fmt, ...) \ { \ char buf[512]; \ snprintf(buf, 511, "ERROR: " fmt, ##__VA_ARGS__); \ buf[511] = '\0'; \ OutputDebugStringA(buf); \ } diff --git a/src/g4wihelp.c b/src/g4wihelp.c index 2a65142e..54a872e2 100644 --- a/src/g4wihelp.c +++ b/src/g4wihelp.c @@ -1,519 +1,534 @@ /* g4wihelp.c - NSIS Helper DLL used with gpg4win. -*- coding: latin-1; -*- * Copyright (C) 2005 g10 Code GmbH * Copyright (C) 2001 Justin Frankel * Copyright (C) 2016, 2017 Intevation GmbH * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any * damages arising from the use of this software. * * Permission is granted to anyone to use this software for any * purpose, including commercial applications, and to alter it and * redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must * not claim that you wrote the original software. If you use this * software in a product, an acknowledgment in the product * documentation would be appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must * not be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source * distribution. ************************************************************ * The code for the splash screen has been taken from the Splash * plugin of the NSIS 2.04 distribution. That code comes without * explicit copyright notices in tyhe source files or author names, it * seems that it has been written by Justin Frankel; not sure about * the year, though. [wk 2005-11-28] */ #include #include #include #include #include "exdll.h" static HINSTANCE g_hInstance; /* Our Instance. */ static HWND g_hwndParent; /* Handle of parent window or NULL. */ static HBITMAP g_hbm; /* Handle of the splash image. */ static int sleepint; /* Milliseconds to show the spals image. */ void slide_stop(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop); /* Standard entry point for DLLs. */ int WINAPI DllMain (HANDLE hinst, DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) g_hInstance = hinst; else if (reason == DLL_PROCESS_DETACH) slide_stop(NULL, 0, NULL, NULL); return TRUE; } /* Dummy function for testing. */ void __declspec(dllexport) -dummy (HWND hwndParent, int string_size, char *variables, +dummy (HWND hwndParent, int string_size, LPTSTR variables, stack_t **stacktop, extra_parameters_t *extra) { g_hwndParent = hwndParent; EXDLL_INIT(); // note if you want parameters from the stack, pop them off in order. // i.e. if you are called via exdll::myFunction file.dat poop.dat // calling popstring() the first time would give you file.dat, // and the second time would give you poop.dat. // you should empty the stack of your parameters, and ONLY your // parameters. // do your stuff here { - char buf[1024]; - sprintf(buf,"$R0=%s\r\n$R1=%s\r\n", + wchar_t buf[1024]; + + swprintf(buf, 1024, + L"stringsize=%d\r\n$0=%s\r\n$1=%s\r\n$R0=%s\r\n$R1=%s\r\n", + string_size, + getuservariable(INST_0), + getuservariable(INST_1), getuservariable(INST_R0), getuservariable(INST_R1)); - MessageBox(g_hwndParent,buf,0,MB_OK); + MessageBoxW(g_hwndParent,buf,0,MB_OK); - sprintf (buf, - "autoclose =%d\r\n" + swprintf (buf, 1024, + L"autoclose =%d\r\n" "all_user_var =%d\r\n" "exec_error =%d\r\n" "abort =%d\r\n" "exec_reboot =%d\r\n" "reboot_called=%d\r\n" + "api_version =%d\r\n" "silent =%d\r\n" "instdir_error=%d\r\n" "rtl =%d\r\n" "errlvl =%d\r\n", extra->exec_flags->autoclose, extra->exec_flags->all_user_var, extra->exec_flags->exec_error, extra->exec_flags->abort, extra->exec_flags->exec_reboot, extra->exec_flags->reboot_called, + extra->exec_flags->plugin_api_version, extra->exec_flags->silent, extra->exec_flags->instdir_error, extra->exec_flags->rtl, extra->exec_flags->errlvl); - MessageBox(g_hwndParent,buf,0,MB_OK); + MessageBoxW(g_hwndParent,buf,0,MB_OK); } } void __declspec(dllexport) -runonce (HWND hwndParent, int string_size, char *variables, +runonce (HWND hwndParent, int string_size, LPTSTR variables, stack_t **stacktop, extra_parameters_t *extra) { - LPCTSTR result; + LPCWSTR result; g_hwndParent = hwndParent; EXDLL_INIT(); - CreateMutexA (NULL, 0, "gpg4win"); + CreateMutexW (NULL, 0, getuservariable(INST_R0)); result = GetLastError ()? L"1" : L"0"; - OutputDebugStringA ("Runonce returns:"); - OutputDebugStringW (result); setuservariable (INST_R0, result); } #include /* Extract config file parameters. FIXME: Not particularly robust. We expect some reasonable formatting. The parser below is very limited. It expects a command line option /c=FILE or /C=FILE, where FILE must be enclosed in double-quotes if it contains spaces. That file should contain a single section [gpg4win] and KEY=VALUE pairs for each additional configuration file to install. Comments are supported only on lines by themselves. VALUE can be quoted in double-quotes, but does not need to be, unless it has whitespace at the beginning or end. KEY can, for example, be "gpg.conf" (without the quotes). */ void config_init (char **keys, char **values, int max) { /* First, parse the command line. */ + LPCWSTR wcmdline; char *cmdline; char *begin = NULL; char *end = NULL; char mark; char *fname; char *ptr; FILE *conf; *keys = NULL; *values = NULL; - cmdline = getuservariable (INST_CMDLINE); + cmdline = malloc (4096); + if (!cmdline) + return; + + wcmdline = getuservariable (INST_CMDLINE); + *cmdline = 0; + WideCharToMultiByte(CP_ACP, 0, wcmdline, -1, cmdline, 4095, NULL, NULL); + if (!*cmdline) + return; mark = (*cmdline == '"') ? (cmdline++, '"') : ' '; while (*cmdline && *cmdline != mark) cmdline++; if (mark == '"' && *cmdline) cmdline++; while (*cmdline && *cmdline == ' ') cmdline++; while (*cmdline) { /* We are at the beginning of a new argument. */ if (cmdline[0] == '/' && (cmdline[1] == 'C' || cmdline[1] == 'c') && cmdline[2] == '=') { cmdline += 3; begin = cmdline; } while (*cmdline && *cmdline != ' ') { /* Skip over quoted parts. */ if (*cmdline == '"') { cmdline++; while (*cmdline && *cmdline != '"') cmdline++; if (*cmdline) cmdline++; } else cmdline++; } if (begin && !end) { end = cmdline - 1; break; } while (*cmdline && *cmdline == ' ') cmdline++; } if (!begin || begin > end) return; /* Strip quotes. */ if (*begin == '"' && *end == '"') { begin++; end--; } if (begin > end) return; fname = malloc (end - begin + 2); if (!fname) return; ptr = fname; while (begin <= end) *(ptr++) = *(begin++); *ptr = '\0'; conf = fopen (fname, "r"); free (fname); + free (cmdline); if (!conf) return; while (max - 1 > 0) { char line[256]; char *ptr2; if (fgets (line, sizeof (line), conf) == NULL) break; ptr = &line[strlen (line)]; while (ptr > line && (ptr[-1] == '\n' || ptr[-1] == '\r' || ptr[-1] == ' ' || ptr[-1] == '\t')) ptr--; *ptr = '\0'; ptr = line; while (*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++; /* Ignore comment lines. */ /* FIXME: Ignore section markers. */ if (*ptr == '\0' || *ptr == ';' || *ptr == '[') continue; begin = ptr; while (*ptr && *ptr != '=' && *ptr != ' ' && *ptr != '\t') ptr++; end = ptr - 1; while (*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++; if (*ptr != '=') continue; ptr++; if (begin > end) continue; /* We found a key. */ *keys = malloc (end - begin + 2); if (!keys) return; ptr2 = *keys; while (begin <= end) *(ptr2++) = *(begin++); *ptr2 = '\0'; *values = NULL; while (*ptr && (*ptr == ' ' || *ptr == '\t')) ptr++; begin = ptr; /* In this case, end points to the byte after the value, which is OK because that is '\0'. */ end = &line[strlen (line)]; if (begin > end) begin = end; /* Strip quotes. */ if (*begin == '"' && end[-1] == '"') { begin++; end--; *end = '\0'; } if (begin > end) return; *values = malloc (end - begin + 1); ptr2 = *values; while (begin <= end) *(ptr2++) = *(begin++); keys++; values++; max--; } fclose (conf); *keys = NULL; *values = NULL; } char * config_lookup (char *key) { #define MAX_KEYS 128 static int initialised = 0; static char *keys[MAX_KEYS]; static char *values[MAX_KEYS]; int i; if (initialised == 0) { initialised = 1; config_init (keys, values, MAX_KEYS); #if 0 MessageBox(g_hwndParent, "Configuration File:", 0, MB_OK); i = 0; while (keys[i]) { char buf[256]; sprintf (buf, "%s=%s\r\n", keys[i], values[i]); MessageBox (g_hwndParent, buf, 0, MB_OK); i++; } #endif } i = 0; while (keys[i]) { if (!strcmp (keys[i], key)) return values[i]; i++; } return NULL; } void __declspec(dllexport) -config_fetch (HWND hwndParent, int string_size, char *variables, +config_fetch (HWND hwndParent, int string_size, LPTSTR variables, stack_t **stacktop, extra_parameters_t *extra) { char key[256]; int err = 0; char *value; g_hwndParent = hwndParent; EXDLL_INIT(); /* The expected stack layout: key. */ - if (popstringn (key, sizeof (key))) + if (PopStringNA (key, sizeof (key))) err = 1; if (err) { - setuservariable (INST_R0, ""); + setuservariable (INST_R0, L""); return; } value = config_lookup (key); - setuservariable (INST_R0, value == NULL ? "" : value); + SetUserVariableA (INST_R0, value == NULL ? "" : value); return; } void __declspec(dllexport) -config_fetch_bool (HWND hwndParent, int string_size, char *variables, +config_fetch_bool (HWND hwndParent, int string_size, LPTSTR variables, stack_t **stacktop, extra_parameters_t *extra) { char key[256]; int err = 0; char *value; int result; g_hwndParent = hwndParent; EXDLL_INIT(); /* The expected stack layout: key. */ - if (popstringn (key, sizeof (key))) + if (PopStringNA (key, sizeof (key))) err = 1; if (err) { - setuservariable (INST_R0, ""); + setuservariable (INST_R0, L""); return; } value = config_lookup (key); if (value == NULL || *value == '\0') { - setuservariable (INST_R0, ""); + setuservariable (INST_R0, L""); return; } result = 0; if (!strcasecmp (value, "true") || !strcasecmp (value, "yes") || atoi (value) != 0) result = 1; - setuservariable (INST_R0, result == 0 ? "0" : "1"); + SetUserVariableA (INST_R0, result == 0 ? "0" : "1"); return; } /* Return a string from the Win32 Registry or NULL in case of error. Caller must release the return value. A NULL for root is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */ char * read_w32_registry_string (HKEY root, const char *dir, const char *name) { HKEY root_key; HKEY key_handle; DWORD n1, nbytes, type; char *result = NULL; root_key = root; if (! root_key) root_key = HKEY_CURRENT_USER; - if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) ) + if( RegOpenKeyExA( root_key, dir, 0, KEY_READ, &key_handle ) ) { if (root) return NULL; /* no need for a RegClose, so return direct */ /* It seems to be common practise to fall back to HKLM. */ - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) return NULL; /* still no need for a RegClose, so return direct */ } nbytes = 1; - if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) { + if( RegQueryValueExA ( key_handle, name, 0, NULL, NULL, &nbytes ) ) { if (root) goto leave; /* Try to fallback to HKLM also vor a missing value. */ RegCloseKey (key_handle); - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) + if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) ) return NULL; /* Nope. */ - if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes)) + if (RegQueryValueExA ( key_handle, name, 0, NULL, NULL, &nbytes)) goto leave; } result = malloc( (n1=nbytes+1) ); if( !result ) goto leave; - if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) { + if( RegQueryValueExA ( key_handle, name, 0, &type, result, &n1 ) ) { free(result); result = NULL; goto leave; } result[nbytes] = 0; /* make sure it is really a string */ leave: RegCloseKey( key_handle ); return result; } /** @brief Kill processes with the name name. * * This function tries to kill a process using ExitProcess. * * If it does not work it does not work. No return values. * The intention is to make an effort to kill something during * installation / uninstallation. * * The function signature is explained by NSIS. */ void __declspec(dllexport) __cdecl KillProc(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) { HANDLE h; PROCESSENTRY32 pe32; if (!stacktop || !*stacktop || !(*stacktop)->text) { ERRORPRINTF ("Invalid call to KillProc."); return; } h = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); if (h == INVALID_HANDLE_VALUE) { ERRORPRINTF ("Failed to create Toolhelp snapshot"); return; } pe32.dwSize = sizeof (PROCESSENTRY32); if (!Process32First (h, &pe32)) { ERRORPRINTF ("Failed to get first process"); CloseHandle (h); return; } do { - if (!strcmp ((*stacktop)->text, pe32.szExeFile)) + if (!wcscmp ((*stacktop)->text, pe32.szExeFile)) { HANDLE hProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); if (!hProc) { ERRORPRINTF ("Failed to open process handle."); continue; } if (!TerminateProcess (hProc, 1)) { ERRORPRINTF ("Failed to terminate process."); } CloseHandle (hProc); } } while (Process32Next (h, &pe32)); CloseHandle (h); }