Rev 4914 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <windows.h>#include <iostream>#include <sstream>#include <cstdlib>#include <string>#include <vector>#include <algorithm>#include <nsis/pluginapi.h> // nsis pluginusing namespace std;extern "C" void __declspec(dllexport) ChangePath ( HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra );int ModifyPath( const string &action, const string &type, string &element );bool FindInPath( string &path, const string &search );bool CleanPath ( string &path, const string &delpath = "" );// GLOBALSHINSTANCE g_hInstance;HWND g_hwndParent;static const string ActionAddBefore("ADDBEFORE");static const string ActionAddAfter ("ADDAFTER");static const string ActionDelete ("DELETE");static const string TypeSystem ("SYSTEM");static const string TypeUser ("USER");// Parameters from NSIS// ACTION : Action to perform// ADDBEFORE : adds element to front of current path// ADDAFTER : adds element to end of current path// DELETE : deletes element from current path// TYPE : Specifies the "SYSTEM" or "USER" path environment to modify// ELEMENT: The element to add/remove from path// Returnes// 0 on success// 1 on failure// 2 on invalid parametersvoid __declspec(dllexport) ChangePath( HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra ){string action, element, type;char dummy[8152];g_hwndParent=hwndParent;EXDLL_INIT();if(popstring(dummy)){pushstring("2");return;}action = dummy;transform(action.begin(), action.end(), action.begin(), ::toupper);if(popstring(dummy)){pushstring("2");return;}type = dummy;transform(type.begin(), type.end(), type.begin(), ::toupper);if(popstring(dummy)){pushstring("2");return;}element = dummy;if ( action != ActionAddBefore && action != ActionAddAfter && action != ActionDelete ){pushstring("2");return;}if ( type != TypeSystem && type != TypeUser ){pushstring("2");return;}// now we are good to goodif ( ModifyPath(action, type, element) )pushstring("0");elsepushstring("1");return;}int ModifyPath(const string &action, const string &type, string &element){string path;string::reverse_iterator rit;HKEY hKey;LONG res;char val[8152];DWORD size = sizeof(val);bool pathChanged = false;// Open the registry key for system or user enviromentif ( type == TypeSystem ){res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"), 0, KEY_ALL_ACCESS, &hKey);}else{res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Environment"), 0, KEY_ALL_ACCESS, &hKey);}if ( res != ERROR_SUCCESS )return 0;// Load the Path subkeyres = RegQueryValueEx(hKey, TEXT("Path"), NULL, NULL, (LPBYTE)&val, &size);if ( res == ERROR_FILE_NOT_FOUND ){ // if not found set val to empty stringval[0] = '\0';}else if ( res != ERROR_SUCCESS ){RegCloseKey(hKey);return 0;}path = val;// Remove any trailing ; from elementfor ( rit = element.rbegin(); *rit == ';'; rit = element.rbegin() )element.resize(element.length()-1);if ( action == ActionAddBefore && ! FindInPath(path, element) ){// make sure new dir to add has a ; on the end so we can insert it to the start of pathelement += ';';path.insert(0, element);// Clean up any empty fieldsCleanPath(path);pathChanged = true;}else if ( action == ActionAddAfter && ! FindInPath(path, element) ){// append ; followed by new dir, clean path will remove empty fields so dont need to check for ; on the endpath += ';';path += element;// Clean up any empty fieldsCleanPath(path);pathChanged = true;}else if ( action == ActionDelete ){// remove element from path if it existspathChanged = CleanPath(path, element);}// Now write the pathres = ERROR_SUCCESS;if ( pathChanged )res = RegSetValueEx(hKey, TEXT("Path"), NULL, REG_EXPAND_SZ, (LPBYTE)path.c_str(), path.length()+1);RegCloseKey(hKey);return ( res != ERROR_SUCCESS ? 0 : 1);}bool FindInPath( string &path, const string &search ){string element;istringstream spath(path);//Split each path element on ; and discard any empty oneswhile ( getline(spath, element, ';') ){if ( element == search )return true;}return false;}bool CleanPath( string &path, const string &delpath ){string newpath("");string element;istringstream spath(path);string::reverse_iterator it;bool changed = false;//Split each path element on ; and discard any empty oneswhile ( getline(spath, element, ';') ){if ( ! element.empty() && ( delpath.empty() || element != delpath )){newpath += element + ";";}else{changed = true;}}// Remove any trailing ;for ( it = newpath.rbegin(); *it == ';'; it = newpath.rbegin() ){newpath.resize(newpath.length()-1);changed = true;}if ( changed )path = newpath;return changed;}BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved){g_hInstance = (HINSTANCE)hInst;return TRUE;}