[PATCH 2/2] kernel32: Handle GEOCLASS_REGION in Get/SetUserGeoID.
João Diogo Ferreira
devilj at outlook.pt
Thu Oct 3 00:45:19 CDT 2019
This is laying the groundwork for implementing
GeoID autodetection on behalf of the user.
These functions should now be 100% compliant with
Windows 7 behaviour. Only a few more ways to make
it behave like Windows 10!
Signed-off-by: João Diogo Craveiro Ferreira <devilj at outlook.pt>
---
dlls/kernel32/locale.c | 77 ++++++++++++++++++++++++++++++++----------
1 file changed, 59 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index d11d17eaa0..e017bb5472 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -4778,34 +4778,43 @@ static const struct geoinfo_t *get_geoinfo_dataptr(GEOID geoid)
/******************************************************************************
* GetUserGeoID (KERNEL32.@)
+ * Fetches the user's geographic location ID for nation or region.
+ *
+ * PARAMS
+ * GeoClass [I] One of GEOCLASS_NATION or GEOCLASS_REGION.
+ *
+ * RETURNS
+ * Success: The GeoID for the requested class.
+ * Failure: GEOID_NOT_AVAILABLE, if the specified GeoClass is invalid or its GeoID had not yet been set.
+ *
*/
GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass )
{
GEOID ret = GEOID_NOT_AVAILABLE;
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};
WCHAR bufferW[40], *end;
DWORD count;
HANDLE hkey, hSubkey = 0;
UNICODE_STRING keyW;
const KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)bufferW;
- RtlInitUnicodeString( &keyW, nationW );
count = sizeof(bufferW);
- if(!(hkey = create_registry_key())) return ret;
+ if (GeoClass == GEOCLASS_NATION)
+ RtlInitUnicodeString( &keyW, nationW );
+ else if (GeoClass == GEOCLASS_REGION)
+ RtlInitUnicodeString( &keyW, regionW );
+ else
+ return ret;
- switch( GeoClass ){
- case GEOCLASS_NATION:
- if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
- {
- if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
- bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength)
- ret = strtolW((LPCWSTR)info->Data, &end, 10);
- }
- break;
- case GEOCLASS_REGION:
- FIXME("GEOCLASS_REGION not handled yet\n");
- break;
+ if (!(hkey = create_registry_key())) return ret;
+
+ if ((hSubkey = NLS_RegOpenKey(hkey, geoW)))
+ {
+ if((NtQueryValueKey(hSubkey, &keyW, KeyValuePartialInformation,
+ bufferW, count, &count) == STATUS_SUCCESS ) && info->DataLength)
+ ret = strtolW((LPCWSTR)info->Data, &end, 10);
}
NtClose(hkey);
@@ -4815,18 +4824,46 @@ GEOID WINAPI GetUserGeoID( GEOCLASS GeoClass )
/******************************************************************************
* SetUserGeoID (KERNEL32.@)
+ * Sets the user's geographic location ID.
+ *
+ * PARAMS
+ * GeoID [I] The new GeoID.
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE, if the GeoID was invalid or an unexpected error occured. Call GetLastError() to learn the reason.
+ *
+ * NOTES
+ * GetLastError() will report the following possible error conditions:
+ * - ERROR_INVALID_PARAMETER: The GeoID was invalid.
+ * - ERROR_INTERNAL_ERROR: There was an unexpected error.
+ *
+ * GeoIDs may be internally classified as LOCATION_BOTH; these are functionally identical to GEOCLASS_REGION,
+ * and will be set as region ID only, not as a nation.
+ *
*/
BOOL WINAPI SetUserGeoID( GEOID GeoID )
{
+ const struct geoinfo_t *geoinfo = get_geoinfo_dataptr(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];
OBJECT_ATTRIBUTES attr;
HANDLE hkey;
- if(!(hkey = create_registry_key())) return FALSE;
+ if (!geoinfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!(hkey = create_registry_key()))
+ {
+ SetLastError(ERROR_INTERNAL_ERROR);
+ return FALSE;
+ }
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
@@ -4835,16 +4872,20 @@ BOOL WINAPI SetUserGeoID( GEOID GeoID )
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, geoW );
- RtlInitUnicodeString( &keyW, nationW );
- if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
+ if (geoinfo->kind == LOCATION_NATION)
+ RtlInitUnicodeString( &keyW, nationW );
+ else
+ RtlInitUnicodeString( &keyW, regionW );
+ if (NtCreateKey( &hkey, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL ) != STATUS_SUCCESS)
{
NtClose(attr.RootDirectory);
+ SetLastError(ERROR_INTERNAL_ERROR);
return FALSE;
}
- sprintfW(bufferW, formatW, GeoID);
+ sprintfW(bufferW, formatW, geoinfo->id);
NtSetValueKey(hkey, &keyW, 0, REG_SZ, bufferW, (strlenW(bufferW) + 1) * sizeof(WCHAR));
NtClose(attr.RootDirectory);
NtClose(hkey);
--
2.23.0
More information about the wine-devel
mailing list