Subversion Repositories DevTools

Rev

Rev 4914 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4914 gchristi 1
#include <windows.h>
2
#include <iostream>
3
#include <sstream>
4
#include <cstdlib>
5
#include <string>
6
#include <vector>
7
#include <algorithm>
8
#include <nsis/pluginapi.h> // nsis plugin
9
 
10
using namespace std;
11
 
12
extern "C" void __declspec(dllexport) ChangePath ( HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra );
13
 
14
int  ModifyPath( const string &action, const string &type, string &element );
4922 gchristi 15
bool FindInPath( string &path, const string &search );
16
bool CleanPath ( string &path, const string &delpath = "" );
4914 gchristi 17
 
18
// GLOBALS
19
HINSTANCE   g_hInstance;
20
HWND        g_hwndParent;
21
 
22
static const string         ActionAddBefore("ADDBEFORE");
23
static const string         ActionAddAfter ("ADDAFTER");
24
static const string         ActionDelete   ("DELETE");
25
 
26
static const string         TypeSystem    ("SYSTEM");
27
static const string         TypeUser      ("USER");
28
 
29
// Parameters from NSIS
30
// ACTION : Action to perform 
31
//          ADDBEFORE : adds element to front of current path
32
//          ADDAFTER  : adds element to end of current path
33
//          DELETE    : deletes element from current path
34
// TYPE   : Specifies the "SYSTEM" or "USER" path environment to modify
35
// ELEMENT: The element to add/remove from path
36
// Returnes
37
// 0 on success
38
// 1 on failure
39
// 2 on invalid parameters
40
void __declspec(dllexport) ChangePath( HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra )
41
{
42
    string  action, element, type;
43
    char    dummy[8152];
44
 
45
    g_hwndParent=hwndParent;
46
 
47
    EXDLL_INIT();
48
 
49
    if(popstring(dummy))
50
    {
51
        pushstring("2");
52
        return;
53
    }
54
    action = dummy;
55
    transform(action.begin(), action.end(), action.begin(), ::toupper);    
56
    if(popstring(dummy))
57
    {
58
        pushstring("2");
59
        return;
60
    }
61
    type = dummy;
62
    transform(type.begin(), type.end(), type.begin(), ::toupper);
63
    if(popstring(dummy))
64
    {
65
        pushstring("2");
66
        return;
67
    }
68
    element = dummy;
69
 
70
    if ( action != ActionAddBefore && action != ActionAddAfter && action != ActionDelete )
71
    {
72
        pushstring("2");
73
        return;
74
    }
75
 
76
    if ( type != TypeSystem && type != TypeUser )
77
    {
78
        pushstring("2");
79
        return;
80
    }
81
 
82
    // now we are good to good
83
    if ( ModifyPath(action, type, element) )
84
        pushstring("0");
85
    else
86
        pushstring("1");
87
 
88
    return;
89
}
90
 
91
 
92
int ModifyPath(const string &action, const string &type, string &element)
93
{
94
    string                      path;
95
    string::reverse_iterator    rit;    
96
    HKEY                        hKey;
97
    LONG                        res;
98
    char                        val[8152];
99
    DWORD                       size = sizeof(val);
4922 gchristi 100
    bool                        pathChanged = false;
4914 gchristi 101
 
102
    // Open the registry key for system or user enviroment
103
    if ( type == TypeSystem )
104
    {
105
        res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"), 0, KEY_ALL_ACCESS, &hKey);
106
    }
107
    else
108
    {
109
        res = RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Environment"), 0, KEY_ALL_ACCESS, &hKey);
110
    }
111
    if ( res != ERROR_SUCCESS )
112
        return 0;
113
 
114
    // Load the Path subkey
115
    res = RegQueryValueEx(hKey, TEXT("Path"), NULL, NULL, (LPBYTE)&val, &size);
116
    if ( res == ERROR_FILE_NOT_FOUND )
117
    {   // if not found set val to empty string
118
        val[0] = '\0';
119
    }
120
    else if ( res != ERROR_SUCCESS )
121
    {
122
        RegCloseKey(hKey);
123
        return 0;
124
    }
125
    path = val;
126
 
127
    // Remove any trailing ; from element
128
    for ( rit = element.rbegin(); *rit == ';'; rit = element.rbegin() )
129
        element.resize(element.length()-1);
130
 
4922 gchristi 131
    if ( action == ActionAddBefore && ! FindInPath(path, element) )
4914 gchristi 132
    {
133
        // make sure new dir to add has a ; on the end so we can insert it to the start of path 
134
        element += ';';
135
        path.insert(0, element);
136
        // Clean up any empty fields
137
        CleanPath(path);
4922 gchristi 138
        pathChanged = true;
4914 gchristi 139
    }
4922 gchristi 140
    else if ( action == ActionAddAfter && ! FindInPath(path, element) )
4914 gchristi 141
    {
142
        // append ; followed by new dir, clean path will remove empty fields so dont need to check for ; on the end
143
        path += ';';
144
        path += element;
145
        // Clean up any empty fields
146
        CleanPath(path);
4922 gchristi 147
        pathChanged = true;
4914 gchristi 148
    }
149
    else if ( action == ActionDelete )
150
    {
151
        // remove element from path if it exists
4922 gchristi 152
        pathChanged = CleanPath(path, element);
4914 gchristi 153
    }
154
 
4922 gchristi 155
    // Now write the path
156
    res = ERROR_SUCCESS;
157
    if ( pathChanged )
158
        res = RegSetValueEx(hKey, TEXT("Path"), NULL, REG_EXPAND_SZ, (LPBYTE)path.c_str(), path.length()+1);
4914 gchristi 159
 
160
    RegCloseKey(hKey);
161
 
162
    return ( res != ERROR_SUCCESS ? 0 : 1);
163
}
164
 
165
 
4922 gchristi 166
bool FindInPath( string &path, const string &search )
4914 gchristi 167
{
4922 gchristi 168
    string                      element;
169
    istringstream               spath(path);
170
 
171
    //Split each path element on ; and discard any empty ones
172
    while ( getline(spath, element, ';') )
173
    {
174
        if ( element == search )
175
            return true;
176
    }
177
 
178
    return false;
179
}
180
 
181
 
182
bool CleanPath( string &path, const string &delpath )
183
{
4914 gchristi 184
    string                      newpath("");
185
    string                      element;
186
    istringstream               spath(path);
187
    string::reverse_iterator    it;
4922 gchristi 188
    bool                        changed = false;
4914 gchristi 189
 
190
    //Split each path element on ; and discard any empty ones
191
    while ( getline(spath, element, ';') )
192
    {
193
        if ( ! element.empty() && ( delpath.empty() || element != delpath ))
194
        {
195
            newpath += element + ";";
196
        }
4922 gchristi 197
        else
198
        {
199
            changed = true;
200
        }
4914 gchristi 201
    }
202
 
203
    // Remove any trailing ;
204
    for ( it = newpath.rbegin(); *it == ';'; it = newpath.rbegin() )
4922 gchristi 205
    {
4914 gchristi 206
        newpath.resize(newpath.length()-1);
4922 gchristi 207
        changed = true;
208
    }
4914 gchristi 209
 
4922 gchristi 210
    if ( changed )
211
        path = newpath;
212
 
213
    return changed;
4914 gchristi 214
}
215
 
216
 
217
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
218
{
219
    g_hInstance = (HINSTANCE)hInst;
220
    return TRUE;
221
}