w32: Look for gpgconf in the new GnuPG 2.1 install dir.
[gpgme.git] / src / w32-util.c
1 /* w32-util.c - Utility functions for the W32 API
2  * Copyright (C) 1999 Free Software Foundation, Inc
3  * Copyright (C) 2001 Werner Koch (dd9jn)
4  * Copyright (C) 2001, 2002, 2003, 2004, 2007, 2013 g10 Code GmbH
5  *
6  * This file is part of GPGME.
7  *
8  * GPGME is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * GPGME is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  **/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <stdint.h>
31 #ifdef HAVE_SYS_TIME_H
32 # include <sys/time.h>
33 #endif
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37 #ifdef HAVE_SYS_STAT_H
38 # include <sys/stat.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif
43 #include <fcntl.h>
44 #include <io.h>
45
46 #if __MINGW64_VERSION_MAJOR >= 2
47 # define _WIN32_IE 0x0501 /* Required by mingw64 toolkit.  */
48 #else
49 # define _WIN32_IE 0x0400 /* Required for SHGetSpecialFolderPathA.  */
50 #endif
51
52 /* We need to include the windows stuff here prior to shlobj.h so that
53    we get the right winsock version.  This is usually done in util.h
54    but that header also redefines some Windows functions which we need
55    to avoid unless having included shlobj.h.  */
56 #include <winsock2.h>
57 #include <ws2tcpip.h>
58 #include <windows.h>
59 #include <shlobj.h>
60
61 #include "util.h"
62 #include "ath.h"
63 #include "sema.h"
64 #include "debug.h"
65 #include "sys-util.h"
66
67
68 #ifndef HAVE_W32CE_SYSTEM
69 #define HAVE_ALLOW_SET_FOREGROUND_WINDOW 1
70 #endif
71 #ifndef F_OK
72 # define F_OK 0
73 #endif
74
75
76 DEFINE_STATIC_LOCK (get_path_lock);
77
78 /* The module handle of this DLL.  If we are linked statically,
79    dllmain does not exists and thus the value of my_hmodule will be
80    NULL.  The effect is that a GetModuleFileName always returns the
81    file name of the DLL or executable which contains the gpgme code.  */
82 static HMODULE my_hmodule;
83
84 /* These variables store the malloced name of alternative default
85    binaries.  The are set only once by gpgme_set_global_flag.  */
86 static char *default_gpg_name;
87 static char *default_gpgconf_name;
88
89
90 #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
91
92 #define RTLD_LAZY 0
93
94 static GPG_ERR_INLINE void *
95 dlopen (const char * name, int flag)
96 {
97   void * hd = LoadLibrary (name);
98   return hd;
99 }
100
101 static GPG_ERR_INLINE void *
102 dlsym (void * hd, const char * sym)
103 {
104   if (hd && sym)
105     {
106       void * fnc = GetProcAddress (hd, sym);
107       if (!fnc)
108         return NULL;
109       return fnc;
110     }
111   return NULL;
112 }
113
114 static GPG_ERR_INLINE int
115 dlclose (void * hd)
116 {
117   if (hd)
118     {
119       FreeLibrary (hd);
120       return 0;
121     }
122   return -1;
123 }
124 #endif /* HAVE_ALLOW_SET_FOREGROUND_WINDOW */
125
126
127 /* Return a malloced string encoded in UTF-8 from the wide char input
128    string STRING.  Caller must free this value.  Returns NULL and sets
129    ERRNO on failure.  Calling this function with STRING set to NULL is
130    not defined.  */
131 static char *
132 wchar_to_utf8 (const wchar_t *string)
133 {
134   int n;
135   char *result;
136
137   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
138   if (n < 0)
139     {
140       gpg_err_set_errno (EINVAL);
141       return NULL;
142     }
143
144   result = malloc (n+1);
145   if (!result)
146     return NULL;
147
148   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
149   if (n < 0)
150     {
151       free (result);
152       gpg_err_set_errno (EINVAL);
153       result = NULL;
154     }
155   return result;
156 }
157
158
159 /* Replace all forward slashes by backslashes.  */
160 static void
161 replace_slashes (char *string)
162 {
163   for (; *string; string++)
164     if (*string == '/')
165       *string = '\\';
166 }
167
168
169 /* Get the base name of NAME.  Returns a pointer into NAME right after
170    the last slash or backslash or to NAME if no slash or backslash
171    exists.  */
172 static const char *
173 get_basename (const char *name)
174 {
175   const char *mark, *s;
176
177   for (mark=NULL, s=name; *s; s++)
178     if (*s == '/' || *s == '\\')
179       mark = s;
180
181   return mark? mark+1 : name;
182 }
183
184
185 void
186 _gpgme_allow_set_foreground_window (pid_t pid)
187 {
188 #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
189   static int initialized;
190   static BOOL (WINAPI * func)(DWORD);
191   void *handle;
192
193   if (!initialized)
194     {
195       /* Available since W2000; thus we dynload it.  */
196       initialized = 1;
197       handle = dlopen ("user32.dll", RTLD_LAZY);
198       if (handle)
199         {
200           func = dlsym (handle, "AllowSetForegroundWindow");
201           if (!func)
202             {
203               dlclose (handle);
204               handle = NULL;
205             }
206         }
207     }
208
209   if (!pid || pid == (pid_t)(-1))
210     {
211       TRACE1 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
212               "no action for pid %d", (int)pid);
213     }
214   else if (func)
215     {
216       int rc = func (pid);
217       TRACE2 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
218               "called for pid %d; result=%d", (int)pid, rc);
219
220     }
221   else
222     {
223       TRACE0 (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", 0,
224               "function not available");
225     }
226 #endif /* HAVE_ALLOW_SET_FOREGROUND_WINDOW */
227 }
228
229
230 /* Return a string from the W32 Registry or NULL in case of error.
231    Caller must release the return value.  A NULL for root is an alias
232    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
233 static char *
234 read_w32_registry_string (const char *root, const char *dir, const char *name)
235 {
236   HKEY root_key, key_handle;
237   DWORD n1, nbytes, type;
238   char *result = NULL;
239
240   if (!root)
241     root_key = HKEY_CURRENT_USER;
242   else if (!strcmp( root, "HKEY_CLASSES_ROOT"))
243     root_key = HKEY_CLASSES_ROOT;
244   else if (!strcmp( root, "HKEY_CURRENT_USER"))
245     root_key = HKEY_CURRENT_USER;
246   else if (!strcmp( root, "HKEY_LOCAL_MACHINE"))
247     root_key = HKEY_LOCAL_MACHINE;
248   else if (!strcmp( root, "HKEY_USERS"))
249     root_key = HKEY_USERS;
250   else if (!strcmp( root, "HKEY_PERFORMANCE_DATA"))
251     root_key = HKEY_PERFORMANCE_DATA;
252   else if (!strcmp( root, "HKEY_CURRENT_CONFIG"))
253     root_key = HKEY_CURRENT_CONFIG;
254   else
255     return NULL;
256
257   if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
258     {
259       if (root)
260         return NULL; /* no need for a RegClose, so return direct */
261       /* It seems to be common practise to fall back to HKLM. */
262       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
263         return NULL; /* still no need for a RegClose, so return direct */
264     }
265
266   nbytes = 1;
267   if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
268     {
269       if (root)
270         goto leave;
271       /* Try to fallback to HKLM also vor a missing value.  */
272       RegCloseKey (key_handle);
273       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
274         return NULL; /* Nope.  */
275       if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
276         goto leave;
277     }
278   n1 = nbytes + 1;
279   result = malloc (n1);
280   if (!result)
281     goto leave;
282   if (RegQueryValueExA (key_handle, name, 0, &type, (LPBYTE) result, &n1))
283     {
284       free (result);
285       result = NULL;
286       goto leave;
287     }
288   result[nbytes] = 0; /* Make sure it is really a string.  */
289
290 #ifndef HAVE_W32CE_SYSTEM
291   /* Windows CE does not have an environment.  */
292   if (type == REG_EXPAND_SZ && strchr (result, '%'))
293     {
294       char *tmp;
295
296       n1 += 1000;
297       tmp = malloc (n1 + 1);
298       if (!tmp)
299         goto leave;
300       nbytes = ExpandEnvironmentStrings (result, tmp, n1);
301       if (nbytes && nbytes > n1)
302         {
303           free (tmp);
304           n1 = nbytes;
305           tmp = malloc (n1 + 1);
306           if (!tmp)
307             goto leave;
308           nbytes = ExpandEnvironmentStrings (result, tmp, n1);
309           if (nbytes && nbytes > n1) {
310             free (tmp); /* Oops - truncated, better don't expand at all. */
311             goto leave;
312           }
313           tmp[nbytes] = 0;
314           free (result);
315           result = tmp;
316         }
317       else if (nbytes)  /* Okay, reduce the length. */
318         {
319           tmp[nbytes] = 0;
320           free (result);
321           result = malloc (strlen (tmp)+1);
322           if (!result)
323             result = tmp;
324           else
325             {
326               strcpy (result, tmp);
327               free (tmp);
328             }
329         }
330       else  /* Error - don't expand. */
331         {
332           free (tmp);
333         }
334     }
335 #endif
336
337  leave:
338   RegCloseKey (key_handle);
339   return result;
340 }
341
342
343 /* Return the name of the directory with the gpgme DLL or the EXE (if
344    statically linked).  May return NULL on severe errors. */
345 const char *
346 _gpgme_get_inst_dir (void)
347 {
348   static char *inst_dir;
349
350   LOCK (get_path_lock);
351   if (!inst_dir)
352     {
353       wchar_t *moddir;
354
355       moddir = malloc ((MAX_PATH+5) * sizeof *moddir);
356       if (moddir)
357         {
358           if (!GetModuleFileNameW (my_hmodule, moddir, MAX_PATH))
359             *moddir = 0;
360           if (!*moddir)
361             gpg_err_set_errno (ENOENT);
362           else
363             {
364               inst_dir = wchar_to_utf8 (moddir);
365               if (inst_dir)
366                 {
367                   char *p = strrchr (inst_dir, '\\');
368                   if (p)
369                     *p = 0;
370                 }
371             }
372           free (moddir);
373         }
374     }
375   UNLOCK (get_path_lock);
376   return inst_dir;
377 }
378
379
380 static char *
381 find_program_in_dir (const char *dir, const char *name)
382 {
383   char *result;
384
385   result = malloc (strlen (dir) + 1 + strlen (name) + 1);
386   if (!result)
387     return NULL;
388
389   strcpy (stpcpy (stpcpy (result, dir), "\\"), name);
390   if (access (result, F_OK))
391     {
392       free (result);
393       return NULL;
394     }
395
396   return result;
397 }
398
399
400 static char *
401 find_program_at_standard_place (const char *name)
402 {
403   char path[MAX_PATH];
404   char *result = NULL;
405
406   /* See http://wiki.tcl.tk/17492 for details on compatibility.  */
407   if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0))
408     {
409       result = malloc (strlen (path) + 1 + strlen (name) + 1);
410       if (result)
411         {
412           strcpy (stpcpy (stpcpy (result, path), "\\"), name);
413           if (access (result, F_OK))
414             {
415               free (result);
416               result = NULL;
417             }
418         }
419     }
420   return result;
421 }
422
423
424 /* Set the default name for the gpg binary.  This function may only be
425    called by gpgme_set_global_flag.  Returns 0 on success.  */
426 int
427 _gpgme_set_default_gpg_name (const char *name)
428 {
429   if (!default_gpg_name)
430     {
431       default_gpg_name = malloc (strlen (name) + 5);
432       if (default_gpg_name)
433         {
434           strcpy (stpcpy (default_gpg_name, name), ".exe");
435           replace_slashes (default_gpg_name);
436         }
437     }
438   return !default_gpg_name;
439 }
440
441 /* Set the default name for the gpgconf binary.  This function may only be
442    called by gpgme_set_global_flag.  Returns 0 on success.  */
443 int
444 _gpgme_set_default_gpgconf_name (const char *name)
445 {
446   if (!default_gpgconf_name)
447     {
448       default_gpgconf_name = malloc (strlen (name) + 5);
449       if (default_gpgconf_name)
450         {
451           strcpy (stpcpy (default_gpgconf_name, name), ".exe");
452           replace_slashes (default_gpgconf_name);
453         }
454     }
455   return !default_gpgconf_name;
456 }
457
458
459 /* Return the full file name of the GPG binary.  This function is used
460    iff gpgconf was not found and thus it can be assumed that gpg2 is
461    not installed.  This function is only called by get_gpgconf_item
462    and may not be called concurrently. */
463 char *
464 _gpgme_get_gpg_path (void)
465 {
466   char *gpg = NULL;
467   const char *name, *inst_dir;
468
469   name = default_gpg_name? get_basename (default_gpg_name) : "gpg.exe";
470
471   /* 1. Try to find gpg.exe in the installation directory of gpgme.  */
472   inst_dir = _gpgme_get_inst_dir ();
473   if (inst_dir)
474     {
475       gpg = find_program_in_dir (inst_dir, name);
476     }
477
478   /* 2. Try to find gpg.exe using that ancient registry key.  */
479   if (!gpg)
480     {
481       char *dir;
482
483       dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
484                                       "Software\\GNU\\GnuPG",
485                                       "Install Directory");
486       if (dir)
487         {
488           gpg = find_program_in_dir (dir, name);
489           free (dir);
490         }
491     }
492
493   /* 3. Try to find gpg.exe below CSIDL_PROGRAM_FILES.  */
494   if (!gpg)
495     {
496       name = default_gpg_name? default_gpg_name : "GNU\\GnuPG\\gpg.exe";
497       gpg = find_program_at_standard_place (name);
498     }
499
500   /* 4. Print a debug message if not found.  */
501   if (!gpg)
502     _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found", name);
503
504   return gpg;
505 }
506
507
508 /* This function is only called by get_gpgconf_item and may not be
509    called concurrently.  */
510 char *
511 _gpgme_get_gpgconf_path (void)
512 {
513   char *gpgconf = NULL;
514   const char *inst_dir, *name;
515
516   name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe";
517
518   /* 1. Try to find gpgconf.exe in the installation directory of gpgme.  */
519   inst_dir = _gpgme_get_inst_dir ();
520   if (inst_dir)
521     {
522       gpgconf = find_program_in_dir (inst_dir, name);
523     }
524
525   /* 2. Try to find gpgconf.exe from GnuPG >= 2.1 below CSIDL_PROGRAM_FILES. */
526   if (!gpgconf)
527     {
528       const char *name2 = (default_gpgconf_name ? default_gpgconf_name
529                            /**/                 : "GnuPG\\bin\\gpgconf.exe");
530       gpgconf = find_program_at_standard_place (name2);
531     }
532
533   /* 3. Try to find gpgconf.exe using that ancient registry key.  This
534         should eventually be removed.  */
535   if (!gpgconf)
536     {
537       char *dir;
538
539       dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
540                                       "Software\\GNU\\GnuPG",
541                                       "Install Directory");
542       if (dir)
543         {
544           gpgconf = find_program_in_dir (dir, name);
545           free (dir);
546         }
547     }
548
549   /* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES.  */
550   if (!gpgconf)
551     {
552       gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
553     }
554
555   /* 5. Print a debug message if not found.  */
556   if (!gpgconf)
557     _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",name);
558
559   return gpgconf;
560 }
561
562
563 const char *
564 _gpgme_get_w32spawn_path (void)
565 {
566   static char *w32spawn_program;
567   const char *inst_dir;
568
569   inst_dir = _gpgme_get_inst_dir ();
570   LOCK (get_path_lock);
571   if (!w32spawn_program)
572     w32spawn_program = find_program_in_dir (inst_dir, "gpgme-w32spawn.exe");
573   UNLOCK (get_path_lock);
574   return w32spawn_program;
575 }
576
577
578 /* Return an integer value from gpgme specific configuration
579    entries. VALUE receives that value; function returns true if a value
580    has been configured and false if not. */
581 int
582 _gpgme_get_conf_int (const char *key, int *value)
583 {
584   char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key);
585   if (!tmp)
586     return 0;
587   *value = atoi (tmp);
588   free (tmp);
589   return 1;
590 }
591
592 \f
593 #ifdef HAVE_W32CE_SYSTEM
594 int
595 _gpgme_mkstemp (int *fd, char **name)
596 {
597   return -1;
598 }
599 #else
600
601 /* mkstemp extracted from libc/sysdeps/posix/tempname.c.  Copyright
602    (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.
603
604    The GNU C Library is free software; you can redistribute it and/or
605    modify it under the terms of the GNU Lesser General Public
606    License as published by the Free Software Foundation; either
607    version 2.1 of the License, or (at your option) any later version.  */
608
609 static const char letters[] =
610 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
611
612 /* Generate a temporary file name based on TMPL.  TMPL must match the
613    rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
614    does not exist at the time of the call to mkstemp.  TMPL is
615    overwritten with the result.  */
616 static int
617 mkstemp (char *tmpl)
618 {
619   int len;
620   char *XXXXXX;
621   static uint64_t value;
622   uint64_t random_time_bits;
623   unsigned int count;
624   int fd = -1;
625   int save_errno = errno;
626
627   /* A lower bound on the number of temporary files to attempt to
628      generate.  The maximum total number of temporary file names that
629      can exist for a given template is 62**6.  It should never be
630      necessary to try all these combinations.  Instead if a reasonable
631      number of names is tried (we define reasonable as 62**3) fail to
632      give the system administrator the chance to remove the problems.  */
633 #define ATTEMPTS_MIN (62 * 62 * 62)
634
635   /* The number of times to attempt to generate a temporary file.  To
636      conform to POSIX, this must be no smaller than TMP_MAX.  */
637 #if ATTEMPTS_MIN < TMP_MAX
638   unsigned int attempts = TMP_MAX;
639 #else
640   unsigned int attempts = ATTEMPTS_MIN;
641 #endif
642
643   len = strlen (tmpl);
644   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
645     {
646       gpg_err_set_errno (EINVAL);
647       return -1;
648     }
649
650   /* This is where the Xs start.  */
651   XXXXXX = &tmpl[len - 6];
652
653   /* Get some more or less random data.  */
654   {
655     FILETIME ft;
656
657     GetSystemTimeAsFileTime (&ft);
658     random_time_bits = (((uint64_t)ft.dwHighDateTime << 32)
659                         | (uint64_t)ft.dwLowDateTime);
660   }
661   value += random_time_bits ^ ath_self ();
662
663   for (count = 0; count < attempts; value += 7777, ++count)
664     {
665       uint64_t v = value;
666
667       /* Fill in the random bits.  */
668       XXXXXX[0] = letters[v % 62];
669       v /= 62;
670       XXXXXX[1] = letters[v % 62];
671       v /= 62;
672       XXXXXX[2] = letters[v % 62];
673       v /= 62;
674       XXXXXX[3] = letters[v % 62];
675       v /= 62;
676       XXXXXX[4] = letters[v % 62];
677       v /= 62;
678       XXXXXX[5] = letters[v % 62];
679
680       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
681       if (fd >= 0)
682         {
683           gpg_err_set_errno (save_errno);
684           return fd;
685         }
686       else if (errno != EEXIST)
687         return -1;
688     }
689
690   /* We got out of the loop because we ran out of combinations to try.  */
691   gpg_err_set_errno (EEXIST);
692   return -1;
693 }
694
695 \f
696 int
697 _gpgme_mkstemp (int *fd, char **name)
698 {
699   char tmp[MAX_PATH + 2];
700   char *tmpname;
701   int err;
702
703   *fd = -1;
704   *name = NULL;
705
706   err = GetTempPathA (MAX_PATH + 1, tmp);
707   if (err == 0 || err > MAX_PATH + 1)
708     strcpy (tmp,"c:\\windows\\temp");
709   else
710     {
711       int len = strlen(tmp);
712
713       /* GetTempPath may return with \ on the end */
714       while(len > 0 && tmp[len - 1] == '\\')
715         {
716           tmp[len-1] = '\0';
717           len--;
718         }
719     }
720
721   tmpname = malloc (strlen (tmp) + 13 + 1);
722   if (!tmpname)
723     return -1;
724   strcpy (stpcpy (tmpname, tmp), "\\gpgme-XXXXXX");
725   *fd = mkstemp (tmpname);
726   if (fd < 0)
727     {
728       free (tmpname);
729       return -1;
730     }
731
732   *name = tmpname;
733   return 0;
734 }
735 #endif
736
737
738 \f
739 #ifdef HAVE_W32CE_SYSTEM
740 /* Return a malloced string with the replacement value for the
741    GPGME_DEBUG envvar.  Caller must release.  Returns NULL if not
742    set.  */
743 char *
744 _gpgme_w32ce_get_debug_envvar (void)
745 {
746   char *tmp;
747
748   tmp = read_w32_registry_string (NULL, "\\Software\\GNU\\gpgme", "debug");
749   if (tmp && !*tmp)
750     {
751       free (tmp);
752       tmp = NULL;
753     }
754   return tmp;
755 }
756 #endif /*HAVE_W32CE_SYSTEM*/
757
758
759 /* Entry point called by the DLL loader.  */
760 #ifdef DLL_EXPORT
761 int WINAPI
762 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
763 {
764   (void)reserved;
765
766   if (reason == DLL_PROCESS_ATTACH)
767     my_hmodule = hinst;
768
769   return TRUE;
770 }
771 #endif /*DLL_EXPORT*/