[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