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 |
* You should have received a copy of the GNU Lesser General Public License |
17 |
* along with GPGOE; if not, write to the Free Software Foundation, |
18 |
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 |
*/ |
20 |
|
21 |
#ifdef HAVE_CONFIG_H |
22 |
#include <config.h> |
23 |
#endif |
24 |
#include <windows.h> |
25 |
#include <tlhelp32.h> |
26 |
#include <stdio.h> |
27 |
#include <ctype.h> |
28 |
|
29 |
#include "resource.h" |
30 |
|
31 |
|
32 |
/* Supported plug-in modes. */ |
33 |
enum gpgoe_mode_t { |
34 |
GPGOE_MODE_NORMAL = 0, |
35 |
GPGOE_MODE_PLAINREPLY = 1 |
36 |
}; |
37 |
|
38 |
/* DLL imports. */ |
39 |
int gpgoe_initialize (void); |
40 |
int gpgoe_remove (void); |
41 |
void gpgoe_set_active_modes (int mode); |
42 |
int gpgoe_get_active_modes (void); |
43 |
|
44 |
|
45 |
/* Global module handle. */ |
46 |
static HINSTANCE glob_hinst = NULL; |
47 |
|
48 |
/* String array of programs which are known to cause trouble |
49 |
with GPGoe. */ |
50 |
static const char *conflict_apps[] = { |
51 |
"DUMMY", /* dummy entry. */ |
52 |
"SPYXX.EXE", |
53 |
NULL |
54 |
}; |
55 |
|
56 |
|
57 |
/* Enumerate all processes and figure out if a program |
58 |
is running which could be a conflict for gpgoe. */ |
59 |
static int |
60 |
check_for_conflict_apps (void) |
61 |
{ |
62 |
PROCESSENTRY32 pe; |
63 |
HANDLE hd; |
64 |
BOOL next; |
65 |
int fnd = 0; |
66 |
|
67 |
hd = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); |
68 |
if (hd == (HANDLE)-1) |
69 |
return 0; |
70 |
|
71 |
memset (&pe, 0, sizeof (pe)); |
72 |
pe.dwSize = sizeof (pe); |
73 |
next = Process32First (hd, &pe); |
74 |
while (next) { |
75 |
size_t i; |
76 |
|
77 |
for (i=0; i < strlen (pe.szExeFile); i++) |
78 |
pe.szExeFile[i] = (char)toupper ((int)pe.szExeFile[i]); |
79 |
for (i=0; conflict_apps[i] != NULL; i++) { |
80 |
if (strstr (pe.szExeFile, conflict_apps[i])) { |
81 |
fnd = i; |
82 |
break; |
83 |
} |
84 |
} |
85 |
next = Process32Next (hd, &pe); |
86 |
if (!next) |
87 |
break; |
88 |
} |
89 |
CloseHandle (hd); |
90 |
return fnd; |
91 |
} |
92 |
|
93 |
|
94 |
/* Return -1 if there was a running instance of OE detected. */ |
95 |
static int |
96 |
outlook_is_running (void) |
97 |
{ |
98 |
if (!FindWindowEx (NULL, NULL, "Outlook Express Browser Class", NULL)) |
99 |
return 0; |
100 |
return -1; |
101 |
} |
102 |
|
103 |
|
104 |
/* Set the menu item @muid to the state @state. */ |
105 |
void |
106 |
set_menu_state (HMENU menu, UINT muid, UINT state) |
107 |
{ |
108 |
MENUITEMINFO mii; |
109 |
|
110 |
memset (&mii, 0, sizeof (mii)); |
111 |
mii.cbSize = sizeof (mii); |
112 |
mii.fMask = MIIM_STATE; |
113 |
mii.fState = state; |
114 |
SetMenuItemInfo (menu, muid, FALSE, &mii); |
115 |
} |
116 |
|
117 |
|
118 |
/* Get an option with the name @name from the registry. */ |
119 |
int |
120 |
get_gpgoe_option (const char *name) |
121 |
{ |
122 |
HKEY hkey; |
123 |
LONG err; |
124 |
char val[32]; |
125 |
DWORD type = 0, vallen = sizeof (val); |
126 |
|
127 |
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", 0, |
128 |
KEY_READ, &hkey); |
129 |
if (err != ERROR_SUCCESS) |
130 |
return 0; |
131 |
err = RegQueryValueEx (hkey, name, NULL, &type, (BYTE*)val, &vallen); |
132 |
RegCloseKey (hkey); |
133 |
if (err != ERROR_SUCCESS) |
134 |
return 0; |
135 |
return atoi (val); |
136 |
} |
137 |
|
138 |
|
139 |
/* Put an option with the name @name and the value @val in th registry. */ |
140 |
int |
141 |
put_gpgoe_option (const char *name, int val) |
142 |
{ |
143 |
HKEY hkey; |
144 |
char buf[32]; |
145 |
LONG err; |
146 |
|
147 |
sprintf (buf, "%d", val); |
148 |
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", 0, |
149 |
KEY_WRITE, &hkey); |
150 |
if (err != ERROR_SUCCESS) |
151 |
return -1; |
152 |
err = RegSetValueEx (hkey, name, 0, REG_SZ, (BYTE *)buf, strlen (buf)); |
153 |
RegCloseKey (hkey); |
154 |
return err != ERROR_SUCCESS? -1 : 0; |
155 |
} |
156 |
|
157 |
|
158 |
/* Create the GPGoe registry if needed. */ |
159 |
static int |
160 |
create_registry_key (void) |
161 |
{ |
162 |
HKEY hkey; |
163 |
LONG err; |
164 |
|
165 |
err = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", |
166 |
0, KEY_READ, &hkey); |
167 |
if (err == ERROR_SUCCESS) { |
168 |
RegCloseKey (hkey); |
169 |
return 0; |
170 |
} |
171 |
err = RegCreateKey (HKEY_CURRENT_USER, "Software\\GNU\\GPGoe", &hkey); |
172 |
if (err != ERROR_SUCCESS) |
173 |
return -1; |
174 |
RegCloseKey (hkey); |
175 |
return 0; |
176 |
} |
177 |
|
178 |
|
179 |
/* Main window procedure for the taskbar program. */ |
180 |
LRESULT CALLBACK |
181 |
gpgoe_main_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) |
182 |
{ |
183 |
static int decrypt_replies = 0; |
184 |
NOTIFYICONDATA NID; |
185 |
POINT p; |
186 |
HMENU hm, popup; |
187 |
int id; |
188 |
|
189 |
switch (msg) { |
190 |
case WM_CREATE: |
191 |
NID.cbSize = sizeof (NID); |
192 |
NID.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; |
193 |
NID.uCallbackMessage = WM_USER; |
194 |
NID.hWnd = hwnd; |
195 |
NID.hIcon = LoadIcon (glob_hinst, MAKEINTRESOURCE (IDI_GPGOE)); |
196 |
strcpy(NID.szTip, "GPG for Outlook Express"); |
197 |
Shell_NotifyIcon (NIM_ADD, &NID); |
198 |
DestroyIcon (NID.hIcon); |
199 |
|
200 |
decrypt_replies = get_gpgoe_option ("PlaintextReply"); |
201 |
if (decrypt_replies) |
202 |
gpgoe_set_active_modes (GPGOE_MODE_PLAINREPLY); |
203 |
if (gpgoe_initialize ()) { |
204 |
MessageBox (hwnd, "Couldn't register GPG OE hook", "Error", MB_ICONERROR|MB_OK); |
205 |
ExitProcess (0); |
206 |
} |
207 |
break; |
208 |
|
209 |
case WM_DESTROY: |
210 |
case WM_ENDSESSION: |
211 |
put_gpgoe_option ("PlaintextReply", decrypt_replies); |
212 |
gpgoe_remove (); |
213 |
Shell_NotifyIcon (NIM_DELETE, &NID); |
214 |
PostQuitMessage (0); |
215 |
ExitProcess (0); |
216 |
return 0; |
217 |
|
218 |
case WM_COMMAND: |
219 |
switch (LOWORD (wparam)) { |
220 |
case ID_INIT_SUPP_PLAINREPLY: |
221 |
decrypt_replies ^= 1; |
222 |
if (!decrypt_replies) { |
223 |
int modes = gpgoe_get_active_modes (); |
224 |
gpgoe_set_active_modes (modes & (~GPGOE_MODE_PLAINREPLY)); |
225 |
} |
226 |
else { |
227 |
gpgoe_set_active_modes (GPGOE_MODE_PLAINREPLY); |
228 |
if (outlook_is_running ()) |
229 |
MessageBox (NULL, "You need to restart Outlook Express.", |
230 |
"GPGOE Information", MB_ICONINFORMATION|MB_OK); |
231 |
} |
232 |
break; |
233 |
|
234 |
case ID_INIT_QUIT: |
235 |
SendMessage (hwnd, WM_DESTROY, 0, 0); |
236 |
break; |
237 |
} |
238 |
break; |
239 |
|
240 |
case WM_USER: |
241 |
switch (lparam) { |
242 |
case WM_LBUTTONDBLCLK: |
243 |
SetForegroundWindow (hwnd); |
244 |
id = MessageBox (NULL, "Remove the GPG OE plug-in from the system?", |
245 |
"Are you sure?", MB_YESNO|MB_ICONINFORMATION); |
246 |
if (id == IDYES) |
247 |
SendMessage (hwnd, WM_DESTROY, 0, 0); |
248 |
break; |
249 |
|
250 |
case WM_RBUTTONUP: |
251 |
SetForegroundWindow (hwnd); |
252 |
GetCursorPos (&p); |
253 |
hm = LoadMenu (glob_hinst, MAKEINTRESOURCE (IDR_INIT)); |
254 |
popup = GetSubMenu (hm, 0); |
255 |
set_menu_state (popup, ID_INIT_SUPP_PLAINREPLY, |
256 |
decrypt_replies? MFS_CHECKED : MFS_UNCHECKED); |
257 |
TrackPopupMenu (popup, TPM_RIGHTALIGN, p.x, p.y, 0, hwnd, NULL); |
258 |
PostMessage (hwnd, WM_USER, 0, 0); |
259 |
DestroyMenu (popup); |
260 |
DestroyMenu (hm); |
261 |
break; |
262 |
} |
263 |
break; |
264 |
} |
265 |
|
266 |
return DefWindowProc (hwnd, msg, wparam, lparam); |
267 |
} |
268 |
|
269 |
|
270 |
/* Main entry function. */ |
271 |
int WINAPI |
272 |
WinMain (HINSTANCE hinst, HINSTANCE prev, LPSTR cmdline, int cmd_show) |
273 |
{ |
274 |
WNDCLASS wc; |
275 |
HWND hwnd; |
276 |
MSG msg; |
277 |
int idx; |
278 |
|
279 |
idx = check_for_conflict_apps (); |
280 |
if (idx > 0) { |
281 |
char buf[256]; |
282 |
_snprintf (buf, sizeof (buf)-1, |
283 |
"GPGoe found an instance of a program which\n" |
284 |
"might be effect the functionality of the plugin.\n" |
285 |
"\n" |
286 |
"Name of the process: %s\n" |
287 |
"\n" |
288 |
"Continue to load the plug-in?", conflict_apps[idx]); |
289 |
idx = MessageBox (NULL, buf, "GPGOE Warning", MB_ICONWARNING|MB_YESNO); |
290 |
if (idx == IDNO) |
291 |
return 0; |
292 |
} |
293 |
|
294 |
create_registry_key (); |
295 |
glob_hinst = hinst; |
296 |
CreateMutex (NULL, 1, "GPGOE"); |
297 |
if (GetLastError () == ERROR_ALREADY_EXISTS) |
298 |
return 0; |
299 |
|
300 |
memset (&wc, 0, sizeof(wc)); |
301 |
wc.hInstance = hinst; |
302 |
wc.lpszClassName = "GPGOE"; |
303 |
wc.lpfnWndProc = (WNDPROC)gpgoe_main_proc; |
304 |
if (!RegisterClass (&wc)) { |
305 |
MessageBox (NULL, "Couldn't register the window class", "Error", |
306 |
MB_ICONERROR|MB_OK); |
307 |
return 1; |
308 |
} |
309 |
|
310 |
hwnd = CreateWindow ("GPGOE", "GPGOE", 0, 0, 0, 0, 0, NULL, NULL, hinst, NULL); |
311 |
if (!hwnd) { |
312 |
MessageBox (NULL, "Couldn't create window", "Error", MB_ICONERROR|MB_OK); |
313 |
return 1; |
314 |
} |
315 |
UpdateWindow (hwnd); |
316 |
while (GetMessage (&msg, hwnd, 0, 0)) { |
317 |
TranslateMessage (&msg); |
318 |
DispatchMessage (&msg); |
319 |
} |
320 |
return 0; |
321 |
} |