diff --git a/Contrib/EnVar/EnVar.vcproj b/Contrib/EnVar/EnVar.vcproj new file mode 100644 index 0000000..ae3cbad --- /dev/null +++ b/Contrib/EnVar/EnVar.vcproj @@ -0,0 +1,666 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Contrib/EnVar/envar.c b/Contrib/EnVar/envar.c new file mode 100644 index 0000000..eb0cff3 --- /dev/null +++ b/Contrib/EnVar/envar.c @@ -0,0 +1,571 @@ +/* + * EnVar plugin for NSIS + * + * 2014-2016, 2018 MouseHelmet Software. + * + * Created By Jason Ross aka JasonFriday13 on the forums + * + * Checks, adds and removes paths to environment variables. + * + * envar.c + */ + +/* Include relevent files. */ +#include +#include +#include "nsis\pluginapi.h" /* This means NSIS 2.42 or higher is required. */ + +/* Registry defines. */ +#define HKCU HKEY_CURRENT_USER +#define HKCU_STR _T("Environment") +#define HKLM HKEY_LOCAL_MACHINE +#define HKLM_STR _T("System\\CurrentControlSet\\Control\\Session Manager\\Environment") + +/* I would have used ints, but removing pushint() also + removes a dependency on wsprintf and user32.dll. */ +#define ERR_SUCCESS _T("0") +#define ERR_NOREAD _T("1") +#define ERR_NOVARIABLE _T("2") +#define ERR_NOVALUE _T("3") +#define ERR_NOWRITE _T("4") + +/* The amount of extra room to allocate to prevent overflows. */ +#define APPEND_SIZE 4 + +/* Unicode and odd value finder. */ +#define IS_UNICODE_AND_ODD(x) ((sizeof(TCHAR) > 1 && (x) & 0x1) ? 1 : 0) + +/* Global declarations. */ +BOOL bRegKeyHKLM = FALSE; +HINSTANCE hInstance; +PTCHAR gptVarName, gptPathString, gptBuffer; + +/* Allocates a string. */ +PTCHAR StrAlloc(SIZE_T strlen) +{ + return (PTCHAR)GlobalAlloc(GPTR, strlen*sizeof(TCHAR)); +} + +/* Frees a string. */ +void StrFree(PTCHAR hVar) +{ + GlobalFree(hVar); + hVar = NULL; +} + +/* Returns the string size. */ +int StrSize(PTCHAR hVar) +{ + return (int)((GlobalSize(hVar)-IS_UNICODE_AND_ODD(GlobalSize(hVar)))/sizeof(TCHAR)); +} + +/* Returns the string length. */ +int StrLen(PTCHAR hVar) +{ + return lstrlen(hVar); +} + +/* Reallocs a buffer. It's more efficient to free and alloc than realloc. */ +BOOL StrReAlloc(PTCHAR hVar, int strlen) +{ + int i; + PTCHAR temp; + + if (GlobalSize(hVar) >= strlen*sizeof(TCHAR)) return 1; + temp = StrAlloc(strlen); + if (!temp) return 0; + for (i = 0; i < StrSize(hVar); i++) + temp[i] = hVar[i]; + StrFree(hVar); + hVar = temp; + + return 1; +} + +/* Initializes the default string size for variables. */ +void AllocStrs(void) +{ + if (!gptVarName) gptVarName = StrAlloc(g_stringsize); + if (!gptPathString) gptPathString = StrAlloc(g_stringsize); + if (!gptBuffer) gptBuffer = StrAlloc(g_stringsize); +} + +/* Frees allocated buffers. */ +void CleanUp(void) +{ + if (gptVarName) StrFree(gptVarName); + if (gptPathString) StrFree(gptPathString); + if (gptBuffer) StrFree(gptBuffer); + + SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)HKCU_STR, 0, 100, 0); +} + +/* Our callback function so that our dll stays loaded. */ +UINT_PTR __cdecl NSISPluginCallback(enum NSPIM Event) +{ + if (Event == NSPIM_UNLOAD) CleanUp(); + + return 0; +} + +/* This function initializes the plugin variables. */ +void Initialize(extra_parameters* xp) +{ + xp->RegisterPluginCallback(hInstance, NSISPluginCallback); + AllocStrs(); +} + +/* Appends a semi-colon to a string. Auto-expands the buffer + if there isn't enough room. */ +BOOL AppendSemiColon(PTCHAR bufStr) +{ + int len; + + if (!bufStr) return FALSE; + len = StrLen(bufStr); + if (!len) return TRUE; + if (bufStr[len-1] != ';' && bufStr[0] != ';') + { + if (!StrReAlloc(bufStr, len+APPEND_SIZE)) return FALSE; + bufStr[len] = ';'; + bufStr[len+1] = 0; + } + return TRUE; +} + +/* Removes the trailing semi-colon if it exists. */ +void RemoveSemiColon(PTCHAR bufStr) +{ + if (!bufStr) return; + if (StrLen(bufStr) < 1) return; + if (bufStr[StrLen(bufStr)-1] == ';') bufStr[StrLen(bufStr)-1] = 0; +} + +/* Sets the current root key. */ +void SetRegKey(BOOL bKeyHKLM) +{ + bRegKeyHKLM = bKeyHKLM; +} + +/* Gets the current root key. */ +BOOL GetRegKey(void) +{ + return bRegKeyHKLM; +} + +/* Registry helper functions. */ +ULONG CreateRegKey(void) +{ + DWORD dwRet, dwDisType = 0; + HKEY hKey; + + if (bRegKeyHKLM) + dwRet = RegCreateKeyEx(HKLM, HKLM_STR, 0, 0, 0, KEY_WRITE, 0, &hKey, &dwDisType); + else + dwRet = RegCreateKeyEx(HKCU, HKCU_STR, 0, 0, 0, KEY_WRITE, 0, &hKey, &dwDisType); + + RegCloseKey(hKey); + + return dwRet; +} + +/* Custom ReadRegVar function with ERROR_MORE_DATA handling. */ +ULONG ReadRegVar(PTCHAR ptName, PDWORD pdwType, PTCHAR ptDest, PDWORD pdwStrLen) +{ + DWORD dwRet, dwSize = *pdwStrLen*sizeof(TCHAR), dwType = *pdwType; + HKEY hKey; + + ptDest[0] = 0; + if (bRegKeyHKLM) + dwRet = RegOpenKeyEx(HKLM, HKLM_STR, 0, KEY_READ, &hKey); + else + dwRet = RegOpenKeyEx(HKCU, HKCU_STR, 0, KEY_READ, &hKey); + + if (dwRet == ERROR_SUCCESS) + { + dwRet = RegQueryValueEx(hKey, ptName, 0, &dwType, (LPBYTE)ptDest, &dwSize); + while (dwRet == ERROR_MORE_DATA) + { + DWORD dwSizeTemp = dwSize + APPEND_SIZE + IS_UNICODE_AND_ODD(dwSize); + + if (!StrReAlloc(ptDest, dwSizeTemp/sizeof(TCHAR))) return 4; /* ERR_NOWRITE */ + dwRet = RegQueryValueEx(hKey, ptName, 0, &dwType, (LPBYTE)ptDest, &dwSizeTemp); + if (dwRet == ERROR_SUCCESS) dwSize = dwSizeTemp; + } + RegCloseKey(hKey); + if (dwRet == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) + { + ptDest[((dwSize+IS_UNICODE_AND_ODD(dwSize))/sizeof(TCHAR))-1] = 0; + *pdwType = dwType; + *pdwStrLen = (dwSize-IS_UNICODE_AND_ODD(dwSize))/sizeof(TCHAR); + + return 0; + } + else + { + ptDest[0] = 0; + /* dwRet can still be ERROR_SUCCESS here, so return an absolute value. */ + return 1; /* ERR_NOREAD */ + } + } + else + return 1; /* ERR_NOREAD */ +} + +/* Custom WriteRegVar function, writes a value to the environment. */ +ULONG WriteRegVar(PTCHAR ptName, DWORD dwKeyType, PTCHAR ptData, DWORD dwStrLen) +{ + DWORD dwRet; + HKEY hKey; + + if (bRegKeyHKLM) + dwRet = RegOpenKeyEx(HKLM, HKLM_STR, 0, KEY_WRITE, &hKey); + else + dwRet = RegOpenKeyEx(HKCU, HKCU_STR, 0, KEY_WRITE, &hKey); + + if (dwRet != ERROR_SUCCESS) return dwRet; + dwRet = RegSetValueEx(hKey, ptName, 0, dwKeyType, (LPBYTE)ptData, dwStrLen*sizeof(TCHAR)); + RegCloseKey(hKey); + + return dwRet; +} + +/* Checks for write access and various conditions about a variable and it's type. */ +LPCTSTR CheckVar(void) +{ + DWORD dwStrSize, dwKeyType; + HKEY hKeyHandle; + + SecureZeroMemory(gptBuffer, GlobalSize(gptBuffer)); + + popstring(gptVarName); + popstring(gptPathString); + + if (!StrLen(gptVarName)) return ERR_NOVARIABLE; + if (lstrcmpi(gptVarName, _T("NULL")) == 0) + { + DWORD dwRet; + + if (bRegKeyHKLM) + dwRet = RegOpenKeyEx(HKLM, HKLM_STR, 0, KEY_WRITE, &hKeyHandle); + else + dwRet = RegOpenKeyEx(HKCU, HKCU_STR, 0, KEY_WRITE, &hKeyHandle); + + if (dwRet == ERROR_SUCCESS) + { + RegCloseKey(hKeyHandle); + return ERR_SUCCESS; + } + else + return ERR_NOWRITE; + } + dwStrSize = StrSize(gptBuffer); + if (ReadRegVar(gptVarName, &dwKeyType, gptBuffer, &dwStrSize) != ERROR_SUCCESS) + return ERR_NOVARIABLE; + + if (!StrLen(gptPathString)) return ERR_NOVARIABLE; + if (lstrcmpi(gptPathString, _T("NULL")) != 0) + { + if (!AppendSemiColon(gptPathString)) return ERR_NOWRITE; + if (!AppendSemiColon(gptBuffer)) return ERR_NOWRITE; + if (StrStrI(gptBuffer, gptPathString) == NULL) + return ERR_NOVALUE; + else + return ERR_SUCCESS; + } + else + if (dwKeyType != REG_SZ && dwKeyType != REG_EXPAND_SZ) + return ERR_NOVALUE; + else + return ERR_SUCCESS; +} + +/* Adds a value to a variable if it's the right type. */ +LPCTSTR AddVarValue(DWORD dwKey) +{ + DWORD dwStrSize; + + SecureZeroMemory(gptBuffer, GlobalSize(gptBuffer)); + + popstring(gptVarName); + popstring(gptPathString); + + if (!StrLen(gptPathString)) return ERR_NOVALUE; + + if (CreateRegKey() != ERROR_SUCCESS) + return ERR_NOWRITE; + else + { + DWORD dwKeyType; + + dwStrSize = StrSize(gptBuffer); + ReadRegVar(gptVarName, &dwKeyType, gptBuffer, &dwStrSize); + + if (dwKeyType == REG_EXPAND_SZ) dwKey = dwKeyType; + if (!AppendSemiColon(gptPathString)) return ERR_NOWRITE; + if (!AppendSemiColon(gptBuffer)) return ERR_NOWRITE; + + if (StrStrI(gptBuffer, gptPathString) == NULL) + { + int i, len = StrLen(gptBuffer); + + /* Add one for separator and one for terminating NULL character. */ + if (!StrReAlloc(gptBuffer, len+StrLen(gptPathString)+APPEND_SIZE)) + return ERR_NOWRITE; + + for (i = 0; i <= StrLen(gptPathString); i++) + gptBuffer[len+i] = gptPathString[i]; + + RemoveSemiColon(gptBuffer); + if (WriteRegVar(gptVarName, dwKey, gptBuffer, StrLen(gptBuffer)+1) != ERROR_SUCCESS) + return ERR_NOWRITE; + else + return ERR_SUCCESS; + } + else + return ERR_SUCCESS; + } +} + +/* Deletes a value from a variable if it's the right type. */ +LPCTSTR DeleteVarValue(void) +{ + DWORD dwStrSize, dwKeyType; + + SecureZeroMemory(gptBuffer, GlobalSize(gptBuffer)); + + popstring(gptVarName); + popstring(gptPathString); + + dwStrSize = StrSize(gptBuffer); + if (ReadRegVar(gptVarName, &dwKeyType, gptBuffer, &dwStrSize) != ERROR_SUCCESS) + return ERR_NOVARIABLE; + + if (!AppendSemiColon(gptPathString)) return ERR_NOWRITE; + if (!AppendSemiColon(gptBuffer)) return ERR_NOWRITE; + + if (StrStrI(gptBuffer, gptPathString) == NULL) + return ERR_NOVALUE; + else + { + do + { + int i, len; + const PTCHAR str = StrStrI(gptBuffer, gptPathString); + + if (str[StrLen(gptPathString)] == ';') + { + len = StrLen(str); + for (i = StrLen(gptPathString); i < len; i++) + str[i] = str[i+1]; + } + len = StrLen(gptBuffer) - StrLen(str); + for (i = StrLen(gptPathString); i <= StrLen(str); i++, len++) + gptBuffer[len] = str[i]; + + } while (StrStrI(gptBuffer, gptPathString) != NULL); + + RemoveSemiColon(gptBuffer); + if (WriteRegVar(gptVarName, dwKeyType, gptBuffer, StrLen(gptBuffer)+1) != ERROR_SUCCESS) + return ERR_NOWRITE; + else + return ERR_SUCCESS; + } +} + +/* Deletes a variable from the environment. */ +LPCTSTR DeleteVar(void) +{ + DWORD dwRet, res; + HKEY hKey; + + popstring(gptVarName); + + if (!lstrcmpi(gptVarName, _T("path"))) + return ERR_NOWRITE; + + if (bRegKeyHKLM) + dwRet = RegOpenKeyEx(HKLM, HKLM_STR, 0, KEY_WRITE, &hKey); + else + dwRet = RegOpenKeyEx(HKCU, HKCU_STR, 0, KEY_WRITE, &hKey); + + if (dwRet == ERROR_SUCCESS) + { + res = RegDeleteValue(hKey, gptVarName); + RegCloseKey(hKey); + if (res == ERROR_SUCCESS) + return ERR_SUCCESS; + } + + return ERR_NOWRITE; +} + +/* Updates the installer environment from the registry. */ +LPCTSTR UpdateVar(void) +{ + PTCHAR ptRegRoot = gptVarName, ptVarName = gptPathString; + DWORD dwRet, dwStrSize, dwKeyType; + BOOL bOldKey = GetRegKey(); + int i; + + popstring(ptRegRoot); + popstring(ptVarName); + + if (!lstrcmpi(ptRegRoot, _T("HKCU")) || !lstrcmpi(ptRegRoot, _T("HKLM"))) + { + if (!lstrcmpi(ptRegRoot, _T("HKLM"))) + SetRegKey(TRUE); + else + SetRegKey(FALSE); + + dwRet = ReadRegVar(ptVarName, &dwKeyType, gptBuffer, &dwStrSize); + SetRegKey(bOldKey); + if (dwRet != ERROR_SUCCESS) + return ERR_NOVARIABLE; + } + else + { + int len; + + SetRegKey(FALSE); + dwRet = ReadRegVar(ptVarName, &dwKeyType, gptBuffer, &dwStrSize); + if (dwRet != ERROR_SUCCESS) + *ptRegRoot = 0; + else + { + if (!StrReAlloc(ptRegRoot, StrLen(gptBuffer)+APPEND_SIZE)) + { + SetRegKey(bOldKey); + return ERR_NOWRITE; + } + /* Update global pointer if ptRegRoot was changed. */ + gptVarName = (gptVarName != ptRegRoot) ? ptRegRoot : gptVarName; + for (i = 0; i <= StrLen(gptBuffer); i++) + ptRegRoot[i] = gptBuffer[i]; + AppendSemiColon(ptRegRoot); + } + SetRegKey(TRUE); + dwRet = ReadRegVar(ptVarName, &dwKeyType, gptBuffer, &dwStrSize); + SetRegKey(bOldKey); + if (dwRet != ERROR_SUCCESS) + if (!(*ptRegRoot)) + return ERR_NOVARIABLE; + else + *gptBuffer = 0; + + AppendSemiColon(gptBuffer); + len = StrLen(gptBuffer); + + /* Add one for separator and one for terminating NULL character. */ + if (!StrReAlloc(gptBuffer, len+StrLen(ptRegRoot)+APPEND_SIZE)) + return ERR_NOWRITE; + + for (i = 0; i <= StrLen(ptRegRoot); i++) + gptBuffer[len+i] = ptRegRoot[i]; + + RemoveSemiColon(gptBuffer); + } + if (SetEnvironmentVariable(ptVarName, gptBuffer)) + return ERR_SUCCESS; + else + return ERR_NOWRITE; +} + +/* This routine sets the environment root, HKCU. */ +__declspec(dllexport) void SetHKCU(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + SetRegKey(FALSE); +} + +/* This routine sets the environment root, HKLM. */ +__declspec(dllexport) void SetHKLM(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + SetRegKey(TRUE); +} + +/* This routine checks for a path in an environment variable. */ +__declspec(dllexport) void Check(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(CheckVar()); +} + +/* This routine adds a REG_SZ value in a environment variable (checks for existing paths first). */ +__declspec(dllexport) void AddValue(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(AddVarValue(REG_SZ)); +} + +/* This routine adds a REG_EXPAND_SZ value in a environment variable (checks for existing paths first). */ +__declspec(dllexport) void AddValueEx(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(AddVarValue(REG_EXPAND_SZ)); +} + +/* This routine deletes a value in an environment variable if it exists. */ +__declspec(dllexport) void DeleteValue(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(DeleteVarValue()); +} + +/* This routine deletes an environment variable if it exists. */ +__declspec(dllexport) void Delete(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(DeleteVar()); +} + +/* This routine reads the registry and updates the process environment. */ +__declspec(dllexport) void Update(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters* xp) +{ + /* Initialize the stack so we can access it from our DLL using + popstring and pushstring. */ + EXDLL_INIT(); + Initialize(xp); + + pushstring(UpdateVar()); +} + +/* Our DLL entry point, this is called when we first load up our DLL. */ +BOOL WINAPI _DllMainCRTStartup(HINSTANCE hInst, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + hInstance = hInst; + + if (ul_reason_for_call == DLL_PROCESS_DETACH) + CleanUp(); + + return TRUE; +} \ No newline at end of file diff --git a/Contrib/EnVar/nsis/api.h b/Contrib/EnVar/nsis/api.h new file mode 100644 index 0000000..85d41c4 --- /dev/null +++ b/Contrib/EnVar/nsis/api.h @@ -0,0 +1,83 @@ +/* + * apih + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * Licensed under the zlib/libpng license (the "License"); + * you may not use this file except in compliance with the License. + * + * Licence details can be found in the file COPYING. + * + * This software is provided 'as-is', without any express or implied + * warranty. + */ + +#ifndef _NSIS_EXEHEAD_API_H_ +#define _NSIS_EXEHEAD_API_H_ + +// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version +// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x)) +// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {} + +#define NSISPIAPIVER_1_0 0x00010000 +#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0 + +// NSIS Plug-In Callback Messages +enum NSPIM +{ + NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup + NSPIM_GUIUNLOAD, // Called after .onGUIEnd +}; + +// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback() +// Return NULL for unknown messages +// Should always be __cdecl for future expansion possibilities +typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM); + +// extra_parameters data structures containing other interesting stuff +// but the stack, variables and HWND passed on to plug-ins. +typedef struct +{ + int autoclose; + int all_user_var; + int exec_error; + int abort; + int exec_reboot; // NSIS_SUPPORT_REBOOT + int reboot_called; // NSIS_SUPPORT_REBOOT + int XXX_cur_insttype; // depreacted + int plugin_api_version; // see NSISPIAPIVER_CURR + // used to be XXX_insttype_changed + int silent; // NSIS_CONFIG_SILENT_SUPPORT + int instdir_error; + int rtl; + int errlvl; + int alter_reg_view; + int status_update; +} exec_flags_t; + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +typedef struct { + exec_flags_t *exec_flags; + int (NSISCALL *ExecuteCodeSegment)(int, HWND); + void (NSISCALL *validate_filename)(TCHAR *); + int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors +} extra_parameters; + +// Definitions for page showing plug-ins +// See Ui.c to understand better how they're used + +// sent to the outer window to tell it to go to the next inner window +#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8) + +// custom pages should send this message to let NSIS know they're ready +#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd) + +// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning +#define NOTIFY_BYE_BYE 'x' + +#endif /* _PLUGIN_H_ */ diff --git a/Contrib/EnVar/nsis/nsis_tchar.h b/Contrib/EnVar/nsis/nsis_tchar.h new file mode 100644 index 0000000..0664768 --- /dev/null +++ b/Contrib/EnVar/nsis/nsis_tchar.h @@ -0,0 +1,229 @@ +/* + * nsis_tchar.h + * + * This file is a part of NSIS. + * + * Copyright (C) 1999-2013 Nullsoft and Contributors + * + * This software is provided 'as-is', without any express or implied + * warranty. + * + * For Unicode support by Jim Park -- 08/30/2007 + */ + +// Jim Park: Only those we use are listed here. + +#pragma once + +#ifdef _UNICODE + +#ifndef _T +#define __T(x) L ## x +#define _T(x) __T(x) +#define _TEXT(x) __T(x) +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +#if !defined(_NATIVE_WCHAR_T_DEFINED) && !defined(_WCHAR_T_DEFINED) +typedef unsigned short TCHAR; +#else +typedef wchar_t TCHAR; +#endif +#endif + + +// program +#define _tenviron _wenviron +#define __targv __wargv + +// printfs +#define _ftprintf fwprintf +#define _sntprintf _snwprintf +#if (defined(_MSC_VER) && (_MSC_VER<=1310||_MSC_FULL_VER<=140040310)) || defined(__MINGW32__) +# define _stprintf swprintf +#else +# define _stprintf _swprintf +#endif +#define _tprintf wprintf +#define _vftprintf vfwprintf +#define _vsntprintf _vsnwprintf +#if defined(_MSC_VER) && (_MSC_VER<=1310) +# define _vstprintf vswprintf +#else +# define _vstprintf _vswprintf +#endif + +// scanfs +#define _tscanf wscanf +#define _stscanf swscanf + +// string manipulations +#define _tcscat wcscat +#define _tcschr wcschr +#define _tcsclen wcslen +#define _tcscpy wcscpy +#define _tcsdup _wcsdup +#define _tcslen wcslen +#define _tcsnccpy wcsncpy +#define _tcsncpy wcsncpy +#define _tcsrchr wcsrchr +#define _tcsstr wcsstr +#define _tcstok wcstok + +// string comparisons +#define _tcscmp wcscmp +#define _tcsicmp _wcsicmp +#define _tcsncicmp _wcsnicmp +#define _tcsncmp wcsncmp +#define _tcsnicmp _wcsnicmp + +// upper / lower +#define _tcslwr _wcslwr +#define _tcsupr _wcsupr +#define _totlower towlower +#define _totupper towupper + +// conversions to numbers +#define _tcstoi64 _wcstoi64 +#define _tcstol wcstol +#define _tcstoul wcstoul +#define _tstof _wtof +#define _tstoi _wtoi +#define _tstoi64 _wtoi64 +#define _ttoi _wtoi +#define _ttoi64 _wtoi64 +#define _ttol _wtol + +// conversion from numbers to strings +#define _itot _itow +#define _ltot _ltow +#define _i64tot _i64tow +#define _ui64tot _ui64tow + +// file manipulations +#define _tfopen _wfopen +#define _topen _wopen +#define _tremove _wremove +#define _tunlink _wunlink + +// reading and writing to i/o +#define _fgettc fgetwc +#define _fgetts fgetws +#define _fputts fputws +#define _gettchar getwchar + +// directory +#define _tchdir _wchdir + +// environment +#define _tgetenv _wgetenv +#define _tsystem _wsystem + +// time +#define _tcsftime wcsftime + +#else // ANSI + +#ifndef _T +#define _T(x) x +#define _TEXT(x) x +#endif + +#ifndef _TCHAR_DEFINED +#define _TCHAR_DEFINED +typedef char TCHAR; +#endif + +// program +#define _tenviron environ +#define __targv __argv + +// printfs +#define _ftprintf fprintf +#define _sntprintf _snprintf +#define _stprintf sprintf +#define _tprintf printf +#define _vftprintf vfprintf +#define _vsntprintf _vsnprintf +#define _vstprintf vsprintf + +// scanfs +#define _tscanf scanf +#define _stscanf sscanf + +// string manipulations +#define _tcscat strcat +#define _tcschr strchr +#define _tcsclen strlen +#define _tcscnlen strnlen +#define _tcscpy strcpy +#define _tcsdup _strdup +#define _tcslen strlen +#define _tcsnccpy strncpy +#define _tcsrchr strrchr +#define _tcsstr strstr +#define _tcstok strtok + +// string comparisons +#define _tcscmp strcmp +#define _tcsicmp _stricmp +#define _tcsncmp strncmp +#define _tcsncicmp _strnicmp +#define _tcsnicmp _strnicmp + +// upper / lower +#define _tcslwr _strlwr +#define _tcsupr _strupr + +#define _totupper toupper +#define _totlower tolower + +// conversions to numbers +#define _tcstol strtol +#define _tcstoul strtoul +#define _tstof atof +#define _tstoi atoi +#define _tstoi64 _atoi64 +#define _tstoi64 _atoi64 +#define _ttoi atoi +#define _ttoi64 _atoi64 +#define _ttol atol + +// conversion from numbers to strings +#define _i64tot _i64toa +#define _itot _itoa +#define _ltot _ltoa +#define _ui64tot _ui64toa + +// file manipulations +#define _tfopen fopen +#define _topen _open +#define _tremove remove +#define _tunlink _unlink + +// reading and writing to i/o +#define _fgettc fgetc +#define _fgetts fgets +#define _fputts fputs +#define _gettchar getchar + +// directory +#define _tchdir _chdir + +// environment +#define _tgetenv getenv +#define _tsystem system + +// time +#define _tcsftime strftime + +#endif + +// is functions (the same in Unicode / ANSI) +#define _istgraph isgraph +#define _istascii __isascii + +#define __TFILE__ _T(__FILE__) +#define __TDATE__ _T(__DATE__) +#define __TTIME__ _T(__TIME__) diff --git a/Contrib/EnVar/nsis/pluginapi-amd64-unicode.lib b/Contrib/EnVar/nsis/pluginapi-amd64-unicode.lib new file mode 100644 index 0000000..e256434 Binary files /dev/null and b/Contrib/EnVar/nsis/pluginapi-amd64-unicode.lib differ diff --git a/Contrib/EnVar/nsis/pluginapi-x86-ansi.lib b/Contrib/EnVar/nsis/pluginapi-x86-ansi.lib new file mode 100644 index 0000000..462070c Binary files /dev/null and b/Contrib/EnVar/nsis/pluginapi-x86-ansi.lib differ diff --git a/Contrib/EnVar/nsis/pluginapi-x86-unicode.lib b/Contrib/EnVar/nsis/pluginapi-x86-unicode.lib new file mode 100644 index 0000000..c83d942 Binary files /dev/null and b/Contrib/EnVar/nsis/pluginapi-x86-unicode.lib differ diff --git a/Contrib/EnVar/nsis/pluginapi.h b/Contrib/EnVar/nsis/pluginapi.h new file mode 100644 index 0000000..ca671a8 --- /dev/null +++ b/Contrib/EnVar/nsis/pluginapi.h @@ -0,0 +1,104 @@ +#ifndef ___NSIS_PLUGIN__H___ +#define ___NSIS_PLUGIN__H___ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "api.h" +#include "nsis_tchar.h" + +#ifndef NSISCALL +# define NSISCALL __stdcall +#endif + +#define EXDLL_INIT() { \ + g_stringsize=string_size; \ + g_stacktop=stacktop; \ + g_variables=variables; } + +typedef struct _stack_t { + struct _stack_t *next; + TCHAR text[1]; // this should be the length of string_size +} stack_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 TCHAR *g_variables; + +void NSISCALL pushstring(const TCHAR *str); +void NSISCALL pushintptr(INT_PTR value); +#define pushint(v) pushintptr((INT_PTR)(v)) +int NSISCALL popstring(TCHAR *str); // 0 on success, 1 on empty stack +int NSISCALL popstringn(TCHAR *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(const TCHAR *s); +#define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer +unsigned int NSISCALL myatou(const TCHAR *s); // converts a string to an unsigned integer, decimal only +int NSISCALL myatoi_or(const TCHAR *s); // with support for or'ing (2|4|8) +TCHAR* NSISCALL getuservariable(const int varnum); +void NSISCALL setuservariable(const int varnum, const TCHAR *var); + +#ifdef _UNICODE +#define PopStringW(x) popstring(x) +#define PushStringW(x) pushstring(x) +#define SetUserVariableW(x,y) setuservariable(x,y) + +int NSISCALL PopStringA(char* ansiStr); +void NSISCALL PushStringA(const char* ansiStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr); + +#else +// ANSI defs + +#define PopStringA(x) popstring(x) +#define PushStringA(x) pushstring(x) +#define SetUserVariableA(x,y) setuservariable(x,y) + +int NSISCALL PopStringW(wchar_t* wideStr); +void NSISCALL PushStringW(wchar_t* wideStr); +void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr); +void NSISCALL GetUserVariableA(const int varnum, char* ansiStr); +void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif//!___NSIS_PLUGIN__H___ diff --git a/Docs/EnVar/license.txt b/Docs/EnVar/license.txt new file mode 100644 index 0000000..a4e466a --- /dev/null +++ b/Docs/EnVar/license.txt @@ -0,0 +1,18 @@ +EnVar plugin for NSIS + +Coded by Jason Ross aka JasonFriday13 on the forums. + +Copyright (C) 2014-2016, 2018 MouseHelmet Software + + +EULA - End User License Agreement + +This software is provided 'as-is', without any express or implied warranty. In no event will the author 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. \ No newline at end of file diff --git a/Docs/EnVar/readme.txt b/Docs/EnVar/readme.txt new file mode 100644 index 0000000..508b25b --- /dev/null +++ b/Docs/EnVar/readme.txt @@ -0,0 +1,68 @@ +EnVar plugin for NSIS + +Coded by Jason Ross aka JasonFriday13 on the forums. + +Copyright (C) 2014-2016, 2018 MouseHelmet Software + + +Introduction +------------ + +This plugin manages environment variables. It allows checking for environment +variables, checking for paths in those variables, adding paths to variables, +removing paths from variables, removing variables from the environment, and +updating the installer enviroment from the registry. This plugin is provided +with 32bit ansi and unicode versions, as well as a 64bit unicode version. + +Functions +--------- + +There are eight functions in this plugin. Returns an error code on the +stack (unless noted otherwise), see below for the codes. + +ERR_SUCCESS 0 Function completed successfully. +ERR_NOREAD 1 Function couldn't read from the environment. +ERR_NOVARIABLE 2 Variable doesn't exist in the current environment. +ERR_NOVALUE 3 Value doesn't exist in the Variable. +ERR_NOWRITE 4 Function can't write to the current environment. + +EnVar::SetHKCU +EnVar::SetHKLM + + SetHKCU sets the environment access to the current user. This is the default. + SetHKLM sets the environment access to the local machine. + These functions do not return a value on the stack. + +EnVar::Check VariableName Path + + Checks for a Path in the specified VariableName. Passing "null" as a Path makes + it check for the existance of VariableName. Passing "null" for both makes it + check for write access to the current environment. + +EnVar::AddValue VariableName Path +EnVar::AddValueEx VariableName Path + + Adds a Path to the specified VariableName. Does does not modify existing variables if + they are not the right type. AddValueEx is for expandable paths, ie %tempdir%. Both + functions respect expandable variables, so if the variable already exists, they + try to leave it intact. AddValueEx converts the variable to its expandable version. + If the path already exists, it returns a success error code. + +EnVar::DeleteValue VariableName Path + + Deletes a path from a variable if it's the right type. The delete is also + recursive, so if it finds multiple paths, all of them are deleted as well. + +EnVar::Delete VariableName + + Deletes a variable from the environment. Note that "path" cannot be deleted. Also, + variables that aren't the right type are not deleted. + +EnVar::Update RegRoot VariableName + + Updates the installer environment by reading VariableName from the registry + and can use RegRoot to specify from which root it reads from: HKCU for the + current user, and HKLM for the local machine. Anything else (including an + empty string) for RegRoot means it reads from both roots, appends the paths + together, and updates the installer environment. This function is not affected + by EnVar::SetHKCU and EnVar::SetHKLM, and does not write to the registry. diff --git a/Examples/EnVar/example.nsi b/Examples/EnVar/example.nsi new file mode 100644 index 0000000..49bc323 --- /dev/null +++ b/Examples/EnVar/example.nsi @@ -0,0 +1,90 @@ +Name "EnVar Example" +OutFile "EnVarExample.exe" + +RequestExecutionLevel User +ShowInstDetails Show + +Page InstFiles + +Unicode True + +Section + + ; Check for write access + EnVar::Check "NULL" "NULL" + Pop $0 + DetailPrint "EnVar::Check write access HKCU returned=|$0|" + + ; Set to HKLM + EnVar::SetHKLM + + ; Check for write access + EnVar::Check "NULL" "NULL" + Pop $0 + DetailPrint "EnVar::Check write access HKLM returned=|$0|" + + ; Set back to HKCU + EnVar::SetHKCU + DetailPrint "EnVar::SetHKCU" + + ; Check for a 'temp' variable + EnVar::Check "temp" "NULL" + Pop $0 + DetailPrint "EnVar::Check returned=|$0|" + + ; Add a value + EnVar::AddValue "ZTestVariable" "C:\Test" + Pop $0 + DetailPrint "EnVar::AddValue returned=|$0|" + + EnVar::AddValue "ZTestVariable" "C:\TestJas" + Pop $0 + DetailPrint "EnVar::AddValue returned=|$0|" + + ; Add an expanded value + EnVar::AddValue "ZTestVariable1" "C:\Test" + Pop $0 + DetailPrint "EnVar::AddValue returned=|$0|" + + EnVar::AddValueEx "ZTestVariable1" "C:\Test" + Pop $0 + DetailPrint "EnVar::AddValue returned=|$0|" + + EnVar::AddValueEx "ZTestVariable1" "C:\TestVariable" + Pop $0 + DetailPrint "EnVar::AddValue returned=|$0|" + + ; Update the installer environment so that new + ; paths are available to the installer + EnVar::Update "HKCU" "ZTestVariable" + Pop $0 + DetailPrint "EnVar::Update returned=|$0|" + + EnVar::Update "" "ZTestVariable1" + Pop $0 + DetailPrint "EnVar::Update returned=|$0|" + + ; Delete a value from a variable + EnVar::DeleteValue "ZTestVariable1" "C:\Test" + Pop $0 + DetailPrint "EnVar::DeleteValue returned=|$0|" + + EnVar::DeleteValue "ZTestVariable1" "C:\Test" + Pop $0 + DetailPrint "EnVar::DeleteValue returned=|$0|" + + EnVar::DeleteValue "ZTestVariable1" "C:\TestJason" + Pop $0 + DetailPrint "EnVar::DeleteValue returned=|$0|" + + ; Delete a variable + EnVar::Delete "ZTestVariable" + Pop $0 + DetailPrint "EnVar::Delete returned=|$0|" + + ; Try deleting "path", this should give an error + EnVar::Delete "path" + Pop $0 + DetailPrint "EnVar::Delete returned=|$0|" + +SectionEnd \ No newline at end of file diff --git a/Plugins/amd64-unicode/EnVar.dll b/Plugins/amd64-unicode/EnVar.dll new file mode 100644 index 0000000..87c5135 Binary files /dev/null and b/Plugins/amd64-unicode/EnVar.dll differ diff --git a/Plugins/x86-ansi/EnVar.dll b/Plugins/x86-ansi/EnVar.dll new file mode 100644 index 0000000..9fe7565 Binary files /dev/null and b/Plugins/x86-ansi/EnVar.dll differ diff --git a/Plugins/x86-unicode/EnVar.dll b/Plugins/x86-unicode/EnVar.dll new file mode 100644 index 0000000..08d60de Binary files /dev/null and b/Plugins/x86-unicode/EnVar.dll differ