Signed-off-by: Sven Baars <sven.wine(a)gmail.com>
---
This should fix some memory leaks where PropVariantClear is expected to
destroy the safearray.
dlls/ole32/ole2.c | 26 ++++++++++++++
dlls/ole32/tests/propvariant.c | 63 ++++++++++++++++++++++++----------
2 files changed, 70 insertions(+), 19 deletions(-)
diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c
index 2de9edbb80..fa39abe2de 100644
--- a/dlls/ole32/ole2.c
+++ b/dlls/ole32/ole2.c
@@ -2797,6 +2797,25 @@ static inline HRESULT PROPVARIANT_ValidateType(VARTYPE vt)
case VT_FILETIME|VT_VECTOR:
case VT_CF|VT_VECTOR:
case VT_CLSID|VT_VECTOR:
+ case VT_ARRAY|VT_I1:
+ case VT_ARRAY|VT_UI1:
+ case VT_ARRAY|VT_I2:
+ case VT_ARRAY|VT_UI2:
+ case VT_ARRAY|VT_I4:
+ case VT_ARRAY|VT_UI4:
+ case VT_ARRAY|VT_INT:
+ case VT_ARRAY|VT_UINT:
+ case VT_ARRAY|VT_R4:
+ case VT_ARRAY|VT_R8:
+ case VT_ARRAY|VT_CY:
+ case VT_ARRAY|VT_DATE:
+ case VT_ARRAY|VT_BSTR:
+ case VT_ARRAY|VT_BOOL:
+ case VT_ARRAY|VT_DECIMAL:
+ case VT_ARRAY|VT_DISPATCH:
+ case VT_ARRAY|VT_UNKNOWN:
+ case VT_ARRAY|VT_ERROR:
+ case VT_ARRAY|VT_VARIANT:
return S_OK;
}
WARN("Bad type %d\n", vt);
@@ -2908,6 +2927,8 @@ HRESULT WINAPI PropVariantClear(PROPVARIANT * pvar) /* [in/out] */
CoTaskMemFree(pvar->u.capropvar.pElems);
}
}
+ else if (pvar->vt & VT_ARRAY)
+ hr = SafeArrayDestroy(pvar->u.parray);
else
{
WARN("Invalid/unsupported type %d\n", pvar->vt);
@@ -3088,6 +3109,11 @@ HRESULT WINAPI PropVariantCopy(PROPVARIANT *pvarDest, /* [out] */
else
CopyMemory(pvarDest->u.capropvar.pElems, pvarSrc->u.capropvar.pElems, len * elemSize);
}
+ else if (pvarSrc->vt & VT_ARRAY)
+ {
+ pvarDest->u.uhVal.QuadPart = 0;
+ return SafeArrayCopy(pvarSrc->u.parray, &pvarDest->u.parray);
+ }
else
WARN("Invalid/unsupported type %d\n", pvarSrc->vt);
}
diff --git a/dlls/ole32/tests/propvariant.c b/dlls/ole32/tests/propvariant.c
index 8c9f79e8d6..18ecfa6528 100644
--- a/dlls/ole32/tests/propvariant.c
+++ b/dlls/ole32/tests/propvariant.c
@@ -46,28 +46,28 @@ static const struct valid_mapping
{
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_EMPTY */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_NULL */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I2 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I4 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R4 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R8 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */
- { PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I2 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I4 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R4 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R8 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */
+ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */
+ { PROP_V1 | PROP_TODO , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */
+ { PROP_V1 , PROP_V1, PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
+ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI1 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI2 */
- { PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */
+ { PROP_V1 , PROP_V1 , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI1 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI2 */
+ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */
{ PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_I8 */
{ PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_UI8 */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */
- { PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */
+ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */
+ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */
@@ -351,6 +351,9 @@ static void test_copy(void)
struct unk_impl unk_obj = {{&unk_vtbl}, 1};
PROPVARIANT propvarSrc;
PROPVARIANT propvarDst;
+ SAFEARRAY *sa;
+ SAFEARRAYBOUND sabound;
+ LONG saindex;
HRESULT hr;
propvarSrc.vt = VT_BSTR;
@@ -392,6 +395,28 @@ static void test_copy(void)
ok(hr == S_OK, "PropVariantClear(...VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
memset(&propvarSrc, 0, sizeof(propvarSrc));
+
+ sabound.lLbound = 0;
+ sabound.cElements = 2;
+ sa = SafeArrayCreate(VT_UNKNOWN, 1, &sabound);
+ saindex = 0;
+ SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
+ saindex = 1;
+ SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
+ ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
+
+ propvarSrc.vt = VT_ARRAY | VT_UNKNOWN;
+ U(propvarSrc).parray = sa;
+ hr = PropVariantCopy(&propvarDst, &propvarSrc);
+ ok(hr == S_OK, "PropVariantCopy(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
+ ok(unk_obj.ref == 5, "got wrong refcount: %d.\n", unk_obj.ref);
+ hr = PropVariantClear(&propvarDst);
+ ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
+ ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
+ hr = PropVariantClear(&propvarSrc);
+ ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
+ ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
+ memset(&propvarSrc, 0, sizeof(propvarSrc));
}
struct _PMemoryAllocator_vtable {
--
2.17.1