msvc-inval.c 3.9 KB

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