| 1 | /* Invalid parameter handler for MSVC runtime libraries. | 
|---|
| 2 | Copyright (C) 2011-2022 Free Software Foundation, Inc. | 
|---|
| 3 |  | 
|---|
| 4 | This file is free software: you can redistribute it and/or modify | 
|---|
| 5 | it under the terms of the GNU Lesser General Public License as | 
|---|
| 6 | published by the Free Software Foundation; either version 2.1 of the | 
|---|
| 7 | License, or (at your option) any later version. | 
|---|
| 8 |  | 
|---|
| 9 | This file is distributed in the hope that it will be useful, | 
|---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 12 | GNU Lesser General Public License for more details. | 
|---|
| 13 |  | 
|---|
| 14 | You should have received a copy of the GNU Lesser General Public License | 
|---|
| 15 | along with this program.  If not, see <https://www.gnu.org/licenses/>.  */ | 
|---|
| 16 |  | 
|---|
| 17 | #include <config.h> | 
|---|
| 18 |  | 
|---|
| 19 | /* Specification.  */ | 
|---|
| 20 | #include "msvc-inval.h" | 
|---|
| 21 |  | 
|---|
| 22 | #if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ | 
|---|
| 23 | && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) | 
|---|
| 24 |  | 
|---|
| 25 | /* Get _invalid_parameter_handler type and _set_invalid_parameter_handler | 
|---|
| 26 | declaration.  */ | 
|---|
| 27 | # include <stdlib.h> | 
|---|
| 28 |  | 
|---|
| 29 | # if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING | 
|---|
| 30 |  | 
|---|
| 31 | static void __cdecl | 
|---|
| 32 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | 
|---|
| 33 | const wchar_t *function, | 
|---|
| 34 | const wchar_t *file, | 
|---|
| 35 | unsigned int line, | 
|---|
| 36 | uintptr_t dummy) | 
|---|
| 37 | { | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | # else | 
|---|
| 41 |  | 
|---|
| 42 | /* Get declarations of the native Windows API functions.  */ | 
|---|
| 43 | #  define WIN32_LEAN_AND_MEAN | 
|---|
| 44 | #  include <windows.h> | 
|---|
| 45 |  | 
|---|
| 46 | #  if defined _MSC_VER | 
|---|
| 47 |  | 
|---|
| 48 | static void __cdecl | 
|---|
| 49 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | 
|---|
| 50 | const wchar_t *function, | 
|---|
| 51 | const wchar_t *file, | 
|---|
| 52 | unsigned int line, | 
|---|
| 53 | uintptr_t dummy) | 
|---|
| 54 | { | 
|---|
| 55 | RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); | 
|---|
| 56 | } | 
|---|
| 57 |  | 
|---|
| 58 | #  else | 
|---|
| 59 |  | 
|---|
| 60 | /* An index to thread-local storage.  */ | 
|---|
| 61 | static DWORD tls_index; | 
|---|
| 62 | static int tls_initialized /* = 0 */; | 
|---|
| 63 |  | 
|---|
| 64 | /* Used as a fallback only.  */ | 
|---|
| 65 | static struct gl_msvc_inval_per_thread not_per_thread; | 
|---|
| 66 |  | 
|---|
| 67 | struct gl_msvc_inval_per_thread * | 
|---|
| 68 | gl_msvc_inval_current (void) | 
|---|
| 69 | { | 
|---|
| 70 | if (!tls_initialized) | 
|---|
| 71 | { | 
|---|
| 72 | tls_index = TlsAlloc (); | 
|---|
| 73 | tls_initialized = 1; | 
|---|
| 74 | } | 
|---|
| 75 | if (tls_index == TLS_OUT_OF_INDEXES) | 
|---|
| 76 | /* TlsAlloc had failed.  */ | 
|---|
| 77 | return ¬_per_thread; | 
|---|
| 78 | else | 
|---|
| 79 | { | 
|---|
| 80 | struct gl_msvc_inval_per_thread *pointer = | 
|---|
| 81 | (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); | 
|---|
| 82 | if (pointer == NULL) | 
|---|
| 83 | { | 
|---|
| 84 | /* First call.  Allocate a new 'struct gl_msvc_inval_per_thread'.  */ | 
|---|
| 85 | pointer = | 
|---|
| 86 | (struct gl_msvc_inval_per_thread *) | 
|---|
| 87 | malloc (sizeof (struct gl_msvc_inval_per_thread)); | 
|---|
| 88 | if (pointer == NULL) | 
|---|
| 89 | /* Could not allocate memory.  Use the global storage.  */ | 
|---|
| 90 | pointer = ¬_per_thread; | 
|---|
| 91 | TlsSetValue (tls_index, pointer); | 
|---|
| 92 | } | 
|---|
| 93 | return pointer; | 
|---|
| 94 | } | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | static void __cdecl | 
|---|
| 98 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | 
|---|
| 99 | const wchar_t *function, | 
|---|
| 100 | const wchar_t *file, | 
|---|
| 101 | unsigned int line, | 
|---|
| 102 | uintptr_t dummy) | 
|---|
| 103 | { | 
|---|
| 104 | struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); | 
|---|
| 105 | if (current->restart_valid) | 
|---|
| 106 | longjmp (current->restart, 1); | 
|---|
| 107 | else | 
|---|
| 108 | /* An invalid parameter notification from outside the gnulib code. | 
|---|
| 109 | Give the caller a chance to intervene.  */ | 
|---|
| 110 | RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); | 
|---|
| 111 | } | 
|---|
| 112 |  | 
|---|
| 113 | #  endif | 
|---|
| 114 |  | 
|---|
| 115 | # endif | 
|---|
| 116 |  | 
|---|
| 117 | static int gl_msvc_inval_initialized /* = 0 */; | 
|---|
| 118 |  | 
|---|
| 119 | void | 
|---|
| 120 | gl_msvc_inval_ensure_handler (void) | 
|---|
| 121 | { | 
|---|
| 122 | if (gl_msvc_inval_initialized == 0) | 
|---|
| 123 | { | 
|---|
| 124 | _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); | 
|---|
| 125 | gl_msvc_inval_initialized = 1; | 
|---|
| 126 | } | 
|---|
| 127 | } | 
|---|
| 128 |  | 
|---|
| 129 | #endif | 
|---|