[PATCH 1/2] shlwapi: Return correct strings in GetAcceptLanguages [try 2]

Detlef Riekenberg wine.dev at web.de
Thu Feb 4 13:20:49 CST 2010


I moved the deletion of 2 broken GetLastError() tests from
Patch 2 to Patch 1.

The tests now succeed also on an unconfigured Wine without a failure.
(unconfigured AcceptLanguages registry entry)

--
By by ... Detlef
---
 dlls/shlwapi/ordinal.c       |   88 ++++++++++++++++++++++++-----------------
 dlls/shlwapi/tests/ordinal.c |    4 --
 2 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 9bb26cf..fc15a5f 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -47,6 +47,7 @@
 #include "shellapi.h"
 #include "commdlg.h"
 #include "mshtmhst.h"
+#include "mlang.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
 
@@ -450,14 +451,14 @@ RegisterDefaultAcceptHeaders_Exit:
  *
  * PARAMS
  *  langbuf [O] Destination for language string
- *  buflen  [I] Length of langbuf
+ *  buflen  [I] Length of langbuf in characters
  *          [0] Success: used length of langbuf
  *
  * RETURNS
- *  Success: S_OK.   langbuf is set to the language string found.
+ *  Success: S_OK.   langbuf is set to the language string found. (used length in buflen)
  *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
  *           does not contain the setting.
- *           E_INVALIDARG, If the buffer is not big enough
+ *           HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
  */
 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
 {
@@ -468,55 +469,56 @@ HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
 	'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};
-    static const WCHAR enusW[] = {'e','n','-','u','s',0};
     DWORD mystrlen, mytype;
+    DWORD len;
     HKEY mykey;
     HRESULT retval;
     LCID mylcid;
     WCHAR *mystr;
+    LONG lres;
+
+    TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
 
     if(!langbuf || !buflen || !*buflen)
-	return E_FAIL;
+        return E_FAIL;
 
-    mystrlen = (*buflen > 20) ? *buflen : 20 ;
-    mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
+    mystrlen = ((*buflen > 20) ? *buflen : 20 );
+    len = mystrlen * sizeof(WCHAR);
+    mystr = HeapAlloc(GetProcessHeap(), 0, len + sizeof(WCHAR));
+    mystr[0] = 0;
     RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
-    if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
-        /* Did not find value */
-        mylcid = GetUserDefaultLCID();
-        /* somehow the mylcid translates into "en-us"
-         *  this is similar to "LOCALE_SABBREVLANGNAME"
-         *  which could be gotten via GetLocaleInfo.
-         *  The only problem is LOCALE_SABBREVLANGUAGE" is
-         *  a 3 char string (first 2 are country code and third is
-         *  letter for "sublanguage", which does not come close to
-         *  "en-us"
-         */
-        lstrcpyW(mystr, enusW);
-        mystrlen = lstrlenW(mystr);
-    } else {
-        /* handle returned string */
-        FIXME("missing code\n");
-    }
-    memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
+    lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
+    RegCloseKey(mykey);
+    len = lstrlenW(mystr);
 
-    if(*buflen > strlenW(mystr)) {
-	*buflen = strlenW(mystr);
-	retval = S_OK;
-    } else {
-	*buflen = 0;
-	retval = E_INVALIDARG;
-	SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    if (!lres && (*buflen > len)) {
+        lstrcpyW(langbuf, mystr);
+        *buflen = len;
+        HeapFree(GetProcessHeap(), 0, mystr);
+        return S_OK;
     }
-    RegCloseKey(mykey);
+
+    /* Did not find a value in the registry or the user buffer is to small */
+    mylcid = GetUserDefaultLCID();
+    retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
+    len = lstrlenW(mystr);
+
+    memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
     HeapFree(GetProcessHeap(), 0, mystr);
-    return retval;
+
+    if (*buflen > len) {
+        *buflen = len;
+        return S_OK;
+    }
+
+    *buflen = 0;
+    return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
 }
 
 /*************************************************************************
  *      @	[SHLWAPI.14]
  *
- * Ascii version of GetAcceptLanguagesW.
+ * See GetAcceptLanguagesW.
  */
 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
 {
@@ -524,6 +526,8 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
     DWORD buflenW, convlen;
     HRESULT retval;
 
+    TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
+
     if(!langbuf || !buflen || !*buflen) return E_FAIL;
 
     buflenW = *buflen;
@@ -533,12 +537,22 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
     if (retval == 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;
+        if (convlen < *buflen)
+        {
+            langbuf[convlen] = 0;
+            convlen--;  /* do not count the terminating 0 */
+        }
+        else
+        {
+            convlen = *buflen;
+        }
     }
+
     *buflen = buflenW ? convlen : 0;
 
     HeapFree(GetProcessHeap(), 0, langbufW);
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c
index 31fced9..9b75a87 100644
--- a/dlls/shlwapi/tests/ordinal.c
+++ b/dlls/shlwapi/tests/ordinal.c
@@ -142,8 +142,6 @@ static void test_GetAcceptLanguagesA(void)
         case __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER): /* Win7 */
             ok(buffersize == 0,
                "buffersize wrong: got %08x, expected 0 (2nd parameter;Win2k)\n", buffersize);
-            ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
-               "last error wrong: got %u; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
             break;
         default:
             ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n",
@@ -178,8 +176,6 @@ static void test_GetAcceptLanguagesA(void)
 	case __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER): /* Win 7 */
             ok(buffersize == 0,
                "buffersize wrong: got %08x, expected 0 (2nd parameter;Win2k)\n", buffersize);
-            ok(ERROR_INSUFFICIENT_BUFFER == GetLastError(),
-               "last error wrong: got %u; expected ERROR_INSUFFICIENT_BUFFER\n", GetLastError());
             break;
         default:
             ok( 0, "retval %08x, size %08x, buffer (%s), last error %u\n",
-- 
1.6.5




More information about the wine-patches mailing list