shell32: Added support for ASSOCF_NOTRUNCATE flag in GetString().
This commit is contained in:
parent
4f6230d5c4
commit
891cf2ac54
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* 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();
|
||||
|
|
Loading…
Reference in New Issue