diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 5fcf8414445..a27adfb3d49 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -253,6 +253,7 @@ @ stdcall SetConvertStg(ptr long) @ stub SetDocumentBitStg @ stdcall SetErrorInfo(long ptr) +@ stdcall StgConvertPropertyToVariant(ptr long ptr ptr) @ stdcall StgCreateDocfile(wstr long long ptr) @ stdcall StgCreateDocfileOnILockBytes(ptr long long ptr) @ stdcall StgCreatePropSetStg(ptr long ptr) diff --git a/dlls/ole32/stg_prop.c b/dlls/ole32/stg_prop.c index 9e3df452c0b..103f14511da 100644 --- a/dlls/ole32/stg_prop.c +++ b/dlls/ole32/stg_prop.c @@ -36,6 +36,9 @@ * PropertyStorage_ReadFromStream */ +#include "config.h" +#include "wine/port.h" + #include #include #include @@ -1030,11 +1033,22 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This, return hr; } +#ifdef __i386__ +#define __thiscall __stdcall +#else +#define __thiscall __cdecl +#endif + +static __thiscall void* Allocate_CoTaskMemAlloc(void *userdata, ULONG size) +{ + return CoTaskMemAlloc(size); +} + /* FIXME: there isn't any checking whether the read property extends past the * end of the buffer. */ -static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, - PROPVARIANT *prop, const BYTE *data) +static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data, + UINT codepage, void* (__thiscall *allocate)(void *userdata, ULONG size), void *allocate_data) { HRESULT hr = S_OK; @@ -1078,21 +1092,21 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, DWORD count; StorageUtl_ReadDWord(data, 0, &count); - if (This->codePage == CP_UNICODE && count / 2) + if (codepage == CP_UNICODE && count / 2) { WARN("Unicode string has odd number of bytes\n"); hr = STG_E_INVALIDHEADER; } else { - prop->u.pszVal = CoTaskMemAlloc(count); + prop->u.pszVal = allocate(allocate_data, count); if (prop->u.pszVal) { memcpy(prop->u.pszVal, data + sizeof(DWORD), count); - /* This is stored in the code page specified in This->codePage. + /* This is stored in the code page specified in codepage. * Don't convert it, the caller will just store it as-is. */ - if (This->codePage == CP_UNICODE) + if (codepage == CP_UNICODE) { /* Make sure it's NULL-terminated */ prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0'; @@ -1117,7 +1131,7 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, StorageUtl_ReadDWord(data, 0, &count); prop->u.blob.cbSize = count; - prop->u.blob.pBlobData = CoTaskMemAlloc(count); + prop->u.blob.pBlobData = allocate(allocate_data, count); if (prop->u.blob.pBlobData) { memcpy(prop->u.blob.pBlobData, data + sizeof(DWORD), count); @@ -1132,7 +1146,7 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, DWORD count; StorageUtl_ReadDWord(data, 0, &count); - prop->u.pwszVal = CoTaskMemAlloc(count * sizeof(WCHAR)); + prop->u.pwszVal = allocate(allocate_data, count * sizeof(WCHAR)); if (prop->u.pwszVal) { memcpy(prop->u.pwszVal, data + sizeof(DWORD), @@ -1159,10 +1173,10 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This, if (len > 8) { len -= 8; - prop->u.pclipdata = CoTaskMemAlloc(sizeof (CLIPDATA)); + prop->u.pclipdata = allocate(allocate_data, sizeof (CLIPDATA)); prop->u.pclipdata->cbSize = len; prop->u.pclipdata->ulClipFmt = tag; - prop->u.pclipdata->pClipData = CoTaskMemAlloc(len - sizeof(prop->u.pclipdata->ulClipFmt)); + prop->u.pclipdata->pClipData = allocate(allocate_data, len - sizeof(prop->u.pclipdata->ulClipFmt)); memcpy(prop->u.pclipdata->pClipData, data+8, len - sizeof(prop->u.pclipdata->ulClipFmt)); } else @@ -1399,8 +1413,9 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This) PROPVARIANT prop; PropVariantInit(&prop); - if (SUCCEEDED(PropertyStorage_ReadProperty(This, &prop, - buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER)))) + if (SUCCEEDED(PropertyStorage_ReadProperty(&prop, + buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER), + This->codePage, Allocate_CoTaskMemAlloc, NULL))) { TRACE("Read property with ID 0x%08x, type %d\n", idOffset->propid, prop.vt); @@ -2673,3 +2688,42 @@ HRESULT WINAPI PropStgNameToFmtId(const LPOLESTR str, FMTID *rfmtid) end: return hr; } + +#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* __thiscall Allocate_PMemoryAllocator(void *this, ULONG cbSize); + +#else + +static void* __thiscall Allocate_PMemoryAllocator(void *this, ULONG cbSize) +{ + void* (__thiscall *fn)(void*,ULONG) = **(void***)this; + return fn(this, cbSize); +} + +#endif + +BOOLEAN WINAPI StgConvertPropertyToVariant(const SERIALIZEDPROPERTYVALUE* prop, + USHORT CodePage, PROPVARIANT* pvar, void* pma) +{ + HRESULT hr; + + hr = PropertyStorage_ReadProperty(pvar, (const BYTE*)prop, CodePage, Allocate_PMemoryAllocator, pma); + + if (FAILED(hr)) + { + FIXME("should raise C++ exception on failure\n"); + PropVariantInit(pvar); + } + + return 0; +} diff --git a/dlls/ole32/tests/propvariant.c b/dlls/ole32/tests/propvariant.c index 29fa2f0e1ec..ec1dfd7af56 100644 --- a/dlls/ole32/tests/propvariant.c +++ b/dlls/ole32/tests/propvariant.c @@ -365,7 +365,7 @@ static void test_propertytovariant(void) if (!pStgConvertPropertyToVariant) { - todo_wine win_skip("StgConvertPropertyToVariant not available\n"); + win_skip("StgConvertPropertyToVariant not available\n"); return; } @@ -395,16 +395,18 @@ static void test_propertytovariant(void) CP_WINUNICODE, &propvar, &allocator); ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret); - ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt); - ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n"); + todo_wine ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt); + if (propvar.vt == VT_BSTR) + ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n"); PropVariantClear(&propvar); ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_mb, CP_UTF8, &propvar, &allocator); ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret); - ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt); - ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n"); + todo_wine ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt); + if (propvar.vt == VT_BSTR) + ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n"); PropVariantClear(&propvar); }