Commit e6107130 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

oleaut32: Fix VariantCopy() for VT_RECORD variants.

parent 52a70451
...@@ -102,6 +102,8 @@ typedef struct IRecordInfoImpl ...@@ -102,6 +102,8 @@ typedef struct IRecordInfoImpl
IRecordInfo IRecordInfo_iface; IRecordInfo IRecordInfo_iface;
LONG ref; LONG ref;
unsigned int recordclear; unsigned int recordclear;
unsigned int getsize;
unsigned int recordcopy;
struct __tagBRECORD *rec; struct __tagBRECORD *rec;
} IRecordInfoImpl; } IRecordInfoImpl;
...@@ -152,15 +154,16 @@ static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, void *data) ...@@ -152,15 +154,16 @@ static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, void *data)
{ {
IRecordInfoImpl* This = impl_from_IRecordInfo(iface); IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->recordclear++; This->recordclear++;
ok(data == (void*)0xdeadbeef, "got %p\n", data);
This->rec->pvRecord = NULL; This->rec->pvRecord = NULL;
return S_OK; return S_OK;
} }
static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, void *pvExisting, void *pvNew) static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, void *src, void *dest)
{ {
ok(0, "unexpected call\n"); IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
return E_NOTIMPL; This->recordcopy++;
ok(src == (void*)0xdeadbeef, "wrong src pointer %p\n", src);
return S_OK;
} }
static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid) static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
...@@ -177,8 +180,10 @@ static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName) ...@@ -177,8 +180,10 @@ static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size) static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
{ {
ok(0, "unexpected call\n"); IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
return E_NOTIMPL; This->getsize++;
*size = 0;
return S_OK;
} }
static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo) static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
...@@ -277,6 +282,10 @@ static IRecordInfoImpl *get_test_recordinfo(void) ...@@ -277,6 +282,10 @@ static IRecordInfoImpl *get_test_recordinfo(void)
rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl)); rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl; rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
rec->ref = 1; rec->ref = 1;
rec->recordclear = 0;
rec->getsize = 0;
rec->recordcopy = 0;
return rec; return rec;
} }
...@@ -765,6 +774,8 @@ static void test_VariantClear(void) ...@@ -765,6 +774,8 @@ static void test_VariantClear(void)
static void test_VariantCopy(void) static void test_VariantCopy(void)
{ {
struct __tagBRECORD *rec;
IRecordInfoImpl *recinfo;
VARIANTARG vSrc, vDst; VARIANTARG vSrc, vDst;
VARTYPE vt; VARTYPE vt;
size_t i; size_t i;
...@@ -880,6 +891,33 @@ static void test_VariantCopy(void) ...@@ -880,6 +891,33 @@ static void test_VariantCopy(void)
} }
VariantClear(&vDst); VariantClear(&vDst);
} }
/* copy RECORD */
recinfo = get_test_recordinfo();
memset(&vDst, 0, sizeof(vDst));
V_VT(&vDst) = VT_EMPTY;
V_VT(&vSrc) = VT_RECORD;
rec = &V_UNION(&vSrc, brecVal);
rec->pRecInfo = &recinfo->IRecordInfo_iface;
rec->pvRecord = (void*)0xdeadbeef;
recinfo->recordclear = 0;
recinfo->recordcopy = 0;
recinfo->getsize = 0;
recinfo->rec = rec;
hres = VariantCopy(&vDst, &vSrc);
ok(hres == S_OK, "ret %08x\n", hres);
rec = &V_UNION(&vDst, brecVal);
ok(rec->pvRecord != (void*)0xdeadbeef && rec->pvRecord != NULL, "got %p\n", rec->pvRecord);
ok(rec->pRecInfo == &recinfo->IRecordInfo_iface, "got %p\n", rec->pRecInfo);
ok(recinfo->getsize == 1, "got %d\n", recinfo->recordclear);
ok(recinfo->recordcopy == 1, "got %d\n", recinfo->recordclear);
VariantClear(&vDst);
VariantClear(&vSrc);
} }
/* Determine if a vt is valid for VariantCopyInd() */ /* Determine if a vt is valid for VariantCopyInd() */
......
...@@ -694,34 +694,32 @@ HRESULT WINAPI VariantClear(VARIANTARG* pVarg) ...@@ -694,34 +694,32 @@ HRESULT WINAPI VariantClear(VARIANTARG* pVarg)
/****************************************************************************** /******************************************************************************
* Copy an IRecordInfo object contained in a variant. * Copy an IRecordInfo object contained in a variant.
*/ */
static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr) static HRESULT VARIANT_CopyIRecordInfo(VARIANT *dest, VARIANT *src)
{ {
HRESULT hres = S_OK; struct __tagBRECORD *dest_rec = &V_UNION(dest, brecVal);
struct __tagBRECORD *src_rec = &V_UNION(src, brecVal);
HRESULT hr = S_OK;
ULONG size;
if (pBr->pRecInfo) if (!src_rec->pRecInfo)
{ {
ULONG ulSize; if (src_rec->pvRecord) return E_INVALIDARG;
return S_OK;
}
hres = IRecordInfo_GetSize(pBr->pRecInfo, &ulSize); hr = IRecordInfo_GetSize(src_rec->pRecInfo, &size);
if (SUCCEEDED(hres)) if (FAILED(hr)) return hr;
{
PVOID pvRecord = HeapAlloc(GetProcessHeap(), 0, ulSize);
if (!pvRecord)
hres = E_OUTOFMEMORY;
else
{
memcpy(pvRecord, pBr->pvRecord, ulSize);
pBr->pvRecord = pvRecord;
hres = IRecordInfo_RecordCopy(pBr->pRecInfo, pvRecord, pvRecord); /* This could look cleaner if only RecordCreate() was used, but native doesn't use it.
if (SUCCEEDED(hres)) Memory should be allocated in a same way as RecordCreate() does, so RecordDestroy()
IRecordInfo_AddRef(pBr->pRecInfo); could free it later. */
} dest_rec->pvRecord = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
} if (!dest_rec->pvRecord) return E_OUTOFMEMORY;
}
else if (pBr->pvRecord) dest_rec->pRecInfo = src_rec->pRecInfo;
hres = E_INVALIDARG; IRecordInfo_AddRef(src_rec->pRecInfo);
return hres;
return IRecordInfo_RecordCopy(src_rec->pRecInfo, src_rec->pvRecord, dest_rec->pvRecord);
} }
/****************************************************************************** /******************************************************************************
...@@ -771,29 +769,25 @@ HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc) ...@@ -771,29 +769,25 @@ HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc)
if (!V_ISBYREF(pvargSrc)) if (!V_ISBYREF(pvargSrc))
{ {
if (V_ISARRAY(pvargSrc)) switch (V_VT(pvargSrc))
{
if (V_ARRAY(pvargSrc))
hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
}
else if (V_VT(pvargSrc) == VT_BSTR)
{ {
case VT_BSTR:
V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc))); V_BSTR(pvargDest) = SysAllocStringByteLen((char*)V_BSTR(pvargSrc), SysStringByteLen(V_BSTR(pvargSrc)));
if (!V_BSTR(pvargDest)) if (!V_BSTR(pvargDest))
{
TRACE("!V_BSTR(pvargDest), SysAllocStringByteLen() failed to allocate %d bytes\n", SysStringByteLen(V_BSTR(pvargSrc)));
hres = E_OUTOFMEMORY; hres = E_OUTOFMEMORY;
} break;
} case VT_RECORD:
else if (V_VT(pvargSrc) == VT_RECORD) hres = VARIANT_CopyIRecordInfo(pvargDest, pvargSrc);
{ break;
hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal)); case VT_DISPATCH:
} case VT_UNKNOWN:
else if (V_VT(pvargSrc) == VT_DISPATCH || V_UNKNOWN(pvargDest) = V_UNKNOWN(pvargSrc);
V_VT(pvargSrc) == VT_UNKNOWN)
{
if (V_UNKNOWN(pvargSrc)) if (V_UNKNOWN(pvargSrc))
IUnknown_AddRef(V_UNKNOWN(pvargSrc)); IUnknown_AddRef(V_UNKNOWN(pvargSrc));
break;
default:
if (V_ISARRAY(pvargSrc))
hres = SafeArrayCopy(V_ARRAY(pvargSrc), &V_ARRAY(pvargDest));
} }
} }
} }
...@@ -912,8 +906,7 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc) ...@@ -912,8 +906,7 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc)
} }
else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF)) else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF))
{ {
V_UNION(pvargDest,brecVal) = V_UNION(pvargSrc,brecVal); hres = VARIANT_CopyIRecordInfo(pvargDest, pvargSrc);
hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal));
} }
else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) || else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) ||
V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF)) V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment