From: Piotr Caban piotr@codeweavers.com
--- dlls/ole32/stg_prop.c | 55 ++++++++++++++++++---------------- dlls/ole32/tests/propvariant.c | 39 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 26 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index b367988f8fc..c4145cf864f 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -1594,43 +1594,46 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read
if (prop->vt & VT_VECTOR) { + size_t elemsize = propertystorage_get_elemsize(prop); + PROPVARIANT elem; DWORD count, i;
- switch (prop->vt & ~VT_VECTOR) - { - case VT_BSTR: - case VT_VARIANT: - case VT_LPSTR: - case VT_LPWSTR: - case VT_CF: - FIXME("Vector with variable length elements are not supported.\n"); - return STG_E_INVALIDPARAMETER; - default: - ; - } + if (!elemsize) + return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); + if (FAILED(hr = buffer_read_dword(buffer, offset, &count))) + return hr; + offset += sizeof(DWORD);
- if (SUCCEEDED(hr = buffer_read_dword(buffer, offset, &count))) - { - size_t elemsize = propertystorage_get_elemsize(prop); - PROPVARIANT elem; + if (!(prop->cac.pElems = call_IMemoryAllocator_Allocate(pma, elemsize * count))) + return STG_E_INSUFFICIENTMEMORY;
- offset += sizeof(DWORD); + prop->cac.cElems = count; + elem.vt = prop->vt & ~VT_VECTOR;
- if ((prop->capropvar.pElems = call_IMemoryAllocator_Allocate(pma, elemsize * count))) + for (i = 0; i < count; ++i) + { + if (FAILED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, pma))) { - prop->capropvar.cElems = count; - elem.vt = prop->vt & ~VT_VECTOR; - - for (i = 0; i < count; ++i) + for (; i > 0; --i) { - if (SUCCEEDED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, pma))) + switch(elem.vt) { - memcpy(&prop->capropvar.pElems[i], &elem.lVal, elemsize); + case VT_LPSTR: + case VT_LPWSTR: + case VT_CF: + case VT_CLSID: + call_IMemoryAllocator_Free(pma, prop->calpwstr.pElems); + break; + case VT_BSTR: + SysFreeString(prop->cabstr.pElems[i -1]); + break; } } + + call_IMemoryAllocator_Free(pma, prop->cac.pElems); + return hr; } - else - hr = STG_E_INSUFFICIENTMEMORY; + memcpy(prop->cac.pElems + elemsize * i, &elem.lVal, elemsize); } } else if (prop->vt & VT_ARRAY) diff --git a/dlls/ole32/tests/propvariant.c b/dlls/ole32/tests/propvariant.c index 01f27f400c1..875a213c197 100644 --- a/dlls/ole32/tests/propvariant.c +++ b/dlls/ole32/tests/propvariant.c @@ -530,6 +530,20 @@ static const char serialized_bstr_mb[] = { 0,0,0,0 };
+static const char serialized_bstr_vec[] = { + VT_LPWSTR, VT_VECTOR >> 8, 0, 0, + 3, 0, 0, 0, + 2, 0, 0, 0, 'a', 0, 0, 0, + 3, 0, 0, 0, 'b', 0, 'c', 0, 0, 0, 0, 0, + 4, 0, 0, 0, 'd', 0, 'e', 0, 'f', 0, 0, 0 +}; + +static const char serialized_i1_vec[] = { + VT_I1, VT_VECTOR >> 8, 0, 0, + 3, 0, 0, 0, + 1, 2, 3, 0 +}; + static void test_propertytovariant(void) { HANDLE hole32; @@ -587,6 +601,31 @@ static void test_propertytovariant(void) ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt); ok(!lstrcmpW(propvar.bstrVal, test_string), "unexpected string value\n"); PropVariantClear(&propvar); + + ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_i1_vec, + CP_WINUNICODE, &propvar, &allocator); + + ok(!ret, "StgConvertPropertyToVariant returned %i\n", ret); + ok(propvar.vt == (VT_VECTOR | VT_I1), "unexpected vt %x\n", propvar.vt); + ok(propvar.cac.cElems == 3, "unexpected cElems %lu\n", propvar.cac.cElems); + ok(propvar.cac.pElems[0] == 1, "pElems[0] = %d\n", propvar.cac.pElems[0]); + ok(propvar.cac.pElems[1] == 2, "pElems[0] = %d\n", propvar.cac.pElems[1]); + ok(propvar.cac.pElems[2] == 3, "pElems[0] = %d\n", propvar.cac.pElems[2]); + PropVariantClear(&propvar); + + ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_vec, + CP_WINUNICODE, &propvar, &allocator); + + ok(!ret, "StgConvertPropertyToVariant returned %i\n", ret); + ok(propvar.vt == (VT_VECTOR | VT_LPWSTR), "unexpected vt %x\n", propvar.vt); + ok(propvar.calpwstr.cElems == 3, "unexpected cElems %lu\n", propvar.calpwstr.cElems); + ok(!wcscmp(propvar.calpwstr.pElems[0], L"a"), "pElems[0] = %s\n", + debugstr_w(propvar.calpwstr.pElems[0])); + ok(!wcscmp(propvar.calpwstr.pElems[1], L"bc"), "pElems[1] = %s\n", + debugstr_w(propvar.calpwstr.pElems[1])); + ok(!wcscmp(propvar.calpwstr.pElems[2], L"def"), "pElems[2] = %s\n", + debugstr_w(propvar.calpwstr.pElems[2])); + PropVariantClear(&propvar); }
static void test_varianttoproperty(void)