⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serviceimpl.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    
    // argument not found
    *puArgErr = position;

    return DISP_E_PARAMNOTFOUND;
}


// GetIDsOfNames
HRESULT ServiceImpl::GetIDsOfNames(OLECHAR FAR *FAR *rgszNames,
                                   unsigned int cNames, 
                                   DISPID FAR *rgDispId)
{
    if(FAILED(m_hrInitResult))
        return m_hrInitResult;
        
    if(!cNames)
        return S_OK;

    CHECK_POINTER(rgszNames);
    CHECK_POINTER(rgDispId);

    unsigned int i;

    // initialize all the names to unknown
    for(i = 0; i < cNames; ++i)
        rgDispId[i] = DISPID_UNKNOWN;

    ce::vector<Action>::iterator it, itEnd;

    // first name is method/property name
    
    // actions (methods)
    for(it = m_Actions.begin(), itEnd = m_Actions.end(); it != itEnd; ++it)
        if(0 == wcscmp(it->GetName(), rgszNames[0]))
        {
            rgDispId[0] = base_dispid + (it - m_Actions.begin());
            break;
        }

    if(it != itEnd)
    {
        // if there are more names they are those of method arguments
        // check [in] arguments
        for(i = 1; i < cNames; ++i)
        {
            for(int j = 0; j < it->GetInArgumentsCount(); ++j)
                if(0 == wcscmp(it->GetInArgument(j).GetName(), rgszNames[i]))
                {
                    Assert(rgDispId[i] == DISPID_UNKNOWN);
                    
                    rgDispId[i] = j;
                    break;
                }
        }

        // check [out] arguments
        for(i = 1; i < cNames; ++i)
        {
            for(int j = 0, position = it->GetInArgumentsCount(); j < it->GetOutArgumentsCount(); ++j, ++position)
            {
                if(it->GetOutArgument(j).IsRetval())
                {
                    // retval doesn't count as argument in IDispatch
                    --position;
                    continue;
                }
                
                if(0 == wcscmp(it->GetOutArgument(j).GetName(), rgszNames[i]))
                {
                    Assert(rgDispId[i] == DISPID_UNKNOWN);

                    rgDispId[i] = position;
                    break;
                }
            }
        }
    }
    else
    {
        // state variables (properties)
        for(ce::vector<StateVar>::iterator itStateVar = m_StateVars.begin(), itEndStateVar = m_StateVars.end(); itStateVar != itEndStateVar; ++itStateVar)
            if(0 == wcscmp(itStateVar->GetName(), rgszNames[0]))
            {
                rgDispId[0] = base_dispid + (itStateVar - m_StateVars.begin()) + m_Actions.size();
                break;
            }
    }
        
    // check if any names remain unknown
    for(i = 0; i < cNames; ++i)
        if(rgDispId[i] == DISPID_UNKNOWN)
            return DISP_E_UNKNOWNNAME;
    
    return S_OK;
}


// Invoke
HRESULT ServiceImpl::Invoke(DISPID dispIdMember, 
							WORD wFlags, 
							DISPPARAMS FAR *pDispParams, 
							VARIANT FAR *pVarResult, 
							EXCEPINFO FAR *pExcepInfo, 
							unsigned int FAR *puArgErr)
{
    Action*         pAction;
    ce::variant     var;
    HRESULT         hr;
    int             i;
    unsigned int    position;

    if(FAILED(m_hrInitResult))
        return m_hrInitResult;
    
    if(wFlags & ~(DISPATCH_PROPERTYGET | DISPATCH_METHOD | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
        return E_INVALIDARG;
    
    if(dispIdMember < base_dispid && dispIdMember != query_state_var_dispid)
        return DISP_E_MEMBERNOTFOUND;

    // propput not supported by UPnP
    if((wFlags == DISPATCH_PROPERTYPUT) || (wFlags == DISPATCH_PROPERTYPUTREF))
        return DISP_E_MEMBERNOTFOUND;
    
    if(dispIdMember >= base_dispid + m_Actions.size())
    {
        // from dispid it can only be propget
        if(!(wFlags & DISPATCH_PROPERTYGET))
            return DISP_E_MEMBERNOTFOUND;
                
        // check if there is a state variable for this dispid
        if(dispIdMember - base_dispid - m_Actions.size() >= m_StateVars.size())
            return DISP_E_MEMBERNOTFOUND;

        return QueryStateVariable(m_StateVars[dispIdMember - base_dispid - m_Actions.size()].GetName(), pVarResult);
    }
    else
    {
        // from dispid it can only be a method
        if(!(wFlags & DISPATCH_METHOD))
            return DISP_E_MEMBERNOTFOUND;

        if(dispIdMember == query_state_var_dispid)
            pAction = &m_actionQueryStateVar;
        else
        {
            assert(dispIdMember >= base_dispid && dispIdMember < base_dispid + m_Actions.size());
                
            pAction = &m_Actions[dispIdMember - base_dispid];
        }
    }

    if(pDispParams->cArgs != pAction->GetInArgumentsCount() + GetActionOutArgumentsCount(dispIdMember))
        return DISP_E_BADPARAMCOUNT;
    
    // init [in] arguments
    for(i = 0, position = 0; i < pAction->GetInArgumentsCount(); ++i, ++position)
    {
        Argument& arg = pAction->GetInArgument(i);

        if(FAILED(hr = DispGetParam(pDispParams, position, arg.GetVartype(), &var, puArgErr)))
            return hr;
        
        arg.SetValue(var);
    }

    SoapRequest request;

    // Send SOAP request
    if(!request.SendMessage(m_strControlURL, pAction->GetSoapActionName(), pAction->CreateSoapMessage()))
    {
        DWORD dwErr = request.GetError();
        
        if(dwErr == ERROR_SUCCESS)
            dwErr = GetLastError();
        
        assert(dwErr != ERROR_SUCCESS);
        
        return HRESULT_FROM_WIN32(dwErr);
    }
    
    m_lLastTransportStatus = request.GetStatus();

    if(request.GetError() != ERROR_SUCCESS)
        return HRESULT_FROM_WIN32(request.GetError());

    // Parse SOAP response
    if(FAILED(hr = pAction->ParseSoapResponse(request)))
        return hr;
    
    if(HTTP_STATUS_OK == m_lLastTransportStatus)
    {
        // return [out] arguments
        for(i = 0, position = pAction->GetInArgumentsCount(); i < pAction->GetOutArgumentsCount(); ++i, ++position)
        {
            Argument&   arg = pAction->GetOutArgument(i);
            ce::variant varValue;

            if(FAILED(hr = arg.GetValue(&varValue)))
                return hr;
        
            if(arg.IsRetval())
            {
                CHECK_POINTER(pVarResult);

                // return [out] argument as result of the Invoke
                if(FAILED(hr = VariantCopy(pVarResult, &varValue)))
					return hr;
            
                // retval doesn't count as argument in IDispatch
                --position;
                continue;
            }

            VARIANTARG* pvarOut;

            // get pointer to variant for the [out] argument
            if(FAILED(hr = DispGetParamPtr(pDispParams, position, &pvarOut, puArgErr)))
                return hr;

            // if [out] argument is VT_BYREF | VT_VARIANT then just return value in it
            if(pvarOut->vt == (VT_BYREF | VT_VARIANT))
            {
                if(FAILED(hr = VariantCopy(V_VARIANTREF(pvarOut), &varValue)))
					return hr;

                continue;
            }

            // check if [out] parameter is a reference to proper type
            if((pvarOut->vt ^ VT_BYREF) != varValue.vt)
            {
			    CHECK_POINTER(puArgErr);

				*puArgErr = position;
				return DISP_E_TYPEMISMATCH;
			}

            Assert((pvarOut->vt ^ VT_BYREF) == varValue.vt);
        
            switch(varValue.vt)
            {
                case VT_UI1:    *V_UI1REF(pvarOut) = V_UI1(&varValue);
                                break;

                case VT_UI2:    *V_UI2REF(pvarOut) = V_UI2(&varValue);
                                break;

                case VT_UI4:    *V_UI4REF(pvarOut) = V_UI4(&varValue);
                                break;

                case VT_I1:     *V_I1REF(pvarOut) = V_I1(&varValue);
                                break;

                case VT_I2:     *V_I2REF(pvarOut) = V_I2(&varValue);
                                break;

                case VT_I4:     *V_I4REF(pvarOut) = V_I4(&varValue);
                                break;

                case VT_R4:     *V_R4REF(pvarOut) = V_R4(&varValue);
                                break;

                case VT_R8:     *V_R8REF(pvarOut) = V_R8(&varValue);
                                break;

                case VT_CY:     *V_CYREF(pvarOut) = V_CY(&varValue);
                                break;

                case VT_BSTR:   VariantClear(pvarOut);
                                *V_BSTRREF(pvarOut) = V_BSTR(&varValue);
                                break;

                case VT_DATE:   *V_DATEREF(pvarOut) = V_DATE(&varValue);
                                break;

                case VT_BOOL:   *V_BOOLREF(pvarOut) = V_BOOL(&varValue);
                                break;

                case VT_ARRAY | VT_UI1:
                                VariantClear(pvarOut);
								if(FAILED(hr = SafeArrayCopy(V_ARRAY(&varValue), V_ARRAYREF(pvarOut))))
									return hr;
                                break;
            
                default:        Assert(0);
                                break;
            }
        }

        Assert(m_lLastTransportStatus == HTTP_STATUS_OK);

        return S_OK;
    }

    Assert(m_lLastTransportStatus != HTTP_STATUS_OK);
        
    if(m_lLastTransportStatus != HTTP_STATUS_SERVER_ERROR)
        return UPNP_E_TRANSPORT_ERROR;

    switch(pAction->GetFaultCode())
    {
        case 0:   return UPNP_E_PROTOCOL_ERROR;
        case 401: return UPNP_E_INVALID_ACTION;
        case 402: return UPNP_E_INVALID_ARGUMENTS;
        case 403: return UPNP_E_DEVICE_ERROR; // TO DO: don't we need a specific error for this?
        case 404: return UPNP_E_INVALID_VARIABLE;
        case 501: return UPNP_E_ACTION_REQUEST_FAILED;
        default:
            return UPNP_E_ACTION_SPECIFIC_BASE + (pAction->GetFaultCode() - FAULT_ACTION_SPECIFIC_BASE);
    }
}


// QueryStateVariable
HRESULT ServiceImpl::QueryStateVariable(LPCWSTR pwszVariableName, VARIANT *pValue)
{
    DISPPARAMS      DispParams;
    ce::variant     varStateVar;
    unsigned int    uArgErr;

    if(FAILED(m_hrInitResult))
        return m_hrInitResult;
    
    ce::vector<StateVar>::iterator it, itEnd;

    for(it = m_StateVars.begin(), itEnd = m_StateVars.end(); it != itEnd; ++it)
        if(0 == wcscmp(pwszVariableName, it->GetName()))
            break;

    if(it == itEnd)
        return UPNP_E_INVALID_VARIABLE;

    // bind [out] argument to the state variable
    m_actionQueryStateVar.GetOutArgument(0).BindStateVar(&*it);
    
    // fabricate a DispParams structure
    DispParams.cArgs = 1;
    DispParams.cNamedArgs = 0;
    DispParams.rgdispidNamedArgs = NULL;
    DispParams.rgvarg = &(varStateVar = it->GetName());
    
    return Invoke(query_state_var_dispid, DISPATCH_METHOD, &DispParams, pValue, NULL, &uArgErr);
}


// GetActionOutArgumentsCount
int ServiceImpl::GetActionOutArgumentsCount(DISPID dispidAction)
{
    assert(!FAILED(m_hrInitResult));

    int nCount = 0;

    if(dispidAction >= base_dispid && dispidAction < base_dispid + m_Actions.size())
    {
        Action* pAction = &m_Actions[dispidAction - base_dispid];

        // count not-retval [out] arguments
        for(int i = 0; i < pAction->GetOutArgumentsCount(); ++i)
        {
            if(!pAction->GetOutArgument(i).IsRetval())
                ++nCount;
        }
    }
    
    return nCount;
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -