|
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*/
|