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