Nikolay Sivov : shell32: Added support for ASSOCF_NOTRUNCATE flag in GetString().

Alexandre Julliard julliard at winehq.org
Mon Sep 9 16:08:08 CDT 2013


Module: wine
Branch: master
Commit: 891cf2ac54b69cf7d2f8c093338108a7b1e24edf
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=891cf2ac54b69cf7d2f8c093338108a7b1e24edf

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Sep  9 11:21:03 2013 +0400

shell32: Added support for ASSOCF_NOTRUNCATE flag in GetString().

---

 dlls/shell32/assoc.c       |   67 +++++++++++++++++++++----------
 dlls/shell32/tests/assoc.c |   93 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 131 insertions(+), 29 deletions(-)

diff --git a/dlls/shell32/assoc.c b/dlls/shell32/assoc.c
index 65f4644..77b0a2d 100644
--- a/dlls/shell32/assoc.c
+++ b/dlls/shell32/assoc.c
@@ -392,17 +392,41 @@ static HRESULT ASSOC_ReturnData(void *out, DWORD *outlen, const void *data,
   }
 }
 
-static HRESULT ASSOC_ReturnString(LPWSTR out, DWORD *outlen, LPCWSTR data,
-        DWORD datalen)
+static HRESULT ASSOC_ReturnString(ASSOCF flags, LPWSTR out, DWORD *outlen, LPCWSTR data, DWORD datalen)
 {
-    HRESULT hres;
+    HRESULT hr = S_OK;
+    DWORD len;
 
-    assert(outlen);
+    TRACE("flags=0x%08x, data=%s\n", flags, debugstr_w(data));
 
-    *outlen *= sizeof(WCHAR);
-    hres = ASSOC_ReturnData(out, outlen, data, datalen*sizeof(WCHAR));
-    *outlen /= sizeof(WCHAR);
-    return hres;
+    if (!out)
+    {
+        *outlen = datalen;
+        return S_FALSE;
+    }
+
+    if (*outlen < datalen)
+    {
+        if (flags & ASSOCF_NOTRUNCATE)
+        {
+            len = 0;
+            if (*outlen > 0) out[0] = 0;
+            hr = E_POINTER;
+        }
+        else
+        {
+            len = min(*outlen, datalen);
+            hr = E_NOT_SUFFICIENT_BUFFER;
+        }
+        *outlen = datalen;
+    }
+    else
+        len = datalen;
+
+    if (len)
+        memcpy(out, data, len*sizeof(WCHAR));
+
+    return hr;
 }
 
 /**************************************************************************
@@ -424,23 +448,22 @@ static HRESULT ASSOC_ReturnString(LPWSTR out, DWORD *outlen, LPCWSTR data,
  */
 static HRESULT WINAPI IQueryAssociations_fnGetString(
   IQueryAssociations *iface,
-  ASSOCF cfFlags,
+  ASSOCF flags,
   ASSOCSTR str,
   LPCWSTR pszExtra,
   LPWSTR pszOut,
   DWORD *pcchOut)
 {
   IQueryAssociationsImpl *This = impl_from_IQueryAssociations(iface);
-  const ASSOCF cfUnimplemented = ~(0);
+  const ASSOCF unimplemented_flags = ~ASSOCF_NOTRUNCATE;
   DWORD len = 0;
   HRESULT hr;
   WCHAR path[MAX_PATH];
 
-  TRACE("(%p,0x%08x,%u,%s,%p,%p)\n", This, cfFlags, str,
-        debugstr_w(pszExtra), pszOut, pcchOut);
+  TRACE("(%p)->(0x%08x, %u, %s, %p, %p)\n", This, flags, str, debugstr_w(pszExtra), pszOut, pcchOut);
 
-  if (cfFlags & cfUnimplemented)
-    FIXME("%08x: unimplemented flags!\n", cfFlags & cfUnimplemented);
+  if (flags & unimplemented_flags)
+    FIXME("%08x: unimplemented flags\n", flags & unimplemented_flags);
 
   if (!pcchOut)
     return E_UNEXPECTED;
@@ -453,7 +476,7 @@ static HRESULT WINAPI IQueryAssociations_fnGetString(
       hr = ASSOC_GetCommand(This, pszExtra, &command);
       if (SUCCEEDED(hr))
       {
-        hr = ASSOC_ReturnString(pszOut, pcchOut, command, strlenW(command) + 1);
+        hr = ASSOC_ReturnString(flags, pszOut, pcchOut, command, strlenW(command) + 1);
         HeapFree(GetProcessHeap(), 0, command);
       }
       return hr;
@@ -465,7 +488,7 @@ static HRESULT WINAPI IQueryAssociations_fnGetString(
       if (FAILED(hr))
         return hr;
       len++;
-      return ASSOC_ReturnString(pszOut, pcchOut, path, len);
+      return ASSOC_ReturnString(flags, pszOut, pcchOut, path, len);
     }
 
     case ASSOCSTR_FRIENDLYDOCNAME:
@@ -486,7 +509,7 @@ static HRESULT WINAPI IQueryAssociations_fnGetString(
         {
           ret = RegGetValueW(HKEY_CLASSES_ROOT, pszFileType, NULL, RRF_RT_REG_SZ, NULL, docName, &size);
           if (ret == ERROR_SUCCESS)
-            hr = ASSOC_ReturnString(pszOut, pcchOut, docName, strlenW(docName) + 1);
+            hr = ASSOC_ReturnString(flags, pszOut, pcchOut, docName, strlenW(docName) + 1);
           else
             hr = HRESULT_FROM_WIN32(ret);
           HeapFree(GetProcessHeap(), 0, docName);
@@ -542,7 +565,7 @@ static HRESULT WINAPI IQueryAssociations_fnGetString(
             /* Does strlenW(bufW) == 0 mean we use the filename? */
             len = strlenW(bufW) + 1;
             TRACE("found FileDescription: %s\n", debugstr_w(bufW));
-            hr = ASSOC_ReturnString(pszOut, pcchOut, bufW, len);
+            hr = ASSOC_ReturnString(flags, pszOut, pcchOut, bufW, len);
             HeapFree(GetProcessHeap(), 0, verinfoW);
             return hr;
           }
@@ -552,7 +575,7 @@ get_friendly_name_fail:
       PathRemoveExtensionW(path);
       PathStripPathW(path);
       TRACE("using filename: %s\n", debugstr_w(path));
-      hr = ASSOC_ReturnString(pszOut, pcchOut, path, strlenW(path) + 1);
+      hr = ASSOC_ReturnString(flags, pszOut, pcchOut, path, strlenW(path) + 1);
       HeapFree(GetProcessHeap(), 0, verinfoW);
       return hr;
     }
@@ -573,7 +596,7 @@ get_friendly_name_fail:
       {
         ret = RegGetValueW(This->hkeySource, NULL, Content_TypeW, RRF_RT_REG_SZ, NULL, contentType, &size);
         if (ret == ERROR_SUCCESS)
-          hr = ASSOC_ReturnString(pszOut, pcchOut, contentType, strlenW(contentType) + 1);
+          hr = ASSOC_ReturnString(flags, pszOut, pcchOut, contentType, strlenW(contentType) + 1);
         else
           hr = HRESULT_FROM_WIN32(ret);
         HeapFree(GetProcessHeap(), 0, contentType);
@@ -606,7 +629,7 @@ get_friendly_name_fail:
           {
             ret = RegGetValueW(hkeyFile, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, icon, &size);
             if (ret == ERROR_SUCCESS)
-              hr = ASSOC_ReturnString(pszOut, pcchOut, icon, strlenW(icon) + 1);
+              hr = ASSOC_ReturnString(flags, pszOut, pcchOut, icon, strlenW(icon) + 1);
             else
               hr = HRESULT_FROM_WIN32(ret);
             HeapFree(GetProcessHeap(), 0, icon);
@@ -645,7 +668,7 @@ get_friendly_name_fail:
         RegCloseKey(hkey);
         if (ret) return HRESULT_FROM_WIN32(ret);
 
-        return ASSOC_ReturnString(pszOut, pcchOut, guid, size / sizeof(WCHAR));
+        return ASSOC_ReturnString(flags, pszOut, pcchOut, guid, size / sizeof(WCHAR));
     }
 
     default:
diff --git a/dlls/shell32/tests/assoc.c b/dlls/shell32/tests/assoc.c
index 29524dc..abfe6d4 100644
--- a/dlls/shell32/tests/assoc.c
+++ b/dlls/shell32/tests/assoc.c
@@ -35,13 +35,8 @@ static void test_IQueryAssociations_QueryInterface(void)
     IUnknown *unk;
     HRESULT hr;
 
-    /* this works since XP */
     hr = CoCreateInstance(&CLSID_QueryAssociations, NULL, CLSCTX_INPROC_SERVER, &IID_IQueryAssociations, (void*)&qa);
-
-    if (FAILED(hr)) {
-        win_skip("CoCreateInstance for IQueryAssociations returned 0x%x\n", hr);
-        return;
-    }
+    ok(hr == S_OK, "got 0x%08x\n", hr);
 
     hr = IQueryAssociations_QueryInterface(qa, &IID_IQueryAssociations, (void**)&qa2);
     ok(hr == S_OK, "QueryInterface (IQueryAssociations) returned 0x%x\n", hr);
@@ -97,12 +92,96 @@ static void test_IApplicationAssociationRegistration_QueryInterface(void)
     IApplicationAssociationRegistration_Release(appreg);
 }
 
+struct assoc_getstring_test
+{
+    const WCHAR *key;
+    ASSOCF       flags;
+    ASSOCSTR     str;
+    DWORD        len;
+    HRESULT      hr;
+    HRESULT      brokenhr;
+};
+
+static const WCHAR httpW[] = {'h','t','t','p',0};
+
+static struct assoc_getstring_test getstring_tests[] =
+{
+    { httpW, 0, ASSOCSTR_EXECUTABLE, 2, 0x8007007a /* E_NOT_SUFFICIENT_BUFFER */, S_OK },
+    { httpW, ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, 2, E_POINTER },
+    { NULL }
+};
+
+static void test_IQueryAssociations_GetString(void)
+{
+    struct assoc_getstring_test *ptr = getstring_tests;
+    IQueryAssociations *assoc;
+    HRESULT hr;
+    DWORD len;
+    int i = 0;
+
+    hr = CoCreateInstance(&CLSID_QueryAssociations, NULL, CLSCTX_INPROC_SERVER, &IID_IQueryAssociations, (void*)&assoc);
+    ok(hr == S_OK, "failed to create object, 0x%x\n", hr);
+
+    hr = IQueryAssociations_Init(assoc, 0, httpW, NULL, NULL);
+    ok(hr == S_OK, "Init failed, 0x%x\n", hr);
+
+    len = 0;
+    hr = IQueryAssociations_GetString(assoc, 0, ASSOCSTR_EXECUTABLE, NULL, NULL, &len);
+    ok(hr == S_FALSE, "got 0x%08x\n", hr);
+    ok(len > 0, "got wrong needed length, %d\n", len);
+
+    while (ptr->key)
+    {
+        WCHAR buffW[MAX_PATH];
+        DWORD len;
+
+        hr = IQueryAssociations_Init(assoc, 0, ptr->key, NULL, NULL);
+        ok(hr == S_OK, "%d: Init failed, 0x%x\n", i, hr);
+
+        len = ptr->len;
+        buffW[0] = ptr->flags & ASSOCF_NOTRUNCATE ? 0x1 : 0;
+        hr = IQueryAssociations_GetString(assoc, ptr->flags, ptr->str, NULL, buffW, &len);
+        if (hr != ptr->hr)
+            ok(broken(hr == ptr->brokenhr), "%d: GetString failed, 0x%08x\n", i, hr);
+        else
+        {
+            ok(hr == ptr->hr, "%d: GetString failed, 0x%08x\n", i, hr);
+            ok(len > ptr->len, "%d: got needed length %d\n", i, len);
+        }
+
+        /* even with ASSOCF_NOTRUNCATE it's null terminated */
+        if ((ptr->flags & ASSOCF_NOTRUNCATE) && (ptr->len > 0))
+            ok(buffW[0] == 0 || broken(buffW[0] == 0x1) /* pre win7 */, "%d: got %x\n", i, buffW[0]);
+
+        if (!(ptr->flags & ASSOCF_NOTRUNCATE) && ptr->len && FAILED(ptr->hr))
+            ok(buffW[0] != 0, "%d: got %x\n", i, buffW[0]);
+
+        i++;
+        ptr++;
+    }
+
+    IQueryAssociations_Release(assoc);
+}
 
 START_TEST(assoc)
 {
+    IQueryAssociations *qa;
+    HRESULT hr;
+
     CoInitialize(NULL);
 
-    test_IQueryAssociations_QueryInterface();
+    /* this works since XP */
+    hr = CoCreateInstance(&CLSID_QueryAssociations, NULL, CLSCTX_INPROC_SERVER, &IID_IQueryAssociations, (void*)&qa);
+    if (hr == S_OK)
+    {
+        test_IQueryAssociations_QueryInterface();
+        test_IQueryAssociations_GetString();
+
+        IQueryAssociations_Release(qa);
+    }
+    else
+        win_skip("IQueryAssociations not supported, 0x%x\n", hr);
+
     test_IApplicationAssociationRegistration_QueryInterface();
 
     CoUninitialize();




More information about the wine-cvs mailing list