Signed-off-by: Sven Baars sven.wine@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 {