65.9K
CodeProject 正在变化。 阅读更多。
Home

解析 Variants

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2001年7月17日

viewsIcon

67096

downloadIcon

2

解引用和解析 Variants 和 IDispatch

引言

我创建了一个递归函数,用于反引用传入的 VARIANT ([in]) 并解析 IDispatch,如果传入的 VARIANT 中包含的变量的类型为 VT_DISPATCH

我可以使用 VariantCopy 和/或 VariantCopyInd,但我希望避免复制数组或其他非预期类型。

请查看我的函数 ResolveVariant()(如果它很长请见谅),并告诉我您是否发现任何问题。我已经进行了一些测试,没有发现任何问题(包括引用计数)。

HRESULT SomeClass::get_Item(VARIANT Index, VARIANT* pVar)
{
    VARIANT varOut;
    VariantInit(&varOut);
    HRESULT hr = ResolveVariant(&Index, &varOut);

    if (!FAILED( hr )
    {
        switch (varOut.vt)
        {
        case VT_BSTR:
            SomeCodeHere to prepare pVar;
            break;

        case VT_I4:
            SomeCodeHere to prepare pVar;
            break;

        default:
            break;
        }



        VariantClear(&varOut);


    }
    else
        return hr;

}


HRESULT ResolveVariant(VARIANT* pVarIn, VARIANT* pVarOut)
{
    VARIANT* tmpVarIn = pVarIn;
    ULONG ByRef = 0;

    while(tmpVarIn->vt == (VT_BYREF | VT_VARIANT) )
        tmpVarIn = tmpVarIn->pvarVal;

    if(tmpVarIn->vt & VT_BYREF)
        ByRef = VT_BYREF;


    switch(tmpVarIn->vt)
    {
    case (VT_I2): case (VT_BYREF|VT_I2):
        if(ByRef)
        {
            if(!tmpVarIn->piVal) return E_POINTER;
            pVarOut->iVal = *(tmpVarIn->piVal);
        }
    break;

    case (VT_I4): case (VT_BYREF|VT_I4):
        if(ByRef)
        {
            if(!tmpVarIn->plVal) return E_POINTER;
            pVarOut->lVal = *(tmpVarIn->plVal);
        }
        break;

    case (VT_BSTR): case (VT_BYREF|VT_BSTR):
        if(ByRef)
        {
            if(!tmpVarIn->pbstrVal) return E_POINTER;
            if(!*(tmpVarIn->pbstrVal) ) return E_POINTER;
            pVarOut->bstrVal = *(tmpVarIn->pbstrVal);
        }
        break;

    case (VT_DISPATCH): case (VT_BYREF|VT_DISPATCH):
        if(ByRef)
        {
            if(!tmpVarIn->ppdispVal) return E_POINTER;
            if(!*(tmpVarIn->ppdispVal) ) return E_POINTER;
            pVarOut->pdispVal = *(tmpVarIn->ppdispVal);
        }
        break;


    default:
        return DISP_E_TYPEMISMATCH;
    }

    if(ByRef)
        pVarOut->vt = (tmpVarIn->vt - ByRef);
    else
        *pVarOut = *tmpVarIn;


    if (pVarOut->vt == VT_DISPATCH)
    {
        VARIANT varResolved;
        DISPPARAMS  dispParamsNoArgs = {NULL, NULL, 0, 0};

        VariantInit(&varResolved);

        if ( SUCCEEDED

            pVarOut->pdispVal->Invoke(DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
            DISPATCH_PROPERTYGET | DISPATCH_METHOD,
            &dispParamsNoArgs, &varResolved, NULL, NULL) ) )
        {
            ResolveVariant(&varResolved, pVarOut);
        }
        else
            return E_FAIL;

        VariantClear(&varResolved);
            return S_OK;
    }
    else
    {
        HRESULT hr;
        VARIANT retVar;
        VariantInit(&retVar);
        hr = VariantCopy(&retVar, pVarOut);
        *pVarOut = retVar;
        return hr;
    }
}
© . All rights reserved.