Imported Upstream version 1.14.0
[platform/upstream/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 <https://gnu.org/licenses/>.
20  * SPDX-License-Identifier: LGPL-2.1-or-later
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <errno.h>
31 #include <stdint.h>
32 #ifdef HAVE_SYS_TIME_H
33 # include <sys/time.h>
34 #endif
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38 #ifdef HAVE_SYS_STAT_H
39 # include <sys/stat.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 # include <unistd.h>
43 #endif
44 #include <fcntl.h>
45 #include <io.h>
46
47 #if __MINGW64_VERSION_MAJOR >= 2
48 # define _WIN32_IE 0x0501 /* Required by mingw64 toolkit.  */
49 #else
50 # define _WIN32_IE 0x0400 /* Required for SHGetSpecialFolderPathA.  */
51 #endif
52
53 /* We need to include the windows stuff here prior to shlobj.h so that
54    we get the right winsock version.  This is usually done in util.h
55    but that header also redefines some Windows functions which we need
56    to avoid unless having included shlobj.h.  */
57 #include <winsock2.h>
58 #include <ws2tcpip.h>
59 #include <windows.h>
60 #include <shlobj.h>
61
62 #include "util.h"
63 #include "ath.h"
64 #include "sema.h"
65 #include "debug.h"
66 #include "sys-util.h"
67
68
69 #define HAVE_ALLOW_SET_FOREGROUND_WINDOW 1
70 #ifndef F_OK
71 # define F_OK 0
72 #endif
73
74 /* The Registry key used by GNUPG.  */
75 #ifdef _WIN64
76 # define GNUPG_REGKEY_2  "Software\\Wow6432Node\\GNU\\GnuPG"
77 #else
78 # define GNUPG_REGKEY_2  "Software\\GNU\\GnuPG"
79 #endif
80 #ifdef _WIN64
81 # define GNUPG_REGKEY_3  "Software\\Wow6432Node\\GnuPG"
82 #else
83 # define GNUPG_REGKEY_3  "Software\\GnuPG"
84 #endif
85
86 DEFINE_STATIC_LOCK (get_path_lock);
87
88 /* The module handle of this DLL.  If we are linked statically,
89    dllmain does not exists and thus the value of my_hmodule will be
90    NULL.  The effect is that a GetModuleFileName always returns the
91    file name of the DLL or executable which contains the gpgme code.  */
92 static HMODULE my_hmodule;
93
94 /* These variables store the malloced name of alternative default
95    binaries.  The are set only once by gpgme_set_global_flag.  */
96 static char *default_gpg_name;
97 static char *default_gpgconf_name;
98 /* If this variable is not NULL the value is assumed to be the
99    installation directory.  The variable may only be set once by
100    gpgme_set_global_flag and accessed by _gpgme_get_inst_dir.  */
101 static char *override_inst_dir;
102
103 #define RTLD_LAZY 0
104
105 static GPG_ERR_INLINE void *
106 dlopen (const char * name, int flag)
107 {
108   void * hd = LoadLibrary (name);
109
110   (void)flag;
111   return hd;
112 }
113
114 static GPG_ERR_INLINE void *
115 dlsym (void * hd, const char * sym)
116 {
117   if (hd && sym)
118     {
119       void * fnc = GetProcAddress (hd, sym);
120       if (!fnc)
121         return NULL;
122       return fnc;
123     }
124   return NULL;
125 }
126
127 static GPG_ERR_INLINE int
128 dlclose (void * hd)
129 {
130   if (hd)
131     {
132       FreeLibrary (hd);
133       return 0;
134     }
135   return -1;
136 }
137
138
139 /* Return a malloced string encoded in UTF-8 from the wide char input
140    string STRING.  Caller must free this value.  Returns NULL and sets
141    ERRNO on failure.  Calling this function with STRING set to NULL is
142    not defined.  */
143 static char *
144 wchar_to_utf8 (const wchar_t *string)
145 {
146   int n;
147   char *result;
148
149   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
150   if (n < 0)
151     {
152       gpg_err_set_errno (EINVAL);
153       return NULL;
154     }
155
156   result = malloc (n+1);
157   if (!result)
158     return NULL;
159
160   n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
161   if (n < 0)
162     {
163       free (result);
164       gpg_err_set_errno (EINVAL);
165       result = NULL;
166     }
167   return result;
168 }
169
170
171 /* Return a malloced wide char string from an UTF-8 encoded input
172    string STRING.  Caller must free this value. On failure returns
173    NULL; caller may use GetLastError to get the actual error number.
174    Calling this function with STRING set to NULL is not defined. */
175 static wchar_t *
176 utf8_to_wchar (const char *string)
177 {
178   int n;
179   wchar_t *result;
180
181
182   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
183   if (n < 0)
184     return NULL;
185
186   result = (wchar_t *) malloc ((n+1) * sizeof *result);
187   if (!result)
188     return NULL;
189
190   n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
191   if (n < 0)
192     {
193       free (result);
194       return NULL;
195     }
196   return result;
197 }
198
199
200 /* Same as utf8_to_wchar but calling it with NULL returns
201    NULL.  So a return value of NULL only indicates failure
202    if STRING is not set to NULL. */
203 static wchar_t *
204 utf8_to_wchar0 (const char *string)
205 {
206   if (!string)
207     return NULL;
208
209   return utf8_to_wchar (string);
210 }
211
212
213 /* Replace all forward slashes by backslashes.  */
214 static void
215 replace_slashes (char *string)
216 {
217   for (; *string; string++)
218     if (*string == '/')
219       *string = '\\';
220 }
221
222
223 /* Get the base name of NAME.  Returns a pointer into NAME right after
224    the last slash or backslash or to NAME if no slash or backslash
225    exists.  */
226 static const char *
227 get_basename (const char *name)
228 {
229   const char *mark, *s;
230
231   for (mark=NULL, s=name; *s; s++)
232     if (*s == '/' || *s == '\\')
233       mark = s;
234
235   return mark? mark+1 : name;
236 }
237
238
239 void
240 _gpgme_allow_set_foreground_window (pid_t pid)
241 {
242 #ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
243   static int initialized;
244   static BOOL (WINAPI * func)(DWORD);
245   void *handle;
246
247   if (!initialized)
248     {
249       /* Available since W2000; thus we dynload it.  */
250       initialized = 1;
251       handle = dlopen ("user32.dll", RTLD_LAZY);
252       if (handle)
253         {
254           func = dlsym (handle, "AllowSetForegroundWindow");
255           if (!func)
256             {
257               dlclose (handle);
258               handle = NULL;
259             }
260         }
261     }
262
263   if (!pid || pid == (pid_t)(-1))
264     {
265       TRACE (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", NULL,
266               "no action for pid %d", (int)pid);
267     }
268   else if (func)
269     {
270       int rc = func (pid);
271       TRACE (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", NULL,
272               "called for pid %d; result=%d", (int)pid, rc);
273
274     }
275   else
276     {
277       TRACE (DEBUG_ENGINE, "gpgme:AllowSetForegroundWindow", NULL,
278               "function not available");
279     }
280 #endif /* HAVE_ALLOW_SET_FOREGROUND_WINDOW */
281 }
282
283
284 /* Wrapper around CancelSynchronousIo which is only available since
285  * Vista.  */
286 void
287 _gpgme_w32_cancel_synchronous_io (HANDLE thread)
288 {
289   static int initialized;
290   static BOOL (WINAPI * func)(DWORD);
291   void *handle;
292
293   if (!initialized)
294     {
295       /* Available since Vista; thus we dynload it.  */
296       initialized = 1;
297       handle = dlopen ("kernel32.dll", RTLD_LAZY);
298       if (handle)
299         {
300           func = dlsym (handle, "CancelSynchronousIo");
301           if (!func)
302             {
303               dlclose (handle);
304               handle = NULL;
305             }
306         }
307     }
308
309   if (func)
310     {
311       if (!func ((DWORD)thread) && GetLastError() != ERROR_NOT_FOUND)
312         {
313           TRACE (DEBUG_ENGINE, "gpgme:CancelSynchronousIo", NULL,
314                  "called for thread %p: ec=%u",
315                  thread, (unsigned int)GetLastError ());
316         }
317     }
318   else
319     {
320       TRACE (DEBUG_ENGINE, "gpgme:CancelSynchronousIo", NULL,
321               "function not available");
322     }
323 }
324
325
326 /* Return a string from the W32 Registry or NULL in case of error.
327    Caller must release the return value.  A NULL for root is an alias
328    for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn. */
329 static char *
330 read_w32_registry_string (const char *root, const char *dir, const char *name)
331 {
332   HKEY root_key, key_handle;
333   DWORD n1, nbytes, type;
334   char *result = NULL;
335
336   if (!root)
337     root_key = HKEY_CURRENT_USER;
338   else if (!strcmp( root, "HKEY_CLASSES_ROOT"))
339     root_key = HKEY_CLASSES_ROOT;
340   else if (!strcmp( root, "HKEY_CURRENT_USER"))
341     root_key = HKEY_CURRENT_USER;
342   else if (!strcmp( root, "HKEY_LOCAL_MACHINE"))
343     root_key = HKEY_LOCAL_MACHINE;
344   else if (!strcmp( root, "HKEY_USERS"))
345     root_key = HKEY_USERS;
346   else if (!strcmp( root, "HKEY_PERFORMANCE_DATA"))
347     root_key = HKEY_PERFORMANCE_DATA;
348   else if (!strcmp( root, "HKEY_CURRENT_CONFIG"))
349     root_key = HKEY_CURRENT_CONFIG;
350   else
351     return NULL;
352
353   if (RegOpenKeyExA (root_key, dir, 0, KEY_READ, &key_handle))
354     {
355       if (root)
356         return NULL; /* no need for a RegClose, so return direct */
357       /* It seems to be common practise to fall back to HKLM. */
358       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
359         return NULL; /* still no need for a RegClose, so return direct */
360     }
361
362   nbytes = 1;
363   if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
364     {
365       if (root)
366         goto leave;
367       /* Try to fallback to HKLM also vor a missing value.  */
368       RegCloseKey (key_handle);
369       if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle))
370         return NULL; /* Nope.  */
371       if (RegQueryValueExA (key_handle, name, 0, NULL, NULL, &nbytes))
372         goto leave;
373     }
374   n1 = nbytes + 1;
375   result = malloc (n1);
376   if (!result)
377     goto leave;
378   if (RegQueryValueExA (key_handle, name, 0, &type, (LPBYTE) result, &n1))
379     {
380       free (result);
381       result = NULL;
382       goto leave;
383     }
384   result[nbytes] = 0; /* Make sure it is really a string.  */
385
386  leave:
387   RegCloseKey (key_handle);
388   return result;
389 }
390
391
392 /* Return the name of the directory with the gpgme DLL or the EXE (if
393    statically linked).  May return NULL on severe errors. */
394 const char *
395 _gpgme_get_inst_dir (void)
396 {
397   static char *inst_dir;
398
399   if (override_inst_dir)
400     return override_inst_dir;
401
402   LOCK (get_path_lock);
403   if (!inst_dir)
404     {
405       wchar_t *moddir;
406
407       moddir = malloc ((MAX_PATH+5) * sizeof *moddir);
408       if (moddir)
409         {
410           if (!GetModuleFileNameW (my_hmodule, moddir, MAX_PATH))
411             *moddir = 0;
412           if (!*moddir)
413             gpg_err_set_errno (ENOENT);
414           else
415             {
416               inst_dir = wchar_to_utf8 (moddir);
417               if (inst_dir)
418                 {
419                   char *p = strrchr (inst_dir, '\\');
420                   if (p)
421                     *p = 0;
422                 }
423             }
424           free (moddir);
425         }
426     }
427   UNLOCK (get_path_lock);
428   return inst_dir;
429 }
430
431
432 static char *
433 find_program_in_dir (const char *dir, const char *name)
434 {
435   char *result;
436
437   result = _gpgme_strconcat (dir, "\\", name, NULL);
438   if (!result)
439     return NULL;
440
441   if (_gpgme_access (result, F_OK))
442     {
443       free (result);
444       return NULL;
445     }
446
447   return result;
448 }
449
450
451 static char *
452 find_program_at_standard_place (const char *name)
453 {
454   wchar_t path[MAX_PATH];
455   char *result = NULL;
456
457   /* See https://wiki.tcl-lang.org/page/Getting+Windows+%22special+folders%22+with+Ffidl for details on compatibility.
458
459      We First try the generic place and then fallback to the x86
460      (i.e. 32 bit) place.  This will prefer a 64 bit of the program
461      over a 32 bit version on 64 bit Windows if installed.  */
462   if (SHGetSpecialFolderPathW (NULL, path, CSIDL_PROGRAM_FILES, 0))
463     {
464       char *utf8_path = wchar_to_utf8 (path);
465       result = _gpgme_strconcat (utf8_path, "\\", name, NULL);
466       free (utf8_path);
467       if (result && _gpgme_access (result, F_OK))
468         {
469           free (result);
470           result = NULL;
471         }
472     }
473   if (!result
474       && SHGetSpecialFolderPathW (NULL, path, CSIDL_PROGRAM_FILESX86, 0))
475     {
476       char *utf8_path = wchar_to_utf8 (path);
477       result = _gpgme_strconcat (utf8_path, "\\", name, NULL);
478       free (utf8_path);
479       if (result && _gpgme_access (result, F_OK))
480         {
481           free (result);
482           result = NULL;
483         }
484     }
485   return result;
486 }
487
488
489 /* Set the default name for the gpg binary.  This function may only be
490    called by gpgme_set_global_flag.  Returns 0 on success.  */
491 int
492 _gpgme_set_default_gpg_name (const char *name)
493 {
494   if (!default_gpg_name)
495     {
496       default_gpg_name = _gpgme_strconcat (name, ".exe", NULL);
497       if (default_gpg_name)
498         replace_slashes (default_gpg_name);
499     }
500   return !default_gpg_name;
501 }
502
503 /* Set the default name for the gpgconf binary.  This function may only be
504    called by gpgme_set_global_flag.  Returns 0 on success.  */
505 int
506 _gpgme_set_default_gpgconf_name (const char *name)
507 {
508   if (!default_gpgconf_name)
509     {
510       default_gpgconf_name = _gpgme_strconcat (name, ".exe", NULL);
511       if (default_gpgconf_name)
512         replace_slashes (default_gpgconf_name);
513     }
514   return !default_gpgconf_name;
515 }
516
517
518 /* Set the override installation directory.  This function may only be
519    called by gpgme_set_global_flag.  Returns 0 on success.  */
520 int
521 _gpgme_set_override_inst_dir (const char *dir)
522 {
523   if (!override_inst_dir)
524     {
525       override_inst_dir = strdup (dir);
526       if (override_inst_dir)
527         {
528           replace_slashes (override_inst_dir);
529           /* Remove a trailing slash.  */
530           if (*override_inst_dir
531               && override_inst_dir[strlen (override_inst_dir)-1] == '\\')
532             override_inst_dir[strlen (override_inst_dir)-1] = 0;
533         }
534     }
535   return !override_inst_dir;
536 }
537
538
539 /* Return the full file name of the GPG binary.  This function is used
540    iff gpgconf was not found and thus it can be assumed that gpg2 is
541    not installed.  This function is only called by get_gpgconf_item
542    and may not be called concurrently. */
543 char *
544 _gpgme_get_gpg_path (void)
545 {
546   char *gpg = NULL;
547   const char *name, *inst_dir;
548
549   name = default_gpg_name? get_basename (default_gpg_name) : "gpg.exe";
550
551   /* 1. Try to find gpg.exe in the installation directory of gpgme.  */
552   inst_dir = _gpgme_get_inst_dir ();
553   if (inst_dir)
554     {
555       gpg = find_program_in_dir (inst_dir, name);
556     }
557
558   /* 2. Try to find gpg.exe using that ancient registry key.  */
559   if (!gpg)
560     {
561       char *dir;
562
563       dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
564                                       GNUPG_REGKEY_2,
565                                       "Install Directory");
566       if (dir)
567         {
568           gpg = find_program_in_dir (dir, name);
569           free (dir);
570         }
571     }
572
573   /* 3. Try to find gpg.exe below CSIDL_PROGRAM_FILES.  */
574   if (!gpg)
575     {
576       name = default_gpg_name? default_gpg_name : "GNU\\GnuPG\\gpg.exe";
577       gpg = find_program_at_standard_place (name);
578     }
579
580   /* 4. Print a debug message if not found.  */
581   if (!gpg)
582     _gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
583                   "_gpgme_get_gpg_path: '%s' not found", name);
584
585   return gpg;
586 }
587
588
589 /* This function is only called by get_gpgconf_item and may not be
590    called concurrently.  */
591 char *
592 _gpgme_get_gpgconf_path (void)
593 {
594   char *gpgconf = NULL;
595   const char *inst_dir, *name;
596
597   name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe";
598
599   /* 1. Try to find gpgconf.exe in the installation directory of gpgme.  */
600   inst_dir = _gpgme_get_inst_dir ();
601   if (inst_dir)
602     {
603       gpgconf = find_program_in_dir (inst_dir, name);
604     }
605
606   /* 2. Try to find gpgconf.exe from GnuPG >= 2.1 below CSIDL_PROGRAM_FILES. */
607   if (!gpgconf)
608     {
609       const char *name2 = (default_gpgconf_name ? default_gpgconf_name
610                            /**/                 : "GnuPG\\bin\\gpgconf.exe");
611       gpgconf = find_program_at_standard_place (name2);
612     }
613
614   /* 3. Try to find gpgconf.exe using the Windows registry. */
615   if (!gpgconf)
616     {
617       char *dir;
618
619       dir = read_w32_registry_string (NULL,
620                                       GNUPG_REGKEY_2,
621                                       "Install Directory");
622       if (!dir)
623         {
624           char *tmp = read_w32_registry_string (NULL,
625                                                 GNUPG_REGKEY_3,
626                                                 "Install Directory");
627           if (tmp)
628             {
629               dir = _gpgme_strconcat (tmp, "\\bin", NULL);
630               free (tmp);
631               if (!dir)
632                 return NULL;
633             }
634         }
635       if (dir)
636         {
637           gpgconf = find_program_in_dir (dir, name);
638           free (dir);
639         }
640     }
641
642   /* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES.  */
643   if (!gpgconf)
644     {
645       gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
646     }
647
648   /* 5. Try to find gpgconf.exe relative to us.  */
649   if (!gpgconf && inst_dir)
650     {
651       char *dir = _gpgme_strconcat (inst_dir, "\\..\\..\\GnuPG\\bin", NULL);
652       gpgconf = find_program_in_dir (dir, name);
653       free (dir);
654     }
655
656   /* 5. Print a debug message if not found.  */
657   if (!gpgconf)
658     _gpgme_debug (NULL, DEBUG_ENGINE, -1, NULL, NULL, NULL,
659                   "_gpgme_get_gpgconf_path: '%s' not found",name);
660
661   return gpgconf;
662 }
663
664
665 const char *
666 _gpgme_get_w32spawn_path (void)
667 {
668   static char *w32spawn_program;
669   const char *inst_dir;
670
671   inst_dir = _gpgme_get_inst_dir ();
672   LOCK (get_path_lock);
673   if (!w32spawn_program)
674     w32spawn_program = find_program_in_dir (inst_dir, "gpgme-w32spawn.exe");
675   UNLOCK (get_path_lock);
676   return w32spawn_program;
677 }
678
679
680 /* Return an integer value from gpgme specific configuration
681    entries. VALUE receives that value; function returns true if a value
682    has been configured and false if not. */
683 int
684 _gpgme_get_conf_int (const char *key, int *value)
685 {
686   char *tmp = read_w32_registry_string (NULL, "Software\\GNU\\gpgme", key);
687   if (!tmp)
688     return 0;
689   *value = atoi (tmp);
690   free (tmp);
691   return 1;
692 }
693
694
695 \f
696 /* mkstemp extracted from libc/sysdeps/posix/tempname.c.  Copyright
697    (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc.
698
699    The GNU C Library is free software; you can redistribute it and/or
700    modify it under the terms of the GNU Lesser General Public
701    License as published by the Free Software Foundation; either
702    version 2.1 of the License, or (at your option) any later version.  */
703
704 static const char letters[] =
705 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
706
707 /* Generate a temporary file name based on TMPL.  TMPL must match the
708    rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
709    does not exist at the time of the call to mkstemp.  TMPL is
710    overwritten with the result.  */
711 static int
712 my_mkstemp (char *tmpl)
713 {
714   int len;
715   char *XXXXXX;
716   static uint64_t value;
717   uint64_t random_time_bits;
718   unsigned int count;
719   int fd = -1;
720   int save_errno = errno;
721
722   /* A lower bound on the number of temporary files to attempt to
723      generate.  The maximum total number of temporary file names that
724      can exist for a given template is 62**6.  It should never be
725      necessary to try all these combinations.  Instead if a reasonable
726      number of names is tried (we define reasonable as 62**3) fail to
727      give the system administrator the chance to remove the problems.  */
728 #define ATTEMPTS_MIN (62 * 62 * 62)
729
730   /* The number of times to attempt to generate a temporary file.  To
731      conform to POSIX, this must be no smaller than TMP_MAX.  */
732 #if ATTEMPTS_MIN < TMP_MAX
733   unsigned int attempts = TMP_MAX;
734 #else
735   unsigned int attempts = ATTEMPTS_MIN;
736 #endif
737
738   len = strlen (tmpl);
739   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
740     {
741       gpg_err_set_errno (EINVAL);
742       return -1;
743     }
744
745   /* This is where the Xs start.  */
746   XXXXXX = &tmpl[len - 6];
747
748   /* Get some more or less random data.  */
749   {
750     FILETIME ft;
751
752     GetSystemTimeAsFileTime (&ft);
753     random_time_bits = (((uint64_t)ft.dwHighDateTime << 32)
754                         | (uint64_t)ft.dwLowDateTime);
755   }
756   value += random_time_bits ^ ath_self ();
757
758   for (count = 0; count < attempts; value += 7777, ++count)
759     {
760       uint64_t v = value;
761
762       /* Fill in the random bits.  */
763       XXXXXX[0] = letters[v % 62];
764       v /= 62;
765       XXXXXX[1] = letters[v % 62];
766       v /= 62;
767       XXXXXX[2] = letters[v % 62];
768       v /= 62;
769       XXXXXX[3] = letters[v % 62];
770       v /= 62;
771       XXXXXX[4] = letters[v % 62];
772       v /= 62;
773       XXXXXX[5] = letters[v % 62];
774
775       fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
776       if (fd >= 0)
777         {
778           gpg_err_set_errno (save_errno);
779           return fd;
780         }
781       else if (errno != EEXIST)
782         return -1;
783     }
784
785   /* We got out of the loop because we ran out of combinations to try.  */
786   gpg_err_set_errno (EEXIST);
787   return -1;
788 }
789
790 \f
791 int
792 _gpgme_mkstemp (int *fd, char **name)
793 {
794   char tmp[MAX_PATH + 2];
795   char *tmpname;
796   int err;
797
798   *fd = -1;
799   *name = NULL;
800
801   err = GetTempPathA (MAX_PATH + 1, tmp);
802   if (err == 0 || err > MAX_PATH + 1)
803     strcpy (tmp,"c:\\windows\\temp");
804   else
805     {
806       int len = strlen(tmp);
807
808       /* GetTempPath may return with \ on the end */
809       while(len > 0 && tmp[len - 1] == '\\')
810         {
811           tmp[len-1] = '\0';
812           len--;
813         }
814     }
815
816   tmpname = _gpgme_strconcat (tmp, "\\gpgme-XXXXXX", NULL);
817   if (!tmpname)
818     return -1;
819   *fd = my_mkstemp (tmpname);
820   if (*fd < 0)
821     {
822       free (tmpname);
823       return -1;
824     }
825
826   *name = tmpname;
827   return 0;
828 }
829
830
831 /* Like access but using windows _waccess */
832 int
833 _gpgme_access (const char *path, int mode)
834 {
835   wchar_t *u16 = utf8_to_wchar0 (path);
836   int r = _waccess (u16, mode);
837
838   free(u16);
839   return r;
840 }
841
842
843 /* Like CreateProcessA but mapping the arguments to wchar API */
844 int _gpgme_create_process_utf8 (const char *application_name_utf8,
845                                 char *command_line_utf8,
846                                 LPSECURITY_ATTRIBUTES lpProcessAttributes,
847                                 LPSECURITY_ATTRIBUTES lpThreadAttributes,
848                                 BOOL bInheritHandles,
849                                 DWORD dwCreationFlags,
850                                 void *lpEnvironment,
851                                 char *working_directory_utf8,
852                                 LPSTARTUPINFOA si,
853                                 LPPROCESS_INFORMATION lpProcessInformation)
854 {
855   BOOL ret;
856   wchar_t *application_name = utf8_to_wchar0 (application_name_utf8);
857   wchar_t *command_line = utf8_to_wchar0 (command_line_utf8);
858   wchar_t *working_directory = utf8_to_wchar0 (working_directory_utf8);
859
860   STARTUPINFOW siw;
861   memset (&siw, 0, sizeof siw);
862   if (si)
863     {
864       siw.cb = sizeof (siw);
865       siw.dwFlags = si->dwFlags;
866       siw.wShowWindow = si->wShowWindow;
867       siw.hStdInput = si->hStdInput;
868       siw.hStdOutput = si->hStdOutput;
869       siw.hStdError = si->hStdError;
870       siw.dwX = si->dwX;
871       siw.dwY = si->dwY;
872       siw.dwXSize = si->dwXSize;
873       siw.dwYSize = si->dwYSize;
874       siw.dwXCountChars = si->dwXCountChars;
875       siw.dwYCountChars = si->dwYCountChars;
876       siw.dwFillAttribute = si->dwFillAttribute;
877       siw.lpDesktop = utf8_to_wchar0 (si->lpDesktop);
878       siw.lpTitle = utf8_to_wchar0 (si->lpTitle);
879     }
880
881   ret = CreateProcessW (application_name,
882                         command_line,
883                         lpProcessAttributes,
884                         lpThreadAttributes,
885                         bInheritHandles,
886                         dwCreationFlags,
887                         lpEnvironment,
888                         working_directory,
889                         si ? &siw : NULL,
890                         lpProcessInformation);
891   free (siw.lpTitle);
892   free (siw.lpDesktop);
893   free (application_name);
894   free (command_line);
895   free (working_directory);
896   return ret;
897 }
898 \f
899 /* Entry point called by the DLL loader.  */
900 #ifdef DLL_EXPORT
901 int WINAPI
902 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
903 {
904   (void)reserved;
905
906   if (reason == DLL_PROCESS_ATTACH)
907     my_hmodule = hinst;
908
909   return TRUE;
910 }
911 #endif /*DLL_EXPORT*/