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