*** a/configure
--- b/configure
***************
*** 17920,17925 **** case " $LIBOBJS " in
--- 17920,17931 ----
  esac
  
  case " $LIBOBJS " in
+   *" win32env.$ac_objext "* ) ;;
+   *) LIBOBJS="$LIBOBJS win32env.$ac_objext"
+  ;;
+ esac
+ 
+ case " $LIBOBJS " in
    *" win32error.$ac_objext "* ) ;;
    *) LIBOBJS="$LIBOBJS win32error.$ac_objext"
   ;;
*** a/configure.in
--- b/configure.in
***************
*** 1274,1279 **** AC_REPLACE_FUNCS(gettimeofday)
--- 1274,1280 ----
  AC_LIBOBJ(kill)
  AC_LIBOBJ(open)
  AC_LIBOBJ(rand)
+ AC_LIBOBJ(win32env)
  AC_LIBOBJ(win32error)
  AC_DEFINE([HAVE_SYMLINK], 1,
            [Define to 1 if you have the `symlink' function.])
*** a/src/backend/utils/adt/pg_locale.c
--- b/src/backend/utils/adt/pg_locale.c
***************
*** 55,60 ****
--- 55,63 ----
  #include "utils/memutils.h"
  #include "utils/pg_locale.h"
  
+ #ifdef WIN32
+ #include <shlwapi.h>
+ #endif
  
  #define		MAX_L10N_DATA		80
  
***************
*** 89,94 **** static char lc_monetary_envbuf[LC_ENV_BUFSIZE];
--- 92,101 ----
  static char lc_numeric_envbuf[LC_ENV_BUFSIZE];
  static char lc_time_envbuf[LC_ENV_BUFSIZE];
  
+ #ifdef WIN32
+ static char *IsoLocaleName(const char *); /* MSVC specific */
+ #endif
+ 
  
  /*
   * pg_perm_setlocale
***************
*** 148,155 **** pg_perm_setlocale(int category, const char *locale)
  		case LC_MESSAGES:
  			envvar = "LC_MESSAGES";
  			envbuf = lc_messages_envbuf;
  			break;
! #endif
  		case LC_MONETARY:
  			envvar = "LC_MONETARY";
  			envbuf = lc_monetary_envbuf;
--- 155,167 ----
  		case LC_MESSAGES:
  			envvar = "LC_MESSAGES";
  			envbuf = lc_messages_envbuf;
+ #ifdef WIN32
+ 			result = IsoLocaleName(locale);
+ 			if (result == NULL)
+ 				result = locale;
+ #endif /* WIN32 */
  			break;
! #endif /* LC_MESSAGES */
  		case LC_MONETARY:
  			envvar = "LC_MONETARY";
  			envbuf = lc_monetary_envbuf;
***************
*** 166,190 **** pg_perm_setlocale(int category, const char *locale)
  			elog(FATAL, "unrecognized LC category: %d", category);
  			envvar = NULL;		/* keep compiler quiet */
  			envbuf = NULL;
! 			break;
  	}
  
  	snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
  
- #ifndef WIN32
  	if (putenv(envbuf))
  		return NULL;
- #else
- 
- 	/*
- 	 * On Windows, we need to modify both the process environment and the
- 	 * cached version in msvcrt
- 	 */
- 	if (!SetEnvironmentVariable(envvar, result))
- 		return NULL;
- 	if (_putenv(envbuf))
- 		return NULL;
- #endif
  
  	return result;
  }
--- 178,190 ----
  			elog(FATAL, "unrecognized LC category: %d", category);
  			envvar = NULL;		/* keep compiler quiet */
  			envbuf = NULL;
! 			return NULL;
  	}
  
  	snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", envvar, result);
  
  	if (putenv(envbuf))
  		return NULL;
  
  	return result;
  }
***************
*** 599,601 **** cache_locale_time(void)
--- 599,650 ----
  
  	CurrentLCTimeValid = true;
  }
+ 
+ 
+ #ifdef WIN32
+ /*
+  *	Convert Windows locale name to the ISO formatted one
+  *	if possible.
+  *
+  *	This function returns NULL if conversion is impossible,
+  *	otherwise returns the pointer to a static area which
+  *	contains the iso formatted locale name.
+  */
+ static
+ char *IsoLocaleName(const char *winlocname)
+ {
+ #if (_MSC_VER >= 1400) /* VC8.0 or later */
+ 
+ 	static char iso_lc_messages[32];
+ 	_locale_t	loct = NULL;
+ 
+ 	if (pg_strcasecmp("c", winlocname) == 0 ||
+ 		pg_strcasecmp("posix", winlocname) == 0)
+ 	{
+ 		strncpy(iso_lc_messages, "C", sizeof(iso_lc_messages));
+ 		return iso_lc_messages;
+ 	}
+ 
+ 	loct = _create_locale(LC_CTYPE, winlocname);
+ 	if (loct != NULL)
+ 	{
+ 		char	isolang[32], isocrty[32];
+ 		LCID	lcid;
+ 
+ 		lcid = loct->locinfo->lc_handle[LC_CTYPE];
+ 		if (lcid == 0)
+ 			lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ 		_free_locale(loct);
+ 
+ 		GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, isolang, sizeof(isolang));
+ 		GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty, sizeof(isocrty));
+ 		snprintf(iso_lc_messages, sizeof(iso_lc_messages) - 1, "%s_%s", isolang, isocrty);
+ 		return iso_lc_messages;
+ 	}
+ 	return NULL;
+ #else
+ 	return NULL; /* does nothing. */
+ #endif /* _MSC_VER >= 1400 */
+ }
+ #endif /* WIN32 */
+ 
*** a/src/include/port/win32.h
--- b/src/include/port/win32.h
***************
*** 291,296 **** extern int	pgwin32_is_service(void);
--- 291,301 ----
  /* in port/win32error.c */
  extern void _dosmaperr(unsigned long);
  
+ /* in port/win32env.c */
+ extern int pgwin32_putenv(const char *);
+ extern void pgwin32_unsetenv(const char *);
+ #define putenv(x) pgwin32_putenv(x)
+ #define unsetenv(x) pgwin32_unsetenv(x)
  
  /* Things that exist in MingW headers, but need to be added to MSVC */
  #ifdef WIN32_ONLY_COMPILER
*** /dev/null
--- b/src/port/win32env.c
***************
*** 0 ****
--- 1,92 ----
+ /*-------------------------------------------------------------------------
+  *
+  * win32env.c
+  *    putenv() and unsetenv() for win32, that updates both process
+  *    environment and the cached versions in (potentially multiple)
+  *    MSVCRT.
+  *
+  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  *
+  * IDENTIFICATION
+  *	  $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "c.h"
+ 
+ int pgwin32_putenv(const char *envval)
+ {
+ 	char   *envcpy;
+ 	char   *cp;
+ 
+ 	/*
+ 	 * Each version of MSVCRT has its own _putenv() call in the runtime
+ 	 * library.
+ 	 *
+ 	 * If we're in VC 7.0 or later (means != mingw), update in
+ 	 * the 6.0 MSVCRT.DLL environment as well, to work with third party
+ 	 * libraries linked against it (such as gnuwin32 libraries).
+ 	 */
+ #if defined(_MSC_VER) && (_MSC_VER >= 1300)
+ 	typedef int 		(_cdecl *PUTENVPROC)(const char *);
+ 	HMODULE				hmodule;
+ 	static PUTENVPROC	putenvFunc = NULL;
+ 	int					ret;
+ 
+ 	if (putenvFunc == NULL)
+ 	{
+ 		hmodule = GetModuleHandle("msvcrt");
+ 		if (hmodule == NULL)
+ 			return 1;
+ 		putenvFunc = (PUTENVPROC)GetProcAddress(hmodule, "_putenv");
+ 		if (putenvFunc == NULL)
+ 			return 1;
+ 	}
+ 	ret = putenvFunc(envval);
+ 	if (ret != 0)
+ 		return ret;
+ #endif /* _MSC_VER >= 1300 */
+ 
+ 
+ 	/*
+ 	 * Update the process environment - to make modifications visible
+ 	 * to child processes.
+ 	 *
+ 	 * Need a copy of the string so we can modify it.
+ 	 */
+ 	envcpy = strdup(envval);
+ 	cp = strchr(envcpy, '=');
+ 	if (cp == NULL)
+ 		return -1;
+ 	*cp = '\0';
+ 	cp++;
+ 	if (strlen(cp) == 0)
+ 		cp = NULL;
+ 	if (!SetEnvironmentVariable(envcpy, cp))
+ 	{
+ 		free(envcpy);
+ 		return -1;
+ 	}
+ 	free(envcpy);
+ 
+ 	/* Finally, update our "own" cache */
+ 	return _putenv(envval);
+ }
+ 
+ void
+ pgwin32_unsetenv(const char *name)
+ {
+ 	char   *envbuf;
+ 
+ 	envbuf = (char *) malloc(strlen(name)+2);
+ 	if (!envbuf)
+ 		return;
+ 
+ 	sprintf(envbuf, "%s=", name);
+ 	pgwin32_putenv(envbuf);
+ 	free(envbuf);
+ }
+ 
*** a/src/tools/msvc/Mkvcbuild.pm
--- b/src/tools/msvc/Mkvcbuild.pm
***************
*** 44,53 **** sub mkvcbuild
  
      our @pgportfiles = qw(
        chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c
!       unsetenv.c getaddrinfo.c gettimeofday.c kill.c open.c rand.c
        snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c
        pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c
!       getopt.c getopt_long.c dirent.c rint.c win32error.c);
  
      $libpgport = $solution->AddProject('libpgport','lib','misc');
      $libpgport->AddDefine('FRONTEND');
--- 44,53 ----
  
      our @pgportfiles = qw(
        chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c
!       getaddrinfo.c gettimeofday.c kill.c open.c rand.c
        snprintf.c strlcat.c strlcpy.c copydir.c dirmod.c exec.c noblock.c path.c pipe.c
        pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c sprompt.c thread.c
!       getopt.c getopt_long.c dirent.c rint.c win32env.c win32error.c);
  
      $libpgport = $solution->AddProject('libpgport','lib','misc');
      $libpgport->AddDefine('FRONTEND');
