Made some PIN pads work.
[gnupg.git] / common / homedir.c
1 /* homedir.c - Setup the home directory.
2  *      Copyright (C) 2004, 2006 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG 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 General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <fcntl.h>
26
27 #ifdef HAVE_W32_SYSTEM
28 #include <shlobj.h>
29 #ifndef CSIDL_APPDATA
30 #define CSIDL_APPDATA 0x001a
31 #endif
32 #ifndef CSIDL_LOCAL_APPDATA
33 #define CSIDL_LOCAL_APPDATA 0x001c
34 #endif
35 #ifndef CSIDL_FLAG_CREATE
36 #define CSIDL_FLAG_CREATE 0x8000
37 #endif
38 #endif /*HAVE_W32_SYSTEM*/
39
40
41
42 #include "util.h"
43 #include "sysutils.h"
44
45
46 /* This is a helper function to load a Windows function from either of
47    one DLLs. */
48 #ifdef HAVE_W32_SYSTEM
49 static HRESULT
50 w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
51 {
52   static int initialized;
53   static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR);
54
55   if (!initialized)
56     {
57       static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
58       void *handle;
59       int i;
60
61       initialized = 1;
62
63       for (i=0, handle = NULL; !handle && dllnames[i]; i++)
64         {
65           handle = dlopen (dllnames[i], RTLD_LAZY);
66           if (handle)
67             {
68               func = dlsym (handle, "SHGetFolderPathA");
69               if (!func)
70                 {
71                   dlclose (handle);
72                   handle = NULL;
73                 }
74             }
75         }
76     }
77
78   if (func)
79     return func (a,b,c,d,e);
80   else
81     return -1;
82 }
83 #endif /*HAVE_W32_SYSTEM*/
84
85
86 /* Set up the default home directory.  The usual --homedir option
87    should be parsed later. */
88 const char *
89 default_homedir (void)
90 {
91   const char *dir;
92
93   dir = getenv("GNUPGHOME");
94 #ifdef HAVE_W32_SYSTEM
95   if (!dir || !*dir)
96     dir = read_w32_registry_string (NULL, "Software\\GNU\\GnuPG", "HomeDir");
97   if (!dir || !*dir)
98     {
99       char path[MAX_PATH];
100       
101       /* It might be better to use LOCAL_APPDATA because this is
102          defined as "non roaming" and thus more likely to be kept
103          locally.  For private keys this is desired.  However, given
104          that many users copy private keys anyway forth and back,
105          using a system roaming services might be better than to let
106          them do it manually.  A security conscious user will anyway
107          use the registry entry to have better control.  */
108       if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, 
109                                NULL, 0, path) >= 0) 
110         {
111           char *tmp = xmalloc (strlen (path) + 6 +1);
112           strcpy (stpcpy (tmp, path), "\\gnupg");
113           dir = tmp;
114           
115           /* Try to create the directory if it does not yet
116              exists.  */
117           if (access (dir, F_OK))
118             CreateDirectory (dir, NULL);
119         }
120     }
121 #endif /*HAVE_W32_SYSTEM*/
122   if (!dir || !*dir)
123     dir = GNUPG_DEFAULT_HOMEDIR;
124
125   return dir;
126 }