summaryrefslogtreecommitdiff
path: root/glib/glib-private.c
diff options
context:
space:
mode:
Diffstat (limited to 'glib/glib-private.c')
-rw-r--r--glib/glib-private.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/glib/glib-private.c b/glib/glib-private.c
index b78f0a22e..6b2205f86 100644
--- a/glib/glib-private.c
+++ b/glib/glib-private.c
@@ -24,6 +24,10 @@
#include "glib-private.h"
#include "glib-init.h"
+#ifdef USE_INVALID_PARAMETER_HANDLER
+#include <crtdbg.h>
+#endif
+
/**
* glib__private__:
* @arg: Do not use this argument
@@ -60,7 +64,83 @@ glib__private__ (void)
g_win32_reopen_noninherited,
g_win32_handle_is_socket,
#endif
+
+ g_win32_push_empty_invalid_parameter_handler,
+ g_win32_pop_invalid_parameter_handler,
+
+ g_find_program_for_path,
};
return &table;
}
+
+#ifdef USE_INVALID_PARAMETER_HANDLER
+/*
+ * This is the (empty) invalid parameter handler
+ * that is used for Visual C++ 2005 (and later) builds
+ * so that we can use this instead of the system automatically
+ * aborting the process, when calling _get_osfhandle(), isatty()
+ * and _commit() (via g_fsync()) and so on with an invalid file
+ * descriptor.
+ *
+ * This is necessary so that the gspawn helper and the test programs
+ * will continue to run as expected, since we are purposely or
+ * forced to use invalid FDs.
+ *
+ * Please see https://learn.microsoft.com/en-us/cpp/c-runtime-library/parameter-validation?view=msvc-170
+ * for an explanation on this.
+ */
+static void
+empty_invalid_parameter_handler (const wchar_t *expression,
+ const wchar_t *function,
+ const wchar_t *file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+}
+
+/* fallback to _set_invalid_parameter_handler() if we don't have _set_thread_local_invalid_parameter_handler() */
+#ifndef HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER
+# define _set_thread_local_invalid_parameter_handler _set_invalid_parameter_handler
+#endif
+
+#endif
+/*
+ * g_win32_push_empty_invalid_parameter_handler:
+ * @handler: a possibly uninitialized GWin32InvalidParameterHandler
+ */
+void
+g_win32_push_empty_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
+{
+#ifdef USE_INVALID_PARAMETER_HANDLER
+ /* use the empty invalid parameter handler to override the default invalid parameter_handler */
+ handler->pushed_handler = empty_invalid_parameter_handler;
+ handler->old_handler = _set_thread_local_invalid_parameter_handler (handler->pushed_handler);
+
+ /* Disable the message box for assertions. */
+ handler->pushed_report_mode = 0;
+ handler->prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->pushed_report_mode);
+#endif
+}
+
+/*
+ * g_win32_pop_invalid_parameter_handler:
+ * @handler: a GWin32InvalidParameterHandler processed with
+ * g_win32_push_empty_invalid_parameter_handler()
+ */
+void
+g_win32_pop_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
+{
+#ifdef USE_INVALID_PARAMETER_HANDLER
+ G_GNUC_UNUSED _invalid_parameter_handler popped_handler;
+ G_GNUC_UNUSED int popped_report_mode;
+
+ /* Restore previous/default invalid parameter handler, check the value returned matches the one we previously pushed */
+ popped_handler = _set_thread_local_invalid_parameter_handler (handler->old_handler);
+ g_return_if_fail (handler->pushed_handler == popped_handler);
+
+ /* Restore the message box for assertions, check the value returned matches the one we previously pushed */
+ popped_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->prev_report_mode);
+ g_return_if_fail (handler->pushed_report_mode == popped_report_mode);
+#endif
+}