oleaut32: Fix memory leaks in ITypeInfo_fnInvoke.

This commit is contained in:
Rob Shearman 2009-11-18 00:17:46 +00:00 committed by Alexandre Julliard
parent 6d7572c0e7
commit 99d9983b61
3 changed files with 80 additions and 23 deletions

View File

@ -6146,7 +6146,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
else else
{ {
VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); 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_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
} }
V_VT(&rgvarg[i]) = rgvt[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)) else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
{ {
VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams); VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
V_VT(&missing_arg[i]) = V_VT(src_arg); if (wParamFlags & PARAMFLAG_FIN)
hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF); 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_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
V_VT(&rgvarg[i]) = rgvt[i]; V_VT(&rgvarg[i]) = rgvt[i];
} }
@ -6268,6 +6271,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
for (i = 0; i < func_desc->cParams; i++) for (i = 0; i < func_desc->cParams; i++)
{ {
USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags; 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) if (wParamFlags & PARAMFLAG_FLCID)
continue; continue;
@ -6286,33 +6290,23 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
hres = VariantCopyInd(pVarResult, prgpvarg[i]); hres = VariantCopyInd(pVarResult, prgpvarg[i]);
} }
/* free data stored in varresult. Note that VARIANT_ClearInd(prgpvarg[i]);
* 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;
} }
else if (vargs_converted < pDispParams->cArgs) else if (vargs_converted < pDispParams->cArgs)
{ {
VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
if (wParamFlags & PARAMFLAG_FOUT) 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)); hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
if (FAILED(hres)) if (FAILED(hres))
{ {
ERR("failed to convert param %d to vt %d\n", i, ERR("failed to convert param %d to vt %d\n", i,
V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted])); V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
break; break;
}
} }
} }
else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) && else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
@ -6351,6 +6345,8 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
if (wParamFlags & PARAMFLAG_FHASDEFAULT) if (wParamFlags & PARAMFLAG_FHASDEFAULT)
VariantClear(&rgvarg[i]); VariantClear(&rgvarg[i]);
} }
VariantClear(&missing_arg[i]);
} }
if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult))) if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))

View File

@ -578,6 +578,66 @@ void WINAPI VariantInit(VARIANTARG* pVarg)
V_VT(pVarg) = VT_EMPTY; /* Native doesn't set any other fields */ 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] * VariantClear [OLEAUT32.9]
* *

View File

@ -126,3 +126,4 @@ typedef struct tagVARIANT_NUMBER_CHARS
BOOL VARIANT_GetLocalisedText(LANGID, DWORD, WCHAR *); BOOL VARIANT_GetLocalisedText(LANGID, DWORD, WCHAR *);
HRESULT VARIANT_ClearInd(VARIANTARG *);