Subversion Repositories DevTools

Rev

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