From: Piotr Caban piotr@codeweavers.com
--- dlls/ole32/stg_prop.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index a19ce8ad3d6..3c36f597a59 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -1471,9 +1471,6 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_
static size_t propertystorage_get_elemsize(const PROPVARIANT *prop) { - if (!(prop->vt & VT_VECTOR)) - return 0; - switch (prop->vt & ~VT_VECTOR) { case VT_I1: return sizeof(*prop->cac.pElems); @@ -1492,9 +1489,14 @@ static size_t propertystorage_get_elemsize(const PROPVARIANT *prop) case VT_DATE: return sizeof(*prop->cadate.pElems); case VT_FILETIME: return sizeof(*prop->cafiletime.pElems); case VT_CLSID: return sizeof(*prop->cauuid.pElems); + case VT_CF: return sizeof(*prop->caclipdata.pElems); + case VT_BSTR: return sizeof(*prop->cabstr.pElems); + case VT_BSTR_BLOB: return sizeof(*prop->cabstrblob.pElems); + case VT_LPSTR: return sizeof(*prop->calpstr.pElems); + case VT_LPWSTR: return sizeof(*prop->calpwstr.pElems); case VT_VARIANT: return sizeof(*prop->capropvar.pElems); default: - FIXME("Unhandled type %#x.\n", prop->vt); + ERR("Unexpected type %#x.\n", prop->vt); return 0; } }
From: Piotr Caban piotr@codeweavers.com
--- dlls/ole32/stg_prop.c | 94 +++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 35 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index 3c36f597a59..7d2e6f12e4c 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -1241,7 +1241,7 @@ static HRESULT buffer_read_len(const struct read_buffer *buffer, size_t offset, return hr; }
-static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_buffer *buffer, size_t offset, +static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_buffer *buffer, size_t *offset, UINT codepage, void* (WINAPI *allocate)(void *this, ULONG size), void *allocate_data) { HRESULT hr; @@ -1255,55 +1255,65 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ hr = S_OK; break; case VT_I1: - hr = buffer_read_byte(buffer, offset, (BYTE *)&prop->cVal); + hr = buffer_read_byte(buffer, *offset, (BYTE *)&prop->cVal); + *offset += sizeof(BYTE); TRACE("Read char 0x%x ('%c')\n", prop->cVal, prop->cVal); break; case VT_UI1: - hr = buffer_read_byte(buffer, offset, &prop->bVal); + hr = buffer_read_byte(buffer, *offset, &prop->bVal); + *offset += sizeof(BYTE); TRACE("Read byte 0x%x\n", prop->bVal); break; case VT_BOOL: - hr = buffer_read_word(buffer, offset, (WORD *)&prop->boolVal); + hr = buffer_read_word(buffer, *offset, (WORD *)&prop->boolVal); + *offset += sizeof(WORD); TRACE("Read bool %d\n", prop->boolVal); break; case VT_I2: - hr = buffer_read_word(buffer, offset, (WORD *)&prop->iVal); + hr = buffer_read_word(buffer, *offset, (WORD *)&prop->iVal); + *offset += sizeof(WORD); TRACE("Read short %d\n", prop->iVal); break; case VT_UI2: - hr = buffer_read_word(buffer, offset, &prop->uiVal); + hr = buffer_read_word(buffer, *offset, &prop->uiVal); + *offset += sizeof(WORD); TRACE("Read ushort %d\n", prop->uiVal); break; case VT_INT: case VT_I4: - hr = buffer_read_dword(buffer, offset, (DWORD *)&prop->lVal); + hr = buffer_read_dword(buffer, *offset, (DWORD *)&prop->lVal); + *offset += sizeof(DWORD); TRACE("Read long %ld\n", prop->lVal); break; case VT_UINT: case VT_UI4: - hr = buffer_read_dword(buffer, offset, &prop->ulVal); + hr = buffer_read_dword(buffer, *offset, &prop->ulVal); + *offset += sizeof(DWORD); TRACE("Read ulong %ld\n", prop->ulVal); break; case VT_I8: - hr = buffer_read_uint64(buffer, offset, (ULARGE_INTEGER *)&prop->hVal); + hr = buffer_read_uint64(buffer, *offset, (ULARGE_INTEGER *)&prop->hVal); + *offset += sizeof(UINT64); TRACE("Read long long %s\n", wine_dbgstr_longlong(prop->hVal.QuadPart)); break; case VT_UI8: - hr = buffer_read_uint64(buffer, offset, &prop->uhVal); + hr = buffer_read_uint64(buffer, *offset, &prop->uhVal); + *offset += sizeof(UINT64); TRACE("Read ulong long %s\n", wine_dbgstr_longlong(prop->uhVal.QuadPart)); break; case VT_R8: - hr = buffer_read_len(buffer, offset, &prop->dblVal, sizeof(prop->dblVal)); + hr = buffer_read_len(buffer, *offset, &prop->dblVal, sizeof(prop->dblVal)); + *offset += sizeof(prop->dblVal); TRACE("Read double %f\n", prop->dblVal); break; case VT_LPSTR: { DWORD count;
- if (FAILED(hr = buffer_read_dword(buffer, offset, &count))) + if (FAILED(hr = buffer_read_dword(buffer, *offset, &count))) break;
- offset += sizeof(DWORD); + *offset += sizeof(DWORD);
if (codepage == CP_UNICODE && count % sizeof(WCHAR)) { @@ -1315,8 +1325,9 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ prop->pszVal = allocate(allocate_data, count); if (prop->pszVal) { - if (FAILED(hr = buffer_read_len(buffer, offset, prop->pszVal, count))) + if (FAILED(hr = buffer_read_len(buffer, *offset, prop->pszVal, count))) break; + *offset += ALIGNED_LENGTH(count, sizeof(DWORD) - 1);
/* This is stored in the code page specified in codepage. * Don't convert it, the caller will just store it as-is. @@ -1344,10 +1355,10 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ { DWORD count, wcount;
- if (FAILED(hr = buffer_read_dword(buffer, offset, &count))) + if (FAILED(hr = buffer_read_dword(buffer, *offset, &count))) break;
- offset += sizeof(DWORD); + *offset += sizeof(DWORD);
if (codepage == CP_UNICODE && count % sizeof(WCHAR)) { @@ -1360,9 +1371,9 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ wcount = count / sizeof(WCHAR); else { - if (FAILED(hr = buffer_test_offset(buffer, offset, count))) + if (FAILED(hr = buffer_test_offset(buffer, *offset, count))) break; - wcount = MultiByteToWideChar(codepage, 0, (LPCSTR)(buffer->data + offset), count, NULL, 0); + wcount = MultiByteToWideChar(codepage, 0, (LPCSTR)(buffer->data + *offset), count, NULL, 0); }
prop->bstrVal = SysAllocStringLen(NULL, wcount); /* FIXME: use allocator? */ @@ -1370,9 +1381,15 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ if (prop->bstrVal) { if (codepage == CP_UNICODE) - hr = buffer_read_len(buffer, offset, prop->bstrVal, count); + { + hr = buffer_read_len(buffer, *offset, prop->bstrVal, count); + offset += ALIGNED_LENGTH(count, sizeof(DWORD) - 1); + } else - MultiByteToWideChar(codepage, 0, (LPCSTR)(buffer->data + offset), count, prop->bstrVal, wcount); + { + MultiByteToWideChar(codepage, 0, (LPCSTR)(buffer->data + *offset), count, prop->bstrVal, wcount); + offset += ALIGNED_LENGTH(wcount, sizeof(DWORD) - 1); + }
prop->bstrVal[wcount - 1] = '\0'; TRACE("Read string value %s\n", debugstr_w(prop->bstrVal)); @@ -1386,16 +1403,17 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ { DWORD count;
- if (FAILED(hr = buffer_read_dword(buffer, offset, &count))) + if (FAILED(hr = buffer_read_dword(buffer, *offset, &count))) break;
- offset += sizeof(DWORD); + *offset += sizeof(DWORD);
prop->blob.cbSize = count; prop->blob.pBlobData = allocate(allocate_data, count); if (prop->blob.pBlobData) { - hr = buffer_read_len(buffer, offset, prop->blob.pBlobData, count); + hr = buffer_read_len(buffer, *offset, prop->blob.pBlobData, count); + *offset += count; TRACE("Read blob value of size %ld\n", count); } else @@ -1406,16 +1424,17 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ { DWORD count;
- if (FAILED(hr = buffer_read_dword(buffer, offset, &count))) + if (FAILED(hr = buffer_read_dword(buffer, *offset, &count))) break;
- offset += sizeof(DWORD); + *offset += sizeof(DWORD);
prop->pwszVal = allocate(allocate_data, count * sizeof(WCHAR)); if (prop->pwszVal) { - if (SUCCEEDED(hr = buffer_read_len(buffer, offset, prop->pwszVal, count * sizeof(WCHAR)))) + if (SUCCEEDED(hr = buffer_read_len(buffer, *offset, prop->pwszVal, count * sizeof(WCHAR)))) { + *offset += ALIGNED_LENGTH(count * sizeof(WCHAR), sizeof(DWORD) - 1); /* make sure string is NULL-terminated */ prop->pwszVal[count - 1] = '\0'; PropertyStorage_ByteSwapString(prop->pwszVal, count); @@ -1427,18 +1446,19 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ break; } case VT_FILETIME: - hr = buffer_read_uint64(buffer, offset, (ULARGE_INTEGER *)&prop->filetime); + hr = buffer_read_uint64(buffer, *offset, (ULARGE_INTEGER *)&prop->filetime); + *offset += sizeof(UINT64); break; case VT_CF: { DWORD len = 0, tag = 0;
- if (SUCCEEDED(hr = buffer_read_dword(buffer, offset, &len))) - hr = buffer_read_dword(buffer, offset + sizeof(DWORD), &tag); + if (SUCCEEDED(hr = buffer_read_dword(buffer, *offset, &len))) + hr = buffer_read_dword(buffer, *offset + sizeof(DWORD), &tag); if (FAILED(hr)) break;
- offset += 2 * sizeof(DWORD); + *offset += 2 * sizeof(DWORD);
if (len > 8) { @@ -1447,7 +1467,8 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ prop->pclipdata->cbSize = len; prop->pclipdata->ulClipFmt = tag; prop->pclipdata->pClipData = allocate(allocate_data, len - sizeof(prop->pclipdata->ulClipFmt)); - hr = buffer_read_len(buffer, offset, prop->pclipdata->pClipData, len - sizeof(prop->pclipdata->ulClipFmt)); + hr = buffer_read_len(buffer, *offset, prop->pclipdata->pClipData, len - sizeof(prop->pclipdata->ulClipFmt)); + *offset += ALIGNED_LENGTH(len - sizeof(prop->pclipdata->ulClipFmt), sizeof(DWORD) - 1); } else hr = STG_E_INVALIDPARAMETER; @@ -1457,8 +1478,11 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ if (!(prop->puuid = allocate(allocate_data, sizeof (*prop->puuid)))) return STG_E_INSUFFICIENTMEMORY;
- if (SUCCEEDED(hr = buffer_test_offset(buffer, offset, sizeof(*prop->puuid)))) - StorageUtl_ReadGUID(buffer->data, offset, prop->puuid); + if (SUCCEEDED(hr = buffer_test_offset(buffer, *offset, sizeof(*prop->puuid)))) + { + StorageUtl_ReadGUID(buffer->data, *offset, prop->puuid); + *offset += sizeof(*prop->puuid); + }
break; default: @@ -1547,7 +1571,7 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read
for (i = 0; i < count; ++i) { - if (SUCCEEDED(hr = propertystorage_read_scalar(&elem, buffer, offset + i * elemsize, codepage, + if (SUCCEEDED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, allocate, allocate_data))) { memcpy(&prop->capropvar.pElems[i], &elem.lVal, elemsize); @@ -1564,7 +1588,7 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read hr = STG_E_INVALIDPARAMETER; } else - hr = propertystorage_read_scalar(prop, buffer, offset, codepage, allocate, allocate_data); + hr = propertystorage_read_scalar(prop, buffer, &offset, codepage, allocate, allocate_data);
return hr; }
From: Piotr Caban piotr@codeweavers.com
So we can free the memory in case of error. --- dlls/ole32/stg_prop.c | 113 ++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 43 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index 7d2e6f12e4c..b367988f8fc 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -57,6 +57,63 @@
WINE_DEFAULT_DEBUG_CHANNEL(storage);
+#ifdef __ASM_USE_THISCALL_WRAPPER + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args + +#define DEFINE_VTBL_WRAPPER(off) \ + __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \ + "popl %eax\n\t" \ + "popl %ecx\n\t" \ + "pushl %eax\n\t" \ + "movl 0(%ecx), %eax\n\t" \ + "jmp *" #off "(%eax)\n\t") + +DEFINE_VTBL_WRAPPER(0); +DEFINE_VTBL_WRAPPER(4); + +#else + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__thiscall***)type)this)[0][off/4]args + +#endif + +#define call_IMemoryAllocator_Allocate(this, size) CALL_VTBL_FUNC(this, 0, \ + void*, (void*, ULONG), (this, size)) +#define call_IMemoryAllocator_Free(this, v) CALL_VTBL_FUNC(this, 4, \ + void, (void*, void*), (this, v)) + +DEFINE_THISCALL_WRAPPER(memory_allocator_Allocate, 8) +static void* __thiscall memory_allocator_Allocate(void *this, ULONG size) +{ + return CoTaskMemAlloc(size); +} + +DEFINE_THISCALL_WRAPPER(memory_allocator_Free, 8) +static void __thiscall memory_allocator_Free(void *this, void *v) +{ + CoTaskMemFree(v); +} + +struct +{ + void *Allocate; + void *Free; +} memory_allocator_vtbl = +{ + THISCALL(memory_allocator_Allocate), + THISCALL(memory_allocator_Free) +}; + +struct +{ + void *vtbl; +} memory_allocator = +{ + &memory_allocator_vtbl +}; + + static inline StorageImpl *impl_from_IPropertySetStorage( IPropertySetStorage *iface ) { return CONTAINING_RECORD(iface, StorageImpl, base.IPropertySetStorage_iface); @@ -1175,11 +1232,6 @@ static void PropertyStorage_ByteSwapString(LPWSTR str, size_t len) #define PropertyStorage_ByteSwapString(s, l) #endif
-static void* WINAPI Allocate_CoTaskMemAlloc(void *this, ULONG size) -{ - return CoTaskMemAlloc(size); -} - struct read_buffer { BYTE *data; @@ -1242,7 +1294,7 @@ static HRESULT buffer_read_len(const struct read_buffer *buffer, size_t offset, }
static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_buffer *buffer, size_t *offset, - UINT codepage, void* (WINAPI *allocate)(void *this, ULONG size), void *allocate_data) + UINT codepage, void *pma) { HRESULT hr;
@@ -1322,7 +1374,7 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ } else { - prop->pszVal = allocate(allocate_data, count); + prop->pszVal = call_IMemoryAllocator_Allocate(pma, count); if (prop->pszVal) { if (FAILED(hr = buffer_read_len(buffer, *offset, prop->pszVal, count))) @@ -1409,7 +1461,7 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ *offset += sizeof(DWORD);
prop->blob.cbSize = count; - prop->blob.pBlobData = allocate(allocate_data, count); + prop->blob.pBlobData = call_IMemoryAllocator_Allocate(pma, count); if (prop->blob.pBlobData) { hr = buffer_read_len(buffer, *offset, prop->blob.pBlobData, count); @@ -1429,7 +1481,7 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_
*offset += sizeof(DWORD);
- prop->pwszVal = allocate(allocate_data, count * sizeof(WCHAR)); + prop->pwszVal = call_IMemoryAllocator_Allocate(pma, count * sizeof(WCHAR)); if (prop->pwszVal) { if (SUCCEEDED(hr = buffer_read_len(buffer, *offset, prop->pwszVal, count * sizeof(WCHAR)))) @@ -1463,10 +1515,10 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ if (len > 8) { len -= 8; - prop->pclipdata = allocate(allocate_data, sizeof (CLIPDATA)); + prop->pclipdata = call_IMemoryAllocator_Allocate(pma, sizeof (CLIPDATA)); prop->pclipdata->cbSize = len; prop->pclipdata->ulClipFmt = tag; - prop->pclipdata->pClipData = allocate(allocate_data, len - sizeof(prop->pclipdata->ulClipFmt)); + prop->pclipdata->pClipData = call_IMemoryAllocator_Allocate(pma, len - sizeof(prop->pclipdata->ulClipFmt)); hr = buffer_read_len(buffer, *offset, prop->pclipdata->pClipData, len - sizeof(prop->pclipdata->ulClipFmt)); *offset += ALIGNED_LENGTH(len - sizeof(prop->pclipdata->ulClipFmt), sizeof(DWORD) - 1); } @@ -1475,7 +1527,7 @@ static HRESULT propertystorage_read_scalar(PROPVARIANT *prop, const struct read_ } break; case VT_CLSID: - if (!(prop->puuid = allocate(allocate_data, sizeof (*prop->puuid)))) + if (!(prop->puuid = call_IMemoryAllocator_Allocate(pma, sizeof (*prop->puuid)))) return STG_E_INSUFFICIENTMEMORY;
if (SUCCEEDED(hr = buffer_test_offset(buffer, *offset, sizeof(*prop->puuid)))) @@ -1526,7 +1578,7 @@ static size_t propertystorage_get_elemsize(const PROPVARIANT *prop) }
static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read_buffer *buffer, - size_t offset, UINT codepage, void* (WINAPI *allocate)(void *this, ULONG size), void *allocate_data) + size_t offset, UINT codepage, void *pma) { HRESULT hr; DWORD vt; @@ -1564,15 +1616,14 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read
offset += sizeof(DWORD);
- if ((prop->capropvar.pElems = allocate(allocate_data, elemsize * count))) + if ((prop->capropvar.pElems = call_IMemoryAllocator_Allocate(pma, elemsize * count))) { prop->capropvar.cElems = count; elem.vt = prop->vt & ~VT_VECTOR;
for (i = 0; i < count; ++i) { - if (SUCCEEDED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, - allocate, allocate_data))) + if (SUCCEEDED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, pma))) { memcpy(&prop->capropvar.pElems[i], &elem.lVal, elemsize); } @@ -1588,7 +1639,7 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read hr = STG_E_INVALIDPARAMETER; } else - hr = propertystorage_read_scalar(prop, buffer, &offset, codepage, allocate, allocate_data); + hr = propertystorage_read_scalar(prop, buffer, &offset, codepage, pma);
return hr; } @@ -1888,8 +1939,7 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
PropVariantInit(&prop); if (SUCCEEDED(PropertyStorage_ReadProperty(&prop, &read_buffer, - idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER), This->codePage, - Allocate_CoTaskMemAlloc, NULL))) + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER), This->codePage, &memory_allocator))) { TRACE("Read property with ID %#lx, type %d\n", idOffset->propid, prop.vt); switch(idOffset->propid) @@ -3024,29 +3074,6 @@ static const IPropertyStorageVtbl IPropertyStorage_Vtbl = IPropertyStorage_fnStat, };
-#ifdef __i386__ /* thiscall functions are i386-specific */ - -#define DEFINE_STDCALL_WRAPPER(num,func,args) \ - __ASM_STDCALL_FUNC(func, args, \ - "popl %eax\n\t" \ - "popl %ecx\n\t" \ - "pushl %eax\n\t" \ - "movl (%ecx), %eax\n\t" \ - "jmp *(4*(" #num "))(%eax)" ) - -DEFINE_STDCALL_WRAPPER(0,Allocate_PMemoryAllocator,8) -extern void* WINAPI Allocate_PMemoryAllocator(void *this, ULONG cbSize); - -#else - -static void* WINAPI Allocate_PMemoryAllocator(void *this, ULONG cbSize) -{ - void* (WINAPI *fn)(void*,ULONG) = **(void***)this; - return fn(this, cbSize); -} - -#endif - BOOLEAN WINAPI StgConvertPropertyToVariant(const SERIALIZEDPROPERTYVALUE* prop, USHORT CodePage, PROPVARIANT* pvar, void* pma) { @@ -3055,7 +3082,7 @@ BOOLEAN WINAPI StgConvertPropertyToVariant(const SERIALIZEDPROPERTYVALUE* prop,
read_buffer.data = (BYTE *)prop; read_buffer.size = ~(size_t)0; - hr = PropertyStorage_ReadProperty(pvar, &read_buffer, 0, CodePage, Allocate_PMemoryAllocator, pma); + hr = PropertyStorage_ReadProperty(pvar, &read_buffer, 0, CodePage, pma);
if (FAILED(hr)) {
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)
From: Piotr Caban piotr@codeweavers.com
--- dlls/ole32/stg_prop.c | 23 +++++++++++++++++++++-- dlls/ole32/tests/propvariant.c | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index c4145cf864f..fedba892c70 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -1612,7 +1612,22 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read
for (i = 0; i < count; ++i) { - if (FAILED(hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, pma))) + if (prop->vt == (VT_VECTOR | VT_VARIANT)) + { + DWORD vt; + + offset = ALIGNED_LENGTH(offset, sizeof(DWORD) - 1); + hr = buffer_read_dword(buffer, offset, &vt); + if (SUCCEEDED(hr)) + { + offset += sizeof(DWORD); + elem.vt = vt; + } + } + + if (SUCCEEDED(hr)) + hr = propertystorage_read_scalar(&elem, buffer, &offset, codepage, pma); + if (FAILED(hr)) { for (; i > 0; --i) { @@ -1633,7 +1648,11 @@ static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const struct read call_IMemoryAllocator_Free(pma, prop->cac.pElems); return hr; } - memcpy(prop->cac.pElems + elemsize * i, &elem.lVal, elemsize); + + if (prop->vt == (VT_VECTOR | VT_VARIANT)) + memcpy(prop->cac.pElems + elemsize * i, &elem, elemsize); + else + 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 875a213c197..891d2a7d141 100644 --- a/dlls/ole32/tests/propvariant.c +++ b/dlls/ole32/tests/propvariant.c @@ -544,6 +544,15 @@ static const char serialized_i1_vec[] = { 1, 2, 3, 0 };
+static const char serialized_variant_vec[] = { + VT_VARIANT, VT_VECTOR >> 8, 0, 0, + 2, 0, 0, 0, + VT_I1, 0, 0, 0, + 1, 0, 0, 0, + VT_I4, 0, 0, 0, + 2, 0, 0, 0 +}; + static void test_propertytovariant(void) { HANDLE hole32; @@ -626,6 +635,18 @@ static void test_propertytovariant(void) ok(!wcscmp(propvar.calpwstr.pElems[2], L"def"), "pElems[2] = %s\n", debugstr_w(propvar.calpwstr.pElems[2])); PropVariantClear(&propvar); + + ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_variant_vec, + CP_WINUNICODE, &propvar, &allocator); + + ok(!ret, "StgConvertPropertyToVariant returned %i\n", ret); + ok(propvar.vt == (VT_VECTOR | VT_VARIANT), "unexpected vt %x\n", propvar.vt); + ok(propvar.capropvar.cElems == 2, "unexpected cElems %lu\n", propvar.calpwstr.cElems); + ok(propvar.capropvar.pElems[0].vt == VT_I1, "pElems[0].vt = %d\n", propvar.capropvar.pElems[0].vt); + ok(propvar.capropvar.pElems[0].cVal == 1, "pElems[0].cVal = %d\n", propvar.capropvar.pElems[0].cVal); + ok(propvar.capropvar.pElems[1].vt == VT_I4, "pElems[1].vt = %d\n", propvar.capropvar.pElems[1].vt); + ok(propvar.capropvar.pElems[1].lVal == 2, "pElems[1].lVal = %ld\n", propvar.capropvar.pElems[1].lVal); + PropVariantClear(&propvar); }
static void test_varianttoproperty(void)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=151001
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000013A00FE, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032