Blame lib/msvc-inval.c

Packit Service fdd496
/* Invalid parameter handler for MSVC runtime libraries.
Packit Service fdd496
   Copyright (C) 2011-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software; you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3, or (at your option)
Packit Service fdd496
   any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License along
Packit Service fdd496
   with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#include <config.h>
Packit Service fdd496
Packit Service fdd496
/* Specification.  */
Packit Service fdd496
#include "msvc-inval.h"
Packit Service fdd496
Packit Service fdd496
#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \
Packit Service fdd496
    && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING)
Packit Service fdd496
Packit Service fdd496
/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler
Packit Service fdd496
   declaration.  */
Packit Service fdd496
# include <stdlib.h>
Packit Service fdd496
Packit Service fdd496
# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING
Packit Service fdd496
Packit Service fdd496
static void __cdecl
Packit Service fdd496
gl_msvc_invalid_parameter_handler (const wchar_t *expression,
Packit Service fdd496
                                   const wchar_t *function,
Packit Service fdd496
                                   const wchar_t *file,
Packit Service fdd496
                                   unsigned int line,
Packit Service fdd496
                                   uintptr_t dummy)
Packit Service fdd496
{
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
# else
Packit Service fdd496
Packit Service fdd496
/* Get declarations of the native Windows API functions.  */
Packit Service fdd496
#  define WIN32_LEAN_AND_MEAN
Packit Service fdd496
#  include <windows.h>
Packit Service fdd496
Packit Service fdd496
#  if defined _MSC_VER
Packit Service fdd496
Packit Service fdd496
static void __cdecl
Packit Service fdd496
gl_msvc_invalid_parameter_handler (const wchar_t *expression,
Packit Service fdd496
                                   const wchar_t *function,
Packit Service fdd496
                                   const wchar_t *file,
Packit Service fdd496
                                   unsigned int line,
Packit Service fdd496
                                   uintptr_t dummy)
Packit Service fdd496
{
Packit Service fdd496
  RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#  else
Packit Service fdd496
Packit Service fdd496
/* An index to thread-local storage.  */
Packit Service fdd496
static DWORD tls_index;
Packit Service fdd496
static int tls_initialized /* = 0 */;
Packit Service fdd496
Packit Service fdd496
/* Used as a fallback only.  */
Packit Service fdd496
static struct gl_msvc_inval_per_thread not_per_thread;
Packit Service fdd496
Packit Service fdd496
struct gl_msvc_inval_per_thread *
Packit Service fdd496
gl_msvc_inval_current (void)
Packit Service fdd496
{
Packit Service fdd496
  if (!tls_initialized)
Packit Service fdd496
    {
Packit Service fdd496
      tls_index = TlsAlloc ();
Packit Service fdd496
      tls_initialized = 1;
Packit Service fdd496
    }
Packit Service fdd496
  if (tls_index == TLS_OUT_OF_INDEXES)
Packit Service fdd496
    /* TlsAlloc had failed.  */
Packit Service fdd496
    return &not_per_thread;
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      struct gl_msvc_inval_per_thread *pointer =
Packit Service fdd496
        (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index);
Packit Service fdd496
      if (pointer == NULL)
Packit Service fdd496
        {
Packit Service fdd496
          /* First call.  Allocate a new 'struct gl_msvc_inval_per_thread'.  */
Packit Service fdd496
          pointer =
Packit Service fdd496
            (struct gl_msvc_inval_per_thread *)
Packit Service fdd496
            malloc (sizeof (struct gl_msvc_inval_per_thread));
Packit Service fdd496
          if (pointer == NULL)
Packit Service fdd496
            /* Could not allocate memory.  Use the global storage.  */
Packit Service fdd496
            pointer = &not_per_thread;
Packit Service fdd496
          TlsSetValue (tls_index, pointer);
Packit Service fdd496
        }
Packit Service fdd496
      return pointer;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
static void __cdecl
Packit Service fdd496
gl_msvc_invalid_parameter_handler (const wchar_t *expression,
Packit Service fdd496
                                   const wchar_t *function,
Packit Service fdd496
                                   const wchar_t *file,
Packit Service fdd496
                                   unsigned int line,
Packit Service fdd496
                                   uintptr_t dummy)
Packit Service fdd496
{
Packit Service fdd496
  struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current ();
Packit Service fdd496
  if (current->restart_valid)
Packit Service fdd496
    longjmp (current->restart, 1);
Packit Service fdd496
  else
Packit Service fdd496
    /* An invalid parameter notification from outside the gnulib code.
Packit Service fdd496
       Give the caller a chance to intervene.  */
Packit Service fdd496
    RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
static int gl_msvc_inval_initialized /* = 0 */;
Packit Service fdd496
Packit Service fdd496
void
Packit Service fdd496
gl_msvc_inval_ensure_handler (void)
Packit Service fdd496
{
Packit Service fdd496
  if (gl_msvc_inval_initialized == 0)
Packit Service fdd496
    {
Packit Service fdd496
      _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
Packit Service fdd496
      gl_msvc_inval_initialized = 1;
Packit Service fdd496
    }
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#endif