Blame lib/msvc-inval.c

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