diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 2562eb5..7ff29a7 100644
--- a/src/backend/utils/adt/pg_locale.c
+++ b/src/backend/utils/adt/pg_locale.c
@@ -971,43 +971,113 @@ cache_locale_time(void)
  * string.  Furthermore, msvcr110.dll changed the undocumented _locale_t
  * content to carry locale names instead of locale identifiers.
  *
- * MinGW headers declare _create_locale(), but msvcrt.dll lacks that symbol.
- * IsoLocaleName() always fails in a MinGW-built postgres.exe, so only
- * Unix-style values of the lc_messages GUC can elicit localized messages.  In
- * particular, every lc_messages setting that initdb can select automatically
- * will yield only C-locale messages.  XXX This could be fixed by running the
- * fully-qualified locale name through a lookup table.
+ * MinGW headers declare _create_locale(), but msvcrt.dll lacks that symbol in
+ * releases before Windows 8. IsoLocaleName() always fails in a MinGW-built
+ * postgres.exe, so only Unix-style values of the lc_messages GUC can elicit
+ * localized messages. In particular, every lc_messages setting that initdb can
+ * select automatically will yield only C-locale messages. XXX This could be
+ * fixed by running the fully-qualified locale name through a lookup table or
+ * using EnumSystemLocalesEx() from Windows Vista/2008.
  *
  * This function returns a pointer to a static buffer bearing the converted
  * name or NULL if conversion fails.
  *
- * [1] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373763.aspx
- * [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373814.aspx
+ * [1] https://docs.microsoft.com/en-us/windows/win32/intl/locale-identifiers
+ * [2] https://docs.microsoft.com/en-us/windows/win32/intl/locale-names
  */
+#if _WIN32_WINNT >= 0x0600
+/*
+ * Callback function for EnumSystemLocalesEx.
+ * Stop enumarating if a match is found for a locale with the format
+ * <Language>_<Country>.
+ */
+static BOOL CALLBACK
+enum_locales_fn(LPWSTR pStr, DWORD dwFlags, LPARAM lparam)
+{
+	WCHAR	**argv = (WCHAR **) lparam;
+	WCHAR	test_locale[LOCALE_NAME_MAX_LENGTH];
+
+	memset(test_locale, 0, sizeof(test_locale));
+	if (GetLocaleInfoEx(pStr, LOCALE_SENGLISHLANGUAGENAME,
+						test_locale, LOCALE_NAME_MAX_LENGTH) > 0)
+	{
+		wcscat(test_locale, L"_");
+		size_t		len = wcslen(test_locale);
+		if (GetLocaleInfoEx(pStr, LOCALE_SENGLISHCOUNTRYNAME,
+							test_locale + len, LOCALE_NAME_MAX_LENGTH - len) > 0)
+		{
+			if (wcsncmp(argv[0], test_locale, wcslen(test_locale)) == 0)
+			{
+				wcscpy(argv[1], pStr);
+				return FALSE;
+			}
+		}
+	}
+	return TRUE;
+}
+#endif		/* _WIN32_WINNT >= 0x0600 */
+
 static char *
 IsoLocaleName(const char *winlocname)
 {
-#ifdef _MSC_VER
-	static char iso_lc_messages[32];
-	_locale_t	loct = NULL;
+#if defined(_MSC_VER) || _WIN32_WINNT >= 0x0600
+	static char iso_lc_messages[LOCALE_NAME_MAX_LENGTH];
 
 	if (pg_strcasecmp("c", winlocname) == 0 ||
 		pg_strcasecmp("posix", winlocname) == 0)
 	{
-		strcpy(iso_lc_messages, "C");
-		return iso_lc_messages;
+		return "C";
 	}
-
-	loct = _create_locale(LC_CTYPE, winlocname);
-	if (loct != NULL)
+	else
 	{
 		size_t		rc;
 		char	   *hyphen;
+#if _WIN32_WINNT >= 0x0600
+		WCHAR		wc_locale_name[LOCALE_NAME_MAX_LENGTH];
+		WCHAR		buffer[LOCALE_NAME_MAX_LENGTH];
+		char	   *period;
+		int			len;
+
+		/*
+		 * Valid locales have the following syntax:
+		 * <Language>[_<Country>[.<CodePage>]]
+		 * GetLocaleInfoEx can only take locale name without code-page.
+		 */
+		period = strchr(winlocname, '.');
+		if (period != NULL)
+			len = period - winlocname;
+		else
+			len = pg_mbstrlen(winlocname);
+
+		memset(wc_locale_name, 0, sizeof(wc_locale_name));
+		memset(buffer, 0, sizeof(buffer));
+		MultiByteToWideChar(CP_ACP, 0, winlocname, len, wc_locale_name,
+							LOCALE_NAME_MAX_LENGTH);
+		if (GetLocaleInfoEx(wc_locale_name, LOCALE_SNAME, (LPWSTR) &buffer,
+						LOCALE_NAME_MAX_LENGTH) <= 0)
+		{
+			/* Enumerate all locales supported by the system until match. */
+			WCHAR	  *argv[2];
+
+			argv[0] = wc_locale_name;
+			argv[1] = buffer;
+			EnumSystemLocalesEx(enum_locales_fn, LOCALE_WINDOWS, (LPARAM) argv,
+								NULL);
+		}
 
 		/* Locale names use only ASCII, any conversion locale suffices. */
-		rc = wchar2char(iso_lc_messages, loct->locinfo->locale_name[LC_CTYPE],
-						sizeof(iso_lc_messages), NULL);
+		rc = wchar2char(iso_lc_messages, buffer, sizeof(iso_lc_messages),
+						NULL);
+#else   	/* _WIN32_WINNT < 0x0600 */
+		_locale_t	loct;
+
+		loct = _create_locale(LC_CTYPE, winlocname);
+		if (loct != NULL)
+			rc = wchar2char(iso_lc_messages, loct->locinfo->locale_name[LC_CTYPE],
+							sizeof(iso_lc_messages), NULL);
 		_free_locale(loct);
+#endif		/* _WIN32_WINNT >= 0x0600 */
+
 		if (rc == -1 || rc == sizeof(iso_lc_messages))
 			return NULL;
 
@@ -1029,7 +1099,7 @@ IsoLocaleName(const char *winlocname)
 			*hyphen = '_';
 		return iso_lc_messages;
 	}
-#endif							/* _MSC_VER */
+#endif							/* defined(_MSC_VER) || _WIN32_WINNT >= 0x0600 */
 	return NULL;				/* Not supported on this version of msvc/mingw */
 }
 #endif							/* WIN32 && LC_MESSAGES */
