From: Piotr Caban piotr@codeweavers.com
--- dlls/propsys/propsys.spec | 2 +- dlls/propsys/propvar.c | 49 ++++++++++++++++++++++++ dlls/propsys/tests/propsys.c | 73 ++++++++++++++++++++++++++++++++++++ include/propvarutil.h | 2 + 4 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec index 6a608ca88c1..6a1a313f93b 100644 --- a/dlls/propsys/propsys.spec +++ b/dlls/propsys/propsys.spec @@ -102,7 +102,7 @@ @ stub PropVariantGetInt16Elem @ stub PropVariantGetInt32Elem @ stub PropVariantGetInt64Elem -@ stub PropVariantGetStringElem +@ stdcall PropVariantGetStringElem(ptr long ptr) @ stub PropVariantGetUInt16Elem @ stub PropVariantGetUInt32Elem @ stub PropVariantGetUInt64Elem diff --git a/dlls/propsys/propvar.c b/dlls/propsys/propvar.c index 7572c33821d..c5d86c0027c 100644 --- a/dlls/propsys/propvar.c +++ b/dlls/propsys/propvar.c @@ -1263,3 +1263,52 @@ HRESULT WINAPI VariantToPropVariant(const VARIANT *var, PROPVARIANT *propvar)
return S_OK; } + +HRESULT WINAPI PropVariantGetStringElem(const PROPVARIANT *propvar, ULONG idx, WCHAR **ret) +{ + const WCHAR *wstr; + + TRACE("propvar %p, idx %lu, ret %p, propvar->vt %#x.\n", propvar, idx, ret, propvar ? propvar->vt : 0); + + *ret = 0; + switch (propvar->vt) + { + case VT_BSTR: + if (idx != 0) return E_INVALIDARG; + wstr = propvar->bstrVal; + break; + case VT_LPWSTR: + if (idx != 0) return E_INVALIDARG; + wstr = propvar->pwszVal; + break; + case VT_BSTR | VT_VECTOR: + if (idx >= propvar->cabstr.cElems) return E_INVALIDARG; + wstr = propvar->cabstr.pElems[idx]; + break; + case VT_LPWSTR | VT_VECTOR: + if (idx >= propvar->calpwstr.cElems) return E_INVALIDARG; + wstr = propvar->calpwstr.pElems[idx]; + break; + case VT_BSTR | VT_ARRAY: + { + LONG l = idx; + HRESULT hr; + + if (SafeArrayGetDim(propvar->parray) != 1) return E_INVALIDARG; + /* bug in native implementation: ignore lower-bound when checking bounds */ + if (idx >= propvar->parray->rgsabound[0].cElements) return E_INVALIDARG; + hr = SafeArrayGetElement(propvar->parray, &l, &wstr); + if (FAILED(hr)) return hr; + break; + } + default: + return E_INVALIDARG; + } + + if (!wstr) wstr = L""; + *ret = CoTaskMemAlloc((wcslen(wstr) + 1) * sizeof(WCHAR)); + if (!*ret) + return E_OUTOFMEMORY; + wcscpy(*ret, wstr); + return S_OK; +} diff --git a/dlls/propsys/tests/propsys.c b/dlls/propsys/tests/propsys.c index 273c99524ea..76d6c866546 100644 --- a/dlls/propsys/tests/propsys.c +++ b/dlls/propsys/tests/propsys.c @@ -2722,6 +2722,78 @@ static void test_PropVariantToVariant(void) VariantClear(&var); }
+void test_PropVariantGetStringElem(void) +{ + const WCHAR *strings[] = { L"a", L"bc" }; + PROPVARIANT propvar; + WCHAR *wstr; + HRESULT hr; + LONG idx; + + propvar.vt = VT_I4; + propvar.lVal = 1; + wstr = (WCHAR*)0xdeadbeef; + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(hr == E_INVALIDARG, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wstr, "wstr = %p\n", wstr); + + propvar.vt = VT_LPSTR; + propvar.pszVal = (char *)"test"; + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(hr == E_INVALIDARG, "PropVariantGetStringElem returned %#lx.\n", hr); + + propvar.vt = VT_BSTR; + propvar.pwszVal = NULL; + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(!hr, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wstr[0], "wstr = %s\n", debugstr_w(wstr)); + + propvar.vt = VT_BSTR; + propvar.bstrVal = SysAllocString(L"test"); + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(!hr, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wcscmp(wstr, L"test"), "wstr = %s\n", debugstr_w(wstr)); + CoTaskMemFree(wstr); + hr = PropVariantGetStringElem(&propvar, 1, &wstr); + ok(hr == E_INVALIDARG, "PropVariantGetStringElem returned %#lx.\n", hr); + PropVariantClear(&propvar); + + hr = InitPropVariantFromStringVector(strings, ARRAY_SIZE(strings), &propvar); + ok(hr == S_OK, "InitPropVariantFromStringAsVector failed %lx\n", hr); + ok(propvar.vt == (VT_VECTOR | VT_LPWSTR), "propvar.vt = %x\n", propvar.vt); + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(!hr, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wcscmp(wstr, L"a"), "wstr = %s\n", debugstr_w(wstr)); + CoTaskMemFree(wstr); + hr = PropVariantGetStringElem(&propvar, 1, &wstr); + ok(!hr, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wcscmp(wstr, L"bc"), "wstr = %s\n", debugstr_w(wstr)); + CoTaskMemFree(wstr); + hr = PropVariantGetStringElem(&propvar, 2, &wstr); + ok(hr == E_INVALIDARG, "PropVariantGetStringElem returned %#lx.\n", hr); + PropVariantClear(&propvar); + + propvar.vt = VT_BSTR | VT_ARRAY; + propvar.parray = SafeArrayCreateVector(VT_BSTR, 1, 2); + ok(propvar.parray != NULL, "SafeArrayCreate failed\n"); + idx = 1; + hr = SafeArrayPutElement(propvar.parray, &idx, SysAllocString(L"test")); + ok(!hr, "SafeArrayPutElement returned %#lx.\n", hr); + idx = 2; + hr = SafeArrayPutElement(propvar.parray, &idx, SysAllocString(L"abc")); + ok(!hr, "SafeArrayPutElement returned %#lx.\n", hr); + hr = PropVariantGetStringElem(&propvar, 0, &wstr); + ok(hr == DISP_E_BADINDEX, "PropVariantGetStringElem returned %#lx.\n", hr); + hr = PropVariantGetStringElem(&propvar, 1, &wstr); + ok(!hr, "PropVariantGetStringElem returned %#lx.\n", hr); + ok(!wcscmp(wstr, L"test"), "wstr = %s\n", debugstr_w(wstr)); + CoTaskMemFree(wstr); + /* function works incorrectry if lower-band != 0 */ + hr = PropVariantGetStringElem(&propvar, 2, &wstr); + ok(hr == E_INVALIDARG, "PropVariantGetStringElem returned %#lx.\n", hr); + PropVariantClear(&propvar); +} + START_TEST(propsys) { test_InitPropVariantFromGUIDAsString(); @@ -2753,4 +2825,5 @@ START_TEST(propsys) test_VariantToString(); test_VariantToPropVariant(); test_PropVariantToVariant(); + test_PropVariantGetStringElem(); } diff --git a/include/propvarutil.h b/include/propvarutil.h index 0c23c7caa70..e35d8c5d0d4 100644 --- a/include/propvarutil.h +++ b/include/propvarutil.h @@ -114,6 +114,8 @@ PSSTDAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret); PSSTDAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var); PSSTDAPI VariantToPropVariant(const VARIANT* var, PROPVARIANT* propvar);
+PSSTDAPI PropVariantGetStringElem(const PROPVARIANT *propvar, ULONG idx, WCHAR **ret); + #ifdef __cplusplus
HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar);