diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 844cff17fd5..193af89b43d 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 3fce23657b9..58f3c33f8e4 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 138fcd9ee9a..0cd50e9e911 100644 --- a/include/shlwapi.h +++ b/include/shlwapi.h @@ -31,6 +31,14 @@ extern "C" { #include +#ifndef NO_SHLWAPI_HTTP + +HRESULT WINAPI GetAcceptLanguagesA(char *buffer, DWORD *buff_len); +HRESULT WINAPI GetAcceptLanguagesW(WCHAR *buffer, DWORD *buff_len); +#define GetAcceptLanguages WINELIB_NAME_AW(GetAcceptLanguages) + +#endif /* NO_SHLWAPI_HTTP */ + #ifndef NO_SHLWAPI_REG /* Registry functions */