(root)/
glib-2.79.0/
glib/
glib-private.c
       1  /* GLIB - Library of useful routines for C programming
       2   * Copyright (C) 2011 Red Hat, Inc.
       3   *
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   *
       6   * This library is free software; you can redistribute it and/or
       7   * modify it under the terms of the GNU Lesser General Public
       8   * License as published by the Free Software Foundation; either
       9   * version 2.1 of the License, or (at your option) any later version.
      10   *
      11   * This library is distributed in the hope that it will be useful,
      12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
      14   * Lesser General Public License for more details.
      15   *
      16   * You should have received a copy of the GNU Lesser General Public
      17   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18   *
      19   * Author: Colin Walters <walters@verbum.org>
      20   */
      21  
      22  #include "config.h"
      23  
      24  #include "glib-private.h"
      25  #include "glib-init.h"
      26  #include "gutilsprivate.h"
      27  
      28  #ifdef USE_INVALID_PARAMETER_HANDLER
      29  #include <crtdbg.h>
      30  #endif
      31  
      32  /**
      33   * glib__private__:
      34   * @arg: Do not use this argument
      35   *
      36   * Do not call this function; it is used to share private
      37   * API between glib, gobject, and gio.
      38   */
      39  GLibPrivateVTable *
      40  glib__private__ (void)
      41  {
      42    static GLibPrivateVTable table = {
      43      g_wakeup_new,
      44      g_wakeup_free,
      45      g_wakeup_get_pollfd,
      46      g_wakeup_signal,
      47      g_wakeup_acknowledge,
      48  
      49      g_get_worker_context,
      50  
      51      g_check_setuid,
      52      g_main_context_new_with_next_id,
      53  
      54      g_dir_open_with_errno,
      55      g_dir_new_from_dirp,
      56  
      57      glib_init,
      58  
      59  #ifdef G_OS_WIN32
      60      g_win32_stat_utf8,
      61      g_win32_lstat_utf8,
      62      g_win32_readlink_utf8,
      63      g_win32_fstat,
      64      g_win32_find_helper_executable_path,
      65      g_win32_reopen_noninherited,
      66      g_win32_handle_is_socket,
      67  #endif
      68  
      69      g_win32_push_empty_invalid_parameter_handler,
      70      g_win32_pop_invalid_parameter_handler,
      71  
      72      g_find_program_for_path,
      73  
      74      g_uri_get_default_scheme_port,
      75  
      76      g_set_prgname_once,
      77    };
      78  
      79    return &table;
      80  }
      81  
      82  #ifdef USE_INVALID_PARAMETER_HANDLER
      83  /*
      84   * This is the (empty) invalid parameter handler
      85   * that is used for Visual C++ 2005 (and later) builds
      86   * so that we can use this instead of the system automatically
      87   * aborting the process, when calling _get_osfhandle(), isatty()
      88   * and _commit() (via g_fsync()) and so on with an invalid file
      89   * descriptor.
      90   *
      91   * This is necessary so that the gspawn helper and the test programs
      92   * will continue to run as expected, since we are purposely or
      93   * forced to use invalid FDs.
      94   *
      95   * Please see https://learn.microsoft.com/en-us/cpp/c-runtime-library/parameter-validation?view=msvc-170
      96   * for an explanation on this.
      97   */
      98  static void
      99  empty_invalid_parameter_handler (const wchar_t *expression,
     100                                   const wchar_t *function,
     101                                   const wchar_t *file,
     102                                   unsigned int   line,
     103                                   uintptr_t      pReserved)
     104  {
     105  }
     106  
     107  /* fallback to _set_invalid_parameter_handler() if we don't have _set_thread_local_invalid_parameter_handler() */
     108  #ifndef HAVE__SET_THREAD_LOCAL_INVALID_PARAMETER_HANDLER
     109  # define _set_thread_local_invalid_parameter_handler _set_invalid_parameter_handler
     110  #endif
     111  
     112  #endif
     113  /*
     114   * g_win32_push_empty_invalid_parameter_handler:
     115   * @handler: a possibly uninitialized GWin32InvalidParameterHandler
     116   */
     117  void
     118  g_win32_push_empty_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
     119  {
     120  #ifdef USE_INVALID_PARAMETER_HANDLER
     121    /* use the empty invalid parameter handler to override the default invalid parameter_handler */
     122    handler->pushed_handler = empty_invalid_parameter_handler;
     123    handler->old_handler = _set_thread_local_invalid_parameter_handler (handler->pushed_handler);
     124  
     125    /* Disable the message box for assertions. */
     126    handler->pushed_report_mode = 0;
     127    handler->prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->pushed_report_mode);
     128  #endif
     129  }
     130  
     131  /*
     132   * g_win32_pop_invalid_parameter_handler:
     133   * @handler: a GWin32InvalidParameterHandler processed with
     134   * g_win32_push_empty_invalid_parameter_handler()
     135   */
     136  void
     137  g_win32_pop_invalid_parameter_handler (GWin32InvalidParameterHandler *handler)
     138  {
     139  #ifdef USE_INVALID_PARAMETER_HANDLER
     140    G_GNUC_UNUSED _invalid_parameter_handler popped_handler;
     141    G_GNUC_UNUSED int popped_report_mode;
     142  
     143    /* Restore previous/default invalid parameter handler, check the value returned matches the one we previously pushed */
     144    popped_handler = _set_thread_local_invalid_parameter_handler (handler->old_handler);
     145    g_return_if_fail (handler->pushed_handler == popped_handler);
     146  
     147    /* Restore the message box for assertions, check the value returned matches the one we previously pushed */
     148    popped_report_mode = _CrtSetReportMode(_CRT_ASSERT, handler->prev_report_mode);
     149    g_return_if_fail (handler->pushed_report_mode == popped_report_mode);
     150  #endif
     151  }