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 + -
显示快捷键?