[PATCH 05/12] kernel32: Implement SetUserGeoName(), add helper set_geo_reg().

João Diogo Ferreira devilj at outlook.pt
Tue Oct 22 12:43:34 CDT 2019


The new helper implements behaviour for both
SetUserGeoName() and SetUserGeoID(), seeing as they behave the same.

Signed-off-by: João Diogo Craveiro Ferreira <devilj at outlook.pt>
---
 dlls/kernel32/kernel32.spec |   1 +
 dlls/kernel32/locale.c      | 111 ++++++++++++++++++++++++++++++++----
 include/winnls.h            |   1 +
 3 files changed, 103 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 23c25b7acd..beebea9c1c 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1469,6 +1469,7 @@
 @ stdcall -arch=x86_64 SetUmsThreadInformation(ptr long ptr long)
 @ stdcall -import SetUnhandledExceptionFilter(ptr)
 @ stdcall SetUserGeoID(long)
+@ stdcall SetUserGeoName(ptr)
 @ stub SetVDMCurrentDirectories
 @ stdcall SetVolumeLabelA(str str)
 @ stdcall SetVolumeLabelW(wstr wstr)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index b582324978..4957e8df5e 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -4121,16 +4121,22 @@ GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass )
 }
 
 /******************************************************************************
- *           SetUserGeoID (KERNEL32.@)
+ *           set_geo_reg
+ *
+ * Does the heavy lifting for SetUserGeoName() and SetUserGeoID().
+ *
+ * The return value and last error set here can (and probably should)
+ * be returned to the callers of those two functions.
  */
-BOOL WINAPI SetUserGeoID( GEOID GeoID )
+static int set_geo_reg(const struct geoinfo_t *geoinfo)
 {
-    const struct geoinfo_t *geoinfo = get_geoinfoptr_by_id(GeoID);
     static const WCHAR nationW[] = {'N','a','t','i','o','n',0};
     static const WCHAR regionW[] = {'R','e','g','i','o','n',0};
-    static const WCHAR formatW[] = {'%','i',0};
-    UNICODE_STRING keyW;
-    WCHAR bufferW[10];
+    static const WCHAR nameW[] = {'N','a','m','e',0};
+    static const WCHAR id_formatW[] = {'%','i',0};
+    UNICODE_STRING idkeyW, namekeyW;
+    WCHAR geoidW[10], geonameW[4];
+    int namelen;
     HANDLE hkey;
 
     if (!geoinfo)
@@ -4144,17 +4150,102 @@ BOOL WINAPI SetUserGeoID( GEOID GeoID )
         return FALSE;
     }
 
+    /* Prepare GeoID */
     if (geoinfo->kind == LOCATION_NATION)
-        RtlInitUnicodeString( &keyW, nationW );
+        RtlInitUnicodeString(&idkeyW, nationW);
     else
-        RtlInitUnicodeString( &keyW, regionW );
+        RtlInitUnicodeString(&idkeyW, regionW);
+
+    sprintfW(geoidW, id_formatW, geoinfo->id);
+
+    /* Now prepare GeoName */
+    RtlInitUnicodeString( &namekeyW, nameW );
+
+    if (geoinfo->kind == LOCATION_REGION)
+    {
+        sprintfW(geonameW, geoname_uncode_fmtW, geoinfo->uncode);
+        namelen = 4;
+    }
+    else
+    {
+        strcpyW(geonameW, geoinfo->iso2W);
+        namelen = 3;
+    }
+
+    NtSetValueKey(hkey, &idkeyW, 0, REG_SZ, geoidW, (strlenW(geoidW) + 1) * sizeof(WCHAR));
+    NtSetValueKey(hkey, &namekeyW, 0, REG_SZ, geonameW, namelen * sizeof(WCHAR));
+
+    TRACE("Set %s to ID %d; set Name to %s\n",
+          wine_dbgstr_w(idkeyW.Buffer), geoinfo->id, wine_dbgstr_w(geonameW));
 
-    sprintfW(bufferW, formatW, geoinfo->id);
-    NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
     NtClose(hkey);
     return TRUE;
 }
 
+/******************************************************************************
+ *           SetUserGeoID (KERNEL32.@)
+ *
+ * Sets the ID of the user's geographic location.
+ *
+ * PARAMS
+ *   GeoID [I] The geographic ID to be set.
+ *
+ * RETURNS
+ *   SUCCESS: TRUE.
+ *   FAILURE: FALSE. Call GetLastError() to determine the cause.
+ *
+ * NOTES
+ *   On success, the geographic name will be set to the location of the specified GeoID.
+ *
+ *   On failure, GetLastError() will return one of the following values:
+ *     - ERROR_INVALID_PARAMETER: the specified GeoID was invalid.
+ *     - ERROR_INTERNAL_ERROR: an internal error prevented Wine from setting the GeoID.
+ */
+BOOL WINAPI SetUserGeoID(GEOID GeoID)
+{
+    TRACE("(%d)\n", GeoID);
+    return set_geo_reg(get_geoinfoptr_by_id(GeoID));
+}
+
+/******************************************************************************
+ *           SetUserGeoName (KERNEL32.@)
+ *
+ * Sets the name of the user's geographic location.
+ *
+ * This name is a two-letter ISO 3166 country code
+ * or a three-digit UN M.49 code for anything other than countries (e.g. continents).
+ *
+ * PARAMS
+ *   geoName [I] The name to be set.
+ *
+ * RETURNS
+ *   SUCCESS: TRUE.
+ *   FAILURE: FALSE. Call GetLastError() to determine the cause.
+ *
+ * NOTES
+ *   If you specify the UN code of a valid country, its two-letter ISO code
+ *   will be used instead.
+ *
+ *   On success, the geographic ID for the relevant class will be set to
+ *   the location of the specified name.
+ *
+ *   On failure, GetLastError() will return one of the following values:
+ *     - ERROR_INVALID_PARAMETER: the specified GeoID was invalid.
+ *     - ERROR_INTERNAL_ERROR: an internal error prevented Wine from setting the name.
+ */
+BOOL WINAPI SetUserGeoName(LPWSTR geoName)
+{
+    if (!geoName || !*geoName)
+    {
+        TRACE("(%p = (null))\n", geoName);
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    TRACE("(%p = %s)\n", geoName, wine_dbgstr_w(geoName));
+    return set_geo_reg(get_geoinfoptr_by_name(geoName));
+}
+
 /******************************************************************************
  *           GetGeoInfoW (KERNEL32.@)
  */
diff --git a/include/winnls.h b/include/winnls.h
index e810c44af7..3aeb47c9e4 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -968,6 +968,7 @@ WINBASEAPI BOOL        WINAPI SetLocaleInfoW(LCID,LCTYPE,LPCWSTR);
 WINBASEAPI BOOL        WINAPI SetThreadLocale(LCID);
 WINBASEAPI LANGID      WINAPI SetThreadUILanguage(LANGID);
 WINBASEAPI BOOL        WINAPI SetUserGeoID(GEOID);
+WINBASEAPI BOOL        WINAPI SetUserGeoName(LPWSTR);
 WINBASEAPI INT         WINAPI WideCharToMultiByte(UINT,DWORD,LPCWSTR,INT,LPSTR,INT,LPCSTR,LPBOOL);
 WINBASEAPI INT         WINAPI FindNLSStringEx(const WCHAR *,DWORD,const WCHAR *,INT,const WCHAR *,INT,INT *,NLSVERSIONINFO *,void *,LPARAM);
 
-- 
2.23.0



More information about the wine-devel mailing list