kernel32: set sLanguage to LOCALE_SABBREVLANGUAGE to match Windows behavior

Jeff Zaroyko jeffzaroyko at gmail.com
Sat Aug 22 22:09:40 CDT 2009


This fixes bug 15181, test included - passes on Windows 95, 2003, XP,
2008, Vista and Windows 7 beta that I've tested.
-------------- next part --------------
From 52ff2d29ba9fbffbe8da46a7523338e8b946bbcd Mon Sep 17 00:00:00 2001
From: Jeff Zaroyko <jeffz at jeffz.name>
Date: Sun, 23 Aug 2009 12:38:17 +1000
Subject: kernel32: set sLanguage to LOCALE_SABBREVLANGUAGE to match Windows behavior

As a Profile entry and under Control Panel\International sLanguage is not
LOCALE_SLANGUAGE but instead appears to be LOCALE_SABBREVLANGNAME.

I've verified this is the case for 95, XP, 2003, 2008, Vista and Win 7.

With the sLanguage override set GetLocaleInfo for LOCALE_SLANGUAGE still
returns the LOCALE_SLANGUAGE string and not the "override", which suggests
that the Control Panel\International sLanguage override should be ignored
by GetLocaleInfo for LOCALE_SLANGUAGE.
---
 dlls/kernel32/locale.c       |   11 +++++++++++
 dlls/kernel32/tests/locale.c |   16 ++++++++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index fa17689..169485b 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -62,6 +62,7 @@ static const union cptable *mac_cptable;
 static const union cptable *unix_cptable;  /* NULL if UTF8 */
 
 static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName);
+static const WCHAR *get_locale_value_name( DWORD lctype );
 
 static const WCHAR szNlsKeyName[] = {
     'M','a','c','h','i','n','e','\\','S','y','s','t','e','m','\\',
@@ -663,6 +664,7 @@ void LOCALE_InitRegistry(void)
     static const WCHAR lc_measurementW[] = { 'L','C','_','M','E','A','S','U','R','E','M','E','N','T',0 };
     static const WCHAR lc_telephoneW[] = { 'L','C','_','T','E','L','E','P','H','O','N','E',0 };
     static const WCHAR lc_paperW[] = { 'L','C','_','P','A','P','E','R',0};
+    static const WCHAR intlW[] = {'i','n','t','l',0 };
     static const struct
     {
         LPCWSTR name;
@@ -753,6 +755,14 @@ void LOCALE_InitRegistry(void)
         NtClose( nls_key );
     }
 
+    /* As a Profile entry and under Control Panel\International sLanguage is not LOCALE_SLANGUAGE
+       but instead appears to be LOCALE_SABBREVLANGNAME, yet GetLocaleInfo for LOCALE_SLANGUAGE
+       should indeed return the LOCALE_SLANGUAGE string. */
+    count = GetLocaleInfoW( lcid, LOCALE_SABBREVLANGNAME, bufferW, sizeof bufferW / sizeof(WCHAR) );
+    RtlInitUnicodeString( &nameW, get_locale_value_name( LOCALE_SLANGUAGE ));
+    NtSetValueKey( hkey, &nameW, 0, REG_SZ, bufferW, count * sizeof(WCHAR) );
+    GetLocaleInfoW( lcid, LOCALE_SABBREVLANGNAME, bufferW, sizeof bufferW / sizeof(WCHAR) );
+    WriteProfileStringW( intlW, get_locale_value_name( LOCALE_SLANGUAGE ), bufferW );
     NtClose( hkey );
 }
 
@@ -1233,6 +1243,7 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len )
     /* first check for overrides in the registry */
 
     if (!(lcflags & LOCALE_NOUSEROVERRIDE) &&
+        (lctype != LOCALE_SLANGUAGE) &&
         lcid == convert_default_lcid( LOCALE_USER_DEFAULT, lctype ))
     {
         const WCHAR *value = get_locale_value_name(lctype);
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 8a56100..fa0ff8e 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -34,6 +34,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "winnls.h"
+#include "winreg.h"
 
 static inline unsigned int strlenW( const WCHAR *str )
 {
@@ -119,6 +120,7 @@ static void test_GetLocaleInfoA(void)
 {
   int ret;
   int len;
+  HKEY cpl;
   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
   char buffer[BUFFER_SIZE];
   char expected[BUFFER_SIZE];
@@ -192,6 +194,20 @@ static void test_GetLocaleInfoA(void)
   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
   ok(ret == 7, "Expected ret == 7, got %d, error %d\n", ret, GetLastError());
   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
+
+  /* Test that ControlPanel/sLanguage does not override LOCALE_SLANGUAGE */
+  memset(buffer, 0, COUNTOF(buffer));
+  ret = RegOpenKeyExA(HKEY_CURRENT_USER, "Control Panel\\International", 0, KEY_ALL_ACCESS, &cpl);
+  ok(ret == ERROR_SUCCESS, "Couldn't get required access to Control Panel\\International\n");
+  if (ret == ERROR_SUCCESS) {
+      BYTE current_sLanguage[BUFFER_SIZE];
+      DWORD length;
+      RegQueryValueExA(cpl, "sLanguage", NULL, NULL, current_sLanguage, &length);
+      RegSetValueExA(cpl, "sLanguage", 0, REG_SZ, (LPBYTE)"foo", 4);
+      GetLocaleInfoA(GetSystemDefaultLCID(), LOCALE_SLANGUAGE, buffer, COUNTOF(buffer));
+      ok(0 != strcmp(buffer, "foo"), "sLanguage should not override LOCALE_SLANGUAGE!\n");
+      RegSetValueExA(cpl, "sLanguage", 0, REG_SZ, current_sLanguage, length);
+  }
 }
 
 static void test_GetTimeFormatA(void)
-- 
1.5.4.3


More information about the wine-patches mailing list