1 /* gpg-error.c - Determining gpg-error error codes.
2 Copyright (C) 2004 g10 Code GmbH
4 This file is part of libgpg-error.
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.
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.
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
36 #ifdef HAVE_W32_SYSTEM
41 # define _(a) gettext (a)
43 # define N_(a) gettext_noop (a)
52 #include <gpg-error.h>
56 /* The implementation follows below. */
57 static char *get_locale_dir (void);
58 static void drop_locale_dir (char *locale_dir);
60 #define get_locale_dir() LOCALEDIR
61 #define drop_locale_dir(dir)
70 # ifdef HAVE_LC_MESSAGES
71 setlocale (LC_TIME, "");
72 setlocale (LC_MESSAGES, "");
74 setlocale (LC_ALL, "" );
77 locale_dir = get_locale_dir ();
80 bindtextdomain (PACKAGE, locale_dir);
81 drop_locale_dir (locale_dir);
88 #ifdef HAVE_W32_SYSTEM
93 get_root_key(const char *root)
98 root_key = HKEY_CURRENT_USER;
99 else if( !strcmp( root, "HKEY_CLASSES_ROOT" ) )
100 root_key = HKEY_CLASSES_ROOT;
101 else if( !strcmp( root, "HKEY_CURRENT_USER" ) )
102 root_key = HKEY_CURRENT_USER;
103 else if( !strcmp( root, "HKEY_LOCAL_MACHINE" ) )
104 root_key = HKEY_LOCAL_MACHINE;
105 else if( !strcmp( root, "HKEY_USERS" ) )
106 root_key = HKEY_USERS;
107 else if( !strcmp( root, "HKEY_PERFORMANCE_DATA" ) )
108 root_key = HKEY_PERFORMANCE_DATA;
109 else if( !strcmp( root, "HKEY_CURRENT_CONFIG" ) )
110 root_key = HKEY_CURRENT_CONFIG;
117 * Return a string from the Win32 Registry or NULL in case of
118 * error. Caller must release the return value. A NULL for root
119 * is an alias for HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE in turn.
120 * NOTE: The value is allocated with a plain malloc() - use free() and not
121 * the usual xfree()!!!
124 read_w32_registry_string( const char *root, const char *dir, const char *name )
126 HKEY root_key, key_handle;
127 DWORD n1, nbytes, type;
130 if ( !(root_key = get_root_key(root) ) )
133 if( RegOpenKeyEx( root_key, dir, 0, KEY_READ, &key_handle ) )
136 return NULL; /* no need for a RegClose, so return direct */
137 /* It seems to be common practise to fall back to HKLM. */
138 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
139 return NULL; /* still no need for a RegClose, so return direct */
143 if( RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes ) ) {
146 /* Try to fallback to HKLM also vor a missing value. */
147 RegCloseKey (key_handle);
148 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, dir, 0, KEY_READ, &key_handle) )
149 return NULL; /* Nope. */
150 if (RegQueryValueEx( key_handle, name, 0, NULL, NULL, &nbytes))
153 result = malloc( (n1=nbytes+1) );
156 if( RegQueryValueEx( key_handle, name, 0, &type, result, &n1 ) ) {
157 free(result); result = NULL;
160 result[nbytes] = 0; /* make sure it is really a string */
161 if (type == REG_EXPAND_SZ && strchr (result, '%')) {
168 nbytes = ExpandEnvironmentStrings (result, tmp, n1);
169 if (nbytes && nbytes > n1) {
172 tmp = malloc (n1 + 1);
175 nbytes = ExpandEnvironmentStrings (result, tmp, n1);
176 if (nbytes && nbytes > n1) {
177 free (tmp); /* oops - truncated, better don't expand at all */
184 else if (nbytes) { /* okay, reduce the length */
187 result = malloc (strlen (tmp)+1);
191 strcpy (result, tmp);
195 else { /* error - don't expand */
201 RegCloseKey( key_handle );
206 #define REGKEY "Software\\GNU\\GnuPG"
209 get_locale_dir (void)
215 instdir = read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY,
216 "Install Directory");
220 /* Build the key: "<instdir>/share/locale". */
221 #define SLDIR "\\share\\locale"
222 dname = malloc (strlen (instdir) + strlen (SLDIR) + 1);
230 p += strlen (instdir);
240 drop_locale_dir (char *locale_dir)
245 #endif /* HAVE_W32_SYSTEM */
248 const char *gpg_strerror_sym (gpg_error_t err);
249 const char *gpg_strsource_sym (gpg_error_t err);
253 get_err_from_number (char *str, gpg_error_t *err)
259 nr = strtoul (str, &tail, 0);
268 unsigned long cnr = strtoul (tail + 1, &tail, 0);
272 if (nr >= GPG_ERR_SOURCE_DIM || cnr >= GPG_ERR_CODE_DIM)
275 nr = gpg_err_make (nr, cnr);
278 *err = (unsigned int) nr;
284 get_err_from_symbol_one (char *str, gpg_error_t *err,
285 int *have_source, int *have_code)
287 static const char src_prefix[] = "GPG_ERR_SOURCE_";
288 static const char code_prefix[] = "GPG_ERR_";
290 if (!strncasecmp (src_prefix, str, sizeof (src_prefix) - 1))
292 gpg_err_source_t src;
297 str += sizeof (src_prefix) - 1;
299 for (src = 0; src < GPG_ERR_SOURCE_DIM; src++)
303 src_sym = gpg_strsource_sym (src << GPG_ERR_SOURCE_SHIFT);
304 if (src_sym && !strcasecmp (str, src_sym + sizeof (src_prefix) - 1))
306 *err |= src << GPG_ERR_SOURCE_SHIFT;
311 else if (!strncasecmp (code_prefix, str, sizeof (code_prefix) - 1))
318 str += sizeof (code_prefix) - 1;
320 for (code = 0; code < GPG_ERR_CODE_DIM; code++)
322 const char *code_sym = gpg_strerror_sym (code);
324 && !strcasecmp (str, code_sym + sizeof (code_prefix) - 1))
336 get_err_from_symbol (char *str, gpg_error_t *err)
342 char *saved_pos = NULL;
346 while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z')
347 || (*str2 >= '0' && *str2 <= '9')
360 ret = get_err_from_symbol_one (str, err, &have_source, &have_code);
362 ret = get_err_from_symbol_one (str2, err, &have_source, &have_code);
365 *saved_pos = saved_char;
371 get_err_from_str_one (char *str, gpg_error_t *err,
372 int *have_source, int *have_code)
374 gpg_err_source_t src;
377 for (src = 0; src < GPG_ERR_SOURCE_DIM; src++)
379 const char *src_str = gpg_strsource (src << GPG_ERR_SOURCE_SHIFT);
380 if (src_str && !strcasecmp (str, src_str))
386 *err |= src << GPG_ERR_SOURCE_SHIFT;
391 for (code = 0; code < GPG_ERR_CODE_DIM; code++)
393 const char *code_str = gpg_strerror (code);
394 if (code_str && !strcasecmp (str, code_str))
410 get_err_from_str (char *str, gpg_error_t *err)
416 char *saved_pos = NULL;
420 ret = get_err_from_str_one (str, err, &have_source, &have_code);
424 while (*str2 && ((*str2 >= 'A' && *str2 <= 'Z')
425 || (*str2 >= 'a' && *str2 <= 'z')
426 || (*str2 >= '0' && *str2 <= '9')
433 *((char *) str2) = '\0';
435 while (*str2 && !((*str2 >= 'A' && *str2 <= 'Z')
436 || (*str2 >= 'a' && *str2 <= 'z')
437 || (*str2 >= '0' && *str2 <= '9')
444 ret = get_err_from_str_one (str, err, &have_source, &have_code);
446 ret = get_err_from_str_one (str2, err, &have_source, &have_code);
449 *saved_pos = saved_char;
456 main (int argc, char *argv[])
460 #ifndef GPG_ERR_INITIALIZED
469 fprintf (stderr, _("Usage: %s GPG-ERROR [...]\n"),
470 strrchr (argv[0],'/')? (strrchr (argv[0], '/')+1): argv[0]);
473 else if (argc == 2 && !strcmp (argv[1], "--version"))
475 fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
484 if (get_err_from_number (argv[i], &err)
485 || get_err_from_symbol (argv[i], &err)
486 || get_err_from_str (argv[i], &err))
488 const char *source_sym = gpg_strsource_sym (err);
489 const char *error_sym = gpg_strerror_sym (err);
491 printf ("%u = (%u, %u) = (%s, %s) = (%s, %s)\n",
492 err, gpg_err_source (err), gpg_err_code (err),
493 source_sym ? source_sym : "-", error_sym ? error_sym : "-",
494 gpg_strsource (err), gpg_strerror (err));
497 fprintf (stderr, _("%s: warning: could not recognize %s\n"),