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