oleaut32: Try to re-use existing memory when unmarshalling variants with byref types.

This commit is contained in:
Rob Shearman 2007-12-07 14:14:05 +00:00 committed by Alexandre Julliard
parent baccba317e
commit 67a213fc1e
2 changed files with 32 additions and 22 deletions

View File

@ -607,11 +607,15 @@ static void test_marshal_VARIANT(void)
ok(*(short*)wirev == s, "wv[6] %08x\n", *wirev);
if (VARIANT_UNMARSHAL_WORKS)
{
void *mem;
VariantInit(&v2);
V_VT(&v2) = VT_I2 | VT_BYREF;
V_BYREF(&v2) = mem = CoTaskMemAlloc(sizeof(V_I2(&v2)));
stubMsg.Buffer = buffer;
next = VARIANT_UserUnmarshal(&umcb.Flags, buffer, &v2);
ok(next == buffer + stubMsg.BufferLength, "got %p expect %p\n", next, buffer + stubMsg.BufferLength);
ok(V_VT(&v) == V_VT(&v2), "got vt %d expect %d\n", V_VT(&v), V_VT(&v2));
ok(V_BYREF(&v2) == mem, "didn't reuse existing memory\n");
ok(*V_I2REF(&v) == *V_I2REF(&v2), "got i2 ref %x expect ui4 ref %x\n", *V_I2REF(&v), *V_I2REF(&v2));
VARIANT_UserFree(&umcb.Flags, &v2);

View File

@ -220,11 +220,11 @@ typedef struct
DWORD switch_is;
} variant_wire_t;
static unsigned int get_type_size(ULONG *pFlags, const VARIANT *pvar)
static unsigned int get_type_size(ULONG *pFlags, VARTYPE vt)
{
if (V_VT(pvar) & VT_ARRAY) return 4;
if (vt & VT_ARRAY) return 4;
switch (V_VT(pvar) & ~VT_BYREF) {
switch (vt & ~VT_BYREF) {
case VT_EMPTY:
case VT_NULL:
return 0;
@ -263,15 +263,15 @@ static unsigned int get_type_size(ULONG *pFlags, const VARIANT *pvar)
case VT_RECORD:
return 0;
default:
FIXME("unhandled VT %d\n", V_VT(pvar));
FIXME("unhandled VT %d\n", vt);
return 0;
}
}
static unsigned int get_type_alignment(ULONG *pFlags, const VARIANT *pvar)
static unsigned int get_type_alignment(ULONG *pFlags, VARTYPE vt)
{
unsigned int size = get_type_size(pFlags, pvar);
if(V_VT(pvar) & VT_BYREF) return 3;
unsigned int size = get_type_size(pFlags, vt);
if(vt & VT_BYREF) return 3;
if(size == 0) return 0;
if(size <= 4) return size - 1;
return 7;
@ -441,12 +441,12 @@ ULONG WINAPI VARIANT_UserSize(ULONG *pFlags, ULONG Start, VARIANT *pvar)
if(V_VT(pvar) & VT_BYREF)
Start += 4;
align = get_type_alignment(pFlags, pvar);
align = get_type_alignment(pFlags, V_VT(pvar));
ALIGN_LENGTH(Start, align);
if(V_VT(pvar) == (VT_VARIANT | VT_BYREF))
Start += 4;
else
Start += get_type_size(pFlags, pvar);
Start += get_type_size(pFlags, V_VT(pvar));
Start = wire_extra_user_size(pFlags, Start, pvar);
TRACE("returning %d\n", Start);
@ -478,8 +478,8 @@ unsigned char * WINAPI VARIANT_UserMarshal(ULONG *pFlags, unsigned char *Buffer,
header->switch_is &= ~VT_TYPEMASK;
Pos = (unsigned char*)(header + 1);
type_size = get_type_size(pFlags, pvar);
align = get_type_alignment(pFlags, pvar);
type_size = get_type_size(pFlags, V_VT(pvar));
align = get_type_alignment(pFlags, V_VT(pvar));
ALIGN_POINTER(Pos, align);
if(header->vt & VT_BYREF)
@ -565,32 +565,33 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe
TRACE("(%x,%p,%p)\n", *pFlags, Buffer, pvar);
ALIGN_POINTER(Buffer, 7);
VariantClear(pvar);
header = (variant_wire_t *)Buffer;
pvar->n1.n2.vt = header->vt;
pvar->n1.n2.wReserved1 = header->wReserved1;
pvar->n1.n2.wReserved2 = header->wReserved2;
pvar->n1.n2.wReserved3 = header->wReserved3;
Pos = (unsigned char*)(header + 1);
type_size = get_type_size(pFlags, pvar);
align = get_type_alignment(pFlags, pvar);
type_size = get_type_size(pFlags, header->vt);
align = get_type_alignment(pFlags, header->vt);
ALIGN_POINTER(Pos, align);
if(header->vt & VT_BYREF)
{
Pos += 4;
pvar->n1.n2.n3.byref = CoTaskMemAlloc(type_size);
memcpy(pvar->n1.n2.n3.byref, Pos, type_size);
if (V_VT(pvar) != header->vt)
{
VariantClear(pvar);
V_BYREF(pvar) = CoTaskMemAlloc(type_size);
}
else if (!V_BYREF(pvar))
V_BYREF(pvar) = CoTaskMemAlloc(type_size);
memcpy(V_BYREF(pvar), Pos, type_size);
if((header->vt & VT_TYPEMASK) != VT_VARIANT)
Pos += type_size;
Pos += type_size;
else
Pos += 4;
}
else
{
VariantClear(pvar);
if((header->vt & VT_TYPEMASK) == VT_DECIMAL)
memcpy(pvar, Pos, type_size);
else
@ -598,6 +599,11 @@ unsigned char * WINAPI VARIANT_UserUnmarshal(ULONG *pFlags, unsigned char *Buffe
Pos += type_size;
}
pvar->n1.n2.vt = header->vt;
pvar->n1.n2.wReserved1 = header->wReserved1;
pvar->n1.n2.wReserved2 = header->wReserved2;
pvar->n1.n2.wReserved3 = header->wReserved3;
if(header->vt & VT_ARRAY)
{
if(header->vt & VT_BYREF)