1 |
twoaday |
1 |
/* GPGOEInit.c - GPGOE DLL Loader |
2 |
|
|
* Copyright (C) 2001, 2002, 2006 Timo Schulz |
3 |
|
|
* |
4 |
|
|
* This file is part of GPGOE. |
5 |
|
|
* |
6 |
|
|
* GPGOE is free software; you can redistribute it and/or modify |
7 |
|
|
* it under the terms of the GNU Lesser General Public License as published by |
8 |
|
|
* the Free Software Foundation; either version 2.1 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* GPGOE is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
*/ |
16 |
|
|
|
17 |
twoaday |
4 |
#ifdef HAVE_CONFIG_H |
18 |
|
|
#include <config.h> |
19 |
|
|
#endif |
20 |
twoaday |
19 |
#include <ctype.h> |
21 |
twoaday |
1 |
#include <windows.h> |
22 |
twoaday |
18 |
#include <tlhelp32.h> |
23 |
|
|
#include <stdio.h> |
24 |
|
|
|
25 |
twoaday |
1 |
#include "resource.h" |
26 |
|
|
|
27 |
|
|
|
28 |
twoaday |
18 |
/* Supported plug-in modes. */ |
29 |
|
|
enum gpgoe_mode_t { |
30 |
|
|
GPGOE_MODE_NORMAL = 0, |
31 |
twoaday |
19 |
GPGOE_MODE_PLAINREPLY = 1, |
32 |
|
|
GPGOE_MODE_CACHEPASS = 2 |
33 |
twoaday |
18 |
}; |
34 |
twoaday |
2 |
|
35 |
twoaday |
18 |
/* DLL imports. */ |
36 |
|
|
int gpgoe_initialize (void); |
37 |
|
|
int gpgoe_remove (void); |
38 |
|
|
void gpgoe_set_active_modes (int mode); |
39 |
|
|
int gpgoe_get_active_modes (void); |
40 |
|
|
|
41 |
|
|
|
42 |
|
|
/* Global module handle. */ |
43 |
twoaday |
1 |
static HINSTANCE glob_hinst = NULL; |
44 |
|
|
|
45 |
twoaday |
23 |
|
46 |
|
|
/* Valid options for the plug-in. */ |
47 |
twoaday |
19 |
struct { |
48 |
|
|
int decrypt_replies; |
49 |
|
|
int cache_passwd; |
50 |
|
|
} opt; |
51 |
|
|
|
52 |
|
|
|
53 |
twoaday |
18 |
/* String array of programs which are known to cause trouble |
54 |
|
|
with GPGoe. */ |
55 |
|
|
static const char *conflict_apps[] = { |
56 |
|
|
"DUMMY", /* dummy entry. */ |
57 |
|
|
"SPYXX.EXE", |
58 |
twoaday |
19 |
"FDM.EXE", /* fast download manager. */ |
59 |
twoaday |
18 |
NULL |
60 |
|
|
}; |
61 |
twoaday |
1 |
|
62 |
twoaday |
18 |
|
63 |
|
|
/* Enumerate all processes and figure out if a program |
64 |
|
|
is running which could be a conflict for gpgoe. */ |
65 |
|
|
static int |
66 |
|
|
check_for_conflict_apps (void) |
67 |
|
|
{ |
68 |
|
|
PROCESSENTRY32 pe; |
69 |
|
|
HANDLE hd; |
70 |
|
|
BOOL next; |
71 |
twoaday |
23 |
size_t i; |
72 |
|
|
int fnd; |
73 |
twoaday |
18 |
|
74 |
|
|
hd = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); |
75 |
|
|
if (hd == (HANDLE)-1) |
76 |
|
|
return 0; |
77 |
|
|
|
78 |
|
|
memset (&pe, 0, sizeof (pe)); |
79 |
|
|
pe.dwSize = sizeof (pe); |
80 |
|
|
next = Process32First (hd, &pe); |
81 |
twoaday |
23 |
fnd = 0; |
82 |
twoaday |
18 |
while (next) { |
83 |
|
|
for (i=0; i < strlen (pe.szExeFile); i++) |
84 |
twoaday |
19 |
pe.szExeFile[i] = (char)toupper (pe.szExeFile[i]); |
85 |
twoaday |
18 |
for (i=0; conflict_apps[i] != NULL; i++) { |
86 |
|
|
if (strstr (pe.szExeFile, conflict_apps[i])) { |
87 |
|
|
fnd = i; |
88 |
|
|
break; |
89 |
|
|
} |
90 |
|
|
} |
91 |
|
|
next = Process32Next (hd, &pe); |
92 |
|
|
} |
93 |
|
|
CloseHandle (hd); |
94 |
|
|
return fnd; |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
|
98 |
|
|
/* Return -1 if there was a running instance of OE detected. */ |
99 |
|
|
static int |
100 |
|
|
outlook_is_running (void) |
101 |
|
|
{ |
102 |
|
|
if (!FindWindowEx (NULL, NULL, "Outlook Express Browser Class", NULL)) |
103 |
|
|
return 0; |
104 |
|
|
return -1; |
105 |
|
|
} |
106 |
|
|
|
107 |
|
|
|
108 |
|
|
/* Get an option with the name @name from the registry. */ |
109 |
|
|
int |
110 |
|
|
get_gpgoe_option (const char *name) |
111 |
|
|
{ |
112 |
|
|
HKEY hkey; |
113 |
|
|
LONG err; |
114 |
|
|
char val[32]; |
115 |
|
|
DWORD type = 0, vallen = sizeof (val); |
116 |
|
|
|
117 |
|
|
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", 0, |
118 |
|
|
KEY_READ, &hkey); |
119 |
|
|
if (err != ERROR_SUCCESS) |
120 |
|
|
return 0; |
121 |
|
|
err = RegQueryValueEx (hkey, name, NULL, &type, (BYTE*)val, &vallen); |
122 |
|
|
RegCloseKey (hkey); |
123 |
|
|
if (err != ERROR_SUCCESS) |
124 |
|
|
return 0; |
125 |
|
|
return atoi (val); |
126 |
|
|
} |
127 |
|
|
|
128 |
|
|
|
129 |
|
|
/* Put an option with the name @name and the value @val in th registry. */ |
130 |
|
|
int |
131 |
|
|
put_gpgoe_option (const char *name, int val) |
132 |
|
|
{ |
133 |
|
|
HKEY hkey; |
134 |
|
|
char buf[32]; |
135 |
|
|
LONG err; |
136 |
|
|
|
137 |
|
|
sprintf (buf, "%d", val); |
138 |
|
|
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", 0, |
139 |
|
|
KEY_WRITE, &hkey); |
140 |
|
|
if (err != ERROR_SUCCESS) |
141 |
|
|
return -1; |
142 |
|
|
err = RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *)buf, strlen (buf)); |
143 |
|
|
RegCloseKey (hkey); |
144 |
|
|
return err != ERROR_SUCCESS? -1 : 0; |
145 |
|
|
} |
146 |
|
|
|
147 |
|
|
|
148 |
|
|
/* Create the GPGoe registry if needed. */ |
149 |
|
|
static int |
150 |
|
|
create_registry_key (void) |
151 |
|
|
{ |
152 |
|
|
HKEY hkey; |
153 |
|
|
LONG err; |
154 |
|
|
|
155 |
|
|
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", |
156 |
|
|
0, KEY_READ, &hkey); |
157 |
|
|
if (err == ERROR_SUCCESS) { |
158 |
|
|
RegCloseKey (hkey); |
159 |
|
|
return 0; |
160 |
|
|
} |
161 |
|
|
err = RegCreateKey (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", &hkey); |
162 |
|
|
if (err != ERROR_SUCCESS) |
163 |
|
|
return -1; |
164 |
|
|
RegCloseKey (hkey); |
165 |
|
|
return 0; |
166 |
|
|
} |
167 |
|
|
|
168 |
|
|
|
169 |
twoaday |
19 |
/* Dialog box procedure for setting preferences. */ |
170 |
|
|
BOOL CALLBACK |
171 |
|
|
prefs_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam) |
172 |
|
|
{ |
173 |
|
|
int modes; |
174 |
|
|
|
175 |
|
|
switch (msg) { |
176 |
|
|
case WM_INITDIALOG: |
177 |
|
|
CheckDlgButton (dlg, IDC_OPT_PLAINREPLY, |
178 |
|
|
opt.decrypt_replies? BST_CHECKED : BST_UNCHECKED); |
179 |
|
|
CheckDlgButton (dlg, IDC_OPT_CACHEPASS, |
180 |
|
|
opt.cache_passwd? BST_CHECKED : BST_UNCHECKED); |
181 |
|
|
SetForegroundWindow (dlg); |
182 |
|
|
return TRUE; |
183 |
|
|
|
184 |
|
|
case WM_COMMAND: |
185 |
|
|
switch (LOWORD (wparam)) { |
186 |
|
|
case IDOK: |
187 |
|
|
opt.decrypt_replies = IsDlgButtonChecked (dlg, IDC_OPT_PLAINREPLY)? 1: 0; |
188 |
|
|
opt.cache_passwd = IsDlgButtonChecked (dlg, IDC_OPT_CACHEPASS)? 1 : 0; |
189 |
|
|
modes = gpgoe_get_active_modes (); |
190 |
|
|
if (!opt.decrypt_replies) |
191 |
|
|
gpgoe_set_active_modes (modes & (~GPGOE_MODE_PLAINREPLY)); |
192 |
|
|
else |
193 |
|
|
gpgoe_set_active_modes (GPGOE_MODE_PLAINREPLY); |
194 |
|
|
if (!opt.cache_passwd) |
195 |
|
|
gpgoe_set_active_modes (modes & (~GPGOE_MODE_CACHEPASS)); |
196 |
|
|
else |
197 |
|
|
gpgoe_set_active_modes (GPGOE_MODE_CACHEPASS); |
198 |
|
|
if (outlook_is_running ()) |
199 |
|
|
MessageBox (NULL, "You need to restart Outlook Express.", |
200 |
|
|
"GPGOE Information", MB_ICONINFORMATION|MB_OK); |
201 |
|
|
EndDialog (dlg, TRUE); |
202 |
|
|
break; |
203 |
|
|
|
204 |
|
|
case IDCANCEL: |
205 |
|
|
EndDialog (dlg, FALSE); |
206 |
|
|
break; |
207 |
|
|
} |
208 |
|
|
break; |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
return FALSE; |
212 |
|
|
} |
213 |
|
|
|
214 |
|
|
|
215 |
twoaday |
18 |
/* Main window procedure for the taskbar program. */ |
216 |
twoaday |
1 |
LRESULT CALLBACK |
217 |
twoaday |
19 |
gpgoe_main_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) |
218 |
twoaday |
23 |
{ |
219 |
twoaday |
1 |
NOTIFYICONDATA NID; |
220 |
twoaday |
18 |
POINT p; |
221 |
|
|
HMENU hm, popup; |
222 |
twoaday |
1 |
int id; |
223 |
|
|
|
224 |
twoaday |
2 |
switch (msg) { |
225 |
twoaday |
1 |
case WM_CREATE: |
226 |
twoaday |
2 |
NID.cbSize = sizeof (NID); |
227 |
twoaday |
18 |
NID.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; |
228 |
twoaday |
1 |
NID.uCallbackMessage = WM_USER; |
229 |
|
|
NID.hWnd = hwnd; |
230 |
twoaday |
2 |
NID.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_GPGOE)); |
231 |
twoaday |
23 |
strcpy (NID.szTip, "GPG for Outlook Express"); |
232 |
twoaday |
1 |
Shell_NotifyIcon (NIM_ADD, &NID); |
233 |
twoaday |
18 |
DestroyIcon (NID.hIcon); |
234 |
|
|
|
235 |
twoaday |
19 |
opt.decrypt_replies = get_gpgoe_option ("PlaintextReply"); |
236 |
|
|
if (opt.decrypt_replies) |
237 |
twoaday |
18 |
gpgoe_set_active_modes (GPGOE_MODE_PLAINREPLY); |
238 |
twoaday |
19 |
opt.cache_passwd = get_gpgoe_option ("CachePassphrase"); |
239 |
|
|
if (opt.cache_passwd) |
240 |
|
|
gpgoe_set_active_modes (GPGOE_MODE_CACHEPASS); |
241 |
twoaday |
1 |
if (gpgoe_initialize ()) { |
242 |
twoaday |
23 |
MessageBox (hwnd, "Could not register GPG OE hook", |
243 |
|
|
"Error", MB_ICONERROR|MB_OK); |
244 |
twoaday |
1 |
ExitProcess (0); |
245 |
|
|
} |
246 |
|
|
break; |
247 |
|
|
|
248 |
|
|
case WM_DESTROY: |
249 |
|
|
case WM_ENDSESSION: |
250 |
twoaday |
19 |
put_gpgoe_option ("PlaintextReply", opt.decrypt_replies); |
251 |
|
|
put_gpgoe_option ("CachePassphrase", opt.cache_passwd); |
252 |
twoaday |
1 |
gpgoe_remove (); |
253 |
twoaday |
2 |
Shell_NotifyIcon (NIM_DELETE, &NID); |
254 |
twoaday |
1 |
PostQuitMessage (0); |
255 |
|
|
ExitProcess (0); |
256 |
|
|
return 0; |
257 |
|
|
|
258 |
twoaday |
18 |
case WM_COMMAND: |
259 |
|
|
switch (LOWORD (wparam)) { |
260 |
twoaday |
19 |
case ID_INIT_PREFS: |
261 |
|
|
DialogBoxParam (glob_hinst, (LPCTSTR)IDD_CONFIG, |
262 |
|
|
GetDesktopWindow (), prefs_dlg_proc, 0); |
263 |
twoaday |
18 |
break; |
264 |
|
|
|
265 |
|
|
case ID_INIT_QUIT: |
266 |
|
|
SendMessage (hwnd, WM_DESTROY, 0, 0); |
267 |
|
|
break; |
268 |
|
|
} |
269 |
|
|
break; |
270 |
|
|
|
271 |
twoaday |
1 |
case WM_USER: |
272 |
|
|
switch (lparam) { |
273 |
|
|
case WM_LBUTTONDBLCLK: |
274 |
twoaday |
2 |
SetForegroundWindow (hwnd); |
275 |
twoaday |
23 |
id = MessageBox (NULL, |
276 |
|
|
"Remove the GPG OE plug-in from the system?", |
277 |
twoaday |
1 |
"Are you sure?", MB_YESNO|MB_ICONINFORMATION); |
278 |
|
|
if (id == IDYES) |
279 |
|
|
SendMessage (hwnd, WM_DESTROY, 0, 0); |
280 |
|
|
break; |
281 |
|
|
|
282 |
|
|
case WM_RBUTTONUP: |
283 |
twoaday |
18 |
SetForegroundWindow (hwnd); |
284 |
|
|
GetCursorPos (&p); |
285 |
|
|
hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_INIT)); |
286 |
|
|
popup = GetSubMenu (hm, 0); |
287 |
|
|
TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, hwnd, NULL); |
288 |
|
|
PostMessage (hwnd, WM_USER, 0, 0); |
289 |
|
|
DestroyMenu (popup); |
290 |
|
|
DestroyMenu (hm); |
291 |
twoaday |
1 |
break; |
292 |
|
|
} |
293 |
|
|
break; |
294 |
twoaday |
18 |
} |
295 |
twoaday |
1 |
|
296 |
twoaday |
2 |
return DefWindowProc (hwnd, msg, wparam, lparam); |
297 |
twoaday |
1 |
} |
298 |
|
|
|
299 |
|
|
|
300 |
twoaday |
18 |
/* Main entry function. */ |
301 |
twoaday |
1 |
int WINAPI |
302 |
|
|
WinMain (HINSTANCE hinst, HINSTANCE prev, LPSTR cmdline, int cmd_show) |
303 |
|
|
{ |
304 |
|
|
WNDCLASS wc; |
305 |
|
|
HWND hwnd; |
306 |
|
|
MSG msg; |
307 |
twoaday |
18 |
int idx; |
308 |
|
|
|
309 |
twoaday |
19 |
memset (&opt, 0, sizeof (opt)); |
310 |
twoaday |
18 |
idx = check_for_conflict_apps (); |
311 |
|
|
if (idx > 0) { |
312 |
|
|
char buf[256]; |
313 |
|
|
_snprintf (buf, sizeof (buf)-1, |
314 |
|
|
"GPGoe found an instance of a program which\n" |
315 |
twoaday |
24 |
"might effect the functionality of the plugin.\n" |
316 |
twoaday |
18 |
"\n" |
317 |
|
|
"Name of the process: %s\n" |
318 |
|
|
"\n" |
319 |
|
|
"Continue to load the plug-in?", conflict_apps[idx]); |
320 |
|
|
idx = MessageBox (NULL, buf, "GPGOE Warning", MB_ICONWARNING|MB_YESNO); |
321 |
|
|
if (idx == IDNO) |
322 |
|
|
return 0; |
323 |
|
|
} |
324 |
twoaday |
1 |
|
325 |
twoaday |
18 |
create_registry_key (); |
326 |
twoaday |
1 |
glob_hinst = hinst; |
327 |
|
|
CreateMutex (NULL, 1, "GPGOE"); |
328 |
|
|
if (GetLastError () == ERROR_ALREADY_EXISTS) |
329 |
|
|
return 0; |
330 |
|
|
|
331 |
twoaday |
2 |
memset (&wc, 0, sizeof(wc)); |
332 |
twoaday |
1 |
wc.hInstance = hinst; |
333 |
|
|
wc.lpszClassName = "GPGOE"; |
334 |
|
|
wc.lpfnWndProc = (WNDPROC)gpgoe_main_proc; |
335 |
twoaday |
2 |
if (!RegisterClass (&wc)) { |
336 |
twoaday |
18 |
MessageBox (NULL, "Couldn't register the window class", "Error", |
337 |
|
|
MB_ICONERROR|MB_OK); |
338 |
|
|
return 1; |
339 |
twoaday |
1 |
} |
340 |
|
|
|
341 |
twoaday |
23 |
hwnd = CreateWindow ("GPGOE", "GPGOE", 0, 0, 0, 0, 0, |
342 |
|
|
NULL, NULL, hinst, NULL); |
343 |
twoaday |
1 |
if (!hwnd) { |
344 |
twoaday |
23 |
MessageBox (NULL, "Could not create window", |
345 |
|
|
"Error", MB_ICONERROR|MB_OK); |
346 |
twoaday |
1 |
return 1; |
347 |
|
|
} |
348 |
|
|
UpdateWindow (hwnd); |
349 |
|
|
while (GetMessage (&msg, hwnd, 0, 0)) { |
350 |
|
|
TranslateMessage (&msg); |
351 |
|
|
DispatchMessage (&msg); |
352 |
|
|
} |
353 |
|
|
return 0; |
354 |
|
|
} |