[PATCH v2 3/3] kernel32: Implement SetUserGeoName().
João Diogo Ferreira
devilj at outlook.pt
Sun Nov 24 09:36:26 CST 2019
Signed-off-by: João Diogo Craveiro Ferreira <devilj at outlook.pt>
---
Treat with low priority.
This actually useful and urgent, rather I mistakingly wrote it
for something else and now I might as well make it useful.
---
dlls/kernel32/kernel32.spec | 1 +
dlls/kernel32/locale.c | 124 +++++++++++++++++++++++++++++-------
include/winnls.h | 1 +
3 files changed, 102 insertions(+), 24 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 30b0b1de67..67fdcd0c3b 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1471,6 +1471,7 @@
@ stdcall -arch=x86_64 SetUmsThreadInformation(ptr long ptr long)
@ stdcall -import SetUnhandledExceptionFilter(ptr)
@ stdcall SetUserGeoID(long)
+@ stdcall SetUserGeoName(wstr)
@ stub SetVDMCurrentDirectories
@ stdcall SetVolumeLabelA(str str)
@ stdcall SetVolumeLabelW(wstr wstr)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 6031ddfd64..1f7c9a0eda 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -3109,7 +3109,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)
{
@@ -3139,30 +3138,28 @@ GEOID WINAPI GetUserGeoID(GEOCLASS geoclass)
}
/******************************************************************************
- * SetUserGeoID (KERNEL32.@)
- *
- * Sets the ID of the user's geographic location.
+ * set_geo_reg
*
- * PARAMS
- * geoid [I] The geographic ID to be set.
+ * Does the heavy lifting for SetUserGeoName() and SetUserGeoID().
*
- * RETURNS
- * SUCCESS: TRUE.
- * FAILURE: FALSE. GetLastError() will return ERROR_INVALID_PARAMETER if the ID was invalid.
+ * The return value and last error set here can and should be
+ * returned to the callers of those two functions.
*/
-BOOL WINAPI SetUserGeoID(GEOID geoid)
+static int WINAPI set_geo_reg(const struct geoinfo_t *geoptr)
{
- const struct geoinfo_t *geoinfo = get_geoinfoptr_by_id(geoid);
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};
- static const WCHAR formatW[] = {'%','i',0};
- UNICODE_STRING nameW, keyW;
- WCHAR bufferW[10];
+ static const WCHAR nameW[] = {'N','a','m','e',0};
+ static const WCHAR id_fmtW[] = {'%','i',0};
+ static const WCHAR un_fmtW[] = {'%','0','3','i',0};
+ static const WCHAR xx[] = {'X','X',0};
+ UNICODE_STRING keyname, id_valuename, name_valuename;
+ WCHAR id_buffer[10], name_buffer[4];
OBJECT_ATTRIBUTES attr;
HANDLE hkey;
- if (!geoinfo)
+ if (!geoptr)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
@@ -3172,16 +3169,11 @@ BOOL WINAPI SetUserGeoID(GEOID geoid)
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
- attr.ObjectName = &nameW;
+ attr.ObjectName = &keyname;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
- RtlInitUnicodeString(&nameW, geoW);
-
- if (geoinfo->kind == LOCATION_NATION)
- RtlInitUnicodeString(&keyW, nationW);
- else
- RtlInitUnicodeString(&keyW, regionW);
+ RtlInitUnicodeString(&keyname, geoW);
if (NtCreateKey(&hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL) != STATUS_SUCCESS)
{
@@ -3189,13 +3181,97 @@ BOOL WINAPI SetUserGeoID(GEOID geoid)
return FALSE;
}
- sprintfW(bufferW, formatW, geoinfo->id);
- NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
+ /* Prepare the GeoID */
+ sprintfW(id_buffer, id_fmtW, geoptr->id);
+
+ if (geoptr->kind == LOCATION_NATION)
+ RtlInitUnicodeString(&id_valuename, nationW);
+ else
+ RtlInitUnicodeString(&id_valuename, regionW);
+
+ /* Now prepare geoname */
+ RtlInitUnicodeString(&name_valuename, nameW);
+
+ if (geoptr->uncode && !strcmpW(xx, geoptr->iso2W))
+ sprintfW(name_buffer, un_fmtW, geoptr->uncode);
+ else
+ strcpyW(name_buffer, geoptr->iso2W);
+
+ NtSetValueKey(hkey, &id_valuename, 0, REG_SZ,
+ id_buffer, (strlenW(id_buffer) + 1) * sizeof(WCHAR));
+ NtSetValueKey(hkey, &name_valuename, 0, REG_SZ,
+ name_buffer, (strlenW(name_buffer) + 1) * sizeof(WCHAR));
+
+ TRACE("Set %s to ID %d; set Name to %s.\n",
+ wine_dbgstr_w(id_valuename.Buffer), geoptr->id, wine_dbgstr_w(name_buffer));
+
NtClose(attr.RootDirectory);
NtClose(hkey);
return TRUE;
}
+/******************************************************************************
+ * SetUserGeoID (KERNEL32.@)
+ *
+ * Sets the user's geographic location via a GeoID.
+ *
+ * PARAMS
+ * geoid [I] The GeoID of the location to be set.
+ *
+ * RETURNS
+ * SUCCESS: TRUE.
+ * FAILURE: FALSE. GetLastError() will return ERROR_INVALID_PARAMETER if the GeoID was invalid.
+ *
+ * NOTES
+ * On success, the geographic name be set to the location of the specified GeoID.
+ *
+ * SEE ALSO
+ * GetUserGeoID(), EnumSystemGeoID(), GetGeoInfoW().
+ */
+BOOL WINAPI SetUserGeoID(GEOID geoid)
+{
+ TRACE("(%d)\n", geoid);
+ return set_geo_reg(get_geoinfoptr_by_id(geoid));
+}
+
+/******************************************************************************
+ * SetUserGeoName (KERNEL32.@)
+ *
+ * Sets the user's geographic location via a GeoName.
+ *
+ * PARAMS
+ * geoname [I] The name of the location to be set.
+ *
+ * RETURNS
+ * SUCCESS: TRUE.
+ * FAILURE: GetLastError() will return ERROR_INVALID_PARAMETER if the name was invalid.
+ *
+ * NOTES
+ * On success, the geographic ID for the relevant class will be set to
+ * the location of the specified name.
+ *
+ * A GeoName is a two-letter ISO 3166 country code
+ * or a three-digit UN M.49 code for anything other than countries (e.g. continents).
+ *
+ * The name must be known to Wine, or this function will fail.
+ * Call EnumSystemGeoNames() to retrieve a list of valid names.
+ *
+ * SEE ALSO
+ * GetUserDefaultGeoName(), EnumSystemGeoNames(), GetGeoInfoEx().
+ */
+BOOL WINAPI SetUserGeoName(WCHAR *geoname)
+{
+ TRACE("(%p = %s)\n", geoname, geoname ? wine_dbgstr_w(geoname) : "(nil)");
+
+ if (!geoname || !*geoname)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ return set_geo_reg(get_geoinfoptr_by_name(geoname));
+}
+
/******************************************************************************
* get_geo_info
*
diff --git a/include/winnls.h b/include/winnls.h
index 7f5a782815..11ec2f6236 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -966,6 +966,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(WCHAR *);
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.24.0
More information about the wine-devel
mailing list