1 /* init.c - Initialize the GnuPG error library.
2 Copyright (C) 2005, 2010 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 this program; if not, see <http://www.gnu.org/licenses/>.
29 #include <gpg-error.h>
34 #ifdef HAVE_W32CE_SYSTEM
35 # include "mkw32errmap.map.c" /* Generated map_w32codes () */
36 # ifndef TLS_OUT_OF_INDEXES
37 # define TLS_OUT_OF_INDEXES 0xFFFFFFFF
39 # ifndef __MINGW32CE__
40 # /* Replace the Mingw32CE provided abort function. */
41 # define abort() do { TerminateProcess (GetCurrentProcess(), 8); } while (0)
46 /* Locale directory support. */
52 static int tls_index = TLS_OUT_OF_INDEXES; /* Index for the TLS functions. */
54 static char *get_locale_dir (void);
55 static void drop_locale_dir (char *locale_dir);
57 #else /*!HAVE_W32_SYSTEM*/
59 #define get_locale_dir() LOCALEDIR
60 #define drop_locale_dir(dir)
62 #endif /*!HAVE_W32_SYSTEM*/
71 /* We only have to bind our locale directory to our text domain. */
72 locale_dir = get_locale_dir ();
75 bindtextdomain (PACKAGE, locale_dir);
76 drop_locale_dir (locale_dir);
81 /* Initialize the library. This function should be run early. */
85 #ifdef HAVE_W32_SYSTEM
87 /* We always have a constructor and thus this function is called
88 automatically. Due to the way the C init code of mingw works,
89 the constructors are called before our DllMain function is
90 called. The problem with that is that the TLS has not been setup
91 and w32-gettext.c requires TLS. To solve this we do nothing here
92 but call the actual init code from our DllMain. */
93 # else /*!DLL_EXPORT*/
94 /* Note that if the TLS is actually used, we can't release the TLS
95 as there is no way to know when a thread terminates (i.e. no
96 thread-specific-atexit). You are really better off to use the
98 if (tls_index == TLS_OUT_OF_INDEXES)
100 tls_index = TlsAlloc ();
101 if (tls_index == TLS_OUT_OF_INDEXES)
103 /* No way to continue - commit suicide. */
106 _gpg_w32__init_gettext_module ();
109 # endif /*!DLL_EXPORT*/
117 /* Deinitialize libgpg-error. This function is only used in special
118 circumstances. No gpg-error function should be used after this
119 function has been called. A value of 0 passed for MODE
120 deinitializes the entire libgpg-error, a value of 1 releases
121 resources allocated for the current thread and only that thread may
122 not anymore access libgpg-error after such a call. Under Windows
123 this function may be called from the DllMain function of a DLL
124 which statically links to libgpg-error. */
126 gpg_err_deinit (int mode)
128 #if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT)
129 struct tls_space_s *tls;
131 tls = TlsGetValue (tls_index);
134 TlsSetValue (tls_index, NULL);
141 tls_index = TLS_OUT_OF_INDEXES;
150 #ifdef HAVE_W32_SYSTEM
152 /* Return a malloced string encoded in UTF-8 from the wide char input
153 string STRING. Caller must free this value. Returns NULL on
154 failure. Caller may use GetLastError to get the actual error
155 number. The result of calling this function with STRING set to
156 NULL is not defined. */
158 wchar_to_utf8 (const wchar_t *string)
163 /* Note, that CP_UTF8 is not defined in Windows versions earlier
165 n = WideCharToMultiByte (CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
169 result = malloc (n+1);
172 n = WideCharToMultiByte (CP_UTF8, 0, string, -1, result, n, NULL, NULL);
183 /* Return a malloced wide char string from an UTF-8 encoded input
184 string STRING. Caller must free this value. Returns NULL on
185 failure. Caller may use GetLastError to get the actual error
186 number. The result of calling this function with STRING set to
187 NULL is not defined. */
189 utf8_to_wchar (const char *string)
194 n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
198 result = malloc ((n+1) * sizeof *result);
201 n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
214 get_locale_dir (void)
216 static wchar_t moddir[MAX_PATH+5];
220 if (!GetModuleFileNameW (NULL, moddir, MAX_PATH))
223 #define SLDIR "\\share\\locale"
226 nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL);
230 result = malloc (nbytes + strlen (SLDIR) + 1);
233 nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1,
234 result, nbytes, NULL, NULL);
242 p = strrchr (result, '\\');
245 /* If we are installed below "bin" strip that part and
246 use the top directory instead.
248 Background: Under Windows we don't install GnuPG
249 below bin/ but in the top directory with only share/,
250 lib/, and etc/ below it. One of the reasons is to
251 keep the the length of the filenames at bay so not to
252 increase the limited length of the PATH envvar.
253 Another and more important reason, however, is that
254 the very first GPG versions on W32 were installed
255 into a flat directory structure and for best
256 compatibility with these versions we didn't changed
257 that later. For WindowsCE we can right away install
258 it under bin, though. The hack with detection of the
259 bin directory part allows us to eventually migrate to
260 such a directory layout under plain Windows without
261 the need to change libgpg-error. */
262 p = strrchr (result, '\\');
263 if (p && !strcmp (p+1, "bin"))
265 /* Append the static part. */
266 strcat (result, SLDIR);
270 else /* Use the old default value. */
272 result = malloc (10 + strlen (SLDIR) + 1);
275 strcpy (result, "c:\\gnupg");
276 strcat (result, SLDIR);
285 drop_locale_dir (char *locale_dir)
291 /* Return the tls object. This function is guaranteed to return a
292 valid non-NULL object. */
296 struct tls_space_s *tls;
298 tls = TlsGetValue (tls_index);
301 /* Called by a thread which existed before this DLL was loaded.
302 Allocate the space. */
303 tls = LocalAlloc (LPTR, sizeof *tls);
306 /* No way to continue - commit suicide. */
309 tls->gt_use_utf8 = 0;
310 TlsSetValue (tls_index, tls);
317 /* Return the value of the ERRNO variable. This needs to be a
318 function so that we can have a per-thread ERRNO. This is used only
319 on WindowsCE because that OS misses an errno. */
320 #ifdef HAVE_W32CE_SYSTEM
322 _gpg_w32ce_get_errno (void)
324 return map_w32codes ( GetLastError () );
326 #endif /*HAVE_W32CE_SYSTEM*/
329 /* Replacement strerror function for WindowsCE. */
330 #ifdef HAVE_W32CE_SYSTEM
332 _gpg_w32ce_strerror (int err)
334 struct tls_space_s *tls = get_tls ();
335 wchar_t tmpbuf[STRBUFFER_SIZE];
339 err = _gpg_w32ce_get_errno ();
341 /* Note: On a German HTC Touch Pro2 device I also tried
342 LOCALE_USER_DEFAULT and LOCALE_SYSTEM_DEFAULT - both returned
344 if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
345 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
346 tmpbuf, STRBUFFER_SIZE -1,
349 n = WideCharToMultiByte (CP_UTF8, 0, tmpbuf, -1,
350 tls->strerror_buffer,
351 sizeof tls->strerror_buffer -1,
358 snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1,
360 return tls->strerror_buffer;
362 #endif /*HAVE_W32CE_SYSTEM*/
366 gpg_err_set_errno (int err)
368 #ifdef HAVE_W32CE_SYSTEM
370 #else /*!HAVE_W32CE_SYSTEM*/
372 #endif /*!HAVE_W32CE_SYSTEM*/
376 /* Entry point called by the DLL loader. */
379 DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
381 struct tls_space_s *tls;
386 case DLL_PROCESS_ATTACH:
387 tls_index = TlsAlloc ();
388 if (tls_index == TLS_OUT_OF_INDEXES)
390 #ifndef _GPG_ERR_HAVE_CONSTRUCTOR
391 /* If we have not constructors (e.g. MSC) we call it here. */
392 _gpg_w32__init_gettext_module ();
395 case DLL_THREAD_ATTACH:
396 tls = LocalAlloc (LPTR, sizeof *tls);
399 tls->gt_use_utf8 = 0;
400 TlsSetValue (tls_index, tls);
401 if (reason == DLL_PROCESS_ATTACH)
407 case DLL_THREAD_DETACH:
408 tls = TlsGetValue (tls_index);
413 case DLL_PROCESS_DETACH:
414 tls = TlsGetValue (tls_index);
426 #endif /*DLL_EXPORT*/
428 #else /*!HAVE_W32_SYSTEM*/
431 gpg_err_set_errno (int err)
436 #endif /*!HAVE_W32_SYSTEM*/