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