Utility Functions

Dispargs.c also includes utility functions used to manage variants and argument arrays. The ClearVariant function sets a variant to zero. This function ignores the current contents of the variant. If you are unsure of the current contents of the variant, you should call the ReleaseVariant function before you clear the variant.

void ClearVariant(VARIANTARG *pvarg)
{
    pvarg->vt = VT_EMPTY;
    pvarg->wReserved1 = 0;
    pvarg->wReserved2 = 0;
    pvarg->wReserved3 = 0;
    pvarg->lVal = 0;
}

The ClearAllArgs function releases any memory in use by the argument array and resets the argument counters. Because these arrays are static, it is important to call the ClearAllArgs function before you begin to set up arguments.

void ClearAllArgs()
{
    int i;

    for (i = 0; i < g_iArgCount; i++) 
    {
        if (g_awFlags[i] & DISPARG_NOFREEVARIANT)
            // free the variant's contents based on type
            ClearVariant(&g_aVargs[i]);
        else
            ReleaseVariant(&g_aVargs[i]);
    }

    g_iArgCount = 0;
    g_iNamedArgCount = 0;
}

The ReleaseVariant function releases any memory allocated for a variant (such as a variant containing a string or array). Use this function anytime you set a variant if you are unsure of its current contents. For example, a memory leak will result if you set a variant that currently contains a string without first releasing the string.

This function supports the following data types: integers, Booleans, doubles, objects, strings, and arrays of any of the listed data types.

void ReleaseVariant(VARIANTARG *pvarg)
{
    VARTYPE vt;
    VARIANTARG _huge *pvargArray;
    long lLBound, lUBound, l;

    vt = pvarg->vt & 0xfff;        // mask off flags

    // check if an array.  If so, free its contents, 
    // then the array itself.
    if (V_ISARRAY(pvarg)) 
    {
        // variant arrays are all this routine currently knows about.
        // Since a variant can contain anything (even other arrays), 
        // call ourselves recursively.
        if (vt == VT_VARIANT) 
        {
            SafeArrayGetLBound(pvarg->parray, 1, &lLBound);
            SafeArrayGetUBound(pvarg->parray, 1, &lUBound);

            if (lUBound > lLBound) 
            {
                lUBound -= lLBound;

                SafeArrayAccessData(pvarg->parray, &pvargArray);

                for (l = 0; l < lUBound; l++) 
                {
                    ReleaseVariant(pvargArray);
                    pvargArray++;
                }

                SafeArrayUnaccessData(pvarg->parray);
            }
        }
        else 
        {
            MessageBox(g_hwndApp, L"ReleaseVariant: Array contains 
                non-variant type", g_szAppTitle, MB_OK | MB_ICONSTOP);
        }

        // Free the array itself.
        SafeArrayDestroy(pvarg->parray);
    }
    else 
    {
        switch (vt) 
        {
            case VT_DISPATCH:
                (*(pvarg->pdispVal->lpVtbl->Release))(pvarg->pdispVal);
                break;

            case VT_BSTR:
                SysFreeString(pvarg->bstrVal);
                break;

            case VT_I2:
            case VT_BOOL:
            case VT_R8:
            case VT_ERROR:        // to avoid erroring on an error return 
                                // from Excel
                // no work for these types
                break;

            default:
                MessageBox(g_hwndApp, L"ReleaseVariant: Unknown type", 
                    g_szAppTitle, MB_OK | MB_ICONSTOP);
                break;
        }
    }

    ClearVariant(pvarg);
}