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@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)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=58232
Your paranoid android.
=== debian10 (32 bit report) ===
kernel32: debugger.c:320: Test failed: GetThreadContext failed: 5
=== debian10 (32 bit Chinese:China report) ===
kernel32: debugger.c:320: Test failed: GetThreadContext failed: 5 debugger.c:320: Test failed: GetThreadContext failed: 5 debugger.c:320: Test failed: GetThreadContext failed: 5 debugger.c:320: Test failed: GetThreadContext failed: 5
=== debian10 (32 bit WoW report) ===
kernel32: comm.c:919: Test failed: OutQueue should not be empty debugger: Timeout