Rob Shearman : oleaut32: Fix memory leaks in ITypeInfo_fnInvoke.

Alexandre Julliard julliard at winehq.org
Wed Nov 18 09:40:41 CST 2009


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

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Wed Nov 18 00:17:46 2009 +0000

oleaut32: Fix memory leaks in ITypeInfo_fnInvoke.

---

 dlls/oleaut32/typelib.c |   42 +++++++++++++++------------------
 dlls/oleaut32/variant.c |   60 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/oleaut32/variant.h |    1 +
 3 files changed, 80 insertions(+), 23 deletions(-)

diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index 07447f2..bc92f5d 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -6146,7 +6146,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         else
                         {
                             VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
-                            hres = VariantCopy(&missing_arg[i], src_arg);
+                            if (wParamFlags & PARAMFLAG_FIN)
+                                hres = VariantCopy(&missing_arg[i], src_arg);
                             V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
                         }
                         V_VT(&rgvarg[i]) = rgvt[i];
@@ -6184,8 +6185,10 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
                     {
                         VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
-                        V_VT(&missing_arg[i]) = V_VT(src_arg);
-                        hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
+                        if (wParamFlags & PARAMFLAG_FIN)
+                            hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
+                        else
+                            V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
                         V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
                         V_VT(&rgvarg[i]) = rgvt[i];
                     }
@@ -6268,6 +6271,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
             for (i = 0; i < func_desc->cParams; i++)
             {
                 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
+                VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
 
                 if (wParamFlags & PARAMFLAG_FLCID)
                     continue;
@@ -6286,33 +6290,23 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                         hres = VariantCopyInd(pVarResult, prgpvarg[i]);
                     }
 
-                    /* free data stored in varresult. Note that
-                     * VariantClear doesn't do what we want because we are
-                     * working with byref types. */
-                    /* FIXME: clear safearrays, bstrs, records and
-                     * variants here too */
-                    if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
-                         (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
-                    {
-                        if(*V_UNKNOWNREF(prgpvarg[i]))
-                            IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
-                    }
-                    break;
+                    VARIANT_ClearInd(prgpvarg[i]);
                 }
                 else if (vargs_converted < pDispParams->cArgs)
                 {
+                    VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
                     if (wParamFlags & PARAMFLAG_FOUT)
                     {
-                        VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
-
-                        if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
+                        if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
+                        {
                             hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
 
-                        if (FAILED(hres))
-                        {
-                            ERR("failed to convert param %d to vt %d\n", i,
-                                V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
-                            break;
+                            if (FAILED(hres))
+                            {
+                                ERR("failed to convert param %d to vt %d\n", i,
+                                    V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
+                                break;
+                            }
                         }
                     }
                     else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
@@ -6351,6 +6345,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     if (wParamFlags & PARAMFLAG_FHASDEFAULT)
                         VariantClear(&rgvarg[i]);
                 }
+
+                VariantClear(&missing_arg[i]);
             }
 
             if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
diff --git a/dlls/oleaut32/variant.c b/dlls/oleaut32/variant.c
index e92a63d..cd99814 100644
--- a/dlls/oleaut32/variant.c
+++ b/dlls/oleaut32/variant.c
@@ -578,6 +578,66 @@ void WINAPI VariantInit(VARIANTARG* pVarg)
   V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */
 }
 
+HRESULT VARIANT_ClearInd(VARIANTARG *pVarg)
+{
+    HRESULT hres;
+
+    TRACE("(%p->(%s%s))\n", pVarg, debugstr_VT(pVarg), debugstr_VF(pVarg));
+
+    hres = VARIANT_ValidateType(V_VT(pVarg));
+    if (FAILED(hres))
+        return hres;
+
+    switch (V_VT(pVarg))
+    {
+    case VT_DISPATCH:
+    case VT_UNKNOWN:
+        if (V_UNKNOWN(pVarg))
+            IUnknown_Release(V_UNKNOWN(pVarg));
+        break;
+    case VT_UNKNOWN | VT_BYREF:
+    case VT_DISPATCH | VT_BYREF:
+        if(*V_UNKNOWNREF(pVarg))
+            IUnknown_Release(*V_UNKNOWNREF(pVarg));
+        break;
+    case VT_BSTR:
+        SysFreeString(V_BSTR(pVarg));
+        break;
+    case VT_BSTR | VT_BYREF:
+        SysFreeString(*V_BSTRREF(pVarg));
+        break;
+    case VT_VARIANT | VT_BYREF:
+        VariantClear(V_VARIANTREF(pVarg));
+        break;
+    case VT_RECORD:
+    case VT_RECORD | VT_BYREF:
+    {
+        struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal);
+        if (pBr->pRecInfo)
+        {
+            IRecordInfo_RecordClear(pBr->pRecInfo, pBr->pvRecord);
+            IRecordInfo_Release(pBr->pRecInfo);
+        }
+        break;
+    }
+    default:
+        if (V_ISARRAY(pVarg) || (V_VT(pVarg) & ~VT_BYREF) == VT_SAFEARRAY)
+        {
+            if (V_ISBYREF(pVarg))
+            {
+                if (*V_ARRAYREF(pVarg))
+                    hres = SafeArrayDestroy(*V_ARRAYREF(pVarg));
+            }
+            else if (V_ARRAY(pVarg))
+                hres = SafeArrayDestroy(V_ARRAY(pVarg));
+        }
+        break;
+    }
+
+    V_VT(pVarg) = VT_EMPTY;
+    return hres;
+}
+
 /******************************************************************************
  *		VariantClear	[OLEAUT32.9]
  *
diff --git a/dlls/oleaut32/variant.h b/dlls/oleaut32/variant.h
index c881b24..265fcc8 100644
--- a/dlls/oleaut32/variant.h
+++ b/dlls/oleaut32/variant.h
@@ -126,3 +126,4 @@ typedef struct tagVARIANT_NUMBER_CHARS
 
 
 BOOL VARIANT_GetLocalisedText(LANGID, DWORD, WCHAR *);
+HRESULT VARIANT_ClearInd(VARIANTARG *);




More information about the wine-cvs mailing list