LCOV - code coverage report
Current view: top level - src - init.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 28 71.4 %
Date: 2016-12-21 11:11:56 Functions: 5 7 71.4 %

          Line data    Source code
       1             : /* init.c - Initialize the GnuPG error library.
       2             :    Copyright (C) 2005, 2010 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 this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #if HAVE_CONFIG_H
      21             : #include <config.h>
      22             : #endif
      23             : 
      24             : #include <stdlib.h>
      25             : #include <stdio.h>
      26             : #include <string.h>
      27             : #include <errno.h>
      28             : 
      29             : #include "gpgrt-int.h"
      30             : #include "gettext.h"
      31             : #include "init.h"
      32             : 
      33             : #ifdef HAVE_W32CE_SYSTEM
      34             : # include "mkw32errmap.map.c"  /* Generated map_w32codes () */
      35             : # ifndef TLS_OUT_OF_INDEXES
      36             : #  define TLS_OUT_OF_INDEXES 0xFFFFFFFF
      37             : # endif
      38             : # ifndef __MINGW32CE__
      39             : #  /* Replace the Mingw32CE provided abort function.  */
      40             : #  define abort() do { TerminateProcess (GetCurrentProcess(), 8); } while (0)
      41             : # endif
      42             : #endif
      43             : 
      44             : 
      45             : /* Locale directory support.  */
      46             : 
      47             : #if HAVE_W32_SYSTEM
      48             : 
      49             : #include <windows.h>
      50             : 
      51             : static int tls_index = TLS_OUT_OF_INDEXES;  /* Index for the TLS functions.  */
      52             : 
      53             : static char *get_locale_dir (void);
      54             : static void drop_locale_dir (char *locale_dir);
      55             : 
      56             : #else /*!HAVE_W32_SYSTEM*/
      57             : 
      58             : #define get_locale_dir() LOCALEDIR
      59             : #define drop_locale_dir(dir)
      60             : 
      61             : #endif /*!HAVE_W32_SYSTEM*/
      62             : 
      63             : 
      64             : /* The realloc function as set by gpgrt_set_alloc_func.  */
      65             : static void *(*custom_realloc)(void *a, size_t n);
      66             : 
      67             : 
      68             : 
      69             : static void
      70             : real_init (void)
      71             : {
      72             : #ifdef ENABLE_NLS
      73             :   char *locale_dir;
      74             : 
      75             :   /* We only have to bind our locale directory to our text domain.  */
      76             :   locale_dir = get_locale_dir ();
      77             :   if (locale_dir)
      78             :     {
      79           6 :       bindtextdomain (PACKAGE, locale_dir);
      80             :       drop_locale_dir (locale_dir);
      81             :     }
      82             : #endif
      83           6 :   _gpgrt_es_init ();
      84             : }
      85             : 
      86             : /* Initialize the library.  This function should be run early.  */
      87             : gpg_error_t
      88           6 : _gpg_err_init (void)
      89             : {
      90             : #ifdef HAVE_W32_SYSTEM
      91             : # ifdef DLL_EXPORT
      92             :   /* We always have a constructor and thus this function is called
      93             :      automatically.  Due to the way the C init code of mingw works,
      94             :      the constructors are called before our DllMain function is
      95             :      called.  The problem with that is that the TLS has not been setup
      96             :      and w32-gettext.c requires TLS.  To solve this we do nothing here
      97             :      but call the actual init code from our DllMain.  */
      98             : # else /*!DLL_EXPORT*/
      99             :   /* Note that if the TLS is actually used, we can't release the TLS
     100             :      as there is no way to know when a thread terminates (i.e. no
     101             :      thread-specific-atexit).  You are really better off to use the
     102             :      DLL! */
     103             :   if (tls_index == TLS_OUT_OF_INDEXES)
     104             :     {
     105             :       tls_index = TlsAlloc ();
     106             :       if (tls_index == TLS_OUT_OF_INDEXES)
     107             :         {
     108             :           /* No way to continue - commit suicide.  */
     109             :           abort ();
     110             :         }
     111             :       _gpg_w32__init_gettext_module ();
     112             :       real_init ();
     113             :     }
     114             : # endif /*!DLL_EXPORT*/
     115             : #else
     116             :   real_init ();
     117             : #endif
     118           6 :   return 0;
     119             : }
     120             : 
     121             : 
     122             : /* Deinitialize libgpg-error.  This function is only used in special
     123             :    circumstances.  No gpg-error function should be used after this
     124             :    function has been called.  A value of 0 passed for MODE
     125             :    deinitializes the entire libgpg-error, a value of 1 releases
     126             :    resources allocated for the current thread and only that thread may
     127             :    not anymore access libgpg-error after such a call.  Under Windows
     128             :    this function may be called from the DllMain function of a DLL
     129             :    which statically links to libgpg-error.  */
     130             : void
     131           0 : _gpg_err_deinit (int mode)
     132             : {
     133             : #if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT)
     134             :   struct tls_space_s *tls;
     135             : 
     136             :   tls = TlsGetValue (tls_index);
     137             :   if (tls)
     138             :     {
     139             :       TlsSetValue (tls_index, NULL);
     140             :       LocalFree (tls);
     141             :     }
     142             : 
     143             :   if (mode == 0)
     144             :     {
     145             :       TlsFree (tls_index);
     146             :       tls_index = TLS_OUT_OF_INDEXES;
     147             :     }
     148             : #else
     149             :   (void)mode;
     150             : #endif
     151           0 : }
     152             : 
     153             : 
     154             : 
     155             : 
     156             : /* Register F as allocation function.  This function is used for all
     157             :    APIs which return an allocated buffer.  F needs to have standard
     158             :    realloc semantics.  It should be called as early as possible and
     159             :    not changed later. */
     160             : void
     161           0 : _gpgrt_set_alloc_func (void *(*f)(void *a, size_t n))
     162             : {
     163           0 :   custom_realloc = f;
     164           0 : }
     165             : 
     166             : 
     167             : /* The realloc to be used for data returned by the public API.  */
     168             : void *
     169         501 : _gpgrt_realloc (void *a, size_t n)
     170             : {
     171         501 :   if (custom_realloc)
     172           0 :     return custom_realloc (a, n);
     173             : 
     174         501 :   if (!n)
     175             :     {
     176         171 :       free (a);
     177         171 :       return NULL;
     178             :     }
     179             : 
     180         330 :   if (!a)
     181         330 :     return malloc (n);
     182             : 
     183           0 :   return realloc (a, n);
     184             : }
     185             : 
     186             : 
     187             : /* The malloc to be used for data returned by the public API.  */
     188             : void *
     189          24 : _gpgrt_malloc (size_t n)
     190             : {
     191          24 :   if (!n)
     192           0 :     n++;
     193          24 :   return _gpgrt_realloc (NULL, n);
     194             : }
     195             : 
     196             : 
     197             : /* The free to be used for data returned by the public API.  */
     198             : void
     199         171 : _gpgrt_free (void *a)
     200             : {
     201         171 :   _gpgrt_realloc (a, 0);
     202         171 : }
     203             : 
     204             : 
     205             : void
     206           1 : _gpg_err_set_errno (int err)
     207             : {
     208             : #ifdef HAVE_W32CE_SYSTEM
     209             :   SetLastError (err);
     210             : #else /*!HAVE_W32CE_SYSTEM*/
     211           1 :   errno = err;
     212             : #endif /*!HAVE_W32CE_SYSTEM*/
     213           1 : }
     214             : 
     215             : 
     216             : 
     217             : #ifdef HAVE_W32_SYSTEM
     218             : /*****************************************
     219             :  ******** Below is only Windows code. ****
     220             :  *****************************************/
     221             : 
     222             : static char *
     223             : get_locale_dir (void)
     224             : {
     225             :   static wchar_t moddir[MAX_PATH+5];
     226             :   char *result, *p;
     227             :   int nbytes;
     228             : 
     229             :   if (!GetModuleFileNameW (NULL, moddir, MAX_PATH))
     230             :     *moddir = 0;
     231             : 
     232             : #define SLDIR "\\share\\locale"
     233             :   if (*moddir)
     234             :     {
     235             :       nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL);
     236             :       if (nbytes < 0)
     237             :         return NULL;
     238             : 
     239             :       result = malloc (nbytes + strlen (SLDIR) + 1);
     240             :       if (result)
     241             :         {
     242             :           nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1,
     243             :                                         result, nbytes, NULL, NULL);
     244             :           if (nbytes < 0)
     245             :             {
     246             :               free (result);
     247             :               result = NULL;
     248             :             }
     249             :           else
     250             :             {
     251             :               p = strrchr (result, '\\');
     252             :               if (p)
     253             :                 *p = 0;
     254             :               /* If we are installed below "bin" strip that part and
     255             :                  use the top directory instead.
     256             : 
     257             :                  Background: Under Windows we don't install GnuPG
     258             :                  below bin/ but in the top directory with only share/,
     259             :                  lib/, and etc/ below it.  One of the reasons is to
     260             :                  keep the the length of the filenames at bay so not to
     261             :                  increase the limited length of the PATH envvar.
     262             :                  Another and more important reason, however, is that
     263             :                  the very first GPG versions on W32 were installed
     264             :                  into a flat directory structure and for best
     265             :                  compatibility with these versions we didn't changed
     266             :                  that later.  For WindowsCE we can right away install
     267             :                  it under bin, though.  The hack with detection of the
     268             :                  bin directory part allows us to eventually migrate to
     269             :                  such a directory layout under plain Windows without
     270             :                  the need to change libgpg-error.  */
     271             :               p = strrchr (result, '\\');
     272             :               if (p && !strcmp (p+1, "bin"))
     273             :                 *p = 0;
     274             :               /* Append the static part.  */
     275             :               strcat (result, SLDIR);
     276             :             }
     277             :         }
     278             :     }
     279             :   else /* Use the old default value.  */
     280             :     {
     281             :       result = malloc (10 + strlen (SLDIR) + 1);
     282             :       if (result)
     283             :         {
     284             :           strcpy (result, "c:\\gnupg");
     285             :           strcat (result, SLDIR);
     286             :         }
     287             :     }
     288             : #undef SLDIR
     289             :   return result;
     290             : }
     291             : 
     292             : 
     293             : static void
     294             : drop_locale_dir (char *locale_dir)
     295             : {
     296             :   free (locale_dir);
     297             : }
     298             : 
     299             : 
     300             : /* Return the tls object.  This function is guaranteed to return a
     301             :    valid non-NULL object.  */
     302             : struct tls_space_s *
     303             : get_tls (void)
     304             : {
     305             :   struct tls_space_s *tls;
     306             : 
     307             :   tls = TlsGetValue (tls_index);
     308             :   if (!tls)
     309             :     {
     310             :       /* Called by a thread which existed before this DLL was loaded.
     311             :          Allocate the space.  */
     312             :       tls = LocalAlloc (LPTR, sizeof *tls);
     313             :       if (!tls)
     314             :         {
     315             :           /* No way to continue - commit suicide.  */
     316             :           abort ();
     317             :         }
     318             :       tls->gt_use_utf8 = 0;
     319             :       TlsSetValue (tls_index, tls);
     320             :     }
     321             : 
     322             :   return tls;
     323             : }
     324             : 
     325             : 
     326             : /* Return the value of the ERRNO variable.  This needs to be a
     327             :    function so that we can have a per-thread ERRNO.  This is used only
     328             :    on WindowsCE because that OS misses an errno.   */
     329             : #ifdef HAVE_W32CE_SYSTEM
     330             : int
     331             : _gpg_w32ce_get_errno (void)
     332             : {
     333             :   return map_w32codes ( GetLastError () );
     334             : }
     335             : #endif /*HAVE_W32CE_SYSTEM*/
     336             : 
     337             : 
     338             : /* Replacement strerror function for WindowsCE.  */
     339             : #ifdef HAVE_W32CE_SYSTEM
     340             : char *
     341             : _gpg_w32ce_strerror (int err)
     342             : {
     343             :   struct tls_space_s *tls = get_tls ();
     344             :   wchar_t tmpbuf[STRBUFFER_SIZE];
     345             :   int n;
     346             : 
     347             :   if (err == -1)
     348             :     err = _gpg_w32ce_get_errno ();
     349             : 
     350             :   /* Note: On a German HTC Touch Pro2 device I also tried
     351             :      LOCALE_USER_DEFAULT and LOCALE_SYSTEM_DEFAULT - both returned
     352             :      English messages.  */
     353             :   if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
     354             :                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
     355             :                       tmpbuf, STRBUFFER_SIZE -1,
     356             :                       NULL))
     357             :     {
     358             :       n = WideCharToMultiByte (CP_UTF8, 0, tmpbuf, -1,
     359             :                                tls->strerror_buffer,
     360             :                                sizeof tls->strerror_buffer -1,
     361             :                                NULL, NULL);
     362             :     }
     363             :   else
     364             :     n = -1;
     365             : 
     366             :   if (n < 0)
     367             :     snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1,
     368             :               "[w32err=%d]", err);
     369             :   return tls->strerror_buffer;
     370             : }
     371             : #endif /*HAVE_W32CE_SYSTEM*/
     372             : 
     373             : 
     374             : /* Entry point called by the DLL loader.  */
     375             : #ifdef DLL_EXPORT
     376             : int WINAPI
     377             : DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
     378             : {
     379             :   struct tls_space_s *tls;
     380             :   (void)reserved;
     381             :   (void)hinst;
     382             : 
     383             :   switch (reason)
     384             :     {
     385             :     case DLL_PROCESS_ATTACH:
     386             :       tls_index = TlsAlloc ();
     387             :       if (tls_index == TLS_OUT_OF_INDEXES)
     388             :         return FALSE;
     389             : #ifndef _GPG_ERR_HAVE_CONSTRUCTOR
     390             :       /* If we have not constructors (e.g. MSC) we call it here.  */
     391             :       _gpg_w32__init_gettext_module ();
     392             : #endif
     393             :       /* falltru.  */
     394             :     case DLL_THREAD_ATTACH:
     395             :       tls = LocalAlloc (LPTR, sizeof *tls);
     396             :       if (!tls)
     397             :         return FALSE;
     398             :       tls->gt_use_utf8 = 0;
     399             :       TlsSetValue (tls_index, tls);
     400             :       if (reason == DLL_PROCESS_ATTACH)
     401             :         {
     402             :           real_init ();
     403             :         }
     404             :       break;
     405             : 
     406             :     case DLL_THREAD_DETACH:
     407             :       tls = TlsGetValue (tls_index);
     408             :       if (tls)
     409             :         LocalFree (tls);
     410             :       break;
     411             : 
     412             :     case DLL_PROCESS_DETACH:
     413             :       tls = TlsGetValue (tls_index);
     414             :       if (tls)
     415             :         LocalFree (tls);
     416             :       TlsFree (tls_index);
     417             :       break;
     418             : 
     419             :     default:
     420             :       break;
     421             :     }
     422             : 
     423             :   return TRUE;
     424             : }
     425             : #endif /*DLL_EXPORT*/
     426             : 
     427             : #endif /*HAVE_W32_SYSTEM*/

Generated by: LCOV version 1.12