diff src/os_win32.c @ 10781:c96534dd2b2f v8.0.0280

patch 8.0.0280: problem setting multi-byte environment var on MS-Windows commit https://github.com/vim/vim/commit/7c23d1d9d9cc1d3d19fe35708da7c5d5b3556e05 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Feb 1 13:14:16 2017 +0100 patch 8.0.0280: problem setting multi-byte environment var on MS-Windows Problem: On MS-Windows setting an environment variable with multi-byte strings does not work well. Solution: Use wputenv when possible. (Taro Muraoka, Ken Takata)
author Christian Brabandt <cb@256bit.org>
date Wed, 01 Feb 2017 13:15:06 +0100
parents b726d3ea70bc
children 04eb70c77cf4
line wrap: on
line diff
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -515,6 +515,7 @@ static char *null_libintl_textdomain(con
 static char *null_libintl_bindtextdomain(const char *, const char *);
 static char *null_libintl_bind_textdomain_codeset(const char *, const char *);
 static int null_libintl_putenv(const char *);
+static int null_libintl_wputenv(const wchar_t *);
 
 static HINSTANCE hLibintlDLL = NULL;
 char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext;
@@ -526,6 +527,7 @@ char *(*dyn_libintl_bindtextdomain)(cons
 char *(*dyn_libintl_bind_textdomain_codeset)(const char *, const char *)
 				       = null_libintl_bind_textdomain_codeset;
 int (*dyn_libintl_putenv)(const char *) = null_libintl_putenv;
+int (*dyn_libintl_wputenv)(const wchar_t *) = null_libintl_wputenv;
 
     int
 dyn_libintl_init(void)
@@ -591,9 +593,14 @@ dyn_libintl_init(void)
     /* _putenv() function for the libintl.dll is optional. */
     hmsvcrt = find_imported_module_by_funcname(hLibintlDLL, "getenv");
     if (hmsvcrt != NULL)
+    {
 	dyn_libintl_putenv = (void *)GetProcAddress(hmsvcrt, "_putenv");
-    if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == putenv)
+	dyn_libintl_wputenv = (void *)GetProcAddress(hmsvcrt, "_wputenv");
+    }
+    if (dyn_libintl_putenv == NULL || dyn_libintl_putenv == _putenv)
 	dyn_libintl_putenv = null_libintl_putenv;
+    if (dyn_libintl_wputenv == NULL || dyn_libintl_wputenv == _wputenv)
+	dyn_libintl_wputenv = null_libintl_wputenv;
 
     return 1;
 }
@@ -610,6 +617,7 @@ dyn_libintl_end(void)
     dyn_libintl_bindtextdomain	= null_libintl_bindtextdomain;
     dyn_libintl_bind_textdomain_codeset = null_libintl_bind_textdomain_codeset;
     dyn_libintl_putenv		= null_libintl_putenv;
+    dyn_libintl_wputenv		= null_libintl_wputenv;
 }
 
 /*ARGSUSED*/
@@ -658,6 +666,13 @@ null_libintl_putenv(const char *envstrin
     return 0;
 }
 
+/*ARGSUSED*/
+    int
+null_libintl_wputenv(const wchar_t *envstring)
+{
+    return 0;
+}
+
 #endif /* DYNAMIC_GETTEXT */
 
 /* This symbol is not defined in older versions of the SDK or Visual C++ */
@@ -6985,3 +7000,43 @@ fix_arg_enc(void)
     set_alist_count();
 }
 #endif
+
+    int
+mch_setenv(char *var, char *value, int x)
+{
+    char_u	*envbuf;
+
+    envbuf = alloc((unsigned)(STRLEN(var) + STRLEN(value) + 2));
+    if (envbuf == NULL)
+	return -1;
+
+    sprintf((char *)envbuf, "%s=%s", var, value);
+
+#ifdef FEAT_MBYTE
+    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
+    {
+	WCHAR	    *p = enc_to_utf16(envbuf, NULL);
+
+	vim_free(envbuf);
+	if (p == NULL)
+	    return -1;
+	_wputenv(p);
+# ifdef libintl_wputenv
+	libintl_wputenv(p);
+# endif
+	/* Unlike Un*x systems, we can free the string for _wputenv(). */
+	vim_free(p);
+    }
+    else
+#endif
+    {
+	_putenv((char *)envbuf);
+# ifdef libintl_putenv
+	libintl_putenv((char *)envbuf);
+# endif
+	/* Unlike Un*x systems, we can free the string for _putenv(). */
+	vim_free(envbuf);
+    }
+
+    return 0;
+}