[PATCH 08/12] kernel32: Implement GetGeoInfoEx(), add helper get_geo_info().

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


Once again, this required hiring a new helper "get_geo_info"
that implements behavior for all A, W and Ex variants,
since the three have basically the same behaviour.

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

diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 9a8e33eb9a..765f65c867 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -694,6 +694,7 @@
 @ stdcall -import GetFullPathNameW(wstr long ptr ptr)
 @ stdcall GetGeoInfoA(long long ptr long long)
 @ stdcall GetGeoInfoW(long long ptr long long)
+@ stdcall GetGeoInfoEx(ptr long ptr long)
 @ stdcall GetHandleContext(long)
 @ stdcall -import GetHandleInformation(long ptr)
 @ stub -i386 GetLSCallbackTarget
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 90698a0e10..adb3b9b3d9 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -4412,37 +4412,39 @@ BOOL WINAPI SetUserGeoName(LPWSTR geoName)
 }
 
 /******************************************************************************
- *           GetGeoInfoW (KERNEL32.@)
+ *           get_geo_info
+ *
+ * Implements GetGeoInfoW() and GetGeoInfoEx().
+ *
+ * The return value and last error set here can (and probably should)
+ * be returned to the caller of those two functions.
  */
-INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len, LANGID lang)
+static int get_geo_info(const struct geoinfo_t *geoinfo, GEOTYPE geotype, WCHAR *data, int data_len, LANGID lang)
 {
-    const struct geoinfo_t *ptr;
     const WCHAR *str = NULL;
     WCHAR buffW[12];
     LONG val = 0;
     INT len;
 
-    TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
-
-    if (!(ptr = get_geoinfoptr_by_id(geoid))) {
+    if (!geoinfo) {
         SetLastError(ERROR_INVALID_PARAMETER);
         return 0;
     }
 
     switch (geotype) {
     case GEO_NATION:
-        val = geoid;
+        val = geoinfo->id;
         break;
     case GEO_ISO_UN_NUMBER:
-        val = ptr->uncode;
+        val = geoinfo->uncode;
         break;
     case GEO_PARENT:
-        val = ptr->parent;
+        val = geoinfo->parent;
         break;
     case GEO_ISO2:
     case GEO_ISO3:
     {
-        str = geotype == GEO_ISO2 ? ptr->iso2W : ptr->iso3W;
+        str = geotype == GEO_ISO2 ? geoinfo->iso2W : geoinfo->iso3W;
         break;
     }
     case GEO_RFC1766:
@@ -4478,8 +4480,41 @@ INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, int data_len,
     return data_len < len ? 0 : len;
 }
 
+/******************************************************************************
+ *           GetGeoInfoW (KERNEL32.@)
+ *
+ * Retrieves information about a geographic location by its GeoID.
+ *
+ * PARAMS
+ *   geoid    [I] The GeoID of the location to learn about.
+ *   geotype  [I] The type of information to be retrieved.
+ *   data     [O] The output buffer to store the information.
+ *   data_len [I] The length of the buffer, measured in WCHARs and including the null terminator.
+ *   lang     [I] Language identifier. Must be 0 if geotype is different than GEO_RFC1766 or GEO_LCID.
+ *
+ * RETURNS
+ *   SUCCESS: The number of WCHARs (including null) written to the buffer -OR-
+ *            If no buffer was provided, the minimum required length to hold the full data.
+ *   FAILURE: Zero. Call GetLastError() to determine the cause.
+ *
+ * NOTES
+ *   On failure, GetLastError() will return one of the following values:
+ *     - ERROR_INVALID_PARAMETER: the location name provided was invalid.
+ *     - ERROR_INVALID_FLAGS: the specified geotype was invalid.
+ *     - ERROR_INSUFFICIENT_BUFFER: the provided buffer was too small to hold the full data.
+ */
+INT WINAPI GetGeoInfoW(GEOID geoid, GEOTYPE geotype, LPWSTR data, INT data_len, LANGID lang)
+{
+    TRACE("%d %d %p %d %d\n", geoid, geotype, data, data_len, lang);
+    return get_geo_info(get_geoinfoptr_by_id(geoid), geotype, data, data_len, lang);
+}
+
 /******************************************************************************
  *           GetGeoInfoA (KERNEL32.@)
+ *
+ * Retrieves information about a geographic location by its GeoID.
+ *
+ * ANSI variant of GetGeoInfoW(). Please refer to that function for documentation.
  */
 INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, LANGID lang)
 {
@@ -4511,6 +4546,56 @@ INT WINAPI GetGeoInfoA(GEOID geoid, GEOTYPE geotype, LPSTR data, int data_len, L
     return data_len < len ? 0 : len;
 }
 
+/******************************************************************************
+ *           GetGeoInfoEx (KERNEL32.@)
+ *
+ * Retrieves information about a geographic location by its ISO or UN code.
+ *
+ * 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
+ *   location     [I] ISO 3166 or UN M.49 code of the location to learn about.
+ *   geotype      [I] Type of information to be retrieved (except GEO_LCID, GEO_NATION and GEO_RFC1766).
+ *   geoData      [O] Output buffer to store the information.
+ *   geoDataCount [I] Length of the buffer, measured in WCHARs and including the null terminator.
+ *
+ * RETURNS
+ *   SUCCESS: The number of WCHARs (including null) written to the buffer -OR-
+ *            If no buffer was provided, the minimum required length to hold the full data.
+ *   FAILURE: Zero. Call GetLastError() to determine the cause.
+ *
+ * NOTES
+ *   This function diallows GEO_LCID, GEO_NATION and GEO_RFC1766 to be passed as geotype.
+ *   Use GetGeoInfoW() if you need those values.
+ *
+ *   On failure, GetLastError() will return one of the following values:
+ *     - ERROR_INVALID_PARAMETER: the location name provided was invalid.
+ *     - ERROR_INVALID_FLAGS: the specified geotype was invalid.
+ *     - ERROR_INSUFFICIENT_BUFFER: the provided buffer was too small to hold the full data.
+ */
+int WINAPI GetGeoInfoEx(PWSTR location, GEOTYPE geotype, PWSTR geoData, int geoDataCount)
+{
+    if (!location || !*location)
+    {
+        TRACE("%p=null %d %p %d\n", location, geotype, geoData, geoDataCount);
+        return 0;
+    }
+    TRACE("%p=%s %d %p %d\n", location, wine_dbgstr_w(location), geotype, geoData, geoDataCount);
+
+    switch (geotype)
+    {
+        case GEO_LCID:
+        case GEO_NATION:
+        case GEO_RFC1766:
+            SetLastError(ERROR_INVALID_FLAGS);
+            return 0;
+        default:
+            return get_geo_info(get_geoinfoptr_by_name(location),
+                                geotype, geoData, geoDataCount, 0);
+    }
+}
+
 /******************************************************************************
  *           EnumSystemGeoID    (KERNEL32.@)
  *
diff --git a/include/winnls.h b/include/winnls.h
index 059a459153..63583f9a6c 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -909,6 +909,7 @@ WINBASEAPI BOOL        WINAPI GetFileMUIPath(DWORD,PCWSTR,PWSTR,PULONG,PWSTR,PUL
 WINBASEAPI INT         WINAPI GetGeoInfoA(GEOID,GEOTYPE,LPSTR,INT,LANGID);
 WINBASEAPI INT         WINAPI GetGeoInfoW(GEOID,GEOTYPE,LPWSTR,INT,LANGID);
 #define                       GetGeoInfo WINELIB_NAME_AW(GetGeoInfo)
+WINBASEAPI int         WINAPI GetGeoInfoEx(PWSTR,GEOTYPE,PWSTR,int);
 WINBASEAPI INT         WINAPI GetLocaleInfoA(LCID,LCTYPE,LPSTR,INT);
 WINBASEAPI INT         WINAPI GetLocaleInfoW(LCID,LCTYPE,LPWSTR,INT);
 #define                       GetLocaleInfo WINELIB_NAME_AW(GetLocaleInfo)
-- 
2.23.0



More information about the wine-devel mailing list