client.cpp

来自「Windows CE 6.0 Server 源码」· C++ 代码 · 共 2,141 行 · 第 1/5 页

CPP
2,141
字号
    //adjust dispid for the unknown methods
    dispid -= DISPID_SOAPCLIENT_UNKNOWNSTART;


    if (pdispparams->cNamedArgs != 0)
        CHK(DISP_E_NONAMEDARGS);

    // Find the method from the Operations list
#ifdef UNDER_CE
    bstrAbstractNames = SysAllocString(m_abstrNames.getName(dispid));
    CHK_BOOL(bstrAbstractNames.valid(), E_OUTOFMEMORY);
    if (FAILED(m_pIEnumWSDLOps->Find(bstrAbstractNames, &pIWSDLOp)))
#else
    if (FAILED(m_pIEnumWSDLOps->Find(m_abstrNames.getName(dispid), &pIWSDLOp)))
#endif
    {
        CHK(DISP_E_MEMBERNOTFOUND);
    }


    // Get the stream
    CHK(pSoapConnector->get_InputStream(&pIStreamIn));

    // Pass the connect stream to SoapSerializer
    pStore->getSerializer()->reset();

    VARIANT vStream;
    VariantInit(&vStream);
    vStream.vt = VT_UNKNOWN;
    V_UNKNOWN(&vStream) = pIStreamIn;

    CHK(pStore->getSerializer()->Init(vStream));

    // set the output encoding on the connector
    if (m_bstrpreferredEncoding && ::SysStringLen(m_bstrpreferredEncoding) > 0)
    {
        CVariant var;
        CAutoBSTR bstrPropName;

        CHK(bstrPropName.Assign(L"HTTPCharset"));

        // we will overwrite anything that was previously set. And we don't care. If this value is different
        // from the value set on the serializer later, we would create an invalid message
        // to set the prefered encoding when working with the highlevel client.
        CHK(var.Assign(m_bstrpreferredEncoding, true));
        CHK(pSoapConnector->put_Property(bstrPropName, var));
    }

    // Begin writing out the message
    CHK(pSoapConnector->BeginMessageWSDL(pIWSDLOp));

    // Create the message body here
    CHK(ConstructSoapRequestMessage(pdispparams, pStore->getSerializer(), pIWSDLOp, pIStreamIn));

    // Send the message over to the server
    hr = pSoapConnector->EndMessage();
    if (FAILED(hr))
    {   // Try to obtain info from the interface, if no SOAP
        // interface, we will construct a generic one later.
        globalAddError(HrToMsgId(hr), SOAP_IDS_CLIENT, hr);
        globalAddError(SOAP_IDS_SENDMESSAGEFAILED, SOAP_IDS_CLIENT,  hr);
        goto Cleanup;
    }

    // Obtain the response stream
    hr = pSoapConnector->get_OutputStream(&pIStreamOut);
    if (FAILED(hr) || pIStreamOut == 0)
    {
        globalAddError(SOAP_IDS_READMESSAGEFAILED, SOAP_IDS_CLIENT,  hr);
        goto Cleanup;
    }

    // Instantiate SoapReader to read the input message
    CHK(CoCreateInstance(CLSID_SoapReader, NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_ISoapReader,
                          (void**)&pISoapRead));

    // Pass the input stream into SoapReader.
    varArg.vt = VT_UNKNOWN;
    CHK(pIStreamOut->QueryInterface(IID_IUnknown, (void **)&(varArg.punkVal)));
    hr = pISoapRead->load(varArg, NULL, &bSuccess);
    if (FAILED(hr) || !bSuccess)
    {
        if (!FAILED(hr))
        {
            hr = CONN_E_BAD_CONTENT;        // Got bad content back from server
        }
        else
        {
            globalAddError(SOAP_IDS_SERVER_COULDNOTLOADREQUEST, SOAP_IDS_CLIENT, hr);
        }
        goto Cleanup;
    }


    // It will return the HRESULT in the FAULT details if there is one
    CHK(CheckForFault(pISoapRead, &bHasFault));

    if (bHasFault)      // Got a fault back but not hresult.
    {
        hr = E_FAIL;
        goto Cleanup;
    }

    // Pass the SoapReader into WSDLReader to get the parts out
    CHK(pIWSDLOp->Load(pISoapRead, VARIANT_FALSE));

    // Process the response, errors/faults if any
    CHK(ProcessSoapResponseMessage(pdispparams, pvarResult, pexcepinfo, pISoapRead, pIWSDLOp));

Cleanup:
    if (FAILED(hr) && pStore)
    {
        // Construct a generic error message
        pStore->getFaultInfo()->FaultMsgFromResourceHr(SOAP_IDS_CLIENT, 0, hr,
                NULL, NULL);
    }
    TRACE(("Exiting Client::InvokeUnknownMethod\n"));
    ::VariantClear(&varArg);
    if (pStore && pSoapConnector)
    {
        pSoapConnector->Reset();
        pStore->ReturnConnector(pSoapConnector);
    }
    if (pStore && pStore->getFaultInfo())
    {
        pStore->getFaultInfo()->PublishErrorInfo();
    }

    return hr;
}


////////////////////////////////////////////////////////////////////////////////////////////////////
//  function: HRESULT CSoapClient::ConstructSoapRequestMessage ( DISPPARAMS * pdispparams,
//                                      ISoapSerializer *pISoapSer, IWSDLOperation * pIWSDLOp,
//                                      ISequentialStream * pIStream)
//
//  parameters:
//
//  description:
//        Creates the SOAP envelope
//        This method assumes that parameter order matches the WSDL file order.
//        No named parameter support is provided for the dispatch parameters
//  returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSoapClient::ConstructSoapRequestMessage(
                    DISPPARAMS * pdispparams,
                    ISoapSerializer *pISoapSer,
                    IWSDLOperation * pIWSDLOp,
                    ISequentialStream * pIStream)
{
    HRESULT hr = S_OK;

#ifndef UNDER_CE
    VARIANT_BOOL    bHeaders;
#endif 
    smIsInputEnum   enIsInput;
    CAutoRefc<IEnumSoapMappers>  pIEnumSoapMaps;
    CAutoRefc<ISoapMapper>  pISoapMap;
#ifndef UNDER_CE
    long        cFetched;
#endif 
    int            i;
    int                iArgs;
    long            lArgCount;
    VARIANTARG      varArg;
    UINT            uiErr;
    VARTYPE        vtType;
    CSoapHeaders    soapHeaders;
    TCHAR           *pchEncStyle; 
#ifdef UNDER_CE    
    ce::auto_bstr bstrEncodingStyle = NULL;
    ce::auto_bstr bstrEnvPrefix = NULL;
#endif    


    VariantInit(&varArg);

    // Pass the parameter values to SoapSerializer
    // call endSoapEnvelope()

    // get the EncodingStyle from the operation
   pchEncStyle = ((CWSDLOperation*)(IWSDLOperation*)pIWSDLOp)->getEncoding(true); 

#ifdef UNDER_CE
    bstrEncodingStyle = SysAllocString(pchEncStyle);
    CHK_BOOL(bstrEncodingStyle.valid(), E_OUTOFMEMORY);

    bstrEnvPrefix = SysAllocString(g_pwstrEnvPrefix);
    CHK_BOOL(bstrEnvPrefix.valid(), E_OUTOFMEMORY);
    
    CHK(pISoapSer->startEnvelope(bstrEnvPrefix, bstrEncodingStyle, m_bstrpreferredEncoding));
#else
    CHK(pISoapSer->startEnvelope(g_pwstrEnvPrefix, pchEncStyle, m_bstrpreferredEncoding));
#endif

    if (m_pHeaderHandler)
    {
        CHK(soapHeaders.Init());
        CHK(soapHeaders.AddHeaderHandler(m_pHeaderHandler));
        CHK(soapHeaders.WriteHeaders(pISoapSer, 0));
    }

    CHK(pISoapSer->startBody(/* BSTR enc_style_uri */ NULL));

    // Go over the SoapMapper enumerations, putting the input parameter   
    // values into each one and then saving the value.
    CHK(pIWSDLOp->GetOperationParts(&pIEnumSoapMaps));

    // Arguments in DISPPARAMS are located in the inverse order.
    // but DispGetParams takes care of this...
    i = 0;
    iArgs = 0;
    // Finally add the soap body elements

    // verify that we have ENOUGH parameters for the mappers

    CHK( ((CEnumSoapMappers*)(IEnumSoapMappers*)pIEnumSoapMaps)->parameterCount(&lArgCount));
#ifndef UNDER_CE
    if (pdispparams->cArgs != lArgCount)
#else
    if (pdispparams->cArgs != (ULONG)lArgCount)
#endif 
    {
           hr = E_INVALIDARG;
           globalAddError(CLIENT_IDS_INCORRECTNUMBEROFPARAMETERS, SOAP_IDS_CLIENT,  hr);
        goto Cleanup;
    }


    while (iArgs < (int) pdispparams->cArgs)
    {
        CHK( ((CEnumSoapMappers*)(IEnumSoapMappers*)pIEnumSoapMaps)->FindParameter(iArgs, &pISoapMap));
           CHK( pISoapMap->get_isInput(&enIsInput));
        if (enIsInput != smOutput)
        {
            // Add the values from the DISPPARAMS to the SoapMapper.
               // get the comtype
            vtType = ((CSoapMapper*)(ISoapMapper*)pISoapMap)->getVTType();
            VariantClear(&varArg);
            if ( (vtType == VT_SAFEARRAY) || (vtType & VT_ARRAY))
                 hr = ArrayGetParam(pdispparams, (UINT)iArgs, &varArg);
            else
                if (vtType == VT_VARIANT)
                    hr = VariantGetParam(pdispparams, (UINT)iArgs, &varArg);
                else
                    hr = DispGetParam(pdispparams, (UINT)iArgs, vtType, &varArg, &uiErr);
            if (FAILED(hr))
            {
                CAutoBSTR bstrName;
                pISoapMap->get_elementName(&bstrName);
                globalAddError(CLIENT_IDS_DISPGETPARAMFAILED, SOAP_IDS_CLIENT,  hr, bstrName);
                goto Cleanup;
            }
            CHK( pISoapMap->put_comValue(varArg));
        }
        iArgs++;
        pISoapMap.Clear();
    }

    // Now save the operation into the body
    CHK( pIWSDLOp->Save(pISoapSer, VARIANT_TRUE));

    // End of Soap body element
    CHK( pISoapSer->endBody());
    // Finally end the envelope
    CHK( pISoapSer->endEnvelope());

Cleanup:
    VariantClear(&varArg);
    return hr;

}


////////////////////////////////////////////////////////////////////////////////////////////////////
//  function: HRESULT CSoapClient::ProcessSoapResponseMessage (DISPPARAMS * pdispparams,
//                                         VARIANT * pvarResult, EXCEPINFO * pexcepinfo,
//                                         ISoapReader * pISoapReader, IWSDLOperation * pIWSDLOp)
//  parameters:
//
//  description:
//        Processes the SOAP envelope response
//  returns:
//
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSoapClient::ProcessSoapResponseMessage(
                    DISPPARAMS * pdispparams,
                    VARIANT * pvarResult,
                    EXCEPINFO * pexcepinfo,
                    ISoapReader * pISoapReader,
                    IWSDLOperation * pIWSDLOp)
{
    HRESULT hr = S_OK;
    CAutoRefc<IEnumSoapMappers> pIEnumSoapMaps;
    CAutoRefc<ISoapMapper>  pISoapMap;
#ifndef UNDER_CE
    long cFetched;
    smIsInputEnum enIsInput;
#endif 
    VARIANT *pvarNext = NULL;
    VARIANTARG varArg;
    LCID lcid;
    int    iArgs;
    CSoapHeaders    soapHeaders;


    VariantInit(&varArg);
    lcid = GetSystemDefaultLCID();

    VariantInit(&varArg);

    // Pass the parameter values to SoapSerializer
    // call endSoapEnvelope()

    if (m_pHeaderHandler)
    {
        CHK(soapHeaders.Init());
        CHK(soapHeaders.AddHeaderHandler(m_pHeaderHandler));
		hr = soapHeaders.ReadHeaders(pISoapReader, 0);

		if (FAILED(hr))
		{
			if (hr == WSDL_MUSTUNDERSTAND)
			{
			    globalAddError(CLIENT_IDS_HEADERNOTUNDERSTOOD, SOAP_IDS_CLIENT, hr);
			}
			goto Cleanup;
		}
    }


    CHK(pIWSDLOp->GetOperationParts(&pIEnumSoapMaps));

    // Go through the the soap response elements

    iArgs = 0;

    while (iArgs < (int) pdispparams->cArgs)
    {
        pvarNext = pdispparams->rgvarg + pdispparams->cArgs - 1 - iArgs ;
        CHK(((CEnumSoapMappers*)(IEnumSoapMappers*)pIEnumSoapMaps)->FindParameter(iArgs, &pISoapMap));
        CHK(moveResult(pISoapMap, pvarNext));
        iArgs++;
        pISoapMap.Clear();
    }

    // let's check the return value
    if (pvarResult)
    {
        hr = ((CEnumSoapMappers*)(IEnumSoapMappers*)pIEnumSoapMaps)->FindParameter(-1, &pISoapMap);
        if (FAILED(hr))
        {
               hr = E_INVALIDARG;
               globalAddError(CLIENT_IDS_INCORRECTNUMBEROFPARAMETERS, SOAP_IDS_CLIENT,  hr);
            goto Cleanup;
        }
        VariantClear(pvarResult);
        CHK(moveResult(pISoapMap, pvarResult));
    }


    // if we got here, change the S_FALSE from the ->Next to S_OK, as everything is OK
    hr = S_OK;

Cleanup:
    VariantClear(&varArg);
    return hr;

}


/////////////////////////////////////////////////////////////////////////////////////////////////////////
//  function: HRESULT CSoapClient::moveResult(ISoapMapper *pMapper, VARIANT *pVariant)
//
//  parameters:
//
//  description:
//
//  returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSoapClient::moveResult(ISoapMapper *pMapper, VARIANT *pVariant)
{
    HRESULT hr;
    smIsInputEnum enIsInput;
    VARIANT varArg;
     LCID lcid;

    VariantInit(&varArg);
    lcid = GetSystemDefaultLCID();

    CHK(pMapper->get_isInput(&enIsInput));
    if (enIsInput != smInput)
    {
        CHK(pMapper->get_comValue(&varArg));
        if ( (pVariant->vt == (VT_VARIANT|VT_BYREF)) ||
              (pVariant->vt == VT_EMPTY) )
        {
            VARIANT * pvarDest = pVariant;
            if (V_ISBYREF(pVariant))
                pvarDest=pVariant->pvarVal;

            if (V_ISARRAY(&varArg))
                CHK(VariantCopy(pvarDest, &varArg))
            else
                 CHK(VariantChangeTypeEx(pvarDest,&varArg, lcid, 0, varArg.vt));
             VariantClear(&varArg);
        }
        else
        {
            // Move the value over
            // but don't do it, if it's not passed by ref
            if (pVariant->vt & VT_BYREF)
            {
                CHK(VariantCopyToByRef(pVariant, &varArg, lcid));
            }
        }
    }
Cleanup:
    VariantClear(&varArg);
    return (hr);
}


////////////////////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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