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

Alexandre Julliard julliard at winehq.org
Fri Dec 7 11:01:58 CST 2007


Module: wine
Branch: master
Commit: 67a213fc1e08eeac21051861692d27ee300287a1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=67a213fc1e08eeac21051861692d27ee300287a1

Author: Rob Shearman <rob at 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)




More information about the wine-cvs mailing list