Add specific option for auto-key-retrieve
[gpgol.git] / src / main.c
1 /* main.c - DLL entry point
2  * Copyright (C) 2005, 2007, 2008 g10 Code GmbH
3  *
4  * This file is part of GpgOL.
5  *
6  * GpgOL is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation; either version 2.1
9  * of the License, or (at your option) any later version.
10  *
11  * GpgOL 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 GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #include <windows.h>
23 #include <wincrypt.h>
24 #include <ctype.h>
25 #include <winnls.h>
26 #include <unistd.h>
27
28 #include "mymapi.h"
29 #include "mymapitags.h"
30
31 #include "common.h"
32 #include "mymapi.h"
33
34 /* Local function prototypes. */
35 static char *get_locale_dir (void);
36 static void drop_locale_dir (char *locale_dir);
37
38 /* The major version of Outlook we are attached to */
39 int g_ol_version_major;
40
41
42 /* For certain operations we need to acquire a log on the logging
43    functions.  This lock is controlled by this Mutex. */
44 HANDLE log_mutex;
45
46 /* Early initialization of this module.  This is done right at startup
47    with only one thread running.  Should be called only once. Returns
48    0 on success. */
49 static int
50 initialize_main (void)
51 {
52   SECURITY_ATTRIBUTES sa;
53
54   memset (&sa, 0, sizeof sa);
55   sa.bInheritHandle = FALSE;
56   sa.lpSecurityDescriptor = NULL;
57   sa.nLength = sizeof sa;
58   log_mutex = CreateMutex (&sa, FALSE, NULL);
59   return log_mutex? 0 : -1;
60 }
61
62 void
63 i18n_init (void)
64 {
65   char *locale_dir;
66
67 #ifdef ENABLE_NLS
68 # ifdef HAVE_LC_MESSAGES
69   setlocale (LC_TIME, "");
70   setlocale (LC_MESSAGES, "");
71 # else
72   setlocale (LC_ALL, "" );
73 # endif
74 #endif
75
76   locale_dir = get_locale_dir ();
77   if (locale_dir)
78     {
79       bindtextdomain (PACKAGE_GT, locale_dir);
80       drop_locale_dir (locale_dir);
81     }
82   textdomain (PACKAGE_GT);
83 }
84
85 static char *
86 get_gpgme_w32_inst_dir (void)
87 {
88   char *gpg4win_dir = get_gpg4win_dir ();
89   char *tmp;
90   gpgrt_asprintf (&tmp, "%s\\bin\\gpgme-w32spawn.exe", gpg4win_dir);
91   memdbg_alloc (tmp);
92
93   if (!access(tmp, R_OK))
94     {
95       xfree (tmp);
96       gpgrt_asprintf (&tmp, "%s\\bin", gpg4win_dir);
97       memdbg_alloc (tmp);
98       xfree (gpg4win_dir);
99       return tmp;
100     }
101   xfree (tmp);
102   gpgrt_asprintf (&tmp, "%s\\gpgme-w32spawn.exe", gpg4win_dir);
103   memdbg_alloc (tmp);
104
105   if (!access(tmp, R_OK))
106     {
107       xfree (tmp);
108       return gpg4win_dir;
109     }
110   OutputDebugString("Failed to find gpgme-w32spawn.exe!");
111   return NULL;
112 }
113
114 /* Entry point called by DLL loader. */
115 int WINAPI
116 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
117 {
118   (void)reserved;
119
120   if (reason == DLL_PROCESS_ATTACH)
121     {
122       set_global_hinstance (hinst);
123
124       gpg_err_init ();
125
126       /* Set the installation directory for GpgME so that
127          it can find tools like gpgme-w32-spawn correctly. */
128       char *instdir = get_gpgme_w32_inst_dir();
129       gpgme_set_global_flag ("w32-inst-dir", instdir);
130       xfree (instdir);
131
132       /* The next call initializes subsystems of gpgme and should be
133          done as early as possible.  The actual return value (the
134          version string) is not used here.  It may be called at any
135          time later for this. */
136       gpgme_check_version (NULL);
137
138       /* Early initializations of our subsystems. */
139       if (initialize_main ())
140         return FALSE;
141     }
142   else if (reason == DLL_PROCESS_DETACH)
143     {
144       gpg_err_deinit (0);
145     }
146
147   return TRUE;
148 }
149
150 static char *
151 get_locale_dir (void)
152 {
153   char *instdir;
154   char *p;
155   char *dname;
156
157   instdir = get_gpg4win_dir();
158   if (!instdir)
159     return NULL;
160
161   /* Build the key: "<instdir>/share/locale".  */
162 #define SLDIR "\\share\\locale"
163   dname = xmalloc (strlen (instdir) + strlen (SLDIR) + 1);
164   if (!dname)
165     {
166       xfree (instdir);
167       return NULL;
168     }
169   p = dname;
170   strcpy (p, instdir);
171   p += strlen (instdir);
172   strcpy (p, SLDIR);
173
174   xfree (instdir);
175
176   return dname;
177 }
178
179
180 static void
181 drop_locale_dir (char *locale_dir)
182 {
183   xfree (locale_dir);
184 }
185
186
187 static int
188 get_conf_bool (const char *name, int defaultVal)
189 {
190   char *val = NULL;
191   int ret;
192   load_extension_value (name, &val);
193   ret = val == NULL ? defaultVal : *val != '1' ? 0 : 1;
194   xfree (val);
195   return ret;
196 }
197
198 static int
199 dbg_compat (int oldval)
200 {
201   // We broke the debug levels at some point
202   // This is cmpatibility code with the old
203   // levels.
204
205 #define DBG_MEMORY_OLD     (1<<5) // 32
206 #define DBG_MIME_PARSER_OLD (1<<7) // 128 Unified as DBG_DATA
207 #define DBG_MIME_DATA_OLD   (1<<8) // 256 Unified in read_options
208 #define DBG_OOM_OLD        (1<<9) // 512 Unified as DBG_OOM
209 #define DBG_OOM_EXTRA_OLD  (1<<10)// 1024 Unified in read_options
210   int new_dbg = oldval;
211   if ((oldval & DBG_MEMORY_OLD))
212     {
213       new_dbg |= DBG_MEMORY;
214       new_dbg -= DBG_MEMORY_OLD;
215     }
216   if ((oldval & DBG_OOM_OLD))
217     {
218       new_dbg |= DBG_OOM;
219       new_dbg -= DBG_OOM_OLD;
220     }
221   if ((oldval & DBG_MIME_PARSER_OLD))
222     {
223       new_dbg |= DBG_DATA;
224       new_dbg -= DBG_MIME_PARSER_OLD;
225     }
226   if ((oldval & DBG_MIME_DATA_OLD))
227     {
228       new_dbg |= DBG_DATA;
229       new_dbg -= DBG_MIME_DATA_OLD;
230     }
231   if ((oldval & DBG_OOM_OLD))
232     {
233       new_dbg |= DBG_OOM;
234       new_dbg -= DBG_OOM_OLD;
235     }
236   if ((oldval & DBG_OOM_EXTRA_OLD))
237     {
238       new_dbg |= DBG_OOM;
239       new_dbg -= DBG_OOM_EXTRA_OLD;
240     }
241 #undef DBG_MEMORY_OLD
242 #undef DBG_MIME_PARSER_OLD
243 #undef DBG_MIME_DATA_OLD
244 #undef DBG_OOM_OLD
245 #undef DBG_OOM_EXTRA_OLD
246   return new_dbg;
247 }
248
249 /* Read option settings from the Registry. */
250 void
251 read_options (void)
252 {
253   char *val = NULL;
254
255   /* Set the log file first so that output from this function is
256      logged too.  */
257   load_extension_value ("logFile", &val);
258   set_log_file (val);
259   xfree (val); val = NULL;
260
261   /* Parse the debug flags.  */
262   load_extension_value ("enableDebug", &val);
263   opt.enable_debug = 0;
264   if (val)
265     {
266       char *p, *pend;
267
268       trim_spaces (val);
269       for (p = val; p; p = pend)
270         {
271           pend = strpbrk (p, ", \t\n\r\f");
272           if (pend)
273             {
274               *pend++ = 0;
275               pend += strspn (pend, ", \t\n\r\f");
276             }
277           if (isascii (*p) && isdigit (*p))
278             {
279               opt.enable_debug |= dbg_compat (strtoul (p, NULL, 0));
280
281             }
282           else if (!strcmp (p, "memory"))
283             opt.enable_debug |= DBG_MEMORY;
284           else if (!strcmp (p, "mime-parser"))
285             opt.enable_debug |= DBG_DATA;
286           else if (!strcmp (p, "mime-data"))
287             opt.enable_debug |= DBG_DATA;
288           else if (!strcmp (p, "oom"))
289             opt.enable_debug |= DBG_OOM;
290           else if (!strcmp (p, "oom-extra"))
291             opt.enable_debug |= DBG_OOM;
292           else
293             log_debug ("invalid debug flag `%s' ignored", p);
294         }
295     }
296   else
297     {
298       /* To help the user enable debugging make sure that the registry
299          key exists.  Note that the other registry keys are stored
300          after using the configuration dialog.  */
301       store_extension_value ("enableDebug", "0");
302     }
303   /* Yes we use free here because memtracing did not track the alloc
304      as the option for debuging was not read before. */
305   free (val); val = NULL;
306   if (opt.enable_debug)
307     log_debug ("enabled debug flags:%s%s%s\n",
308                (opt.enable_debug & DBG_MEMORY)? " memory":"",
309                (opt.enable_debug & DBG_DATA)? " data":"",
310                (opt.enable_debug & DBG_OOM)? " oom":""
311                );
312
313   opt.enable_smime = get_conf_bool ("enableSmime", 0);
314   opt.encrypt_default = get_conf_bool ("encryptDefault", 0);
315   opt.sign_default = get_conf_bool ("signDefault", 0);
316   opt.inline_pgp = get_conf_bool ("inlinePGP", 0);
317   opt.reply_crypt = get_conf_bool ("replyCrypt", 1);
318   opt.prefer_smime = get_conf_bool ("preferSmime", 0);
319   opt.autoresolve = get_conf_bool ("autoresolve", 1);
320   opt.autoretrieve = get_conf_bool ("autoretrieve", 0);
321   opt.automation = get_conf_bool ("automation", 1);
322   opt.autosecure = get_conf_bool ("autosecure", 1);
323   opt.autotrust = get_conf_bool ("autotrust", 0);
324   opt.smime_html_warn_shown = get_conf_bool ("smimeHtmlWarnShown", 0);
325
326   if (!opt.automation)
327     {
328       // Disabling automation is a shorthand to disable the
329       // others, too.
330       opt.autosecure = 0;
331       opt.autoresolve = 0;
332       opt.autotrust = 0;
333       opt.autoretrieve = 0;
334     }
335
336   /* Hidden options  */
337   opt.sync_enc = get_conf_bool ("_syncEnc", 0);
338 }
339
340
341 /* Write current options back to the Registry. */
342 int
343 write_options (void)
344 {
345   struct
346   {
347     const char *name;
348     int  mode;
349     int  value;
350     char *s_val;
351   } table[] = {
352     {"smimeHtmlWarnShown",       0, opt.smime_html_warn_shown, NULL},
353     {NULL, 0, 0, NULL}
354   };
355   char buf[32];
356   int rc, i;
357   const char *string;
358
359   for (i=0; table[i].name; i++)
360     {
361       switch (table[i].mode)
362         {
363         case 0:
364           string = table[i].value? "1": "0";
365           log_debug ("storing option `%s' value=`%s'\n",
366                      table[i].name, string);
367           rc = store_extension_value (table[i].name, string);
368           break;
369         case 1:
370           sprintf (buf, "%d", table[i].value);
371           log_debug ("storing option `%s' value=`%s'\n",
372                      table[i].name, buf);
373           rc = store_extension_value (table[i].name, buf);
374           break;
375         case 2:
376           string = table[i].s_val? table[i].s_val : "";
377           log_debug ("storing option `%s' value=`%s'\n",
378                      table[i].name, string);
379           rc = store_extension_value (table[i].name, string);
380           break;
381 /*         case 3: */
382 /*           buf[0] = '0'; */
383 /*           buf[1] = 0; */
384 /*           switch (opt.default_protocol) */
385 /*             { */
386 /*             case PROTOCOL_UNKNOWN: buf[0] = '0'; /\* auto *\/ break; */
387 /*             case PROTOCOL_OPENPGP: buf[0] = '1'; break; */
388 /*             case PROTOCOL_SMIME:   buf[0] = '2'; break; */
389 /*             } */
390 /*           log_debug ("storing option `%s' value=`%s'\n", */
391 /*                      table[i].name, buf); */
392 /*           rc = store_extension_value (table[i].name, buf); */
393 /*           break;   */
394
395         case 4:
396           sprintf (buf, "0x%x", table[i].value);
397           log_debug ("storing option `%s' value=`%s'\n",
398                      table[i].name, buf);
399           rc = store_extension_value (table[i].name, buf);
400           break;
401
402         default:
403           rc = -1;
404           break;
405         }
406       if (rc)
407         log_error ("error storing option `%s': rc = %d\n", table[i].name, rc);
408     }
409
410   return 0;
411 }