Blame gl/msvc-inval.c

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