// interopsvcdimedocObj.cpp : Implementation of CinteropsvcdimedocObj #include "stdafx.h" #include "interopsvcdimedocObj.h" #include "..\soap_source\xmlparser.h" #include "..\wmsoapmsg\wmsoapmsg_i.c" #include "..\wmsoapmsg\wmsoapmsg.h" #include "..\soap_source\charencode.h" #include "..\soap_source\DIMEPayload.h" #include "..\soap_source\base64.h" #include "..\soap_source\soap.h" #include "comdef.h" // CinteropsvcdimedocObj static wchar_t *g_pwszMsgNS = L"http://soapinterop.org/attachments/xsd"; static wchar_t *g_pwszRefNS = L"http://schemas.xmlsoap.org/ws/2002/04/reference/"; void LeftTrim(string& strData) { // left trim string::size_type pos; for (pos = 0; pos < strData.length(); pos++) { if (!isspace(strData[pos])) { break; } } if (pos > 0) { strData = strData.substr(pos); } } void RightTrim(string& strData) { // right trim string::size_type pos; string::size_type upperbound = strData.length() - 1; for (pos = upperbound; pos >= 0; pos--) { if (!isspace(strData[pos])) { break; } } if (pos < upperbound) { strData = strData.substr(0, pos + 1); } } void TrimWhitespace(string& strData) { LeftTrim(strData); RightTrim(strData); } bool ParseParameters(string& strParams, map& mapParams) { while (true) { // seek delimiting ';' between parameters string::size_type pos = strParams.find(';'); // extract attribute/value pair string strTemp = strParams.substr(0, pos); // find '=' in attribute/value pair string::size_type index = strTemp.find('='); // if found then process if (index != string::npos) { string strAttr = strTemp.substr(0, index); // trim whitespace TrimWhitespace(strAttr); // attribute name is not case sensitive for (string::size_type i = 0; i < strAttr.length(); i++) { // force to uppercase... comparisons are case-insensitive strAttr[i] = toupper(strAttr[i]); } string strValue = strTemp.substr(index + 1); // trim whitespace TrimWhitespace(strValue); // unquote value if necessary string::size_type start, stop; start = strValue.find('"'); stop = strValue.rfind('"'); if (start != string::npos && stop != string::npos) { ++start; strValue = strValue.substr(start, stop - start); } // now add to map mapParams[strAttr] = strValue; } // was this the last one? if (pos == string::npos) { // yes, we are done break; } strParams = strParams.substr(pos + 1); } return true; } bool ParseMIMEType( string& strFieldBody, string& strMIMEType, map& mapParams) { // split content type and parameters string::size_type pos; pos = strFieldBody.find(';'); strMIMEType = strFieldBody.substr(0, pos); TrimWhitespace(strMIMEType); // content type is not case sensitive for (string::size_type i = 0; i < strMIMEType.length(); i++) { // force to uppercase... comparisons are case-insensitive strMIMEType[i] = toupper(strMIMEType[i]); } // now parse parameters ParseParameters(strFieldBody.substr(pos + 1), mapParams); return true; } BSTR GenerateUUID() { GUID g; CoCreateGuid(&g); OLECHAR wszBuffer1[64]; OLECHAR wszBuffer2[64]; StringFromGUID2(g, wszBuffer1, 64); wszBuffer1[37] = 0; swprintf(wszBuffer2, L"uuid:%s", &wszBuffer1[1]); return SysAllocString(wszBuffer2); } STDMETHODIMP CinteropsvcdimedocObj::OnProcessBody(VARIANT SOAPMsgInterface, VARIANT_BOOL *pResult) { *pResult = VARIANT_TRUE; // get interface ptr IDispatch *pIDispatch = SOAPMsgInterface.pdispVal; Iwmsoapmsg2 *pIwmsoapmsg; HRESULT hRes = pIDispatch->QueryInterface(IID_Iwmsoapmsg2, (void **)&pIwmsoapmsg); if (hRes != S_OK) { return E_FAIL; } // process if (ProcessMessage(pIwmsoapmsg) == false) { GenerateFault(pIwmsoapmsg); } pIwmsoapmsg->Release(); return S_OK; } bool CinteropsvcdimedocObj::ProcessMessage(Iwmsoapmsg2 *pIwmsoapmsg) { BSTR bstrXML; wstring wstrXML; VARIANT_BOOL bResult; HRESULT hRes = pIwmsoapmsg->GetBodyElemLiteral( &bstrXML, &bResult); if (hRes != S_OK || bResult == VARIANT_FALSE) { return false; } // set up for parsing WMXMLParser Parser; Parser.SetBuildTree(true); bool bRtn = true; // parse the XML fragment representing the message try { Parser.ParseXML_WideString(bstrXML, NULL); } catch(int e) { int x = e; SysFreeString(bstrXML); return false; } SysFreeString(bstrXML); // get the WMXMLElement pointer representing root node of parse tree WMXMLElement *pRoot = Parser.DetachDocRoot(); if (pRoot == NULL) { return false; } vector arrAttachments; bool bEchoAttachmentElemFound = false; bool bEchoAttachmentsElemFound = false; bool bEchoAttachmentAsBase64ElemFound = false; bool bEchoBase64AsAttachmentElemFound = false; bool bEchoUnrefAttachmentsElemFound = false; bool bAttachmentAsStringElemFound = false; wstring wstrBase64Encoded; wstring wstrStringOut; WMXMLElement *pWrapper = NULL; // look for 'EchoAttachment' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoAttachment")); if (pWrapper != NULL) { bEchoAttachmentElemFound = true; WMXMLElement *pAttachment = pWrapper->GetChildElement(wstring(g_pwszMsgNS), wstring(L"In")); if (pAttachment != NULL) { wstring wstrValue; wstring wstrKey(g_pwszRefNS); if (pAttachment->GetAttribute(wstrKey, wstring(L"location"), wstrValue) == true) { // found "location" attribute, get value wstring wstrId = wstrValue; // now we will query message object for attachment with matching id IStorage *pIStorage; IUnknown *pIUnknown; BSTR bstrId = SysAllocString(wstrValue.c_str()); BSTR bstrType; long lTNF; VARIANT_BOOL bResult; _variant_t varOptions; pIwmsoapmsg->GetDIMEAttachmentReq( bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &bResult); if (bResult == VARIANT_FALSE) { // no such attachment return false; } // found referenced attachment, get interface ptr HRESULT res = pIUnknown->QueryInterface(IID_IStorage, (void **)&pIStorage); if (FAILED(res)) { return false; } string strId, strType; WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); // wrap it DIMEPayload *pPayload = new DIMEPayload(pIStorage, strId, strType, lTNF); pIStorage->Release(); // create output storage IStorage *pIStorageOut; HRESULT hRes = StgCreateDocfile(NULL, STGM_DELETEONRELEASE | STGM_DIRECT | STGM_READWRITE| STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorageOut); if (FAILED(hRes)) { return false; } // wrap it DIMEPayload *pPayloadOut = new DIMEPayload( pIStorageOut, strId, strType, lTNF); // now copy contents from input storage to output storage char szTemp[4096]; unsigned long ulNumBytes = 0; unsigned long ulBytesWritten = 0; pPayload->OpenForRead(); pPayloadOut->OpenForWrite(); int count = 0; do { pPayload->Read(szTemp, 4096, &ulNumBytes); pPayloadOut->Write(szTemp, ulNumBytes, &ulBytesWritten); count += ulNumBytes; } while (ulNumBytes == 4096); pPayload->Close(); pPayloadOut->Close(); // add response header entry to message pIwmsoapmsg->AddDIMEAttachmentResp( bstrId, bstrType, lTNF, pIStorageOut, varOptions, &bResult); pIStorageOut->Release(); SysFreeString(bstrId); SysFreeString(bstrType); delete pPayload; delete pPayloadOut; if (bResult == VARIANT_FALSE) { return false; } // store id string arrAttachments.push_back(wstrId); } else { } } goto response; } // look for 'EchoAttachments' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoAttachments")); if (pWrapper != NULL) { bEchoAttachmentsElemFound = true; ChildElementsList::iterator iter; unsigned long ulCounter = 0; for (iter = pWrapper->GetChildElements().begin(); iter != pWrapper->GetChildElements().end(); iter++) { WMXMLElement *pAttachment = *iter; // is this child an "Item" element? if (pAttachment->GetLocalName() == L"Item" && pAttachment->GetURI() == g_pwszMsgNS) { // yes, so look for "location" attribute wstring wstrValue; wstring wstrKey(g_pwszRefNS); if (pAttachment->GetAttribute(wstrKey, wstring(L"location"), wstrValue) == true) { // found "location" attribute, get value wstring wstrId = wstrValue; // now we will query message object for attachment with matching id IStorage *pIStorage; IUnknown *pIUnknown; BSTR bstrId = SysAllocString(wstrValue.c_str()); BSTR bstrType; long lTNF; VARIANT_BOOL bResult; _variant_t varOptions; pIwmsoapmsg->GetDIMEAttachmentReq( bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &bResult); if (bResult == VARIANT_FALSE) { // no such attachment return false; } // found referenced attachment, get interface ptr HRESULT res = pIUnknown->QueryInterface(IID_IStorage, (void **)&pIStorage); if (FAILED(res)) { return false; } string strId, strType; WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); // wrap it DIMEPayload *pPayload = new DIMEPayload(pIStorage, strId, strType, lTNF); pIStorage->Release(); // create output storage IStorage *pIStorageOut; HRESULT hRes = StgCreateDocfile(NULL, STGM_DELETEONRELEASE | STGM_DIRECT | STGM_READWRITE| STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorageOut); if (FAILED(hRes)) { return false; } // wrap it DIMEPayload *pPayloadOut = new DIMEPayload( pIStorageOut, strId, strType, lTNF); // now copy contents from input storage to output storage char szTemp[4096]; unsigned long ulNumBytes = 0; unsigned long ulBytesWritten = 0; pPayload->OpenForRead(); pPayloadOut->OpenForWrite(); int count = 0; do { pPayload->Read(szTemp, 4096, &ulNumBytes); pPayloadOut->Write(szTemp, ulNumBytes, &ulBytesWritten); count += ulNumBytes; } while (ulNumBytes == 4096); pPayload->Close(); pPayloadOut->Close(); // add response header entry to message pIwmsoapmsg->AddDIMEAttachmentResp( bstrId, bstrType, lTNF, pIStorageOut, varOptions, &bResult); varOptions.Clear(); pIStorageOut->Release(); SysFreeString(bstrId); SysFreeString(bstrType); delete pPayload; delete pPayloadOut; if (bResult == VARIANT_FALSE) { return false; } // store id string arrAttachments.push_back(wstrId); } } } goto response; } // look for 'EchoAttachmentAsBase64' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoAttachmentAsBase64")); if (pWrapper != NULL) { bEchoAttachmentAsBase64ElemFound = true; WMXMLElement *pAttachment = pWrapper->GetChildElement(wstring(g_pwszMsgNS), wstring(L"In")); if (pAttachment != NULL) { wstring wstrValue; wstring wstrKey(g_pwszRefNS); if (pAttachment->GetAttribute(wstrKey, wstring(L"location"), wstrValue) == true) { // found "location" attribute, get value wstring wstrId = wstrValue; // now we will query message object for attachment with matching id IStorage *pIStorage; IUnknown *pIUnknown; BSTR bstrId = SysAllocString(wstrValue.c_str()); BSTR bstrType; long lTNF; VARIANT_BOOL bResult; _variant_t varOptions; pIwmsoapmsg->GetDIMEAttachmentReq( bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &bResult); if (bResult == VARIANT_FALSE) { // no such attachment return false; } // found referenced attachment, get interface ptr HRESULT res = pIUnknown->QueryInterface(IID_IStorage, (void **)&pIStorage); if (FAILED(res)) { return false; } string strId, strType; WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); // wrap it DIMEPayload *pPayload = new DIMEPayload(pIStorage, strId, strType, lTNF); pIStorage->Release(); pPayload->OpenForRead(); unsigned long ulNumBytesRead = 0; unsigned long ulLength = pPayload->GetDataLength(); unsigned char *pBuffer = (unsigned char *)malloc(ulLength); pPayload->Read((char *)pBuffer, ulLength, &ulNumBytesRead); pPayload->Close(); delete pPayload; // base64 encode WMBase64 base64; string strEncoded; base64.Encode(pBuffer, ulLength, strEncoded); free(pBuffer); UTF8ToWideString(strEncoded, wstrBase64Encoded); // store id string arrAttachments.push_back(wstrId); } } goto response; } // look for 'EchoBase64AsAttachment' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoBase64AsAttachment")); if (pWrapper != NULL) { bEchoBase64AsAttachmentElemFound = true; WMXMLElement *pData = pWrapper->GetChildElement(wstring(g_pwszMsgNS), wstring(L"In")); if (pData != NULL) { wstring wstrValue = pData->GetContent(); string strEncodedData; WideStringToUTF8(wstrValue, strEncodedData); WMBase64 base64; // get length of decoded data int nLength; if (base64.Decode(strEncodedData, NULL, nLength) == false) { return false; } char *pszBuffer = NULL; bool bIsZeroLength = false; if (nLength == 0) { bIsZeroLength = true; } else { // decode pszBuffer = (char *)malloc(nLength); if (pszBuffer == NULL) { return false; } base64.Decode(strEncodedData, (unsigned char*)pszBuffer, nLength); } // create output storage IStorage *pIStorageOut; HRESULT hRes = StgCreateDocfile(NULL, STGM_DELETEONRELEASE | STGM_DIRECT | STGM_READWRITE| STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorageOut); if (FAILED(hRes)) { return false; } // wrap it long lTNF = 1; BSTR bstrType = SysAllocString(L"application/octetstream"); BSTR bstrId = GenerateUUID(); string strId, strType; wstring wstrId(bstrId); WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); DIMEPayload *pPayloadOut = new DIMEPayload( pIStorageOut, strId, strType, lTNF); if (bIsZeroLength == false && pszBuffer != NULL) { // now copy decoded data to output storage unsigned long ulBytesWritten = 0; pPayloadOut->OpenForWrite(); pPayloadOut->Write(pszBuffer, nLength, &ulBytesWritten); pPayloadOut->Close(); free(pszBuffer); } // add payload to message _variant_t varOptions; pIwmsoapmsg->AddDIMEAttachmentResp( bstrId, bstrType, lTNF, pIStorageOut, varOptions, &bResult); SysFreeString(bstrId); SysFreeString(bstrType); pIStorageOut->Release(); delete pPayloadOut; if (bResult == VARIANT_FALSE) { return false; } // store id string arrAttachments.push_back(wstrId); } goto response; } // look for 'EchoUnrefAttachments' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoUnrefAttachments")); if (pWrapper != NULL) { bEchoUnrefAttachmentsElemFound = true; // now get payloads long lPosition; BSTR bstrId, bstrType; long lTNF; IUnknown *pIUnknown; _variant_t varOptions; for (pIwmsoapmsg->GetFirstDIMEAttachmentReq(&bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &lPosition, &bResult); bResult == VARIANT_TRUE; pIwmsoapmsg->GetNextDIMEAttachmentReq( &bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &lPosition, &bResult) ) { string strId, strType; WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); SysFreeString(bstrId); SysFreeString(bstrType); IStorage *pIStorage; HRESULT res = pIUnknown->QueryInterface(IID_IStorage, (void **)&pIStorage); if (FAILED(res)) { return false; } // wrap it DIMEPayload *pPayload = new DIMEPayload(pIStorage, strId, strType, lTNF); pIStorage->Release(); // create output storage IStorage *pIStorageOut; HRESULT hRes = StgCreateDocfile(NULL, STGM_DELETEONRELEASE | STGM_DIRECT | STGM_READWRITE| STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorageOut); if (FAILED(hRes)) { return false; } // wrap it DIMEPayload *pPayloadOut = new DIMEPayload( pIStorageOut, strId, strType, lTNF); // now copy contents from input storage to output storage char szTemp[4096]; unsigned long ulNumBytes = 0; unsigned long ulBytesWritten = 0; pPayload->OpenForRead(); pPayloadOut->OpenForWrite(); int count = 0; do { pPayload->Read(szTemp, 4096, &ulNumBytes); pPayloadOut->Write(szTemp, ulNumBytes, &ulBytesWritten); count += ulNumBytes; } while (ulNumBytes == 4096); pPayload->Close(); pPayloadOut->Close(); // add payload to message pIwmsoapmsg->AddDIMEAttachmentResp( bstrId, bstrType, lTNF, pIStorageOut, varOptions, &bResult); varOptions.Clear(); pIStorageOut->Release(); SysFreeString(bstrId); SysFreeString(bstrType); delete pPayload; delete pPayloadOut; if (bResult == VARIANT_FALSE) { return false; } } goto response; } // look for 'EchoAttachmentAsString' element pWrapper = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"EchoAttachmentAsString")); if (pWrapper != NULL) { bAttachmentAsStringElemFound = true; WMXMLElement *pAttachment = pWrapper->GetChildElement(wstring(g_pwszMsgNS), wstring(L"In")); if (pAttachment != NULL) { wstring wstrValue; wstring wstrKey(g_pwszRefNS); if (pAttachment->GetAttribute(wstrKey, wstring(L"location"), wstrValue) == true) { // found "location" attribute, get value wstring wstrId = wstrValue; // now we will query message object for attachment with matching id IStorage *pIStorage; IUnknown *pIUnknown; BSTR bstrId = SysAllocString(wstrValue.c_str()); BSTR bstrType; long lTNF; VARIANT_BOOL bResult; _variant_t varOptions; pIwmsoapmsg->GetDIMEAttachmentReq( bstrId, &bstrType, &lTNF, &pIUnknown, &varOptions, &bResult); if (bResult == VARIANT_FALSE) { // no such attachment return false; } // found referenced attachment, get interface ptr HRESULT res = pIUnknown->QueryInterface(IID_IStorage, (void **)&pIStorage); if (FAILED(res)) { return false; } string strId, strType; WideStringToUTF8(wstring(bstrId), strId); WideStringToUTF8(wstring(bstrType), strType); // wrap it DIMEPayload *pPayload = new DIMEPayload(pIStorage, strId, strType, lTNF); pIStorage->Release(); pPayload->OpenForRead(); unsigned long ulNumBytesRead = 0; unsigned long ulLength = pPayload->GetDataLength(); unsigned char *pBuffer = (unsigned char *)malloc(ulLength); pPayload->Read((char *)pBuffer, ulLength, &ulNumBytesRead); pPayload->Close(); delete pPayload; // MIME type? map mapParams; string strMIMEType; ParseMIMEType( strType, strMIMEType, mapParams); if (strMIMEType.find("TEXT/") != 0) { return false; } // charset param? string strCharset = "US-ASCII"; map::iterator iM; if ((iM = mapParams.find(string("CHARSET"))) != mapParams.end()) { strCharset = iM->second; // charset value is not case sensitive for (string::size_type i = 0; i < strCharset.length(); i++) { // force to uppercase... comparisons are case-insensitive strCharset[i] = toupper(strCharset[i]); } } if (strCharset == "UTF-16") { wstrStringOut.append((wchar_t *)pBuffer, ulLength / 2); } else if (strCharset == "UTF-8" || strCharset == "US-ASCII") { string strTemp((char *)pBuffer, ulLength); UTF8ToWideString(strTemp, wstrStringOut); } // store id string arrAttachments.push_back(wstrId); } } goto response; } response: delete pRoot; // create response long lSOAPVersion; pIwmsoapmsg->GetSOAPVersion(&lSOAPVersion); WMXMLElement *pBody = new WMXMLElement(wstring(L"SOAP-ENV:Body")); if (pBody != NULL) { if (lSOAPVersion == SOAP_VERSION_1_1) { pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoapEnvelopeNS)); } else { pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS)); } if (bEchoAttachmentElemFound == true) { WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:EchoAttachmentResponse")); if (pElem != NULL) { pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pElem); WMXMLElement *pItem = new WMXMLElement(wstring(L"iop:Out")); if (pItem != NULL && arrAttachments.size() > 0) { pItem->SetAttribute(wstring(L"ref:location"), arrAttachments[0]); pItem->SetNSPrefix(wstring(L"ref"), wstring(g_pwszRefNS)); pElem->AddChildElement(pItem); } } } else if (bEchoAttachmentsElemFound == true) { WMXMLElement *pList = new WMXMLElement(wstring(L"iop:EchoAttachmentsResponse")); if (pList != NULL) { pList->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pList); for (unsigned int i = 0; i < arrAttachments.size(); i++) { WMXMLElement *pItem = new WMXMLElement(wstring(L"iop:Item")); if (pItem != NULL) { pItem->SetAttribute(wstring(L"ref:location"), arrAttachments[i]); pItem->SetNSPrefix(wstring(L"ref"), wstring(g_pwszRefNS)); pList->AddChildElement(pItem); } } } } else if (bEchoAttachmentAsBase64ElemFound == true) { WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:EchoAttachmentAsBase64Response")); if (pElem != NULL) { pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pElem); WMXMLElement *pItem = new WMXMLElement(wstring(L"iop:Out")); if (pItem != NULL) { pItem->SetContent(wstrBase64Encoded); pElem->AddChildElement(pItem); } } } else if (bEchoBase64AsAttachmentElemFound == true) { WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:EchoBase64AsAttachmentResponse")); if (pElem != NULL) { pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pElem); WMXMLElement *pItem = new WMXMLElement(wstring(L"iop:Out")); if (pItem != NULL && arrAttachments.size() > 0) { pItem->SetAttribute(wstring(L"ref:location"), arrAttachments[0]); pItem->SetNSPrefix(wstring(L"ref"), wstring(g_pwszRefNS)); pElem->AddChildElement(pItem); } } } else if (bEchoUnrefAttachmentsElemFound == true) { WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:EchoUnrefAttachmentsResponse")); if (pElem != NULL) { pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pElem); } } else if (bAttachmentAsStringElemFound == true) { WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:EchoAttachmentAsStringResponse")); if (pElem != NULL) { pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS)); pBody->AddChildElement(pElem); WMXMLElement *pItem = new WMXMLElement(wstring(L"iop:Out")); if (pItem != NULL) { pItem->SetContent(wstrStringOut); pElem->AddChildElement(pItem); } } } // finish up BSTR bstrXML = pBody->Serialize(NULL); BSTR bstrEncodingStyle = SysAllocString(L""); pIwmsoapmsg->SetBodyElemLiteral(bstrXML, bstrEncodingStyle, &bResult); SysFreeString(bstrXML); SysFreeString(bstrEncodingStyle); delete pBody; } return true; } bool CinteropsvcdimedocObj::GenerateFault(Iwmsoapmsg2 *pIwmsoapmsg) { long lSOAPVersion; pIwmsoapmsg->GetSOAPVersion(&lSOAPVersion); BSTR bstrFaultcode, bstrFaultcodeNS; if (lSOAPVersion == SOAP_VERSION_1_1) { bstrFaultcode = SysAllocString(L"Client"); bstrFaultcodeNS = SysAllocString(g_pwszSoapEnvelopeNS); } else { bstrFaultcode = SysAllocString(L"Sender"); bstrFaultcodeNS = SysAllocString(g_pwszSoap12EnvelopeNS); } BSTR bstrFaultstring = SysAllocString(L"Message processing failed."); VARIANT_BOOL bNeedDetail = VARIANT_TRUE; VARIANT_BOOL bResult = VARIANT_FALSE; pIwmsoapmsg->SetSOAPFault(bstrFaultcode, bstrFaultcodeNS, bstrFaultstring, bNeedDetail, &bResult); SysFreeString(bstrFaultcode); SysFreeString(bstrFaultcodeNS); SysFreeString(bstrFaultstring); return true; }