FIX: _AfxDispatchPushArgs Incorrectly AddRef's Invoke Argument

ID: Q123274

1.50 WINDOWS kbole kbbuglist kbfixlist

The information in this article applies to:

SYMPTOMS

The CCmdTarget::InvokeHelper member function uses an internal helper function _AfxDispatchPushArgs to set up the arguments to be passed eventually to IDispatch::Invoke on the OLE Automation object.

If OLE objects are passed as arguments by value, the user may see memory leaks due to these objects not being freed after being passed to _AfxDispatchPushArgs.

CAUSE

When _AfxDispatchPushArgs trys to change parameters passed by reference into the appropriate type, an extra AddRef is performed on the object by the VariantChangeType API. Consequently those objects do not shutdown correctly.

STATUS

Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article. This bug was corrected in Microsoft Visual C++ 1.51 for Windows.

MORE INFORMATION

Below is the original section followed by the fixed version of _AfxDispatchPushArgs responsible for changing the parameter data (OLEDISP1.CPP 546-559).

=== ORIGINAL VERSION === if (vt != VT_VARIANT && vt != pArg->vt) {

    VariantInit(&va);

    // argument is not of appropriate type, attempt to coerce it
    // 
    // BUG: the VariantChangeType actually does an AddRef if pArg
    // is an LPDISPATCH or LPUNKNOWN parameter
    // 
    if (VariantChangeType(&va, pArg, 0, vt) != NOERROR)
    {
        // argument could not be coerced
   *puArgErr = iArg;
   return DISP_E_TYPEMISMATCH;
    }
    ASSERT(va.vt == vt);
    pArg = &va;
}

=== FIXED VERSION === NOTE: rgTempVars in the following code is a list of temporary VARIANT objects supplied, and explicitly cleaned up, by CCmdTarget::InvokeHelper to be used for the VariantChangeType API.

if (vt != VT_VARIANT && vt != pArg->vt) {

    // argument is not of appropriate type, attempt to coerce it
    LPVARIANT pArgTemp = &rgTempVars[iArg];
    ASSERT(pArgTemp->vt == VT_EMPTY);
    SCODE sc = GetScode(VariantChangeType(pArgTemp, pArg, 0, vt));
    if (FAILED(sc))
    {
        // argument could not be coerced
        *puArgErr = iArg;
        return sc;
    }
    ASSERT(pArgTemp->vt == vt);
    pArg = pArgTemp;
}

Additional reference words: 1.50 2.50 KBCategory: kbole kbbuglist kbfixlist KBSubcategory: MfcOLE

Keywords          : kbole kb16bitonly kbMFC kbVC kbbuglist kbfixlist
Version           : 1.50
Platform          : WINDOWS
Solution Type     : kbfix

Last Reviewed: September 21, 1997