Blame gnulib/lib/msvc-inval.c

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