gkdbus: Fix underflow and unreachable code bug
[platform/upstream/glib.git] / glib / gwin32.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-1999  Tor Lillqvist
4  *
5  * SPDX-License-Identifier: LGPL-2.1-or-later
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GLib Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 /* 
29  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
30  */
31
32 #include "config.h"
33
34 #include "glibconfig.h"
35
36 #include <glib/gstdio.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <wchar.h>
41 #include <errno.h>
42 #include <fcntl.h>
43
44 #define STRICT                  /* Strict typing, please */
45 #include <winsock2.h>
46 #include <windows.h>
47 #undef STRICT
48 #ifndef G_WITH_CYGWIN
49 #include <direct.h>
50 #endif
51 #include <errno.h>
52 #include <ctype.h>
53 #if defined(_MSC_VER) || defined(__DMC__)
54 #  include <io.h>
55 #endif /* _MSC_VER || __DMC__ */
56
57 #define MODERN_API_FAMILY 2
58
59 #if WINAPI_FAMILY == MODERN_API_FAMILY
60 /* This is for modern UI Builds, where we can't use LoadLibraryW()/GetProcAddress() */
61 /* ntddk.h is found in the WDK, and MinGW */
62 #include <ntddk.h>
63
64 #ifdef _MSC_VER
65 #pragma comment (lib, "ntoskrnl.lib")
66 #endif
67 #elif defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
68 /* mingw-w64 must use winternl.h, but not MinGW */
69 #include <ntdef.h>
70 #else
71 #include <winternl.h>
72 #endif
73
74 #include "glib.h"
75 #include "gthreadprivate.h"
76 #include "glib-init.h"
77
78 #ifdef G_WITH_CYGWIN
79 #include <sys/cygwin.h>
80 #endif
81
82 #ifndef G_WITH_CYGWIN
83
84 gint
85 g_win32_ftruncate (gint  fd,
86                    guint size)
87 {
88   return _chsize (fd, size);
89 }
90
91 #endif
92
93 /**
94  * g_win32_getlocale:
95  *
96  * The setlocale() function in the Microsoft C library uses locale
97  * names of the form "English_United States.1252" etc. We want the
98  * UNIXish standard form "en_US", "zh_TW" etc. This function gets the
99  * current thread locale from Windows - without any encoding info -
100  * and returns it as a string of the above form for use in forming
101  * file names etc. The returned string should be deallocated with
102  * g_free().
103  *
104  * Returns: newly-allocated locale name.
105  **/
106
107 #ifndef SUBLANG_SERBIAN_LATIN_BA
108 #define SUBLANG_SERBIAN_LATIN_BA 0x06
109 #endif
110
111 gchar *
112 g_win32_getlocale (void)
113 {
114   gchar *result;
115   LCID lcid;
116   LANGID langid;
117   const gchar *ev;
118   gint primary, sub;
119   WCHAR iso639[10];
120   gchar *iso639_utf8;
121   WCHAR iso3166[10];
122   gchar *iso3166_utf8;
123   const gchar *script = NULL;
124
125   /* Let the user override the system settings through environment
126    * variables, as on POSIX systems. Note that in GTK applications
127    * since GTK 2.10.7 setting either LC_ALL or LANG also sets the
128    * Win32 locale and C library locale through code in gtkmain.c.
129    */
130   if (((ev = g_getenv ("LC_ALL")) != NULL && ev[0] != '\0')
131       || ((ev = g_getenv ("LC_MESSAGES")) != NULL && ev[0] != '\0')
132       || ((ev = g_getenv ("LANG")) != NULL && ev[0] != '\0'))
133     return g_strdup (ev);
134
135   lcid = GetThreadLocale ();
136
137   if (!GetLocaleInfoW (lcid, LOCALE_SISO639LANGNAME, iso639, sizeof (iso639)) ||
138       !GetLocaleInfoW (lcid, LOCALE_SISO3166CTRYNAME, iso3166, sizeof (iso3166)))
139     return g_strdup ("C");
140   
141   /* Strip off the sorting rules, keep only the language part.  */
142   langid = LANGIDFROMLCID (lcid);
143
144   /* Split into language and territory part.  */
145   primary = PRIMARYLANGID (langid);
146   sub = SUBLANGID (langid);
147
148   /* Handle special cases */
149   switch (primary)
150     {
151     case LANG_AZERI:
152       switch (sub)
153         {
154         case SUBLANG_AZERI_LATIN:
155           script = "@Latn";
156           break;
157         case SUBLANG_AZERI_CYRILLIC:
158           script = "@Cyrl";
159           break;
160         }
161       break;
162     case LANG_SERBIAN:          /* LANG_CROATIAN == LANG_SERBIAN */
163       switch (sub)
164         {
165         case SUBLANG_SERBIAN_LATIN:
166         case 0x06: /* Serbian (Latin) - Bosnia and Herzegovina */
167           script = "@Latn";
168           break;
169         }
170       break;
171     case LANG_UZBEK:
172       switch (sub)
173         {
174         case SUBLANG_UZBEK_LATIN:
175           script = "@Latn";
176           break;
177         case SUBLANG_UZBEK_CYRILLIC:
178           script = "@Cyrl";
179           break;
180         }
181       break;
182     }
183
184   iso639_utf8 = g_utf16_to_utf8 (iso639, -1, NULL, NULL, NULL);
185   iso3166_utf8 = g_utf16_to_utf8 (iso3166, -1, NULL, NULL, NULL);
186
187   result = g_strconcat (iso639_utf8, "_", iso3166_utf8, script, NULL);
188
189   g_free (iso3166_utf8);
190   g_free (iso639_utf8);
191
192   return result;
193 }
194
195 /**
196  * g_win32_error_message:
197  * @error: error code.
198  *
199  * Translate a Win32 error code (as returned by GetLastError() or
200  * WSAGetLastError()) into the corresponding message. The message is
201  * either language neutral, or in the thread's language, or the user's
202  * language, the system's language, or US English (see docs for
203  * FormatMessage()). The returned string is in UTF-8. It should be
204  * deallocated with g_free().
205  *
206  * Returns: newly-allocated error message
207  **/
208 gchar *
209 g_win32_error_message (gint error)
210 {
211   gchar *retval;
212   wchar_t *msg = NULL;
213   size_t nchars;
214
215   FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER
216                   |FORMAT_MESSAGE_IGNORE_INSERTS
217                   |FORMAT_MESSAGE_FROM_SYSTEM,
218                   NULL, error, 0,
219                   (LPWSTR) &msg, 0, NULL);
220   if (msg != NULL)
221     {
222       nchars = wcslen (msg);
223
224       if (nchars >= 2 && msg[nchars-1] == L'\n' && msg[nchars-2] == L'\r')
225         msg[nchars-2] = L'\0';
226
227       retval = g_utf16_to_utf8 (msg, -1, NULL, NULL, NULL);
228
229       LocalFree (msg);
230     }
231   else
232     retval = g_strdup ("");
233
234   return retval;
235 }
236
237 /**
238  * g_win32_get_package_installation_directory_of_module:
239  * @hmodule: (nullable): The Win32 handle for a DLL loaded into the current process, or %NULL
240  *
241  * This function tries to determine the installation directory of a
242  * software package based on the location of a DLL of the software
243  * package.
244  *
245  * @hmodule should be the handle of a loaded DLL or %NULL. The
246  * function looks up the directory that DLL was loaded from. If
247  * @hmodule is NULL, the directory the main executable of the current
248  * process is looked up. If that directory's last component is "bin"
249  * or "lib", its parent directory is returned, otherwise the directory
250  * itself.
251  *
252  * It thus makes sense to pass only the handle to a "public" DLL of a
253  * software package to this function, as such DLLs typically are known
254  * to be installed in a "bin" or occasionally "lib" subfolder of the
255  * installation folder. DLLs that are of the dynamically loaded module
256  * or plugin variety are often located in more private locations
257  * deeper down in the tree, from which it is impossible for GLib to
258  * deduce the root of the package installation.
259  *
260  * The typical use case for this function is to have a DllMain() that
261  * saves the handle for the DLL. Then when code in the DLL needs to
262  * construct names of files in the installation tree it calls this
263  * function passing the DLL handle.
264  *
265  * Returns: a string containing the guessed installation directory for
266  * the software package @hmodule is from. The string is in the GLib
267  * file name encoding, i.e. UTF-8. The return value should be freed
268  * with g_free() when not needed any longer. If the function fails
269  * %NULL is returned.
270  *
271  * Since: 2.16
272  */
273 gchar *
274 g_win32_get_package_installation_directory_of_module (gpointer hmodule)
275 {
276   gchar *filename;
277   gchar *retval;
278   gchar *p;
279   wchar_t wc_fn[MAX_PATH];
280
281   /* NOTE: it relies that GetModuleFileNameW returns only canonical paths */
282   if (!GetModuleFileNameW (hmodule, wc_fn, MAX_PATH))
283     return NULL;
284
285   filename = g_utf16_to_utf8 (wc_fn, -1, NULL, NULL, NULL);
286
287   if ((p = strrchr (filename, G_DIR_SEPARATOR)) != NULL)
288     *p = '\0';
289
290   retval = g_strdup (filename);
291
292   do
293     {
294       p = strrchr (retval, G_DIR_SEPARATOR);
295       if (p == NULL)
296         break;
297
298       *p = '\0';
299
300       if (g_ascii_strcasecmp (p + 1, "bin") == 0 ||
301           g_ascii_strcasecmp (p + 1, "lib") == 0)
302         break;
303     }
304   while (p != NULL);
305
306   if (p == NULL)
307     {
308       g_free (retval);
309       retval = filename;
310     }
311   else
312     g_free (filename);
313
314 #ifdef G_WITH_CYGWIN
315   /* In Cygwin we need to have POSIX paths */
316   {
317     gchar tmp[MAX_PATH];
318
319     cygwin_conv_to_posix_path (retval, tmp);
320     g_free (retval);
321     retval = g_strdup (tmp);
322   }
323 #endif
324
325   return retval;
326 }
327
328 static gchar *
329 get_package_directory_from_module (const gchar *module_name)
330 {
331   static GHashTable *module_dirs = NULL;
332   G_LOCK_DEFINE_STATIC (module_dirs);
333   HMODULE hmodule = NULL;
334   gchar *fn;
335
336   G_LOCK (module_dirs);
337
338   if (module_dirs == NULL)
339     module_dirs = g_hash_table_new (g_str_hash, g_str_equal);
340   
341   fn = g_hash_table_lookup (module_dirs, module_name ? module_name : "");
342       
343   if (fn)
344     {
345       G_UNLOCK (module_dirs);
346       return g_strdup (fn);
347     }
348
349   if (module_name)
350     {
351       wchar_t *wc_module_name = g_utf8_to_utf16 (module_name, -1, NULL, NULL, NULL);
352       hmodule = GetModuleHandleW (wc_module_name);
353       g_free (wc_module_name);
354
355       if (!hmodule)
356         {
357           G_UNLOCK (module_dirs);
358           return NULL;
359         }
360     }
361
362   fn = g_win32_get_package_installation_directory_of_module (hmodule);
363
364   if (fn == NULL)
365     {
366       G_UNLOCK (module_dirs);
367       return NULL;
368     }
369   
370   g_hash_table_insert (module_dirs, module_name ? g_strdup (module_name) : "", fn);
371
372   G_UNLOCK (module_dirs);
373
374   return g_strdup (fn);
375 }
376
377 /**
378  * g_win32_get_package_installation_directory:
379  * @package: (nullable): You should pass %NULL for this.
380  * @dll_name: (nullable): The name of a DLL that a package provides in UTF-8, or %NULL.
381  *
382  * Try to determine the installation directory for a software package.
383  *
384  * This function is deprecated. Use
385  * g_win32_get_package_installation_directory_of_module() instead.
386  *
387  * The use of @package is deprecated. You should always pass %NULL. A
388  * warning is printed if non-NULL is passed as @package.
389  *
390  * The original intended use of @package was for a short identifier of
391  * the package, typically the same identifier as used for
392  * `GETTEXT_PACKAGE` in software configured using GNU
393  * autotools. The function first looks in the Windows Registry for the
394  * value `#InstallationDirectory` in the key
395  * `#HKLM\Software\@package`, and if that value
396  * exists and is a string, returns that.
397  *
398  * It is strongly recommended that packagers of GLib-using libraries
399  * for Windows do not store installation paths in the Registry to be
400  * used by this function as that interfers with having several
401  * parallel installations of the library. Enabling multiple
402  * installations of different versions of some GLib-using library, or
403  * GLib itself, is desirable for various reasons.
404  *
405  * For this reason it is recommended to always pass %NULL as
406  * @package to this function, to avoid the temptation to use the
407  * Registry. In version 2.20 of GLib the @package parameter
408  * will be ignored and this function won't look in the Registry at all.
409  *
410  * If @package is %NULL, or the above value isn't found in the
411  * Registry, but @dll_name is non-%NULL, it should name a DLL loaded
412  * into the current process. Typically that would be the name of the
413  * DLL calling this function, looking for its installation
414  * directory. The function then asks Windows what directory that DLL
415  * was loaded from. If that directory's last component is "bin" or
416  * "lib", the parent directory is returned, otherwise the directory
417  * itself. If that DLL isn't loaded, the function proceeds as if
418  * @dll_name was %NULL.
419  *
420  * If both @package and @dll_name are %NULL, the directory from where
421  * the main executable of the process was loaded is used instead in
422  * the same way as above.
423  *
424  * Returns: a string containing the installation directory for
425  * @package. The string is in the GLib file name encoding,
426  * i.e. UTF-8. The return value should be freed with g_free() when not
427  * needed any longer. If the function fails %NULL is returned.
428  *
429  * Deprecated: 2.18: Pass the HMODULE of a DLL or EXE to
430  * g_win32_get_package_installation_directory_of_module() instead.
431  **/
432
433 gchar *
434 g_win32_get_package_installation_directory (const gchar *package,
435                                             const gchar *dll_name)
436 {
437   gchar *result = NULL;
438
439   if (package != NULL)
440       g_warning ("Passing a non-NULL package to g_win32_get_package_installation_directory() is deprecated and it is ignored.");
441
442   if (dll_name != NULL)
443     result = get_package_directory_from_module (dll_name);
444
445   if (result == NULL)
446     result = get_package_directory_from_module (NULL);
447
448   return result;
449 }
450
451 /**
452  * g_win32_get_package_installation_subdirectory:
453  * @package: (nullable): You should pass %NULL for this.
454  * @dll_name: (nullable): The name of a DLL that a package provides, in UTF-8, or %NULL.
455  * @subdir: A subdirectory of the package installation directory, also in UTF-8
456  *
457  * This function is deprecated. Use
458  * g_win32_get_package_installation_directory_of_module() and
459  * g_build_filename() instead.
460  *
461  * Returns a newly-allocated string containing the path of the
462  * subdirectory @subdir in the return value from calling
463  * g_win32_get_package_installation_directory() with the @package and
464  * @dll_name parameters. See the documentation for
465  * g_win32_get_package_installation_directory() for more details. In
466  * particular, note that it is deprecated to pass anything except NULL
467  * as @package.
468  *
469  * Returns: a string containing the complete path to @subdir inside
470  * the installation directory of @package. The returned string is in
471  * the GLib file name encoding, i.e. UTF-8. The return value should be
472  * freed with g_free() when no longer needed. If something goes wrong,
473  * %NULL is returned.
474  *
475  * Deprecated: 2.18: Pass the HMODULE of a DLL or EXE to
476  * g_win32_get_package_installation_directory_of_module() instead, and
477  * then construct a subdirectory pathname with g_build_filename().
478  **/
479
480 gchar *
481 g_win32_get_package_installation_subdirectory (const gchar *package,
482                                                const gchar *dll_name,
483                                                const gchar *subdir)
484 {
485   gchar *prefix;
486   gchar *dirname;
487
488 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
489   prefix = g_win32_get_package_installation_directory (package, dll_name);
490 G_GNUC_END_IGNORE_DEPRECATIONS
491
492   dirname = g_build_filename (prefix, subdir, NULL);
493   g_free (prefix);
494
495   return dirname;
496 }
497
498 /*
499  * private API to call Windows's RtlGetVersion(), which may need to be called
500  * via GetProcAddress()
501  */
502 gboolean
503 _g_win32_call_rtl_version (OSVERSIONINFOEXW *info)
504 {
505   static OSVERSIONINFOEXW result;
506   static gsize inited = 0;
507
508   g_return_val_if_fail (info != NULL, FALSE);
509
510   if (g_once_init_enter (&inited))
511     {
512 #if WINAPI_FAMILY != MODERN_API_FAMILY
513       /* For non-modern UI Apps, use the LoadLibraryW()/GetProcAddress() thing */
514       typedef NTSTATUS (WINAPI fRtlGetVersion) (PRTL_OSVERSIONINFOEXW);
515
516       fRtlGetVersion *RtlGetVersion;
517       HMODULE hmodule = LoadLibraryW (L"ntdll.dll");
518       g_return_val_if_fail (hmodule != NULL, FALSE);
519
520       RtlGetVersion = (fRtlGetVersion *) GetProcAddress (hmodule, "RtlGetVersion");
521       g_return_val_if_fail (RtlGetVersion != NULL, FALSE);
522 #endif
523
524       memset (&result, 0, sizeof (OSVERSIONINFOEXW));
525       result.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
526
527       RtlGetVersion (&result);
528
529 #if WINAPI_FAMILY != MODERN_API_FAMILY
530       FreeLibrary (hmodule);
531 #endif
532       g_once_init_leave (&inited, TRUE);
533     }
534
535   *info = result;
536
537   return TRUE;
538 }
539
540 /**
541  * g_win32_check_windows_version:
542  * @major: major version of Windows
543  * @minor: minor version of Windows
544  * @spver: Windows Service Pack Level, 0 if none
545  * @os_type: Type of Windows OS
546  *
547  * Returns whether the version of the Windows operating system the
548  * code is running on is at least the specified major, minor and
549  * service pack versions.  See MSDN documentation for the Operating
550  * System Version.  Software that needs even more detailed version and
551  * feature information should use the Win32 API VerifyVersionInfo()
552  * directly.
553  *
554  * Successive calls of this function can be used for enabling or
555  * disabling features at run-time for a range of Windows versions,
556  * as per the VerifyVersionInfo() API documentation.
557  *
558  * Returns: %TRUE if the Windows Version is the same or greater than
559  *          the specified major, minor and service pack versions, and
560  *          whether the running Windows is a workstation or server edition
561  *          of Windows, if specifically specified.
562  *
563  * Since: 2.44
564  **/
565 gboolean
566 g_win32_check_windows_version (const gint major,
567                                const gint minor,
568                                const gint spver,
569                                const GWin32OSType os_type)
570 {
571   OSVERSIONINFOEXW osverinfo;
572   gboolean is_ver_checked = FALSE;
573   gboolean is_type_checked = FALSE;
574
575   /* We Only Support Checking for XP or later */
576   g_return_val_if_fail (major >= 5 && (major <= 6 || major == 10), FALSE);
577   g_return_val_if_fail ((major >= 5 && minor >= 1) || major >= 6, FALSE);
578
579   /* Check for Service Pack Version >= 0 */
580   g_return_val_if_fail (spver >= 0, FALSE);
581
582   if (!_g_win32_call_rtl_version (&osverinfo))
583     return FALSE;
584
585   /* check the OS and Service Pack Versions */
586   if (osverinfo.dwMajorVersion > (DWORD) major)
587     is_ver_checked = TRUE;
588   else if (osverinfo.dwMajorVersion == (DWORD) major)
589     {
590       if (osverinfo.dwMinorVersion > (DWORD) minor)
591         is_ver_checked = TRUE;
592       else if (osverinfo.dwMinorVersion == (DWORD) minor)
593         if (osverinfo.wServicePackMajor >= (DWORD) spver)
594           is_ver_checked = TRUE;
595     }
596
597   /* Check OS Type */
598   if (is_ver_checked)
599     {
600       switch (os_type)
601         {
602           case G_WIN32_OS_ANY:
603             is_type_checked = TRUE;
604             break;
605           case G_WIN32_OS_WORKSTATION:
606             if (osverinfo.wProductType == VER_NT_WORKSTATION)
607               is_type_checked = TRUE;
608             break;
609           case G_WIN32_OS_SERVER:
610             if (osverinfo.wProductType == VER_NT_SERVER ||
611                 osverinfo.wProductType == VER_NT_DOMAIN_CONTROLLER)
612               is_type_checked = TRUE;
613             break;
614           default:
615             /* shouldn't get here normally */
616             g_warning ("Invalid os_type specified");
617             break;
618         }
619     }
620
621   return is_ver_checked && is_type_checked;
622 }
623
624 /**
625  * g_win32_get_windows_version:
626  *
627  * This function is deprecated. Use
628  * g_win32_check_windows_version() instead.
629  *
630  * Returns version information for the Windows operating system the
631  * code is running on. See MSDN documentation for the GetVersion()
632  * function. To summarize, the most significant bit is one on Win9x,
633  * and zero on NT-based systems. Since version 2.14, GLib works only
634  * on NT-based systems, so checking whether your are running on Win9x
635  * in your own software is moot. The least significant byte is 4 on
636  * Windows NT 4, and 5 on Windows XP. Software that needs really
637  * detailed version and feature information should use Win32 API like
638  * GetVersionEx() and VerifyVersionInfo().
639  *
640  * Returns: The version information.
641  *
642  * Deprecated: 2.44: Be aware that for Windows 8.1 and Windows Server
643  * 2012 R2 and later, this will return 62 unless the application is
644  * manifested for Windows 8.1/Windows Server 2012 R2, for example.
645  * MSDN stated that GetVersion(), which is used here, is subject to
646  * further change or removal after Windows 8.1.
647  **/
648 guint
649 g_win32_get_windows_version (void)
650 {
651   static gsize windows_version;
652
653   if (g_once_init_enter (&windows_version))
654     g_once_init_leave (&windows_version, GetVersion ());
655
656   return windows_version;
657 }
658
659 /*
660  * Doesn't use gettext (and gconv), preventing recursive calls when
661  * g_win32_locale_filename_from_utf8() is called during
662  * gettext initialization.
663  */
664 static gchar *
665 special_wchar_to_locale_encoding (wchar_t *wstring)
666 {
667   int sizeof_output;
668   int wctmb_result;
669   char *result;
670   BOOL not_representable = FALSE;
671
672   sizeof_output = WideCharToMultiByte (CP_ACP,
673                                        WC_NO_BEST_FIT_CHARS,
674                                        wstring, -1,
675                                        NULL, 0,
676                                        NULL,
677                                        &not_representable);
678
679   if (not_representable ||
680       sizeof_output == 0 ||
681       sizeof_output > MAX_PATH)
682     return NULL;
683
684   result = g_malloc0 (sizeof_output + 1);
685
686   wctmb_result = WideCharToMultiByte (CP_ACP,
687                                       WC_NO_BEST_FIT_CHARS,
688                                       wstring, -1,
689                                       result, sizeof_output + 1,
690                                       NULL,
691                                       &not_representable);
692
693   if (wctmb_result == sizeof_output &&
694       not_representable == FALSE)
695     return result;
696
697   g_free (result);
698
699   return NULL;
700 }
701
702 /**
703  * g_win32_locale_filename_from_utf8:
704  * @utf8filename: a UTF-8 encoded filename.
705  *
706  * Converts a filename from UTF-8 to the system codepage.
707  *
708  * On NT-based Windows, on NTFS file systems, file names are in
709  * Unicode. It is quite possible that Unicode file names contain
710  * characters not representable in the system codepage. (For instance,
711  * Greek or Cyrillic characters on Western European or US Windows
712  * installations, or various less common CJK characters on CJK Windows
713  * installations.)
714  *
715  * In such a case, and if the filename refers to an existing file, and
716  * the file system stores alternate short (8.3) names for directory
717  * entries, the short form of the filename is returned. Note that the
718  * "short" name might in fact be longer than the Unicode name if the
719  * Unicode name has very short pathname components containing
720  * non-ASCII characters. If no system codepage name for the file is
721  * possible, %NULL is returned.
722  *
723  * The return value is dynamically allocated and should be freed with
724  * g_free() when no longer needed.
725  *
726  * Returns: The converted filename, or %NULL on conversion
727  * failure and lack of short names.
728  *
729  * Since: 2.8
730  */
731 gchar *
732 g_win32_locale_filename_from_utf8 (const gchar *utf8filename)
733 {
734   gchar *retval;
735   wchar_t *wname;
736
737   wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL);
738
739   if (wname == NULL)
740     return NULL;
741
742   retval = special_wchar_to_locale_encoding (wname);
743
744   if (retval == NULL)
745     {
746       /* Conversion failed, so check if there is a 8.3 version, and use that. */
747       wchar_t wshortname[MAX_PATH + 1];
748
749       if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname)))
750         retval = special_wchar_to_locale_encoding (wshortname);
751     }
752
753   g_free (wname);
754
755   return retval;
756 }
757
758 /**
759  * g_win32_get_command_line:
760  *
761  * Gets the command line arguments, on Windows, in the GLib filename
762  * encoding (ie: UTF-8).
763  *
764  * Normally, on Windows, the command line arguments are passed to main()
765  * in the system codepage encoding.  This prevents passing filenames as
766  * arguments if the filenames contain characters that fall outside of
767  * this codepage.  If such filenames are passed, then substitutions
768  * will occur (such as replacing some characters with '?').
769  *
770  * GLib's policy of using UTF-8 as a filename encoding on Windows was
771  * designed to localise the pain of dealing with filenames outside of
772  * the system codepage to one area: dealing with commandline arguments
773  * in main().
774  *
775  * As such, most GLib programs should ignore the value of argv passed to
776  * their main() function and call g_win32_get_command_line() instead.
777  * This will get the "full Unicode" commandline arguments using
778  * GetCommandLineW() and convert it to the GLib filename encoding (which
779  * is UTF-8 on Windows).
780  *
781  * The strings returned by this function are suitable for use with
782  * functions such as g_open() and g_file_new_for_commandline_arg() but
783  * are not suitable for use with g_option_context_parse(), which assumes
784  * that its input will be in the system codepage.  The return value is
785  * suitable for use with g_option_context_parse_strv(), however, which
786  * is a better match anyway because it won't leak memory.
787  *
788  * Unlike argv, the returned value is a normal strv and can (and should)
789  * be freed with g_strfreev() when no longer needed.
790  *
791  * Returns: (transfer full): the commandline arguments in the GLib
792  *   filename encoding (ie: UTF-8)
793  *
794  * Since: 2.40
795  **/
796 gchar **
797 g_win32_get_command_line (void)
798 {
799   gchar **result;
800   LPWSTR *args;
801   gint i, n;
802
803   args = CommandLineToArgvW (GetCommandLineW(), &n);
804
805   result = g_new (gchar *, n + 1);
806   for (i = 0; i < n; i++)
807     result[i] = g_utf16_to_utf8 (args[i], -1, NULL, NULL, NULL);
808   result[i] = NULL;
809
810   LocalFree (args);
811   return result;
812 }
813
814 /* Binary compatibility versions. Not for newly compiled code. */
815
816 _GLIB_EXTERN gchar *g_win32_get_package_installation_directory_utf8    (const gchar *package,
817                                                                         const gchar *dll_name);
818
819 _GLIB_EXTERN gchar *g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
820                                                                         const gchar *dll_name,
821                                                                         const gchar *subdir);
822
823 gchar *
824 g_win32_get_package_installation_directory_utf8 (const gchar *package,
825                                                  const gchar *dll_name)
826 {
827 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
828   return g_win32_get_package_installation_directory (package, dll_name);
829 G_GNUC_END_IGNORE_DEPRECATIONS
830 }
831
832 gchar *
833 g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
834                                                     const gchar *dll_name,
835                                                     const gchar *subdir)
836 {
837 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
838   return g_win32_get_package_installation_subdirectory (package,
839                                                         dll_name,
840                                                         subdir);
841 G_GNUC_END_IGNORE_DEPRECATIONS
842 }
843
844 /* This function looks up two environment
845  * variables, G_WIN32_ALLOC_CONSOLE and G_WIN32_ATTACH_CONSOLE.
846  * G_WIN32_ALLOC_CONSOLE, if set to 1, makes the process
847  * call AllocConsole(). This is useful for binaries that
848  * are compiled to run without automatically-allocated console
849  * (like most GUI applications).
850  * G_WIN32_ATTACH_CONSOLE, if set to a comma-separated list
851  * of one or more strings "stdout", "stdin" and "stderr",
852  * makes the process reopen the corresponding standard streams
853  * to ensure that they are attached to the files that
854  * GetStdHandle() returns, which, hopefully, would be
855  * either a file handle or a console handle.
856  *
857  * This function is called automatically when glib DLL is
858  * attached to a process, from DllMain().
859  */
860 void
861 g_console_win32_init (void)
862 {
863   struct
864     {
865       gboolean     redirect;
866       FILE        *stream;
867       const gchar *stream_name;
868       DWORD        std_handle_type;
869       int          flags;
870       const gchar *mode;
871     }
872   streams[] =
873     {
874       { FALSE, stdin, "stdin", STD_INPUT_HANDLE, _O_RDONLY, "rb" },
875       { FALSE, stdout, "stdout", STD_OUTPUT_HANDLE, 0, "wb" },
876       { FALSE, stderr, "stderr", STD_ERROR_HANDLE, 0, "wb" },
877     };
878
879   const gchar  *attach_envvar;
880   guint         i;
881   gchar       **attach_strs;
882
883   /* Note: it's not a very good practice to use DllMain()
884    * to call any functions not in Kernel32.dll.
885    * The following only works if there are no weird
886    * circular DLL dependencies that could cause glib DllMain()
887    * to be called before CRT DllMain().
888    */
889
890   if (g_strcmp0 (g_getenv ("G_WIN32_ALLOC_CONSOLE"), "1") == 0)
891     AllocConsole (); /* no error handling, fails if console already exists */
892
893   attach_envvar = g_getenv ("G_WIN32_ATTACH_CONSOLE");
894
895   if (attach_envvar == NULL)
896     return;
897
898   /* Re-use parent console, if we don't have our own.
899    * If we do, it will fail, so just ignore the error.
900    */
901   AttachConsole (ATTACH_PARENT_PROCESS);
902
903   attach_strs = g_strsplit (attach_envvar, ",", -1);
904
905   for (i = 0; attach_strs[i]; i++)
906     {
907       if (g_strcmp0 (attach_strs[i], "stdout") == 0)
908         streams[1].redirect = TRUE;
909       else if (g_strcmp0 (attach_strs[i], "stderr") == 0)
910         streams[2].redirect = TRUE;
911       else if (g_strcmp0 (attach_strs[i], "stdin") == 0)
912         streams[0].redirect = TRUE;
913       else
914         g_warning ("Unrecognized stream name %s", attach_strs[i]);
915     }
916
917   g_strfreev (attach_strs);
918
919   for (i = 0; i < G_N_ELEMENTS (streams); i++)
920     {
921       int          old_fd;
922       int          backup_fd;
923       int          new_fd;
924       int          preferred_fd = i;
925       HANDLE       std_handle;
926       errno_t      errsv = 0;
927
928       if (!streams[i].redirect)
929         continue;
930
931       if (ferror (streams[i].stream) != 0)
932         {
933           g_warning ("Stream %s is in error state", streams[i].stream_name);
934           continue;
935         }
936
937       std_handle = GetStdHandle (streams[i].std_handle_type);
938
939       if (std_handle == INVALID_HANDLE_VALUE)
940         {
941           DWORD gle = GetLastError ();
942           g_warning ("Standard handle for %s can't be obtained: %lu",
943                      streams[i].stream_name, gle);
944           continue;
945         }
946
947       old_fd = fileno (streams[i].stream);
948
949       /* We need the stream object to be associated with
950        * any valid integer fd for the code to work.
951        * If it isn't, reopen it with NUL (/dev/null) to
952        * ensure that it is.
953        */
954       if (old_fd < 0)
955         {
956           if (freopen ("NUL", streams[i].mode, streams[i].stream) == NULL)
957             {
958               errsv = errno;
959               g_warning ("Failed to redirect %s: %d - %s",
960                          streams[i].stream_name,
961                          errsv,
962                          strerror (errsv));
963               continue;
964             }
965
966           old_fd = fileno (streams[i].stream);
967
968           if (old_fd < 0)
969             {
970               g_warning ("Stream %s does not have a valid fd",
971                          streams[i].stream_name);
972               continue;
973             }
974         }
975
976       new_fd = _open_osfhandle ((intptr_t) std_handle, streams[i].flags);
977
978       if (new_fd < 0)
979         {
980           g_warning ("Failed to create new fd for stream %s",
981                      streams[i].stream_name);
982           continue;
983         }
984
985       backup_fd = dup (old_fd);
986
987       if (backup_fd < 0)
988         g_warning ("Failed to backup old fd %d for stream %s",
989                    old_fd, streams[i].stream_name);
990
991       errno = 0;
992
993       /* Force old_fd to be associated with the same file
994        * as new_fd, i.e with the standard handle we need
995        * (or, rather, with the same kernel object; handle
996        * value will be different, but the kernel object
997        * won't be).
998        */
999       /* NOTE: MSDN claims that _dup2() returns 0 on success and -1 on error,
1000        * POSIX claims that dup2() reurns new FD on success and -1 on error.
1001        * The "< 0" check satisfies the error condition for either implementation.
1002        */
1003       if (_dup2 (new_fd, old_fd) < 0)
1004         {
1005           errsv = errno;
1006           g_warning ("Failed to substitute fd %d for stream %s: %d : %s",
1007                      old_fd, streams[i].stream_name, errsv, strerror (errsv));
1008
1009           _close (new_fd);
1010
1011           if (backup_fd < 0)
1012             continue;
1013
1014           errno = 0;
1015
1016           /* Try to restore old_fd back to its previous
1017            * handle, in case the _dup2() call above succeeded partially.
1018            */
1019           if (_dup2 (backup_fd, old_fd) < 0)
1020             {
1021               errsv = errno;
1022               g_warning ("Failed to restore fd %d for stream %s: %d : %s",
1023                          old_fd, streams[i].stream_name, errsv, strerror (errsv));
1024             }
1025
1026           _close (backup_fd);
1027
1028           continue;
1029         }
1030
1031       /* Success, drop the backup */
1032       if (backup_fd >= 0)
1033         _close (backup_fd);
1034
1035       /* Sadly, there's no way to check that preferred_fd
1036        * is currently valid, so we can't back it up.
1037        * Doing operations on invalid FDs invokes invalid
1038        * parameter handler, which is bad for us.
1039        */
1040       if (old_fd != preferred_fd)
1041         /* This extra code will also try to ensure that
1042          * the expected file descriptors 0, 1 and 2 are
1043          * associated with the appropriate standard
1044          * handles.
1045          */
1046         if (_dup2 (new_fd, preferred_fd) < 0)
1047           g_warning ("Failed to dup fd %d into fd %d", new_fd, preferred_fd);
1048
1049       _close (new_fd);
1050     }
1051 }
1052
1053 /* This is a handle to the Vectored Exception Handler that
1054  * we install on library initialization. If installed correctly,
1055  * it will be non-NULL. Only used to later de-install the handler
1056  * on library de-initialization.
1057  */
1058 static void        *WinVEH_handle = NULL;
1059
1060 #define             DEBUGGER_BUFFER_SIZE (MAX_PATH + 1)
1061 /* This is the debugger that we'll run on crash */
1062 static wchar_t      debugger[DEBUGGER_BUFFER_SIZE];
1063
1064 static gsize        number_of_exceptions_to_catch = 0;
1065 static DWORD       *exceptions_to_catch = NULL;
1066
1067 static HANDLE       debugger_wakeup_event = 0;
1068 static DWORD        debugger_spawn_flags = 0;
1069
1070 #include "gwin32-private.c"
1071
1072 static char *
1073 copy_chars (char       *buffer,
1074             gsize      *buffer_size,
1075             const char *to_copy)
1076 {
1077   gsize copy_count = MIN (strlen (to_copy), *buffer_size - 1);
1078   memset (buffer, 0x20, copy_count);
1079   strncpy_s (buffer, *buffer_size, to_copy, _TRUNCATE);
1080   *buffer_size -= copy_count;
1081   return &buffer[copy_count];
1082 }
1083
1084 /* Handles exceptions (useful for debugging).
1085  * Issues a DebugBreak() call if the process is being debugged (not really
1086  * useful - if the process is being debugged, this handler won't be invoked
1087  * anyway). If it is not, runs a debugger from G_DEBUGGER env var,
1088  * substituting first %p in it for PID, and the first %e for the event handle -
1089  * that event should be set once the debugger attaches itself (otherwise the
1090  * only way out of WaitForSingleObject() is to time out after 1 minute).
1091  * For example, G_DEBUGGER can be set to the following command:
1092  * ```
1093  * gdb.exe -ex "attach %p" -ex "signal-event %e" -ex "bt" -ex "c"
1094  * ```
1095  * This will make GDB attach to the process, signal the event (GDB must be
1096  * recent enough for the signal-event command to be available),
1097  * show the backtrace and resume execution, which should make it catch
1098  * the exception when Windows re-raises it again.
1099  * The command line can't be longer than MAX_PATH (260 characters).
1100  *
1101  * This function will only stop (and run a debugger) on the following exceptions:
1102  * * EXCEPTION_ACCESS_VIOLATION
1103  * * EXCEPTION_STACK_OVERFLOW
1104  * * EXCEPTION_ILLEGAL_INSTRUCTION
1105  * To make it stop at other exceptions one should set the G_VEH_CATCH
1106  * environment variable to a list of comma-separated hexadecimal numbers,
1107  * where each number is the code of an exception that should be caught.
1108  * This is done to prevent GLib from breaking when Windows uses
1109  * exceptions to shuttle information (SetThreadName(), OutputDebugString())
1110  * or for control flow.
1111  *
1112  * This function deliberately avoids calling any GLib code.
1113  * This is done on purpose. This function can be called when the program
1114  * is in a bad state (crashing). It can also be called very early, as soon
1115  * as the handler is installed. Therefore, it's imperative that
1116  * it does as little as possible. Preferably, all the work that can be
1117  * done in advance (when the program is not crashing yet) should be done
1118  * in advance.
1119  */
1120 static LONG __stdcall
1121 g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo)
1122 {
1123   EXCEPTION_RECORD    *er;
1124   gsize                i;
1125   STARTUPINFOW         si;
1126   PROCESS_INFORMATION  pi;
1127 #define ITOA_BUFFER_SIZE 100
1128   char                 itoa_buffer[ITOA_BUFFER_SIZE];
1129 #define DEBUG_STRING_SIZE 1024
1130   gsize                dbgs = DEBUG_STRING_SIZE;
1131   char                 debug_string[DEBUG_STRING_SIZE];
1132   char                *dbgp;
1133
1134   if (ExceptionInfo == NULL ||
1135       ExceptionInfo->ExceptionRecord == NULL ||
1136       IsDebuggerPresent () ||
1137       debugger[0] == 0)
1138     return EXCEPTION_CONTINUE_SEARCH;
1139
1140   er = ExceptionInfo->ExceptionRecord;
1141
1142   switch (er->ExceptionCode)
1143     {
1144     case EXCEPTION_ACCESS_VIOLATION:
1145     case EXCEPTION_STACK_OVERFLOW:
1146     case EXCEPTION_ILLEGAL_INSTRUCTION:
1147       break;
1148     default:
1149       for (i = 0; i < number_of_exceptions_to_catch; i++)
1150         if (exceptions_to_catch[i] == er->ExceptionCode)
1151           break;
1152
1153       if (i == number_of_exceptions_to_catch)
1154         return EXCEPTION_CONTINUE_SEARCH;
1155
1156       break;
1157     }
1158
1159   memset (&si, 0, sizeof (si));
1160   memset (&pi, 0, sizeof (pi));
1161   si.cb = sizeof (si);
1162
1163   /* Run the debugger */
1164   if (0 != CreateProcessW (NULL, debugger, NULL, NULL, TRUE, debugger_spawn_flags, NULL, NULL, &si, &pi))
1165     {
1166       CloseHandle (pi.hProcess);
1167       CloseHandle (pi.hThread);
1168       /* If successful, wait for 60 seconds on the event
1169        * we passed. The debugger should signal that event.
1170        * 60 second limit is here to prevent us from hanging
1171        * up forever in case the debugger does not support
1172        * event signalling.
1173        */
1174       WaitForSingleObject (debugger_wakeup_event, 60000);
1175
1176       dbgp = &debug_string[0];
1177
1178       dbgp = copy_chars (dbgp, &dbgs, "Exception code=0x");
1179       itoa_buffer[0] = 0;
1180       _ui64toa_s (er->ExceptionCode, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1181       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1182       dbgp = copy_chars (dbgp, &dbgs, " flags=0x");
1183       itoa_buffer[0] = 0;
1184       _ui64toa_s (er->ExceptionFlags, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1185       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1186       dbgp = copy_chars (dbgp, &dbgs, " at 0x");
1187       itoa_buffer[0] = 0;
1188       _ui64toa_s ((guintptr) er->ExceptionAddress, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1189       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1190
1191       switch (er->ExceptionCode)
1192         {
1193         case EXCEPTION_ACCESS_VIOLATION:
1194           dbgp = copy_chars (dbgp, &dbgs, ". Access violation - attempting to ");
1195           if (er->ExceptionInformation[0] == 0)
1196             dbgp = copy_chars (dbgp, &dbgs, "read data");
1197           else if (er->ExceptionInformation[0] == 1)
1198             dbgp = copy_chars (dbgp, &dbgs, "write data");
1199           else if (er->ExceptionInformation[0] == 8)
1200             dbgp = copy_chars (dbgp, &dbgs, "execute data");
1201           else
1202             dbgp = copy_chars (dbgp, &dbgs, "do something bad");
1203           dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
1204           itoa_buffer[0] = 0;
1205           _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1206           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1207           break;
1208         case EXCEPTION_IN_PAGE_ERROR:
1209           dbgp = copy_chars (dbgp, &dbgs, ". Page access violation - attempting to ");
1210           if (er->ExceptionInformation[0] == 0)
1211             dbgp = copy_chars (dbgp, &dbgs, "read from an inaccessible page");
1212           else if (er->ExceptionInformation[0] == 1)
1213             dbgp = copy_chars (dbgp, &dbgs, "write to an inaccessible page");
1214           else if (er->ExceptionInformation[0] == 8)
1215             dbgp = copy_chars (dbgp, &dbgs, "execute data in page");
1216           else
1217             dbgp = copy_chars (dbgp, &dbgs, "do something bad with a page");
1218           dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
1219           itoa_buffer[0] = 0;
1220           _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1221           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1222           dbgp = copy_chars (dbgp, &dbgs, " with status ");
1223           itoa_buffer[0] = 0;
1224           _ui64toa_s (er->ExceptionInformation[2], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1225           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1226           break;
1227         default:
1228           break;
1229         }
1230
1231       dbgp = copy_chars (dbgp, &dbgs, "\n");
1232       OutputDebugStringA (debug_string);
1233     }
1234
1235   /* Now the debugger is present, and we can try
1236    * resuming execution, re-triggering the exception,
1237    * which will be caught by debugger this time around.
1238    */
1239   if (IsDebuggerPresent ())
1240     return EXCEPTION_CONTINUE_EXECUTION;
1241
1242   return EXCEPTION_CONTINUE_SEARCH;
1243 }
1244
1245 static gsize
1246 parse_catch_list (const wchar_t *catch_buffer,
1247                   DWORD         *exceptions,
1248                   gsize          num_exceptions)
1249 {
1250   const wchar_t *catch_list = catch_buffer;
1251   gsize          result = 0;
1252   gsize          i = 0;
1253
1254   while (catch_list != NULL &&
1255          catch_list[0] != 0)
1256     {
1257       unsigned long  catch_code;
1258       wchar_t       *end;
1259       errno = 0;
1260       catch_code = wcstoul (catch_list, &end, 16);
1261       if (errno != NO_ERROR)
1262         break;
1263       catch_list = end;
1264       if (catch_list != NULL && catch_list[0] == L',')
1265         catch_list++;
1266       if (exceptions && i < num_exceptions)
1267         exceptions[i++] = catch_code;
1268     }
1269
1270   return result;
1271 }
1272
1273 void
1274 g_crash_handler_win32_init (void)
1275 {
1276   wchar_t      debugger_env[DEBUGGER_BUFFER_SIZE];
1277 #define CATCH_BUFFER_SIZE 1024
1278   wchar_t      catch_buffer[CATCH_BUFFER_SIZE];
1279   SECURITY_ATTRIBUTES  sa;
1280
1281   if (WinVEH_handle != NULL)
1282     return;
1283
1284   /* Do not register an exception handler if we're not supposed to catch any
1285    * exceptions. Exception handlers are considered dangerous to use, and can
1286    * break advanced exception handling such as in CLRs like C# or other managed
1287    * code. See: http://www.windows-tech.info/13/785f590867bd6316.php
1288    */
1289   debugger_env[0] = 0;
1290   if (!GetEnvironmentVariableW (L"G_DEBUGGER", debugger_env, DEBUGGER_BUFFER_SIZE))
1291     return;
1292
1293   /* Create an inheritable event */
1294   memset (&sa, 0, sizeof (sa));
1295   sa.nLength = sizeof (sa);
1296   sa.bInheritHandle = TRUE;
1297   debugger_wakeup_event = CreateEvent (&sa, FALSE, FALSE, NULL);
1298
1299   /* Put process ID and event handle into debugger commandline */
1300   if (!_g_win32_subst_pid_and_event_w (debugger, G_N_ELEMENTS (debugger),
1301                                        debugger_env, GetCurrentProcessId (),
1302                                        (guintptr) debugger_wakeup_event))
1303     {
1304       CloseHandle (debugger_wakeup_event);
1305       debugger_wakeup_event = 0;
1306       debugger[0] = 0;
1307       return;
1308     }
1309   debugger[MAX_PATH] = L'\0';
1310
1311   catch_buffer[0] = 0;
1312   if (GetEnvironmentVariableW (L"G_VEH_CATCH", catch_buffer, CATCH_BUFFER_SIZE))
1313     {
1314       number_of_exceptions_to_catch = parse_catch_list (catch_buffer, NULL, 0);
1315       if (number_of_exceptions_to_catch > 0)
1316         {
1317           exceptions_to_catch = g_new0 (DWORD, number_of_exceptions_to_catch);
1318           parse_catch_list (catch_buffer, exceptions_to_catch, number_of_exceptions_to_catch);
1319         }
1320     }
1321
1322   if (GetEnvironmentVariableW (L"G_DEBUGGER_OLD_CONSOLE", (wchar_t *) &debugger_spawn_flags, 1))
1323     debugger_spawn_flags = 0;
1324   else
1325     debugger_spawn_flags = CREATE_NEW_CONSOLE;
1326
1327   WinVEH_handle = AddVectoredExceptionHandler (0, &g_win32_veh_handler);
1328 }
1329
1330 void
1331 g_crash_handler_win32_deinit (void)
1332 {
1333   if (WinVEH_handle != NULL)
1334     RemoveVectoredExceptionHandler (WinVEH_handle);
1335
1336   WinVEH_handle = NULL;
1337 }
1338
1339 /**
1340  * g_win32_find_helper_executable_path:
1341  * @executable_name: (transfer none): name of the helper executable to find
1342  * (something like gspawn-win64-helper.exe or gdbus.exe for example).
1343  * @dll_handle: handle of the DLL to use as searching base path. Pass NULL
1344  * to take current process executable as searching base path.
1345  *
1346  * Find an external executable path and name starting in the same folder
1347  * as a specified DLL or current process executable path. Helper executables
1348  * (like gspawn-win64-helper.exe, gspawn-win64-helper-console.exe or
1349  * gdbus.exe for example) are generally installed in the same folder as the
1350  * corresponding DLL file.
1351  *
1352  * So, if package has been correctly installed, with a dynamic build of GLib,
1353  * the helper executable should be in the same directory as the corresponding
1354  * DLL file and searching should be straightforward.
1355  *
1356  * But if built statically, DLL handle is not available and we have to start
1357  * searching from the directory holding current executable. It may be very
1358  * different from the directory containing the helper program. In order to
1359  * find the right helper program automatically in all common situations, we
1360  * use this pattern:
1361  *
1362  * current directory
1363  *             |-- ???
1364  *             |-- bin
1365  *             |    |-- ???
1366  *             |-- lib
1367  *             |    |-- ???
1368  *             |-- glib
1369  *             |    |-- ???
1370  *             |-- gio
1371  *                  |-- ???
1372  *
1373  * starting at base searching path (DLL or current executable directory) and
1374  * getting up until the root path. If we cannot still find the helper program,
1375  * we'll rely on PATH as the last resort.
1376  *
1377  * Returns: (transfer full) (type filename) (nullable): the helper executable
1378  * path and name in the GLib filename encoding or NULL in case of error. It
1379  * should be deallocated with g_free().
1380  */
1381 gchar *
1382 g_win32_find_helper_executable_path (const gchar *executable_name, void *dll_handle)
1383 {
1384   static const gchar *const subdirs[] = { "", "bin", "lib", "glib", "gio" };
1385   static const gsize nb_subdirs = G_N_ELEMENTS (subdirs);
1386
1387   DWORD module_path_len;
1388   wchar_t module_path[MAX_PATH + 2] = { 0 };
1389   gchar *base_searching_path;
1390   gchar *p;
1391   gchar *executable_path;
1392   gsize i;
1393
1394   g_return_val_if_fail (executable_name && *executable_name, NULL);
1395
1396   module_path_len = GetModuleFileNameW (dll_handle, module_path, MAX_PATH + 1);
1397   /* The > MAX_PATH check prevents truncated module path usage */
1398   if (module_path_len == 0 || module_path_len > MAX_PATH)
1399     return NULL;
1400
1401   base_searching_path = g_utf16_to_utf8 (module_path, -1, NULL, NULL, NULL);
1402   if (base_searching_path == NULL)
1403     return NULL;
1404
1405   p = strrchr (base_searching_path, G_DIR_SEPARATOR);
1406   if (p == NULL)
1407     {
1408       g_free (base_searching_path);
1409       return NULL;
1410     }
1411   *p = '\0';
1412
1413   for (;;)
1414     {
1415       /* Search in subdirectories */
1416       for (i = 0; i < nb_subdirs; ++i)
1417         {
1418           /* As this function is exclusively used on Windows, the
1419            * executable_path is always an absolute path. At worse, when
1420            * reaching the root of the filesystem, base_searching_path may
1421            * equal something like "[Drive letter]:" but never "/" like on
1422            * Linux or Mac.
1423            * For the peace of mind we still assert this, just in case that
1424            * one day someone tries to use this function on Linux or Mac.
1425            */
1426           executable_path = g_build_filename (base_searching_path, subdirs[i], executable_name, NULL);
1427           g_assert (g_path_is_absolute (executable_path));
1428           if (g_file_test (executable_path, G_FILE_TEST_IS_REGULAR))
1429             break;
1430
1431           g_free (executable_path);
1432           executable_path = NULL;
1433         }
1434
1435       if (executable_path != NULL)
1436         break;
1437
1438       /* Let's get one directory level up */
1439       p = strrchr (base_searching_path, G_DIR_SEPARATOR);
1440       if (p == NULL)
1441         break;
1442
1443       *p = '\0';
1444     }
1445   g_free (base_searching_path);
1446
1447   if (executable_path == NULL)
1448     {
1449       /* Search in system PATH */
1450       executable_path = g_find_program_in_path (executable_name);
1451       if (executable_path == NULL)
1452         executable_path = g_strdup (executable_name);
1453     }
1454
1455   return executable_path;
1456 }
1457
1458 /*
1459  * g_win32_handle_is_socket:
1460  * @h: a win32 HANDLE
1461  *
1462  * Returns: %TRUE if the handle is a `SOCKET`.
1463  */
1464 gboolean
1465 g_win32_handle_is_socket (HANDLE h)
1466 {
1467   int option = 0;
1468   int optlen = sizeof (option);
1469
1470   /* according to: https://stackoverflow.com/a/50981652/1277510, this is reasonable */
1471   if (getsockopt ((SOCKET) h, SOL_SOCKET, SO_DEBUG, (char *) &option, &optlen) == SOCKET_ERROR)
1472     return FALSE;
1473
1474   return TRUE;
1475 }
1476
1477 /*
1478  * g_win32_reopen_noninherited:
1479  * @fd: (transfer full): A file descriptor
1480  * @mode: _open_osfhandle flags
1481  * @error: A location to return an error of type %G_FILE_ERROR
1482  *
1483  * Reopen the given @fd with `_O_NOINHERIT`.
1484  *
1485  * The @fd is closed on success.
1486  *
1487  * Returns: (transfer full): The new file-descriptor, or -1 on error.
1488  */
1489 int
1490 g_win32_reopen_noninherited (int fd,
1491                              int mode,
1492                              GError **error)
1493 {
1494   HANDLE h;
1495   HANDLE duph;
1496   int dupfd, errsv;
1497
1498   h = (HANDLE) _get_osfhandle (fd);
1499   errsv = errno;
1500
1501   if (h == INVALID_HANDLE_VALUE)
1502     {
1503       const char *emsg = g_strerror (errsv);
1504       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
1505                    "_get_osfhandle() failed: %s", emsg);
1506       return -1;
1507     }
1508
1509   if (g_win32_handle_is_socket (h))
1510     {
1511       WSAPROTOCOL_INFO info;
1512
1513       if (WSADuplicateSocket ((SOCKET) h,
1514                               GetCurrentProcessId (),
1515                               &info))
1516         {
1517           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1518           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1519                        "WSADuplicateSocket() failed: %s", emsg);
1520           g_free (emsg);
1521           return -1;
1522         }
1523
1524       duph = (HANDLE) WSASocket (FROM_PROTOCOL_INFO,
1525                                  FROM_PROTOCOL_INFO,
1526                                  FROM_PROTOCOL_INFO,
1527                                  &info, 0, 0);
1528       if (duph == (HANDLE) INVALID_SOCKET)
1529         {
1530           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1531           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1532                        "WSASocket() failed: %s", emsg);
1533           g_free (emsg);
1534           return -1;
1535         }
1536     }
1537   else if (DuplicateHandle (GetCurrentProcess (), h,
1538                             GetCurrentProcess (), &duph,
1539                             0, FALSE, DUPLICATE_SAME_ACCESS) == 0)
1540     {
1541       char *emsg = g_win32_error_message (GetLastError ());
1542       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1543                    "DuplicateHandle() failed: %s", emsg);
1544       g_free (emsg);
1545       return -1;
1546     }
1547
1548   /* the duph ownership is transferred to dupfd */
1549   dupfd = _open_osfhandle ((gintptr) duph, mode | _O_NOINHERIT);
1550   if (dupfd < 0)
1551     {
1552       g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1553                            "_open_osfhandle() failed");
1554       CloseHandle (duph);
1555       return -1;
1556     }
1557
1558   if (!g_close (fd, error))
1559     {
1560       /* ignore extra errors in this case */
1561       g_close (dupfd, NULL);
1562       return -1;
1563     }
1564
1565   return dupfd;
1566 }