ole32: Implement StgConvertPropertyToVariant.
This commit is contained in:
parent
ae722c45ad
commit
58c2462c36
|
@ -253,6 +253,7 @@
|
||||||
@ stdcall SetConvertStg(ptr long)
|
@ stdcall SetConvertStg(ptr long)
|
||||||
@ stub SetDocumentBitStg
|
@ stub SetDocumentBitStg
|
||||||
@ stdcall SetErrorInfo(long ptr)
|
@ stdcall SetErrorInfo(long ptr)
|
||||||
|
@ stdcall StgConvertPropertyToVariant(ptr long ptr ptr)
|
||||||
@ stdcall StgCreateDocfile(wstr long long ptr)
|
@ stdcall StgCreateDocfile(wstr long long ptr)
|
||||||
@ stdcall StgCreateDocfileOnILockBytes(ptr long long ptr)
|
@ stdcall StgCreateDocfileOnILockBytes(ptr long long ptr)
|
||||||
@ stdcall StgCreatePropSetStg(ptr long ptr)
|
@ stdcall StgCreatePropSetStg(ptr long ptr)
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
* PropertyStorage_ReadFromStream
|
* PropertyStorage_ReadFromStream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -1030,11 +1033,22 @@ static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
|
||||||
return hr;
|
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
|
/* FIXME: there isn't any checking whether the read property extends past the
|
||||||
* end of the buffer.
|
* end of the buffer.
|
||||||
*/
|
*/
|
||||||
static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
|
static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data,
|
||||||
PROPVARIANT *prop, const BYTE *data)
|
UINT codepage, void* (__thiscall *allocate)(void *userdata, ULONG size), void *allocate_data)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
@ -1078,21 +1092,21 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
|
||||||
DWORD count;
|
DWORD count;
|
||||||
|
|
||||||
StorageUtl_ReadDWord(data, 0, &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");
|
WARN("Unicode string has odd number of bytes\n");
|
||||||
hr = STG_E_INVALIDHEADER;
|
hr = STG_E_INVALIDHEADER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prop->u.pszVal = CoTaskMemAlloc(count);
|
prop->u.pszVal = allocate(allocate_data, count);
|
||||||
if (prop->u.pszVal)
|
if (prop->u.pszVal)
|
||||||
{
|
{
|
||||||
memcpy(prop->u.pszVal, data + sizeof(DWORD), count);
|
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.
|
* 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 */
|
/* Make sure it's NULL-terminated */
|
||||||
prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0';
|
prop->u.pszVal[count / sizeof(WCHAR) - 1] = '\0';
|
||||||
|
@ -1117,7 +1131,7 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
|
||||||
|
|
||||||
StorageUtl_ReadDWord(data, 0, &count);
|
StorageUtl_ReadDWord(data, 0, &count);
|
||||||
prop->u.blob.cbSize = 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)
|
if (prop->u.blob.pBlobData)
|
||||||
{
|
{
|
||||||
memcpy(prop->u.blob.pBlobData, data + sizeof(DWORD), count);
|
memcpy(prop->u.blob.pBlobData, data + sizeof(DWORD), count);
|
||||||
|
@ -1132,7 +1146,7 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
|
||||||
DWORD count;
|
DWORD count;
|
||||||
|
|
||||||
StorageUtl_ReadDWord(data, 0, &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)
|
if (prop->u.pwszVal)
|
||||||
{
|
{
|
||||||
memcpy(prop->u.pwszVal, data + sizeof(DWORD),
|
memcpy(prop->u.pwszVal, data + sizeof(DWORD),
|
||||||
|
@ -1159,10 +1173,10 @@ static HRESULT PropertyStorage_ReadProperty(PropertyStorage_impl *This,
|
||||||
if (len > 8)
|
if (len > 8)
|
||||||
{
|
{
|
||||||
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->cbSize = len;
|
||||||
prop->u.pclipdata->ulClipFmt = tag;
|
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));
|
memcpy(prop->u.pclipdata->pClipData, data+8, len - sizeof(prop->u.pclipdata->ulClipFmt));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1399,8 +1413,9 @@ static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
|
||||||
PROPVARIANT prop;
|
PROPVARIANT prop;
|
||||||
|
|
||||||
PropVariantInit(&prop);
|
PropVariantInit(&prop);
|
||||||
if (SUCCEEDED(PropertyStorage_ReadProperty(This, &prop,
|
if (SUCCEEDED(PropertyStorage_ReadProperty(&prop,
|
||||||
buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER))))
|
buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER),
|
||||||
|
This->codePage, Allocate_CoTaskMemAlloc, NULL)))
|
||||||
{
|
{
|
||||||
TRACE("Read property with ID 0x%08x, type %d\n",
|
TRACE("Read property with ID 0x%08x, type %d\n",
|
||||||
idOffset->propid, prop.vt);
|
idOffset->propid, prop.vt);
|
||||||
|
@ -2673,3 +2688,42 @@ HRESULT WINAPI PropStgNameToFmtId(const LPOLESTR str, FMTID *rfmtid)
|
||||||
end:
|
end:
|
||||||
return hr;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -365,7 +365,7 @@ static void test_propertytovariant(void)
|
||||||
|
|
||||||
if (!pStgConvertPropertyToVariant)
|
if (!pStgConvertPropertyToVariant)
|
||||||
{
|
{
|
||||||
todo_wine win_skip("StgConvertPropertyToVariant not available\n");
|
win_skip("StgConvertPropertyToVariant not available\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,16 +395,18 @@ static void test_propertytovariant(void)
|
||||||
CP_WINUNICODE, &propvar, &allocator);
|
CP_WINUNICODE, &propvar, &allocator);
|
||||||
|
|
||||||
ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
|
ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
|
||||||
ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
|
todo_wine ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
|
||||||
ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
|
if (propvar.vt == VT_BSTR)
|
||||||
|
ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
|
||||||
PropVariantClear(&propvar);
|
PropVariantClear(&propvar);
|
||||||
|
|
||||||
ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_mb,
|
ret = pStgConvertPropertyToVariant((SERIALIZEDPROPERTYVALUE*)serialized_bstr_mb,
|
||||||
CP_UTF8, &propvar, &allocator);
|
CP_UTF8, &propvar, &allocator);
|
||||||
|
|
||||||
ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
|
ok(ret == 0, "StgConvertPropertyToVariant returned %i\n", ret);
|
||||||
ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
|
todo_wine ok(propvar.vt == VT_BSTR, "unexpected vt %x\n", propvar.vt);
|
||||||
ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
|
if (propvar.vt == VT_BSTR)
|
||||||
|
ok(!lstrcmpW(U(propvar).bstrVal, test_string), "unexpected string value\n");
|
||||||
PropVariantClear(&propvar);
|
PropVariantClear(&propvar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue