Tizen 2.1 base
[external/libgpg-error.git] / src / init.c
1 /* init.c - Initialize the GnuPG error library.
2    Copyright (C) 2005 g10 Code GmbH
3
4    This file is part of libgpg-error.
5
6    libgpg-error 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 of
9    the License, or (at your option) any later version.
10  
11    libgpg-error is distributed in the hope that it will be useful, but
12    WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15  
16    You should have received a copy of the GNU Lesser General Public
17    License along with libgpg-error; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19    02111-1307, USA.  */
20
21 #if HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29
30 #include <gpg-error.h>
31
32 #include "gettext.h"
33
34 \f
35 /* Locale directory support.  */
36
37 #if HAVE_W32_SYSTEM
38 /* The implementation follows below.  */
39 static char *get_locale_dir (void);
40 static void drop_locale_dir (char *locale_dir);
41 #else
42 #define get_locale_dir() LOCALEDIR
43 #define drop_locale_dir(dir)
44 #endif
45
46 \f
47 /* Initialize the library.  This function should be run early.  */
48 gpg_error_t
49 gpg_err_init (void)
50 {
51 #ifdef ENABLE_NLS
52   char *locale_dir;
53
54   /* We only have to bind our locale directory to our text domain.  */
55
56   locale_dir = get_locale_dir ();
57   if (locale_dir)
58     {
59       bindtextdomain (PACKAGE, locale_dir);
60       drop_locale_dir (locale_dir);
61     }
62 #endif
63
64   return 0;
65 }
66
67
68 \f
69 #ifdef HAVE_W32_SYSTEM
70
71 #include <windows.h>
72
73 static HKEY
74 get_root_key(const char *root)
75 {
76   HKEY root_key;
77
78   if( !root )
79     root_key = HKEY_CURRENT_USER;
80   else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
81     root_key = HKEY_CLASSES_ROOT;
82   else if( !strcmp( root, "HKEY_CURRENT_USER" ) )
83     root_key = HKEY_CURRENT_USER;
84   else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
85     root_key = HKEY_LOCAL_MACHINE;
86   else if( !strcmp( root, "HKEY_USERS" ) )
87     root_key = HKEY_USERS;
88   else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
89     root_key = HKEY_PERFORMANCE_DATA;
90   else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
91     root_key = HKEY_CURRENT_CONFIG;
92   else
93     return NULL;
94   return root_key;
95 }
96
97 /****************
98  * Return a string from the Win32 Registry or NULL in case of
99  * error.  Caller must release the return value.   A NULL for root
100  * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.
101  * NOTE: The value is allocated with a plain malloc() - use free() and not
102  * the usual xfree()!!!
103  */
104 static char *
105 read_w32_registry_string( const char *root, const char *dir, const char *name )
106 {
107   HKEY root_key, key_handle;
108   DWORD n1, nbytes, type;
109   char *result = NULL;
110
111   if ( !(root_key = get_root_key(root) ) )
112     return NULL;
113
114   if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
115     {
116       if (root)
117         return NULL; /* no need for a RegClose, so return direct */
118       /* It seems to be common practise to fall back to HKLM. */
119       if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
120         return NULL; /* still no need for a RegClose, so return direct */
121     }
122
123   nbytes = 1;
124   if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) {
125     if (root)
126       goto leave;
127     /* Try to fallback to HKLM also vor a missing value.  */
128     RegCloseKey (key_handle);
129     if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
130       return NULL; /* Nope.  */
131     if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes))
132       goto leave;
133   }
134   result = malloc( (n1=nbytes+1) );
135   if( !result )
136     goto leave;
137   if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) {
138     free(result); result = NULL;
139     goto leave;
140   }
141   result[nbytes] = 0; /* make sure it is really a string  */
142   if (type == REG_EXPAND_SZ && strchr (result, '%')) {
143     char *tmp;
144
145     n1 += 1000;
146     tmp = malloc (n1+1);
147     if (!tmp)
148       goto leave;
149     nbytes = ExpandEnvironmentStrings (result, tmp, n1);
150     if (nbytes && nbytes > n1) {
151       free (tmp);
152       n1 = nbytes;
153       tmp = malloc (n1 + 1);
154       if (!tmp)
155         goto leave;
156       nbytes = ExpandEnvironmentStrings (result, tmp, n1);
157       if (nbytes && nbytes > n1) {
158         free (tmp); /* oops - truncated, better don't expand at all */
159         goto leave;
160       }
161       tmp[nbytes] = 0;
162       free (result);
163       result = tmp;
164     }
165     else if (nbytes) { /* okay, reduce the length */
166       tmp[nbytes] = 0;
167       free (result);
168       result = malloc (strlen (tmp)+1);
169       if (!result)
170         result = tmp;
171       else {
172         strcpy (result, tmp);
173         free (tmp);
174       }
175     }
176     else {  /* error - don't expand */
177       free (tmp);
178     }
179   }
180
181  leave:
182   RegCloseKey( key_handle );
183   return result;
184 }
185
186
187 #define REGKEY "Software\\GNU\\GnuPG"
188
189 static char *
190 get_locale_dir (void)
191 {
192   char *instdir;
193   char *p;
194   char *dname;
195
196   instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY,
197                                       "Install Directory");
198   if (!instdir)
199     return NULL;
200   
201   /* Build the key: "<instdir>/share/locale".  */
202 #define SLDIR "\\share\\locale"
203   dname = malloc (strlen (instdir) + strlen (SLDIR) + 1);
204   if (!dname)
205     {
206       free (instdir);
207       return NULL;
208     }
209   p = dname;
210   strcpy (p, instdir);
211   p += strlen (instdir);
212   strcpy (p, SLDIR);
213   
214   free (instdir);
215   
216   return dname;
217 }
218
219
220 static void
221 drop_locale_dir (char *locale_dir)
222 {
223   free (locale_dir);
224 }
225
226 #endif  /* HAVE_W32_SYSTEM */