Module: wine Branch: master Commit: 67a213fc1e08eeac21051861692d27ee300287a1 URL: http://source.winehq.org/git/wine.git/?a=commit;h=67a213fc1e08eeac2105186169...
Author: Rob Shearman rob@codeweavers.com Date: Fri Dec 7 14:14:05 2007 +0000
oleaut32: Try to re-use existing memory when unmarshalling variants with byref types.
---
dlls/oleaut32/tests/usrmarshal.c | 4 +++ dlls/oleaut32/usrmarshal.c | 50 +++++++++++++++++++++---------------- 2 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/dlls/oleaut32/tests/usrmarshal.c b/dlls/oleaut32/tests/usrmarshal.c index 633a382..3139442 100644 --- a/dlls/oleaut32/tests/usrmarshal.c +++ b/dlls/oleaut32/tests/usrmarshal.c @@ -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); diff --git a/dlls/oleaut32/usrmarshal.c b/dlls/oleaut32/usrmarshal.c index 49570f4..a9a738c 100644 --- a/dlls/oleaut32/usrmarshal.c +++ b/dlls/oleaut32/usrmarshal.c @@ -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)