[PATCH 3/3] kernelbase: Add GetAcceptLanguages().
Nikolay Sivov
nsivov at codeweavers.com
Thu May 23 06:20:22 CDT 2019
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/kernelbase/kernelbase.spec | 4 +-
dlls/kernelbase/main.c | 122 ++++++++++++++++++++++++++++++++
include/shlwapi.h | 8 +++
3 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec
index 844cff17fd..193af89b43 100644
--- a/dlls/kernelbase/kernelbase.spec
+++ b/dlls/kernelbase/kernelbase.spec
@@ -403,8 +403,8 @@
@ stdcall GenerateConsoleCtrlEvent(long long) kernel32.GenerateConsoleCtrlEvent
# @ stub GenerateGPNotificationInternal
@ stdcall GetACP() kernel32.GetACP
-@ stdcall GetAcceptLanguagesA(ptr ptr) shlwapi.GetAcceptLanguagesA
-@ stdcall GetAcceptLanguagesW(ptr ptr) shlwapi.GetAcceptLanguagesW
+@ stdcall GetAcceptLanguagesA(ptr ptr)
+@ stdcall GetAcceptLanguagesW(ptr ptr)
@ stdcall GetAce(ptr long ptr) advapi32.GetAce
@ stdcall GetAclInformation(ptr ptr long long) advapi32.GetAclInformation
# @ stub GetAdjustObjectAttributesForPrivateNamespaceRoutine
diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c
index 3fce23657b..58f3c33f8e 100644
--- a/dlls/kernelbase/main.c
+++ b/dlls/kernelbase/main.c
@@ -26,6 +26,7 @@
#include "shlwapi.h"
#include "wine/debug.h"
+#include "wine/heap.h"
#include "winternl.h"
WINE_DEFAULT_DEBUG_CHANNEL(kernelbase);
@@ -165,3 +166,124 @@ HRESULT WINAPI QISearch(void *base, const QITAB *table, REFIID riid, void **obj)
*obj = NULL;
return E_NOINTERFACE;
}
+
+HRESULT WINAPI GetAcceptLanguagesA(LPSTR langbuf, DWORD *buflen)
+{
+ DWORD buflenW, convlen;
+ WCHAR *langbufW;
+ HRESULT hr;
+
+ TRACE("%p, %p, *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
+
+ if (!langbuf || !buflen || !*buflen)
+ return E_FAIL;
+
+ buflenW = *buflen;
+ langbufW = heap_alloc(sizeof(WCHAR) * buflenW);
+ hr = GetAcceptLanguagesW(langbufW, &buflenW);
+
+ if (hr == S_OK)
+ {
+ convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
+ convlen--; /* do not count the terminating 0 */
+ }
+ else /* copy partial string anyway */
+ {
+ convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
+ if (convlen < *buflen)
+ {
+ langbuf[convlen] = 0;
+ convlen--; /* do not count the terminating 0 */
+ }
+ else
+ {
+ convlen = *buflen;
+ }
+ }
+ *buflen = buflenW ? convlen : 0;
+
+ heap_free(langbufW);
+ return hr;
+}
+
+static HRESULT lcid_to_rfc1766(LCID lcid, WCHAR *rfc1766, INT len)
+{
+ WCHAR buffer[6 /* MAX_RFC1766_NAME */];
+ INT n = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME, buffer, ARRAY_SIZE(buffer));
+ INT i;
+
+ if (n)
+ {
+ i = PRIMARYLANGID(lcid);
+ if ((((i == LANG_ENGLISH) || (i == LANG_CHINESE) || (i == LANG_ARABIC)) &&
+ (SUBLANGID(lcid) == SUBLANG_DEFAULT)) ||
+ (SUBLANGID(lcid) > SUBLANG_DEFAULT)) {
+
+ buffer[n - 1] = '-';
+ i = GetLocaleInfoW(lcid, LOCALE_SISO3166CTRYNAME, buffer + n, ARRAY_SIZE(buffer) - n);
+ if (!i)
+ buffer[n - 1] = '\0';
+ }
+ else
+ i = 0;
+
+ LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, buffer, n + i, rfc1766, len);
+ return ((n + i) > len) ? E_INVALIDARG : S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT WINAPI GetAcceptLanguagesW(WCHAR *langbuf, DWORD *buflen)
+{
+ static const WCHAR keyW[] = {
+ 'S','o','f','t','w','a','r','e','\\',
+ 'M','i','c','r','o','s','o','f','t','\\',
+ 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
+ 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
+ static const WCHAR valueW[] = {'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
+ DWORD mystrlen, mytype;
+ WCHAR *mystr;
+ LCID mylcid;
+ HKEY mykey;
+ LONG lres;
+ DWORD len;
+
+ TRACE("%p, %p, *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
+
+ if (!langbuf || !buflen || !*buflen)
+ return E_FAIL;
+
+ mystrlen = (*buflen > 20) ? *buflen : 20 ;
+ len = mystrlen * sizeof(WCHAR);
+ mystr = heap_alloc(len);
+ mystr[0] = 0;
+ RegOpenKeyW(HKEY_CURRENT_USER, keyW, &mykey);
+ lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
+ RegCloseKey(mykey);
+ len = lstrlenW(mystr);
+
+ if (!lres && (*buflen > len))
+ {
+ lstrcpyW(langbuf, mystr);
+ *buflen = len;
+ heap_free(mystr);
+ return S_OK;
+ }
+
+ /* Did not find a value in the registry or the user buffer is too small */
+ mylcid = GetUserDefaultLCID();
+ lcid_to_rfc1766(mylcid, mystr, mystrlen);
+ len = lstrlenW(mystr);
+
+ memcpy(langbuf, mystr, min(*buflen, len + 1)*sizeof(WCHAR));
+ heap_free(mystr);
+
+ if (*buflen > len)
+ {
+ *buflen = len;
+ return S_OK;
+ }
+
+ *buflen = 0;
+ return E_NOT_SUFFICIENT_BUFFER;
+}
diff --git a/include/shlwapi.h b/include/shlwapi.h
index 138fcd9ee9..a1cbc576e8 100644
--- a/include/shlwapi.h
+++ b/include/shlwapi.h
@@ -31,6 +31,14 @@ extern "C" {
#include <pshpack8.h>
+#ifndef NO_SHLWAPI_HTTP
+
+HRESULT WINAPI GetAcceptLanguagesA(char *buffer, DWORD *buff_len);
+HRESULT WINAPI GetAcceptLanguagesW(WCHAR *buffer, DWORD *buff_len);
+#define GetAcceptLanguages WINELING_NAME_AW(GetAcceptLanguages)
+
+#endif /* NO_SHLWAPI_HTTP */
+
#ifndef NO_SHLWAPI_REG
/* Registry functions */
--
2.20.1
More information about the wine-devel
mailing list