Signed-off-by: João Diogo Craveiro Ferreira devilj@outlook.pt --- Supersedes: 172360 V4: Use NLS_RegOpenKey() instead of other helper; fix unicode issue. --- dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/locale.c | 132 ++++++++++++++++++++++++++++++++++++ include/winnls.h | 1 + 3 files changed, 134 insertions(+)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 9898bdec6e..c2dd727135 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -869,6 +869,7 @@ # @ stub GetUILanguageInfo @ stdcall -arch=x86_64 GetUmsCompletionListEvent(ptr ptr) # @ stub -arch=x86_64 GetUmsSystemThreadInformation +@ stdcall GetUserDefaultGeoName(ptr long) @ stdcall -import GetUserDefaultLCID() @ stdcall -import GetUserDefaultLangID() @ stdcall -import GetUserDefaultLocaleName(ptr long) diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index 63d9e03d8b..4dcad37c72 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -4141,6 +4141,138 @@ GEOID WINAPI GetUserGeoID(GEOCLASS geoclass) return ret; }
+/****************************************************************************** + * GetUserDefaultGeoName (KERNEL32.@) + * + * Retrieves 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). + * + * If geoname_len is 0, this function will return the minimum length + * required for a buffer to hold the name. + * + * PARAMS + * buffer [O] Pointer to a buffer to hold the name. + * buffer_len [I] Length of the buffer, including null terminator, measured in WCHARs. + * + * RETURNS + * SUCCESS: Number of WCHARs written to the buffer -OR- minimum length required for the buffer. + * FAILURE: Zero. Call GetLastError() to determine the cause. + * + * NOTES + * On failure, GetLastError() will return one of the following values: + * - ERROR_INVALID_PARAMETER: one of the parameters was invalid. + * - ERROR_INSUFFICIENT_BUFFER: the specified buffer was too small to hold the name. + * - ERROR_BADDB: an internal error occured and Wine couldn't retrieve the name. + * - ERROR_NOT_ENOUGH_MEMORY: (Wine implementation) could not allocate more memory. + */ +int WINAPI GetUserDefaultGeoName(WCHAR *buffer, int buffer_len) +{ + int ret = 0, name_len; + WCHAR fallback[] = {'0','0','1',0}; /* World */ + int fallback_len = ARRAY_SIZE(fallback); + int use_fallback = 0; + + static const WCHAR geokeyname[] = {'G','e','o',0}; + HANDLE hkey = create_registry_key(), hsubkey; + KEY_VALUE_PARTIAL_INFORMATION kvi = {0}; + WCHAR valuename[] = {'N','a','m','e',0}; + UNICODE_STRING uvaluename; + DWORD reg_len; + + TRACE("(%p, %d)\n", buffer, buffer_len); + + if (buffer_len < 0 || (buffer_len && !buffer)) + { + SetLastError(ERROR_INVALID_PARAMETER); + if (hkey) NtClose(hkey); + return 0; + } + + if (!hkey) + { + ERR("Couldn't open the International regkey; please report.\n"); + SetLastError(ERROR_BADDB); + return 0; + } + + hsubkey = NLS_RegOpenKey(hkey, geokeyname); + + RtlInitUnicodeString(&uvaluename, valuename); + + /* If we don't get an overflow, it's the wrong value. */ + if (hsubkey && + NtQueryValueKey(hsubkey, &uvaluename, KeyValuePartialInformation, + &kvi, sizeof(kvi), ®_len) == STATUS_BUFFER_OVERFLOW) + name_len = kvi.DataLength / sizeof(WCHAR); + else + { + TRACE("We've fallen back to our hardcoded value.\n"); + use_fallback = 1; + } + + if (!use_fallback) + { + if (!buffer_len) + ret = name_len; + else if (buffer_len < name_len) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + ret = 0; + } + else if (buffer_len >= name_len) + { + KEY_VALUE_PARTIAL_INFORMATION *kvi; + DWORD kvi_size = sizeof(*kvi) + (name_len * sizeof(WCHAR)); + + if ((kvi = HeapAlloc(GetProcessHeap(), 0, kvi_size))) + { + NTSTATUS status = NtQueryValueKey(hsubkey, &uvaluename, KeyValuePartialInformation, + kvi, kvi_size, ®_len); + if (status == STATUS_SUCCESS) + { + memcpy(buffer, kvi->Data, name_len * sizeof(WCHAR)); + ret = name_len; + } + else + { + ERR("Failure: status=0x%x, kvi_size=%d, reg_len=%d, DataLength=%u\n", + status, kvi_size, reg_len, kvi->DataLength); + SetLastError(ERROR_BADDB); + ret = 0; + } + HeapFree(GetProcessHeap(), 0, kvi); + } + else + { + ERR("We couldn't allocate memory somehow.\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ret = 0; + } + } + } + else + { + if (!buffer_len) + ret = fallback_len; + else if (buffer_len < fallback_len) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + ret = 0; + } + else if (buffer_len >= fallback_len) + { + strcpyW(buffer, fallback); + ret = fallback_len; + } + } + + if (hsubkey) NtClose(hsubkey); + if (hkey) NtClose(hkey); + return ret; +} + /****************************************************************************** * set_geo_reg * diff --git a/include/winnls.h b/include/winnls.h index 4f84c64f81..6e60ceaa1d 100644 --- a/include/winnls.h +++ b/include/winnls.h @@ -935,6 +935,7 @@ WINBASEAPI INT WINAPI GetTimeFormatA(LCID,DWORD,const SYSTEMTIME*,LPCSTR WINBASEAPI INT WINAPI GetTimeFormatEx(LPCWSTR,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,INT); WINBASEAPI INT WINAPI GetTimeFormatW(LCID,DWORD,const SYSTEMTIME*,LPCWSTR,LPWSTR,INT); #define GetTimeFormat WINELIB_NAME_AW(GetTimeFormat) +WINBASEAPI int WINAPI GetUserDefaultGeoName(WCHAR*,int); WINBASEAPI LANGID WINAPI GetUserDefaultLangID(void); WINBASEAPI LCID WINAPI GetUserDefaultLCID(void); WINBASEAPI INT WINAPI GetUserDefaultLocaleName(LPWSTR,int);
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=58784
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/kernel32/locale.c:3994 error: patch failed: dlls/kernel32/locale.c:4141 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/kernel32/locale.c:3994 error: patch failed: dlls/kernel32/locale.c:4141 Task: Patch failed to apply
Well, that's new: Marvin mixed my stale patches with the newer ones and now it can't build them anymore. Didn't know this could happen.
Please disregard; I've made sure my v4 patches apply in succession (and ignore all v3, they're superseded 🙂).
________________________________ From: Marvin testbot@winehq.org Sent: Thursday, October 31, 2019 5:13:39 AM To: devilj@outlook.pt devilj@outlook.pt Cc: wine-devel@winehq.org wine-devel@winehq.org Subject: Re: [PATCH v4 4/7] kernel32: Implement GetUserDefaultGeoName().
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://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Ftestbot.wi...
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/kernel32/locale.c:3994 error: patch failed: dlls/kernel32/locale.c:4141 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/kernel32/locale.c:3994 error: patch failed: dlls/kernel32/locale.c:4141 Task: Patch failed to apply
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=58787
Your paranoid android.
=== debian10 (32 bit Chinese:China report) ===
kernel32: debugger.c:320: Test failed: GetThreadContext failed: 5