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@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);