Imported Upstream version 2.74.3
[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   g_return_val_if_fail (_g_win32_call_rtl_version (&osverinfo), FALSE);
582
583   /* check the OS and Service Pack Versions */
584   if (osverinfo.dwMajorVersion > (DWORD) major)
585     is_ver_checked = TRUE;
586   else if (osverinfo.dwMajorVersion == (DWORD) major)
587     {
588       if (osverinfo.dwMinorVersion > (DWORD) minor)
589         is_ver_checked = TRUE;
590       else if (osverinfo.dwMinorVersion == (DWORD) minor)
591         if (osverinfo.wServicePackMajor >= (DWORD) spver)
592           is_ver_checked = TRUE;
593     }
594
595   /* Check OS Type */
596   if (is_ver_checked)
597     {
598       switch (os_type)
599         {
600           case G_WIN32_OS_ANY:
601             is_type_checked = TRUE;
602             break;
603           case G_WIN32_OS_WORKSTATION:
604             if (osverinfo.wProductType == VER_NT_WORKSTATION)
605               is_type_checked = TRUE;
606             break;
607           case G_WIN32_OS_SERVER:
608             if (osverinfo.wProductType == VER_NT_SERVER ||
609                 osverinfo.wProductType == VER_NT_DOMAIN_CONTROLLER)
610               is_type_checked = TRUE;
611             break;
612           default:
613             /* shouldn't get here normally */
614             g_warning ("Invalid os_type specified");
615             break;
616         }
617     }
618
619   return is_ver_checked && is_type_checked;
620 }
621
622 /**
623  * g_win32_get_windows_version:
624  *
625  * This function is deprecated. Use
626  * g_win32_check_windows_version() instead.
627  *
628  * Returns version information for the Windows operating system the
629  * code is running on. See MSDN documentation for the GetVersion()
630  * function. To summarize, the most significant bit is one on Win9x,
631  * and zero on NT-based systems. Since version 2.14, GLib works only
632  * on NT-based systems, so checking whether your are running on Win9x
633  * in your own software is moot. The least significant byte is 4 on
634  * Windows NT 4, and 5 on Windows XP. Software that needs really
635  * detailed version and feature information should use Win32 API like
636  * GetVersionEx() and VerifyVersionInfo().
637  *
638  * Returns: The version information.
639  *
640  * Deprecated: 2.44: Be aware that for Windows 8.1 and Windows Server
641  * 2012 R2 and later, this will return 62 unless the application is
642  * manifested for Windows 8.1/Windows Server 2012 R2, for example.
643  * MSDN stated that GetVersion(), which is used here, is subject to
644  * further change or removal after Windows 8.1.
645  **/
646 guint
647 g_win32_get_windows_version (void)
648 {
649   static gsize windows_version;
650
651   if (g_once_init_enter (&windows_version))
652     g_once_init_leave (&windows_version, GetVersion ());
653
654   return windows_version;
655 }
656
657 /*
658  * Doesn't use gettext (and gconv), preventing recursive calls when
659  * g_win32_locale_filename_from_utf8() is called during
660  * gettext initialization.
661  */
662 static gchar *
663 special_wchar_to_locale_encoding (wchar_t *wstring)
664 {
665   int sizeof_output;
666   int wctmb_result;
667   char *result;
668   BOOL not_representable = FALSE;
669
670   sizeof_output = WideCharToMultiByte (CP_ACP,
671                                        WC_NO_BEST_FIT_CHARS,
672                                        wstring, -1,
673                                        NULL, 0,
674                                        NULL,
675                                        &not_representable);
676
677   if (not_representable ||
678       sizeof_output == 0 ||
679       sizeof_output > MAX_PATH)
680     return NULL;
681
682   result = g_malloc0 (sizeof_output + 1);
683
684   wctmb_result = WideCharToMultiByte (CP_ACP,
685                                       WC_NO_BEST_FIT_CHARS,
686                                       wstring, -1,
687                                       result, sizeof_output + 1,
688                                       NULL,
689                                       &not_representable);
690
691   if (wctmb_result == sizeof_output &&
692       not_representable == FALSE)
693     return result;
694
695   g_free (result);
696
697   return NULL;
698 }
699
700 /**
701  * g_win32_locale_filename_from_utf8:
702  * @utf8filename: a UTF-8 encoded filename.
703  *
704  * Converts a filename from UTF-8 to the system codepage.
705  *
706  * On NT-based Windows, on NTFS file systems, file names are in
707  * Unicode. It is quite possible that Unicode file names contain
708  * characters not representable in the system codepage. (For instance,
709  * Greek or Cyrillic characters on Western European or US Windows
710  * installations, or various less common CJK characters on CJK Windows
711  * installations.)
712  *
713  * In such a case, and if the filename refers to an existing file, and
714  * the file system stores alternate short (8.3) names for directory
715  * entries, the short form of the filename is returned. Note that the
716  * "short" name might in fact be longer than the Unicode name if the
717  * Unicode name has very short pathname components containing
718  * non-ASCII characters. If no system codepage name for the file is
719  * possible, %NULL is returned.
720  *
721  * The return value is dynamically allocated and should be freed with
722  * g_free() when no longer needed.
723  *
724  * Returns: The converted filename, or %NULL on conversion
725  * failure and lack of short names.
726  *
727  * Since: 2.8
728  */
729 gchar *
730 g_win32_locale_filename_from_utf8 (const gchar *utf8filename)
731 {
732   gchar *retval;
733   wchar_t *wname;
734
735   wname = g_utf8_to_utf16 (utf8filename, -1, NULL, NULL, NULL);
736
737   if (wname == NULL)
738     return NULL;
739
740   retval = special_wchar_to_locale_encoding (wname);
741
742   if (retval == NULL)
743     {
744       /* Conversion failed, so check if there is a 8.3 version, and use that. */
745       wchar_t wshortname[MAX_PATH + 1];
746
747       if (GetShortPathNameW (wname, wshortname, G_N_ELEMENTS (wshortname)))
748         retval = special_wchar_to_locale_encoding (wshortname);
749     }
750
751   g_free (wname);
752
753   return retval;
754 }
755
756 /**
757  * g_win32_get_command_line:
758  *
759  * Gets the command line arguments, on Windows, in the GLib filename
760  * encoding (ie: UTF-8).
761  *
762  * Normally, on Windows, the command line arguments are passed to main()
763  * in the system codepage encoding.  This prevents passing filenames as
764  * arguments if the filenames contain characters that fall outside of
765  * this codepage.  If such filenames are passed, then substitutions
766  * will occur (such as replacing some characters with '?').
767  *
768  * GLib's policy of using UTF-8 as a filename encoding on Windows was
769  * designed to localise the pain of dealing with filenames outside of
770  * the system codepage to one area: dealing with commandline arguments
771  * in main().
772  *
773  * As such, most GLib programs should ignore the value of argv passed to
774  * their main() function and call g_win32_get_command_line() instead.
775  * This will get the "full Unicode" commandline arguments using
776  * GetCommandLineW() and convert it to the GLib filename encoding (which
777  * is UTF-8 on Windows).
778  *
779  * The strings returned by this function are suitable for use with
780  * functions such as g_open() and g_file_new_for_commandline_arg() but
781  * are not suitable for use with g_option_context_parse(), which assumes
782  * that its input will be in the system codepage.  The return value is
783  * suitable for use with g_option_context_parse_strv(), however, which
784  * is a better match anyway because it won't leak memory.
785  *
786  * Unlike argv, the returned value is a normal strv and can (and should)
787  * be freed with g_strfreev() when no longer needed.
788  *
789  * Returns: (transfer full): the commandline arguments in the GLib
790  *   filename encoding (ie: UTF-8)
791  *
792  * Since: 2.40
793  **/
794 gchar **
795 g_win32_get_command_line (void)
796 {
797   gchar **result;
798   LPWSTR *args;
799   gint i, n;
800
801   args = CommandLineToArgvW (GetCommandLineW(), &n);
802
803   result = g_new (gchar *, n + 1);
804   for (i = 0; i < n; i++)
805     result[i] = g_utf16_to_utf8 (args[i], -1, NULL, NULL, NULL);
806   result[i] = NULL;
807
808   LocalFree (args);
809   return result;
810 }
811
812 /* Binary compatibility versions. Not for newly compiled code. */
813
814 _GLIB_EXTERN gchar *g_win32_get_package_installation_directory_utf8    (const gchar *package,
815                                                                         const gchar *dll_name);
816
817 _GLIB_EXTERN gchar *g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
818                                                                         const gchar *dll_name,
819                                                                         const gchar *subdir);
820
821 gchar *
822 g_win32_get_package_installation_directory_utf8 (const gchar *package,
823                                                  const gchar *dll_name)
824 {
825 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
826   return g_win32_get_package_installation_directory (package, dll_name);
827 G_GNUC_END_IGNORE_DEPRECATIONS
828 }
829
830 gchar *
831 g_win32_get_package_installation_subdirectory_utf8 (const gchar *package,
832                                                     const gchar *dll_name,
833                                                     const gchar *subdir)
834 {
835 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
836   return g_win32_get_package_installation_subdirectory (package,
837                                                         dll_name,
838                                                         subdir);
839 G_GNUC_END_IGNORE_DEPRECATIONS
840 }
841
842 /* This function looks up two environment
843  * variables, G_WIN32_ALLOC_CONSOLE and G_WIN32_ATTACH_CONSOLE.
844  * G_WIN32_ALLOC_CONSOLE, if set to 1, makes the process
845  * call AllocConsole(). This is useful for binaries that
846  * are compiled to run without automatically-allocated console
847  * (like most GUI applications).
848  * G_WIN32_ATTACH_CONSOLE, if set to a comma-separated list
849  * of one or more strings "stdout", "stdin" and "stderr",
850  * makes the process reopen the corresponding standard streams
851  * to ensure that they are attached to the files that
852  * GetStdHandle() returns, which, hopefully, would be
853  * either a file handle or a console handle.
854  *
855  * This function is called automatically when glib DLL is
856  * attached to a process, from DllMain().
857  */
858 void
859 g_console_win32_init (void)
860 {
861   struct
862     {
863       gboolean     redirect;
864       FILE        *stream;
865       const gchar *stream_name;
866       DWORD        std_handle_type;
867       int          flags;
868       const gchar *mode;
869     }
870   streams[] =
871     {
872       { FALSE, stdin, "stdin", STD_INPUT_HANDLE, _O_RDONLY, "rb" },
873       { FALSE, stdout, "stdout", STD_OUTPUT_HANDLE, 0, "wb" },
874       { FALSE, stderr, "stderr", STD_ERROR_HANDLE, 0, "wb" },
875     };
876
877   const gchar  *attach_envvar;
878   guint         i;
879   gchar       **attach_strs;
880
881   /* Note: it's not a very good practice to use DllMain()
882    * to call any functions not in Kernel32.dll.
883    * The following only works if there are no weird
884    * circular DLL dependencies that could cause glib DllMain()
885    * to be called before CRT DllMain().
886    */
887
888   if (g_strcmp0 (g_getenv ("G_WIN32_ALLOC_CONSOLE"), "1") == 0)
889     AllocConsole (); /* no error handling, fails if console already exists */
890
891   attach_envvar = g_getenv ("G_WIN32_ATTACH_CONSOLE");
892
893   if (attach_envvar == NULL)
894     return;
895
896   /* Re-use parent console, if we don't have our own.
897    * If we do, it will fail, so just ignore the error.
898    */
899   AttachConsole (ATTACH_PARENT_PROCESS);
900
901   attach_strs = g_strsplit (attach_envvar, ",", -1);
902
903   for (i = 0; attach_strs[i]; i++)
904     {
905       if (g_strcmp0 (attach_strs[i], "stdout") == 0)
906         streams[1].redirect = TRUE;
907       else if (g_strcmp0 (attach_strs[i], "stderr") == 0)
908         streams[2].redirect = TRUE;
909       else if (g_strcmp0 (attach_strs[i], "stdin") == 0)
910         streams[0].redirect = TRUE;
911       else
912         g_warning ("Unrecognized stream name %s", attach_strs[i]);
913     }
914
915   g_strfreev (attach_strs);
916
917   for (i = 0; i < G_N_ELEMENTS (streams); i++)
918     {
919       int          old_fd;
920       int          backup_fd;
921       int          new_fd;
922       int          preferred_fd = i;
923       HANDLE       std_handle;
924       errno_t      errsv = 0;
925
926       if (!streams[i].redirect)
927         continue;
928
929       if (ferror (streams[i].stream) != 0)
930         {
931           g_warning ("Stream %s is in error state", streams[i].stream_name);
932           continue;
933         }
934
935       std_handle = GetStdHandle (streams[i].std_handle_type);
936
937       if (std_handle == INVALID_HANDLE_VALUE)
938         {
939           DWORD gle = GetLastError ();
940           g_warning ("Standard handle for %s can't be obtained: %lu",
941                      streams[i].stream_name, gle);
942           continue;
943         }
944
945       old_fd = fileno (streams[i].stream);
946
947       /* We need the stream object to be associated with
948        * any valid integer fd for the code to work.
949        * If it isn't, reopen it with NUL (/dev/null) to
950        * ensure that it is.
951        */
952       if (old_fd < 0)
953         {
954           if (freopen ("NUL", streams[i].mode, streams[i].stream) == NULL)
955             {
956               errsv = errno;
957               g_warning ("Failed to redirect %s: %d - %s",
958                          streams[i].stream_name,
959                          errsv,
960                          strerror (errsv));
961               continue;
962             }
963
964           old_fd = fileno (streams[i].stream);
965
966           if (old_fd < 0)
967             {
968               g_warning ("Stream %s does not have a valid fd",
969                          streams[i].stream_name);
970               continue;
971             }
972         }
973
974       new_fd = _open_osfhandle ((intptr_t) std_handle, streams[i].flags);
975
976       if (new_fd < 0)
977         {
978           g_warning ("Failed to create new fd for stream %s",
979                      streams[i].stream_name);
980           continue;
981         }
982
983       backup_fd = dup (old_fd);
984
985       if (backup_fd < 0)
986         g_warning ("Failed to backup old fd %d for stream %s",
987                    old_fd, streams[i].stream_name);
988
989       errno = 0;
990
991       /* Force old_fd to be associated with the same file
992        * as new_fd, i.e with the standard handle we need
993        * (or, rather, with the same kernel object; handle
994        * value will be different, but the kernel object
995        * won't be).
996        */
997       /* NOTE: MSDN claims that _dup2() returns 0 on success and -1 on error,
998        * POSIX claims that dup2() reurns new FD on success and -1 on error.
999        * The "< 0" check satisfies the error condition for either implementation.
1000        */
1001       if (_dup2 (new_fd, old_fd) < 0)
1002         {
1003           errsv = errno;
1004           g_warning ("Failed to substitute fd %d for stream %s: %d : %s",
1005                      old_fd, streams[i].stream_name, errsv, strerror (errsv));
1006
1007           _close (new_fd);
1008
1009           if (backup_fd < 0)
1010             continue;
1011
1012           errno = 0;
1013
1014           /* Try to restore old_fd back to its previous
1015            * handle, in case the _dup2() call above succeeded partially.
1016            */
1017           if (_dup2 (backup_fd, old_fd) < 0)
1018             {
1019               errsv = errno;
1020               g_warning ("Failed to restore fd %d for stream %s: %d : %s",
1021                          old_fd, streams[i].stream_name, errsv, strerror (errsv));
1022             }
1023
1024           _close (backup_fd);
1025
1026           continue;
1027         }
1028
1029       /* Success, drop the backup */
1030       if (backup_fd >= 0)
1031         _close (backup_fd);
1032
1033       /* Sadly, there's no way to check that preferred_fd
1034        * is currently valid, so we can't back it up.
1035        * Doing operations on invalid FDs invokes invalid
1036        * parameter handler, which is bad for us.
1037        */
1038       if (old_fd != preferred_fd)
1039         /* This extra code will also try to ensure that
1040          * the expected file descriptors 0, 1 and 2 are
1041          * associated with the appropriate standard
1042          * handles.
1043          */
1044         if (_dup2 (new_fd, preferred_fd) < 0)
1045           g_warning ("Failed to dup fd %d into fd %d", new_fd, preferred_fd);
1046
1047       _close (new_fd);
1048     }
1049 }
1050
1051 /* This is a handle to the Vectored Exception Handler that
1052  * we install on library initialization. If installed correctly,
1053  * it will be non-NULL. Only used to later de-install the handler
1054  * on library de-initialization.
1055  */
1056 static void        *WinVEH_handle = NULL;
1057
1058 #define             DEBUGGER_BUFFER_SIZE (MAX_PATH + 1)
1059 /* This is the debugger that we'll run on crash */
1060 static wchar_t      debugger[DEBUGGER_BUFFER_SIZE];
1061
1062 static gsize        number_of_exceptions_to_catch = 0;
1063 static DWORD       *exceptions_to_catch = NULL;
1064
1065 static HANDLE       debugger_wakeup_event = 0;
1066 static DWORD        debugger_spawn_flags = 0;
1067
1068 #include "gwin32-private.c"
1069
1070 static char *
1071 copy_chars (char       *buffer,
1072             gsize      *buffer_size,
1073             const char *to_copy)
1074 {
1075   gsize copy_count = MIN (strlen (to_copy), *buffer_size - 1);
1076   memset (buffer, 0x20, copy_count);
1077   strncpy_s (buffer, *buffer_size, to_copy, _TRUNCATE);
1078   *buffer_size -= copy_count;
1079   return &buffer[copy_count];
1080 }
1081
1082 /* Handles exceptions (useful for debugging).
1083  * Issues a DebugBreak() call if the process is being debugged (not really
1084  * useful - if the process is being debugged, this handler won't be invoked
1085  * anyway). If it is not, runs a debugger from G_DEBUGGER env var,
1086  * substituting first %p in it for PID, and the first %e for the event handle -
1087  * that event should be set once the debugger attaches itself (otherwise the
1088  * only way out of WaitForSingleObject() is to time out after 1 minute).
1089  * For example, G_DEBUGGER can be set to the following command:
1090  * ```
1091  * gdb.exe -ex "attach %p" -ex "signal-event %e" -ex "bt" -ex "c"
1092  * ```
1093  * This will make GDB attach to the process, signal the event (GDB must be
1094  * recent enough for the signal-event command to be available),
1095  * show the backtrace and resume execution, which should make it catch
1096  * the exception when Windows re-raises it again.
1097  * The command line can't be longer than MAX_PATH (260 characters).
1098  *
1099  * This function will only stop (and run a debugger) on the following exceptions:
1100  * * EXCEPTION_ACCESS_VIOLATION
1101  * * EXCEPTION_STACK_OVERFLOW
1102  * * EXCEPTION_ILLEGAL_INSTRUCTION
1103  * To make it stop at other exceptions one should set the G_VEH_CATCH
1104  * environment variable to a list of comma-separated hexadecimal numbers,
1105  * where each number is the code of an exception that should be caught.
1106  * This is done to prevent GLib from breaking when Windows uses
1107  * exceptions to shuttle information (SetThreadName(), OutputDebugString())
1108  * or for control flow.
1109  *
1110  * This function deliberately avoids calling any GLib code.
1111  * This is done on purpose. This function can be called when the program
1112  * is in a bad state (crashing). It can also be called very early, as soon
1113  * as the handler is installed. Therefore, it's imperative that
1114  * it does as little as possible. Preferably, all the work that can be
1115  * done in advance (when the program is not crashing yet) should be done
1116  * in advance.
1117  */
1118 static LONG __stdcall
1119 g_win32_veh_handler (PEXCEPTION_POINTERS ExceptionInfo)
1120 {
1121   EXCEPTION_RECORD    *er;
1122   gsize                i;
1123   STARTUPINFOW         si;
1124   PROCESS_INFORMATION  pi;
1125 #define ITOA_BUFFER_SIZE 100
1126   char                 itoa_buffer[ITOA_BUFFER_SIZE];
1127 #define DEBUG_STRING_SIZE 1024
1128   gsize                dbgs = DEBUG_STRING_SIZE;
1129   char                 debug_string[DEBUG_STRING_SIZE];
1130   char                *dbgp;
1131
1132   if (ExceptionInfo == NULL ||
1133       ExceptionInfo->ExceptionRecord == NULL ||
1134       IsDebuggerPresent () ||
1135       debugger[0] == 0)
1136     return EXCEPTION_CONTINUE_SEARCH;
1137
1138   er = ExceptionInfo->ExceptionRecord;
1139
1140   switch (er->ExceptionCode)
1141     {
1142     case EXCEPTION_ACCESS_VIOLATION:
1143     case EXCEPTION_STACK_OVERFLOW:
1144     case EXCEPTION_ILLEGAL_INSTRUCTION:
1145       break;
1146     default:
1147       for (i = 0; i < number_of_exceptions_to_catch; i++)
1148         if (exceptions_to_catch[i] == er->ExceptionCode)
1149           break;
1150
1151       if (i == number_of_exceptions_to_catch)
1152         return EXCEPTION_CONTINUE_SEARCH;
1153
1154       break;
1155     }
1156
1157   memset (&si, 0, sizeof (si));
1158   memset (&pi, 0, sizeof (pi));
1159   si.cb = sizeof (si);
1160
1161   /* Run the debugger */
1162   if (0 != CreateProcessW (NULL, debugger, NULL, NULL, TRUE, debugger_spawn_flags, NULL, NULL, &si, &pi))
1163     {
1164       CloseHandle (pi.hProcess);
1165       CloseHandle (pi.hThread);
1166       /* If successful, wait for 60 seconds on the event
1167        * we passed. The debugger should signal that event.
1168        * 60 second limit is here to prevent us from hanging
1169        * up forever in case the debugger does not support
1170        * event signalling.
1171        */
1172       WaitForSingleObject (debugger_wakeup_event, 60000);
1173
1174       dbgp = &debug_string[0];
1175
1176       dbgp = copy_chars (dbgp, &dbgs, "Exception code=0x");
1177       itoa_buffer[0] = 0;
1178       _ui64toa_s (er->ExceptionCode, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1179       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1180       dbgp = copy_chars (dbgp, &dbgs, " flags=0x");
1181       itoa_buffer[0] = 0;
1182       _ui64toa_s (er->ExceptionFlags, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1183       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1184       dbgp = copy_chars (dbgp, &dbgs, " at 0x");
1185       itoa_buffer[0] = 0;
1186       _ui64toa_s ((guintptr) er->ExceptionAddress, itoa_buffer, ITOA_BUFFER_SIZE, 16);
1187       dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1188
1189       switch (er->ExceptionCode)
1190         {
1191         case EXCEPTION_ACCESS_VIOLATION:
1192           dbgp = copy_chars (dbgp, &dbgs, ". Access violation - attempting to ");
1193           if (er->ExceptionInformation[0] == 0)
1194             dbgp = copy_chars (dbgp, &dbgs, "read data");
1195           else if (er->ExceptionInformation[0] == 1)
1196             dbgp = copy_chars (dbgp, &dbgs, "write data");
1197           else if (er->ExceptionInformation[0] == 8)
1198             dbgp = copy_chars (dbgp, &dbgs, "execute data");
1199           else
1200             dbgp = copy_chars (dbgp, &dbgs, "do something bad");
1201           dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
1202           itoa_buffer[0] = 0;
1203           _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1204           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1205           break;
1206         case EXCEPTION_IN_PAGE_ERROR:
1207           dbgp = copy_chars (dbgp, &dbgs, ". Page access violation - attempting to ");
1208           if (er->ExceptionInformation[0] == 0)
1209             dbgp = copy_chars (dbgp, &dbgs, "read from an inaccessible page");
1210           else if (er->ExceptionInformation[0] == 1)
1211             dbgp = copy_chars (dbgp, &dbgs, "write to an inaccessible page");
1212           else if (er->ExceptionInformation[0] == 8)
1213             dbgp = copy_chars (dbgp, &dbgs, "execute data in page");
1214           else
1215             dbgp = copy_chars (dbgp, &dbgs, "do something bad with a page");
1216           dbgp = copy_chars (dbgp, &dbgs, " at address 0x");
1217           itoa_buffer[0] = 0;
1218           _ui64toa_s (er->ExceptionInformation[1], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1219           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1220           dbgp = copy_chars (dbgp, &dbgs, " with status ");
1221           itoa_buffer[0] = 0;
1222           _ui64toa_s (er->ExceptionInformation[2], itoa_buffer, ITOA_BUFFER_SIZE, 16);
1223           dbgp = copy_chars (dbgp, &dbgs, itoa_buffer);
1224           break;
1225         default:
1226           break;
1227         }
1228
1229       dbgp = copy_chars (dbgp, &dbgs, "\n");
1230       OutputDebugStringA (debug_string);
1231     }
1232
1233   /* Now the debugger is present, and we can try
1234    * resuming execution, re-triggering the exception,
1235    * which will be caught by debugger this time around.
1236    */
1237   if (IsDebuggerPresent ())
1238     return EXCEPTION_CONTINUE_EXECUTION;
1239
1240   return EXCEPTION_CONTINUE_SEARCH;
1241 }
1242
1243 static gsize
1244 parse_catch_list (const wchar_t *catch_buffer,
1245                   DWORD         *exceptions,
1246                   gsize          num_exceptions)
1247 {
1248   const wchar_t *catch_list = catch_buffer;
1249   gsize          result = 0;
1250   gsize          i = 0;
1251
1252   while (catch_list != NULL &&
1253          catch_list[0] != 0)
1254     {
1255       unsigned long  catch_code;
1256       wchar_t       *end;
1257       errno = 0;
1258       catch_code = wcstoul (catch_list, &end, 16);
1259       if (errno != NO_ERROR)
1260         break;
1261       catch_list = end;
1262       if (catch_list != NULL && catch_list[0] == L',')
1263         catch_list++;
1264       if (exceptions && i < num_exceptions)
1265         exceptions[i++] = catch_code;
1266     }
1267
1268   return result;
1269 }
1270
1271 void
1272 g_crash_handler_win32_init (void)
1273 {
1274   wchar_t      debugger_env[DEBUGGER_BUFFER_SIZE];
1275 #define CATCH_BUFFER_SIZE 1024
1276   wchar_t      catch_buffer[CATCH_BUFFER_SIZE];
1277   SECURITY_ATTRIBUTES  sa;
1278
1279   if (WinVEH_handle != NULL)
1280     return;
1281
1282   /* Do not register an exception handler if we're not supposed to catch any
1283    * exceptions. Exception handlers are considered dangerous to use, and can
1284    * break advanced exception handling such as in CLRs like C# or other managed
1285    * code. See: http://www.windows-tech.info/13/785f590867bd6316.php
1286    */
1287   debugger_env[0] = 0;
1288   if (!GetEnvironmentVariableW (L"G_DEBUGGER", debugger_env, DEBUGGER_BUFFER_SIZE))
1289     return;
1290
1291   /* Create an inheritable event */
1292   memset (&sa, 0, sizeof (sa));
1293   sa.nLength = sizeof (sa);
1294   sa.bInheritHandle = TRUE;
1295   debugger_wakeup_event = CreateEvent (&sa, FALSE, FALSE, NULL);
1296
1297   /* Put process ID and event handle into debugger commandline */
1298   if (!_g_win32_subst_pid_and_event_w (debugger, G_N_ELEMENTS (debugger),
1299                                        debugger_env, GetCurrentProcessId (),
1300                                        (guintptr) debugger_wakeup_event))
1301     {
1302       CloseHandle (debugger_wakeup_event);
1303       debugger_wakeup_event = 0;
1304       debugger[0] = 0;
1305       return;
1306     }
1307   debugger[MAX_PATH] = L'\0';
1308
1309   catch_buffer[0] = 0;
1310   if (GetEnvironmentVariableW (L"G_VEH_CATCH", catch_buffer, CATCH_BUFFER_SIZE))
1311     {
1312       number_of_exceptions_to_catch = parse_catch_list (catch_buffer, NULL, 0);
1313       if (number_of_exceptions_to_catch > 0)
1314         {
1315           exceptions_to_catch = g_new0 (DWORD, number_of_exceptions_to_catch);
1316           parse_catch_list (catch_buffer, exceptions_to_catch, number_of_exceptions_to_catch);
1317         }
1318     }
1319
1320   if (GetEnvironmentVariableW (L"G_DEBUGGER_OLD_CONSOLE", (wchar_t *) &debugger_spawn_flags, 1))
1321     debugger_spawn_flags = 0;
1322   else
1323     debugger_spawn_flags = CREATE_NEW_CONSOLE;
1324
1325   WinVEH_handle = AddVectoredExceptionHandler (0, &g_win32_veh_handler);
1326 }
1327
1328 void
1329 g_crash_handler_win32_deinit (void)
1330 {
1331   if (WinVEH_handle != NULL)
1332     RemoveVectoredExceptionHandler (WinVEH_handle);
1333
1334   WinVEH_handle = NULL;
1335 }
1336
1337 /**
1338  * g_win32_find_helper_executable_path:
1339  * @executable_name: (transfer none): name of the helper executable to find
1340  * (something like gspawn-win64-helper.exe or gdbus.exe for example).
1341  * @dll_handle: handle of the DLL to use as searching base path. Pass NULL
1342  * to take current process executable as searching base path.
1343  *
1344  * Find an external executable path and name starting in the same folder
1345  * as a specified DLL or current process executable path. Helper executables
1346  * (like gspawn-win64-helper.exe, gspawn-win64-helper-console.exe or
1347  * gdbus.exe for example) are generally installed in the same folder as the
1348  * corresponding DLL file.
1349  *
1350  * So, if package has been correctly installed, with a dynamic build of GLib,
1351  * the helper executable should be in the same directory as the corresponding
1352  * DLL file and searching should be straightforward.
1353  *
1354  * But if built statically, DLL handle is not available and we have to start
1355  * searching from the directory holding current executable. It may be very
1356  * different from the directory containing the helper program. In order to
1357  * find the right helper program automatically in all common situations, we
1358  * use this pattern:
1359  *
1360  * current directory
1361  *             |-- ???
1362  *             |-- bin
1363  *             |    |-- ???
1364  *             |-- lib
1365  *             |    |-- ???
1366  *             |-- glib
1367  *             |    |-- ???
1368  *             |-- gio
1369  *                  |-- ???
1370  *
1371  * starting at base searching path (DLL or current executable directory) and
1372  * getting up until the root path. If we cannot still find the helper program,
1373  * we'll rely on PATH as the last resort.
1374  *
1375  * Returns: (transfer full) (type filename) (nullable): the helper executable
1376  * path and name in the GLib filename encoding or NULL in case of error. It
1377  * should be deallocated with g_free().
1378  */
1379 gchar *
1380 g_win32_find_helper_executable_path (const gchar *executable_name, void *dll_handle)
1381 {
1382   static const gchar *const subdirs[] = { "", "bin", "lib", "glib", "gio" };
1383   static const gsize nb_subdirs = G_N_ELEMENTS (subdirs);
1384
1385   DWORD module_path_len;
1386   wchar_t module_path[MAX_PATH + 2] = { 0 };
1387   gchar *base_searching_path;
1388   gchar *p;
1389   gchar *executable_path;
1390   gsize i;
1391
1392   g_return_val_if_fail (executable_name && *executable_name, NULL);
1393
1394   module_path_len = GetModuleFileNameW (dll_handle, module_path, MAX_PATH + 1);
1395   /* The > MAX_PATH check prevents truncated module path usage */
1396   if (module_path_len == 0 || module_path_len > MAX_PATH)
1397     return NULL;
1398
1399   base_searching_path = g_utf16_to_utf8 (module_path, -1, NULL, NULL, NULL);
1400   if (base_searching_path == NULL)
1401     return NULL;
1402
1403   p = strrchr (base_searching_path, G_DIR_SEPARATOR);
1404   if (p == NULL)
1405     {
1406       g_free (base_searching_path);
1407       return NULL;
1408     }
1409   *p = '\0';
1410
1411   for (;;)
1412     {
1413       /* Search in subdirectories */
1414       for (i = 0; i < nb_subdirs; ++i)
1415         {
1416           /* As this function is exclusively used on Windows, the
1417            * executable_path is always an absolute path. At worse, when
1418            * reaching the root of the filesystem, base_searching_path may
1419            * equal something like "[Drive letter]:" but never "/" like on
1420            * Linux or Mac.
1421            * For the peace of mind we still assert this, just in case that
1422            * one day someone tries to use this function on Linux or Mac.
1423            */
1424           executable_path = g_build_filename (base_searching_path, subdirs[i], executable_name, NULL);
1425           g_assert (g_path_is_absolute (executable_path));
1426           if (g_file_test (executable_path, G_FILE_TEST_IS_REGULAR))
1427             break;
1428
1429           g_free (executable_path);
1430           executable_path = NULL;
1431         }
1432
1433       if (executable_path != NULL)
1434         break;
1435
1436       /* Let's get one directory level up */
1437       p = strrchr (base_searching_path, G_DIR_SEPARATOR);
1438       if (p == NULL)
1439         break;
1440
1441       *p = '\0';
1442     }
1443   g_free (base_searching_path);
1444
1445   if (executable_path == NULL)
1446     {
1447       /* Search in system PATH */
1448       executable_path = g_find_program_in_path (executable_name);
1449       if (executable_path == NULL)
1450         executable_path = g_strdup (executable_name);
1451     }
1452
1453   return executable_path;
1454 }
1455
1456 /*
1457  * g_win32_handle_is_socket:
1458  * @h: a win32 HANDLE
1459  *
1460  * Returns: %TRUE if the handle is a `SOCKET`.
1461  */
1462 gboolean
1463 g_win32_handle_is_socket (HANDLE h)
1464 {
1465   int option = 0;
1466   int optlen = sizeof (option);
1467
1468   /* according to: https://stackoverflow.com/a/50981652/1277510, this is reasonable */
1469   if (getsockopt ((SOCKET) h, SOL_SOCKET, SO_DEBUG, (char *) &option, &optlen) == SOCKET_ERROR)
1470     return FALSE;
1471
1472   return TRUE;
1473 }
1474
1475 /*
1476  * g_win32_reopen_noninherited:
1477  * @fd: (transfer full): A file descriptor
1478  * @mode: _open_osfhandle flags
1479  * @error: A location to return an error of type %G_FILE_ERROR
1480  *
1481  * Reopen the given @fd with `_O_NOINHERIT`.
1482  *
1483  * The @fd is closed on success.
1484  *
1485  * Returns: (transfer full): The new file-descriptor, or -1 on error.
1486  */
1487 int
1488 g_win32_reopen_noninherited (int fd,
1489                              int mode,
1490                              GError **error)
1491 {
1492   HANDLE h;
1493   HANDLE duph;
1494   int dupfd, errsv;
1495
1496   h = (HANDLE) _get_osfhandle (fd);
1497   errsv = errno;
1498
1499   if (h == INVALID_HANDLE_VALUE)
1500     {
1501       const char *emsg = g_strerror (errsv);
1502       g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errsv),
1503                    "_get_osfhandle() failed: %s", emsg);
1504       return -1;
1505     }
1506
1507   if (g_win32_handle_is_socket (h))
1508     {
1509       WSAPROTOCOL_INFO info;
1510
1511       if (WSADuplicateSocket ((SOCKET) h,
1512                               GetCurrentProcessId (),
1513                               &info))
1514         {
1515           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1516           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1517                        "WSADuplicateSocket() failed: %s", emsg);
1518           g_free (emsg);
1519           return -1;
1520         }
1521
1522       duph = (HANDLE) WSASocket (FROM_PROTOCOL_INFO,
1523                                  FROM_PROTOCOL_INFO,
1524                                  FROM_PROTOCOL_INFO,
1525                                  &info, 0, 0);
1526       if (duph == (HANDLE) INVALID_SOCKET)
1527         {
1528           gchar *emsg = g_win32_error_message (WSAGetLastError ());
1529           g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1530                        "WSASocket() failed: %s", emsg);
1531           g_free (emsg);
1532           return -1;
1533         }
1534     }
1535   else if (DuplicateHandle (GetCurrentProcess (), h,
1536                             GetCurrentProcess (), &duph,
1537                             0, FALSE, DUPLICATE_SAME_ACCESS) == 0)
1538     {
1539       char *emsg = g_win32_error_message (GetLastError ());
1540       g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1541                    "DuplicateHandle() failed: %s", emsg);
1542       g_free (emsg);
1543       return -1;
1544     }
1545
1546   /* the duph ownership is transferred to dupfd */
1547   dupfd = _open_osfhandle ((gintptr) duph, mode | _O_NOINHERIT);
1548   if (dupfd < 0)
1549     {
1550       g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1551                            "_open_osfhandle() failed");
1552       CloseHandle (duph);
1553       return -1;
1554     }
1555
1556   if (!g_close (fd, error))
1557     {
1558       /* ignore extra errors in this case */
1559       g_close (dupfd, NULL);
1560       return -1;
1561     }
1562
1563   return dupfd;
1564 }