Blame src/init.c

Packit fc043f
/* init.c - Initialize the GnuPG error library.
Packit fc043f
   Copyright (C) 2005, 2010 g10 Code GmbH
Packit fc043f
Packit fc043f
   This file is part of libgpg-error.
Packit fc043f
Packit fc043f
   libgpg-error is free software; you can redistribute it and/or
Packit fc043f
   modify it under the terms of the GNU Lesser General Public License
Packit fc043f
   as published by the Free Software Foundation; either version 2.1 of
Packit fc043f
   the License, or (at your option) any later version.
Packit fc043f
Packit fc043f
   libgpg-error is distributed in the hope that it will be useful, but
Packit fc043f
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit fc043f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit fc043f
   Lesser General Public License for more details.
Packit fc043f
Packit fc043f
   You should have received a copy of the GNU Lesser General Public
Packit fc043f
   License along with this program; if not, see <https://www.gnu.org/licenses/>.
Packit fc043f
 */
Packit fc043f
Packit fc043f
#if HAVE_CONFIG_H
Packit fc043f
#include <config.h>
Packit fc043f
#endif
Packit fc043f
Packit fc043f
#include <stdlib.h>
Packit fc043f
#include <stdio.h>
Packit fc043f
#include <string.h>
Packit fc043f
#include <errno.h>
Packit fc043f
Packit fc043f
#include "gpgrt-int.h"
Packit fc043f
#include "gettext.h"
Packit fc043f
#include "init.h"
Packit fc043f
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
# include "mkw32errmap.map.c"  /* Generated map_w32codes () */
Packit fc043f
# ifndef TLS_OUT_OF_INDEXES
Packit fc043f
#  define TLS_OUT_OF_INDEXES 0xFFFFFFFF
Packit fc043f
# endif
Packit fc043f
# ifndef __MINGW32CE__
Packit fc043f
#  /* Replace the Mingw32CE provided abort function.  */
Packit fc043f
#  define abort() do { TerminateProcess (GetCurrentProcess(), 8); } while (0)
Packit fc043f
# endif
Packit fc043f
#endif
Packit fc043f
Packit fc043f

Packit fc043f
/* Locale directory support.  */
Packit fc043f
Packit fc043f
#if HAVE_W32_SYSTEM
Packit fc043f
Packit fc043f
#include <windows.h>
Packit fc043f
Packit fc043f
static int tls_index = TLS_OUT_OF_INDEXES;  /* Index for the TLS functions.  */
Packit fc043f
Packit fc043f
static char *get_locale_dir (void);
Packit fc043f
static void drop_locale_dir (char *locale_dir);
Packit fc043f
Packit fc043f
#else /*!HAVE_W32_SYSTEM*/
Packit fc043f
Packit fc043f
#define get_locale_dir() LOCALEDIR
Packit fc043f
#define drop_locale_dir(dir)
Packit fc043f
Packit fc043f
#endif /*!HAVE_W32_SYSTEM*/
Packit fc043f
Packit fc043f
Packit fc043f
/* The realloc function as set by gpgrt_set_alloc_func.  */
Packit fc043f
static void *(*custom_realloc)(void *a, size_t n);
Packit fc043f
Packit fc043f
Packit fc043f

Packit fc043f
static void
Packit fc043f
real_init (void)
Packit fc043f
{
Packit fc043f
#ifdef ENABLE_NLS
Packit fc043f
  char *locale_dir;
Packit fc043f
Packit fc043f
  /* We only have to bind our locale directory to our text domain.  */
Packit fc043f
  locale_dir = get_locale_dir ();
Packit fc043f
  if (locale_dir)
Packit fc043f
    {
Packit fc043f
      bindtextdomain (PACKAGE, locale_dir);
Packit fc043f
      drop_locale_dir (locale_dir);
Packit fc043f
    }
Packit fc043f
#endif
Packit fc043f
  _gpgrt_estream_init ();
Packit fc043f
}
Packit fc043f
Packit fc043f
/* Initialize the library.  This function should be run early.  */
Packit fc043f
gpg_error_t
Packit fc043f
_gpg_err_init (void)
Packit fc043f
{
Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
# ifdef DLL_EXPORT
Packit fc043f
  /* We always have a constructor and thus this function is called
Packit fc043f
     automatically.  Due to the way the C init code of mingw works,
Packit fc043f
     the constructors are called before our DllMain function is
Packit fc043f
     called.  The problem with that is that the TLS has not been setup
Packit fc043f
     and w32-gettext.c requires TLS.  To solve this we do nothing here
Packit fc043f
     but call the actual init code from our DllMain.  */
Packit fc043f
# else /*!DLL_EXPORT*/
Packit fc043f
  /* Note that if the TLS is actually used, we can't release the TLS
Packit fc043f
     as there is no way to know when a thread terminates (i.e. no
Packit fc043f
     thread-specific-atexit).  You are really better off to use the
Packit fc043f
     DLL! */
Packit fc043f
  if (tls_index == TLS_OUT_OF_INDEXES)
Packit fc043f
    {
Packit fc043f
      tls_index = TlsAlloc ();
Packit fc043f
      if (tls_index == TLS_OUT_OF_INDEXES)
Packit fc043f
        {
Packit fc043f
          /* No way to continue - commit suicide.  */
Packit fc043f
          abort ();
Packit fc043f
        }
Packit fc043f
      _gpg_w32__init_gettext_module ();
Packit fc043f
      real_init ();
Packit fc043f
    }
Packit fc043f
# endif /*!DLL_EXPORT*/
Packit fc043f
#else
Packit fc043f
  real_init ();
Packit fc043f
#endif
Packit fc043f
  return 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Deinitialize libgpg-error.  This function is only used in special
Packit fc043f
   circumstances.  No gpg-error function should be used after this
Packit fc043f
   function has been called.  A value of 0 passed for MODE
Packit fc043f
   deinitializes the entire libgpg-error, a value of 1 releases
Packit fc043f
   resources allocated for the current thread and only that thread may
Packit fc043f
   not anymore access libgpg-error after such a call.  Under Windows
Packit fc043f
   this function may be called from the DllMain function of a DLL
Packit fc043f
   which statically links to libgpg-error.  */
Packit fc043f
void
Packit fc043f
_gpg_err_deinit (int mode)
Packit fc043f
{
Packit fc043f
#if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT)
Packit fc043f
  struct tls_space_s *tls;
Packit fc043f
Packit fc043f
  tls = TlsGetValue (tls_index);
Packit fc043f
  if (tls)
Packit fc043f
    {
Packit fc043f
      TlsSetValue (tls_index, NULL);
Packit fc043f
      LocalFree (tls);
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (mode == 0)
Packit fc043f
    {
Packit fc043f
      TlsFree (tls_index);
Packit fc043f
      tls_index = TLS_OUT_OF_INDEXES;
Packit fc043f
    }
Packit fc043f
#else
Packit fc043f
  (void)mode;
Packit fc043f
#endif
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
Packit fc043f
Packit fc043f
/* Register F as allocation function.  This function is used for all
Packit fc043f
   APIs which return an allocated buffer.  F needs to have standard
Packit fc043f
   realloc semantics.  It should be called as early as possible and
Packit fc043f
   not changed later. */
Packit fc043f
void
Packit fc043f
_gpgrt_set_alloc_func (void *(*f)(void *a, size_t n))
Packit fc043f
{
Packit fc043f
  custom_realloc = f;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* The realloc to be used for data returned by the public API.  */
Packit fc043f
void *
Packit fc043f
_gpgrt_realloc (void *a, size_t n)
Packit fc043f
{
Packit fc043f
  if (custom_realloc)
Packit fc043f
    return custom_realloc (a, n);
Packit fc043f
Packit fc043f
  if (!n)
Packit fc043f
    {
Packit fc043f
      free (a);
Packit fc043f
      return NULL;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  if (!a)
Packit fc043f
    return malloc (n);
Packit fc043f
Packit fc043f
  return realloc (a, n);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* The malloc to be used for data returned by the public API.  */
Packit fc043f
void *
Packit fc043f
_gpgrt_malloc (size_t n)
Packit fc043f
{
Packit fc043f
  if (!n)
Packit fc043f
    n++;
Packit fc043f
  return _gpgrt_realloc (NULL, n);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void *
Packit fc043f
_gpgrt_calloc (size_t n, size_t m)
Packit fc043f
{
Packit fc043f
  size_t bytes;
Packit fc043f
  void *p;
Packit fc043f
Packit fc043f
  bytes = n * m; /* size_t is unsigned so the behavior on overflow is
Packit fc043f
                    defined. */
Packit fc043f
  if (m && bytes / m != n)
Packit fc043f
    {
Packit fc043f
      _gpg_err_set_errno (ENOMEM);
Packit fc043f
      return NULL;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  p = _gpgrt_realloc (NULL, bytes);
Packit fc043f
  if (p)
Packit fc043f
    memset (p, 0, bytes);
Packit fc043f
  return p;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
char *
Packit fc043f
_gpgrt_strdup (const char *string)
Packit fc043f
{
Packit fc043f
  size_t len = strlen (string);
Packit fc043f
  char *p;
Packit fc043f
Packit fc043f
  p = _gpgrt_realloc (NULL, len + 1);
Packit fc043f
  if (p)
Packit fc043f
    strcpy (p, string);
Packit fc043f
  return p;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Helper for _gpgrt_strconcat and gpgrt_strconcat.  */
Packit fc043f
char *
Packit fc043f
_gpgrt_strconcat_core (const char *s1, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  const char *argv[48];
Packit fc043f
  size_t argc;
Packit fc043f
  size_t needed;
Packit fc043f
  char *buffer, *p;
Packit fc043f
Packit fc043f
  argc = 0;
Packit fc043f
  argv[argc++] = s1;
Packit fc043f
  needed = strlen (s1);
Packit fc043f
  while (((argv[argc] = va_arg (arg_ptr, const char *))))
Packit fc043f
    {
Packit fc043f
      needed += strlen (argv[argc]);
Packit fc043f
      if (argc >= DIM (argv)-1)
Packit fc043f
        {
Packit fc043f
          _gpg_err_set_errno (EINVAL);
Packit fc043f
          return NULL;
Packit fc043f
        }
Packit fc043f
      argc++;
Packit fc043f
    }
Packit fc043f
  needed++;
Packit fc043f
  buffer = _gpgrt_malloc (needed);
Packit fc043f
  if (buffer)
Packit fc043f
    {
Packit fc043f
      for (p = buffer, argc=0; argv[argc]; argc++)
Packit fc043f
        p = stpcpy (p, argv[argc]);
Packit fc043f
    }
Packit fc043f
  return buffer;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
char *
Packit fc043f
_gpgrt_strconcat (const char *s1, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
  char *result;
Packit fc043f
Packit fc043f
  if (!s1)
Packit fc043f
    result = _gpgrt_strdup ("");
Packit fc043f
  else
Packit fc043f
    {
Packit fc043f
      va_start (arg_ptr, s1);
Packit fc043f
      result = _gpgrt_strconcat_core (s1, arg_ptr);
Packit fc043f
      va_end (arg_ptr);
Packit fc043f
    }
Packit fc043f
  return result;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* The free to be used for data returned by the public API.  */
Packit fc043f
void
Packit fc043f
_gpgrt_free (void *a)
Packit fc043f
{
Packit fc043f
  _gpgrt_realloc (a, 0);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpg_err_set_errno (int err)
Packit fc043f
{
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
  SetLastError (err);
Packit fc043f
#else /*!HAVE_W32CE_SYSTEM*/
Packit fc043f
  errno = err;
Packit fc043f
#endif /*!HAVE_W32CE_SYSTEM*/
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f

Packit fc043f
/* Internal tracing functions.  Except for TRACE_FP we use flockfile
Packit fc043f
 * and funlockfile to protect their use.
Packit fc043f
 *
Packit fc043f
 * Warning: Take care with the trace functions - they may not use any
Packit fc043f
 * of our services, in particular not the syscall clamp mechanism for
Packit fc043f
 * reasons explained in w32-stream.c:create_reader.  */
Packit fc043f
static FILE *trace_fp;
Packit fc043f
static int trace_save_errno;
Packit fc043f
static int trace_with_errno;
Packit fc043f
static const char *trace_arg_module;
Packit fc043f
static const char *trace_arg_file;
Packit fc043f
static int trace_arg_line;
Packit fc043f
static int trace_missing_lf;
Packit fc043f
static int trace_prefix_done;
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_internal_trace_begin (const char *module, const char *file, int line,
Packit fc043f
                             int with_errno)
Packit fc043f
{
Packit fc043f
  int save_errno = errno;
Packit fc043f
Packit fc043f
  if (!trace_fp)
Packit fc043f
    {
Packit fc043f
      FILE *fp;
Packit fc043f
      const char *s = getenv ("GPGRT_TRACE_FILE");
Packit fc043f
Packit fc043f
      if (!s || !(fp = fopen (s, "wb")))
Packit fc043f
        fp = stderr;
Packit fc043f
      trace_fp = fp;
Packit fc043f
    }
Packit fc043f
Packit fc043f
#ifdef HAVE_FLOCKFILE
Packit fc043f
  flockfile (trace_fp);
Packit fc043f
#endif
Packit fc043f
  trace_save_errno = save_errno;
Packit fc043f
  trace_with_errno = with_errno;
Packit fc043f
  trace_arg_module = module;
Packit fc043f
  trace_arg_file = file;
Packit fc043f
  trace_arg_line = line;
Packit fc043f
  trace_missing_lf = 0;
Packit fc043f
  trace_prefix_done = 0;
Packit fc043f
}
Packit fc043f
Packit fc043f
static void
Packit fc043f
print_internal_trace_prefix (void)
Packit fc043f
{
Packit fc043f
  if (!trace_prefix_done)
Packit fc043f
    {
Packit fc043f
      trace_prefix_done = 1;
Packit fc043f
      fprintf (trace_fp, "%s:%s:%d: ",
Packit fc043f
               trace_arg_module,/* npth_is_protected ()?"":"^",*/
Packit fc043f
               trace_arg_file, trace_arg_line);
Packit fc043f
    }
Packit fc043f
}
Packit fc043f
Packit fc043f
static void
Packit fc043f
do_internal_trace (const char *format, va_list arg_ptr)
Packit fc043f
{
Packit fc043f
  print_internal_trace_prefix ();
Packit fc043f
  vfprintf (trace_fp, format, arg_ptr);
Packit fc043f
  if (trace_with_errno)
Packit fc043f
    fprintf (trace_fp, " errno=%s", strerror (trace_save_errno));
Packit fc043f
  if (*format && format[strlen(format)-1] != '\n')
Packit fc043f
    fputc ('\n', trace_fp);
Packit fc043f
}
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_internal_trace_printf (const char *format, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  print_internal_trace_prefix ();
Packit fc043f
  va_start (arg_ptr, format) ;
Packit fc043f
  vfprintf (trace_fp, format, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
  trace_missing_lf = (*format && format[strlen(format)-1] != '\n');
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_internal_trace (const char *format, ...)
Packit fc043f
{
Packit fc043f
  va_list arg_ptr;
Packit fc043f
Packit fc043f
  va_start (arg_ptr, format) ;
Packit fc043f
  do_internal_trace (format, arg_ptr);
Packit fc043f
  va_end (arg_ptr);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
void
Packit fc043f
_gpgrt_internal_trace_end (void)
Packit fc043f
{
Packit fc043f
  int save_errno = trace_save_errno;
Packit fc043f
Packit fc043f
  if (trace_missing_lf)
Packit fc043f
    fputc ('\n', trace_fp);
Packit fc043f
#ifdef HAVE_FLOCKFILE
Packit fc043f
  funlockfile (trace_fp);
Packit fc043f
#endif
Packit fc043f
  errno = save_errno;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f

Packit fc043f
#ifdef HAVE_W32_SYSTEM
Packit fc043f
/*****************************************
Packit fc043f
 ******** Below is only Windows code. ****
Packit fc043f
 *****************************************/
Packit fc043f
Packit fc043f
static char *
Packit fc043f
get_locale_dir (void)
Packit fc043f
{
Packit fc043f
  static wchar_t moddir[MAX_PATH+5];
Packit fc043f
  char *result, *p;
Packit fc043f
  int nbytes;
Packit fc043f
Packit fc043f
  if (!GetModuleFileNameW (NULL, moddir, MAX_PATH))
Packit fc043f
    *moddir = 0;
Packit fc043f
Packit fc043f
#define SLDIR "\\share\\locale"
Packit fc043f
  if (*moddir)
Packit fc043f
    {
Packit fc043f
      nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL);
Packit fc043f
      if (nbytes < 0)
Packit fc043f
        return NULL;
Packit fc043f
Packit fc043f
      result = malloc (nbytes + strlen (SLDIR) + 1);
Packit fc043f
      if (result)
Packit fc043f
        {
Packit fc043f
          nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1,
Packit fc043f
                                        result, nbytes, NULL, NULL);
Packit fc043f
          if (nbytes < 0)
Packit fc043f
            {
Packit fc043f
              free (result);
Packit fc043f
              result = NULL;
Packit fc043f
            }
Packit fc043f
          else
Packit fc043f
            {
Packit fc043f
              p = strrchr (result, '\\');
Packit fc043f
              if (p)
Packit fc043f
                *p = 0;
Packit fc043f
              /* If we are installed below "bin" strip that part and
Packit fc043f
                 use the top directory instead.
Packit fc043f
Packit fc043f
                 Background: Under Windows we don't install GnuPG
Packit fc043f
                 below bin/ but in the top directory with only share/,
Packit fc043f
                 lib/, and etc/ below it.  One of the reasons is to
Packit fc043f
                 keep the the length of the filenames at bay so not to
Packit fc043f
                 increase the limited length of the PATH envvar.
Packit fc043f
                 Another and more important reason, however, is that
Packit fc043f
                 the very first GPG versions on W32 were installed
Packit fc043f
                 into a flat directory structure and for best
Packit fc043f
                 compatibility with these versions we didn't changed
Packit fc043f
                 that later.  For WindowsCE we can right away install
Packit fc043f
                 it under bin, though.  The hack with detection of the
Packit fc043f
                 bin directory part allows us to eventually migrate to
Packit fc043f
                 such a directory layout under plain Windows without
Packit fc043f
                 the need to change libgpg-error.  */
Packit fc043f
              p = strrchr (result, '\\');
Packit fc043f
              if (p && !strcmp (p+1, "bin"))
Packit fc043f
                *p = 0;
Packit fc043f
              /* Append the static part.  */
Packit fc043f
              strcat (result, SLDIR);
Packit fc043f
            }
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
  else /* Use the old default value.  */
Packit fc043f
    {
Packit fc043f
      result = malloc (10 + strlen (SLDIR) + 1);
Packit fc043f
      if (result)
Packit fc043f
        {
Packit fc043f
          strcpy (result, "c:\\gnupg");
Packit fc043f
          strcat (result, SLDIR);
Packit fc043f
        }
Packit fc043f
    }
Packit fc043f
#undef SLDIR
Packit fc043f
  return result;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
static void
Packit fc043f
drop_locale_dir (char *locale_dir)
Packit fc043f
{
Packit fc043f
  free (locale_dir);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Return the tls object.  This function is guaranteed to return a
Packit fc043f
   valid non-NULL object.  */
Packit fc043f
struct tls_space_s *
Packit fc043f
get_tls (void)
Packit fc043f
{
Packit fc043f
  struct tls_space_s *tls;
Packit fc043f
Packit fc043f
  tls = TlsGetValue (tls_index);
Packit fc043f
  if (!tls)
Packit fc043f
    {
Packit fc043f
      /* Called by a thread which existed before this DLL was loaded.
Packit fc043f
         Allocate the space.  */
Packit fc043f
      tls = LocalAlloc (LPTR, sizeof *tls);
Packit fc043f
      if (!tls)
Packit fc043f
        {
Packit fc043f
          /* No way to continue - commit suicide.  */
Packit fc043f
          abort ();
Packit fc043f
        }
Packit fc043f
      tls->gt_use_utf8 = 0;
Packit fc043f
      TlsSetValue (tls_index, tls);
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return tls;
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
/* Return the value of the ERRNO variable.  This needs to be a
Packit fc043f
   function so that we can have a per-thread ERRNO.  This is used only
Packit fc043f
   on WindowsCE because that OS misses an errno.   */
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
int
Packit fc043f
_gpg_w32ce_get_errno (void)
Packit fc043f
{
Packit fc043f
  return map_w32codes ( GetLastError () );
Packit fc043f
}
Packit fc043f
#endif /*HAVE_W32CE_SYSTEM*/
Packit fc043f
Packit fc043f
Packit fc043f
/* Replacement strerror function for WindowsCE.  */
Packit fc043f
#ifdef HAVE_W32CE_SYSTEM
Packit fc043f
char *
Packit fc043f
_gpg_w32ce_strerror (int err)
Packit fc043f
{
Packit fc043f
  struct tls_space_s *tls = get_tls ();
Packit fc043f
  wchar_t tmpbuf[STRBUFFER_SIZE];
Packit fc043f
  int n;
Packit fc043f
Packit fc043f
  if (err == -1)
Packit fc043f
    err = _gpg_w32ce_get_errno ();
Packit fc043f
Packit fc043f
  /* Note: On a German HTC Touch Pro2 device I also tried
Packit fc043f
     LOCALE_USER_DEFAULT and LOCALE_SYSTEM_DEFAULT - both returned
Packit fc043f
     English messages.  */
Packit fc043f
  if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
Packit fc043f
                      MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
Packit fc043f
                      tmpbuf, STRBUFFER_SIZE -1,
Packit fc043f
                      NULL))
Packit fc043f
    {
Packit fc043f
      n = WideCharToMultiByte (CP_UTF8, 0, tmpbuf, -1,
Packit fc043f
                               tls->strerror_buffer,
Packit fc043f
                               sizeof tls->strerror_buffer -1,
Packit fc043f
                               NULL, NULL);
Packit fc043f
    }
Packit fc043f
  else
Packit fc043f
    n = -1;
Packit fc043f
Packit fc043f
  if (n < 0)
Packit fc043f
    snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1,
Packit fc043f
              "[w32err=%d]", err);
Packit fc043f
  return tls->strerror_buffer;
Packit fc043f
}
Packit fc043f
#endif /*HAVE_W32CE_SYSTEM*/
Packit fc043f
Packit fc043f
Packit fc043f
/* Entry point called by the DLL loader.  */
Packit fc043f
#ifdef DLL_EXPORT
Packit fc043f
int WINAPI
Packit fc043f
DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
Packit fc043f
{
Packit fc043f
  struct tls_space_s *tls;
Packit fc043f
  (void)reserved;
Packit fc043f
  (void)hinst;
Packit fc043f
Packit fc043f
  switch (reason)
Packit fc043f
    {
Packit fc043f
    case DLL_PROCESS_ATTACH:
Packit fc043f
      tls_index = TlsAlloc ();
Packit fc043f
      if (tls_index == TLS_OUT_OF_INDEXES)
Packit fc043f
        return FALSE;
Packit fc043f
#ifndef _GPG_ERR_HAVE_CONSTRUCTOR
Packit fc043f
      /* If we have not constructors (e.g. MSC) we call it here.  */
Packit fc043f
      _gpg_w32__init_gettext_module ();
Packit fc043f
#endif
Packit fc043f
      /* falltru.  */
Packit fc043f
    case DLL_THREAD_ATTACH:
Packit fc043f
      tls = LocalAlloc (LPTR, sizeof *tls);
Packit fc043f
      if (!tls)
Packit fc043f
        return FALSE;
Packit fc043f
      tls->gt_use_utf8 = 0;
Packit fc043f
      TlsSetValue (tls_index, tls);
Packit fc043f
      if (reason == DLL_PROCESS_ATTACH)
Packit fc043f
        {
Packit fc043f
          real_init ();
Packit fc043f
        }
Packit fc043f
      break;
Packit fc043f
Packit fc043f
    case DLL_THREAD_DETACH:
Packit fc043f
      tls = TlsGetValue (tls_index);
Packit fc043f
      if (tls)
Packit fc043f
        LocalFree (tls);
Packit fc043f
      break;
Packit fc043f
Packit fc043f
    case DLL_PROCESS_DETACH:
Packit fc043f
      tls = TlsGetValue (tls_index);
Packit fc043f
      if (tls)
Packit fc043f
        LocalFree (tls);
Packit fc043f
      TlsFree (tls_index);
Packit fc043f
      break;
Packit fc043f
Packit fc043f
    default:
Packit fc043f
      break;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  return TRUE;
Packit fc043f
}
Packit fc043f
#endif /*DLL_EXPORT*/
Packit fc043f
Packit fc043f
#endif /*HAVE_W32_SYSTEM*/