[PATCH v7 3/3] kernel32: Make GetUserGeoID() pretend we set a GeoID even if we didn't.

João Diogo Ferreira devilj at outlook.pt
Sat Nov 16 01:23:57 CST 2019


This undocumented behaviour was implemented in Windows 10 v1709 along
all the GeoName functions.

For Wine, this fixes an edge-case scenario where we would autodetect a
region-class ID from a locale, leaving the nation class empty.
As most apps only care about nations, this would make some apps crash
regardless of our autodetection mechanism.

For Windows developers, it means bugs in their programs can no longer
be tested and found, and now their apps are crashing on Wine.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46196
Signed-off-by: João Diogo Craveiro Ferreira <devilj at outlook.pt>
---
GetUserDefaultGeoName stub added to allow testing.
V7: It's ptr instead of wstr
V6: Include testing.
Supersedes: 173821
---
 dlls/kernel32/kernel32.spec  |  1 +
 dlls/kernel32/locale.c       |  5 ++---
 dlls/kernel32/tests/locale.c | 28 ++++++++++++++++++++++++++++
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index cf2f622a77..9a49050d6f 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -869,6 +869,7 @@
 # @ stub GetUILanguageInfo
 @ stdcall -arch=x86_64 GetUmsCompletionListEvent(ptr ptr)
 # @ stub -arch=x86_64 GetUmsSystemThreadInformation
+@ stub GetUserDefaultGeoName(ptr long)
 @ stdcall -import GetUserDefaultLCID()
 @ stdcall -import GetUserDefaultLangID()
 @ stdcall -import GetUserDefaultLocaleName(ptr long)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index f1ff3fbaa7..40d5296be9 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -4016,7 +4016,7 @@ static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
  */
 GEOID WINAPI GetUserGeoID(GEOCLASS geoclass)
 {
-    GEOID ret = GEOID_NOT_AVAILABLE;
+    GEOID ret = 39070;
     static const WCHAR geoW[] = {'G','e','o',0};
     static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
     static const WCHAR regionW[] = {'R','e','g','i','o','n',0};
@@ -4025,7 +4025,6 @@ GEOID WINAPI GetUserGeoID(GEOCLASS geoclass)
     UNICODE_STRING keyW;
     const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)bufferW;
     DWORD count = sizeof(bufferW);
-    RtlInitUnicodeString(&keyW, nationW);
 
     switch (geoclass)
     {
@@ -4037,7 +4036,7 @@ GEOID WINAPI GetUserGeoID(GEOCLASS geoclass)
         break;
     default:
         WARN("Unknown geoclass %d\n", geoclass);
-        return ret;
+        return GEOID_NOT_AVAILABLE;
     }
 
     if (!(hkey = create_registry_key())) return ret;
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 81e74531ea..8a49259836 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -98,6 +98,8 @@ static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT
 static INT (WINAPI *pGetGeoInfoA)(GEOID, GEOTYPE, LPSTR, INT, LANGID);
 static INT (WINAPI *pGetGeoInfoW)(GEOID, GEOTYPE, LPWSTR, INT, LANGID);
 static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC);
+static GEOID (WINAPI *pGetUserGeoID)(GEOCLASS);
+static int (WINAPI *pGetUserDefaultGeoName)(WCHAR*, int);
 static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
 static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
 static BOOL (WINAPI *pGetUserPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*);
@@ -136,6 +138,8 @@ static void InitFunctionPointers(void)
   X(GetGeoInfoA);
   X(GetGeoInfoW);
   X(EnumSystemGeoID);
+  X(GetUserGeoID);
+  X(GetUserDefaultGeoName);
   X(GetSystemPreferredUILanguages);
   X(GetThreadPreferredUILanguages);
   X(GetUserPreferredUILanguages);
@@ -4893,6 +4897,29 @@ static void test_EnumSystemGeoID(void)
     }
 }
 
+static void test_GetUserGeoID(void)
+{
+    GEOID id;
+
+    if (pGetUserDefaultGeoName)
+    {
+        ok(GEOID_NOT_AVAILABLE != GetUserGeoID(GEOCLASS_NATION),
+            "GEOCLASS_NATION: should never return GEOID_NOT_AVAILABLE in this platform.\n");
+        ok(GEOID_NOT_AVAILABLE != GetUserGeoID(GEOCLASS_REGION),
+            "GEOCLASS_REGION: should never return GEOID_NOT_AVAILABLE in this platform.\n");
+    }
+    else
+        win_skip("This platform allows returning GEOID_NOT_AVAILABLE on success.\n");
+
+    id = GetUserGeoID(GEOCLASS_ALL);
+    ok(id == GEOID_NOT_AVAILABLE,
+        "GEOCLASS_ALL: expected GEOID_NOT_AVAILABLE, got %d.\n", id);
+
+    id = GetUserGeoID(0xdeadbeef);
+    ok(id == GEOID_NOT_AVAILABLE,
+        "Gibberish argument: expected GEOID_NOT_AVAILABLE, got %d.\n", id);
+}
+
 struct invariant_entry {
   const char *name;
   int id;
@@ -6048,6 +6075,7 @@ START_TEST(locale)
   test_IsValidLocaleName();
   test_CompareStringOrdinal();
   test_GetGeoInfo();
+  test_GetUserGeoID();
   test_EnumSystemGeoID();
   test_invariant();
   test_GetSystemPreferredUILanguages();
-- 
2.24.0



More information about the wine-devel mailing list