Commit 28e0d8ff authored by Kevin Puetz's avatar Kevin Puetz Committed by Alexandre Julliard

oleaut32: Dereference VT_RECORD|VT_BYREF in place.

VariantCopyInd allows pvargDest == pvargSrc in order to dereference in place To avoid confusing the source values and a partially-written destination, wine's implementation makes a shallow copy and uses that as pSrc. However, the call to VARIANT_CopyIRecordInfo did not use this, leading to it copying from the zeroed-out memory it just allocated.
parent 27f417eb
...@@ -902,6 +902,19 @@ static void test_VariantClear(void) ...@@ -902,6 +902,19 @@ static void test_VariantClear(void)
ok(recinfo->recordclear == 1, "got %d\n", recinfo->recordclear); ok(recinfo->recordclear == 1, "got %d\n", recinfo->recordclear);
ok(recinfo->ref == 1, "got %ld\n", recinfo->ref); ok(recinfo->ref == 1, "got %ld\n", recinfo->ref);
IRecordInfo_Release(&recinfo->IRecordInfo_iface); IRecordInfo_Release(&recinfo->IRecordInfo_iface);
/* RECORD BYREF */
recinfo = get_test_recordinfo();
V_VT(&v) = VT_RECORD|VT_BYREF;
V_RECORDINFO(&v) = &recinfo->IRecordInfo_iface;
V_RECORD(&v) = recinfo->validsrc;
hres = VariantClear(&v);
ok(hres == S_OK, "ret %08lx\n", hres);
ok(V_VT(&v) == VT_EMPTY, "got vt = %d",V_VT(&v));
/* BYREF does not own the pointed-to V_RECORD/INFO, so no RecordClear and no Release */
ok(recinfo->recordclear == 0, "got %d\n", recinfo->recordclear);
ok(recinfo->ref == 1, "got %ld\n", recinfo->ref);
IRecordInfo_Release(&recinfo->IRecordInfo_iface);
} }
static void test_VariantCopy(void) static void test_VariantCopy(void)
...@@ -1069,6 +1082,7 @@ static void test_VariantCopyInd(void) ...@@ -1069,6 +1082,7 @@ static void test_VariantCopyInd(void)
size_t i; size_t i;
BYTE buffer[64]; BYTE buffer[64];
HRESULT hres, hExpected; HRESULT hres, hExpected;
IRecordInfoImpl *recinfo;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
...@@ -1259,6 +1273,52 @@ static void test_VariantCopyInd(void) ...@@ -1259,6 +1273,52 @@ static void test_VariantCopyInd(void)
hres = VariantCopyInd(&vDst, &vSrc); hres = VariantCopyInd(&vDst, &vSrc);
ok(hres == E_INVALIDARG, ok(hres == E_INVALIDARG,
"CopyInd(ref->ref): expected E_INVALIDARG, got 0x%08lx\n", hres); "CopyInd(ref->ref): expected E_INVALIDARG, got 0x%08lx\n", hres);
/* source data for a deep-copy of VT_BYREF|VT_RECORD... */
recinfo = get_test_recordinfo();
V_VT(&vSrc) = VT_RECORD|VT_BYREF;
V_RECORDINFO(&vSrc) = &recinfo->IRecordInfo_iface;
V_RECORD(&vSrc) = recinfo->validsrc;
/* into a separate vDst */
VariantInit(&vDst);
hres = VariantCopyInd(&vDst, &vSrc);
ok(hres == S_OK, "VariantCopyInd failed: 0x%08lx\n", hres);
ok(V_VT(&vDst) == VT_RECORD, "got vt = %d|0x%X\n", V_VT(&vDst) & VT_TYPEMASK, V_VT(&vDst) & ~VT_TYPEMASK);
ok(V_RECORDINFO(&vDst) == &recinfo->IRecordInfo_iface, "got %p\n", V_RECORDINFO(&vDst));
ok(recinfo->recordclear == 0,"got %d\n", recinfo->recordclear);
ok(V_RECORD(&vDst) != recinfo->validsrc, "expected a newly-allocated deep copy\n");
ok(recinfo->getsize == 1,"got %d\n", recinfo->getsize);
ok(recinfo->recordcopy == 1,"got %d\n", recinfo->recordcopy);
ok(recinfo->ref == 2,"got %ld\n", recinfo->ref);
VariantClear(&vDst);
ok(recinfo->ref == 1,"got %ld\n", recinfo->ref);
ok(recinfo->recordclear == 1,"got %d\n", recinfo->recordclear);
recinfo->getsize = 0;
recinfo->recordcopy = 0;
recinfo->recordclear = 0;
/* and also in-place */
hres = VariantCopyInd(&vSrc, &vSrc);
ok(V_VT(&vSrc) == VT_RECORD, "got vt = %d|0x%X\n", V_VT(&vSrc) & VT_TYPEMASK, V_VT(&vSrc) & ~VT_TYPEMASK);
ok(V_RECORDINFO(&vSrc) == &recinfo->IRecordInfo_iface, "got %p\n", V_RECORDINFO(&vSrc));
/* ++ref and no RecordClear, since the source BYREF does not own the V_RECORD/INFO
* which it pointed to, and thus did not free them when overwritten */
ok(recinfo->ref == 2,"got %ld\n", recinfo->ref);
ok(recinfo->recordclear == 0,"got %d\n", recinfo->recordclear);
ok(V_RECORD(&vDst) != recinfo->validsrc, "expected a newly-allocated deep copy\n");
ok(recinfo->getsize == 1,"got %d\n", recinfo->getsize);
ok(recinfo->recordcopy == 1,"got %d\n", recinfo->recordcopy);
/* but the no-longer-BYREF output owns and will free its copies */
VariantClear(&vSrc);
ok(recinfo->ref == 1,"got %ld\n", recinfo->ref);
ok(recinfo->recordclear == 1,"got %d\n", recinfo->recordclear);
IRecordInfo_Release(&recinfo->IRecordInfo_iface);
} }
static HRESULT (WINAPI *pVarParseNumFromStr)(const OLECHAR*,LCID,ULONG,NUMPARSE*,BYTE*); static HRESULT (WINAPI *pVarParseNumFromStr)(const OLECHAR*,LCID,ULONG,NUMPARSE*,BYTE*);
......
...@@ -879,7 +879,7 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, const VARIANTARG* pvargSrc) ...@@ -879,7 +879,7 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, const VARIANTARG* pvargSrc)
} }
else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF)) else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF))
{ {
hres = VARIANT_CopyIRecordInfo(pvargDest, pvargSrc); hres = VARIANT_CopyIRecordInfo(pvargDest, pSrc);
} }
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