[PATCH v4 4/7] kernel32: Implement GetUserDefaultGeoName().
João Diogo Ferreira
devilj at outlook.pt
Wed Oct 30 23:47:31 CDT 2019
Signed-off-by: João Diogo Craveiro Ferreira <devilj at 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);
--
2.23.0
More information about the wine-devel
mailing list