Support unrar64.dll
[xy_vsfilter.git] / include / atl / atlsoap.h
blobb286e7c61542ab4dde0749f527f5b693d4bcf956
1 // This is a part of the Active Template Library.
2 // Copyright (C) Microsoft Corporation
3 // All rights reserved.
4 //
5 // This source code is only intended as a supplement to the
6 // Active Template Library Reference and related
7 // electronic documentation provided with the library.
8 // See these sources for detailed information regarding the
9 // Active Template Library product.
11 #ifndef __ATLSOAP_H__
12 #define __ATLSOAP_H__
14 #pragma once
16 #if (defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_))
17 #error require winsock2.h -- include <winsock2.h> before you include <windows.h>
18 #endif
20 #if ((_WIN32_WINNT < 0x0400) && (_WIN32_WINDOWS <= 0x0400))
21 #error require _WIN32_WINNT >= 0x0400 or _WIN32_WINDOWS > 0x0400
22 #endif
24 #ifndef ATLSOAP_TRACE
25 #ifdef _ATLSOAP_TRACE_XML
26 #define ATLSOAP_TRACE(__data, __len) AtlSoapTraceXML(__data, __len)
27 #else
28 #define ATLSOAP_TRACE(__data, __len) __noop
29 #endif
30 #endif // ATLSOAP_TRACE
32 // override this macro to ATL_BASE64_FLAG_NOCRLF if you do
33 // not want Base64-encoded binary data to contain CRLFs
34 #ifndef ATLSOAP_BASE64_FLAGS
35 #define ATLSOAP_BASE64_FLAGS ATL_BASE64_FLAG_NONE
36 #endif // ATLSOAP_BASE64_FLAGS
38 [ emitidl(restricted) ];
39 #include <winsock2.h>
40 #include <atlstr.h>
41 #include <atlcoll.h>
42 #include <atlbase.h>
43 #include <msxml2.h>
44 #include <atlenc.h>
45 #include <fcntl.h>
46 #include <float.h>
47 #include <math.h>
48 #include <limits>
49 #include <atlisapi.h>
50 #include <atlstencil.h>
51 #include <atlhttp.h>
52 #include <atlhttp.inl>
54 #pragma warning(push)
55 #pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible
56 #pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible
57 #pragma warning(disable: 4061) // enumerate 'enum value' in switch of enum 'enum type' is not explicitly handled by a case label
59 #ifndef _CPPUNWIND
60 #pragma warning(disable: 4702) // unreachable code
61 #endif // _CPPUNWIND
63 #ifndef ATLSOAP_NOWININET
64 #include <wininet.h>
65 #ifndef ATLSOAPINET_CLIENT
66 #define ATLSOAPINET_CLIENT _T("VCSoapClient")
67 #endif
68 #endif
70 #ifndef _ATL_NO_DEFAULT_LIBS
71 #pragma comment(lib, "msxml2.lib")
72 #ifndef ATLSOAP_NOWININET
73 #pragma comment(lib, "wininet.lib")
74 #endif
75 #endif
77 #define _ATLSOAP_MAKEWIDESTR( str ) L ## str
78 #define ATLSOAP_MAKEWIDESTR( str ) _ATLSOAP_MAKEWIDESTR( str )
81 #pragma pack(push,_ATL_PACKING)
82 namespace ATL
85 ATL_NOINLINE inline void AtlSoapTraceXML(LPBYTE pdwData, DWORD dwLen)
87 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
88 if (hStdOut != INVALID_HANDLE_VALUE)
90 DWORD dwWritten;
91 WriteFile(hStdOut,
92 "\n-----------------------------------------------------------------\n",
93 sizeof("\n-----------------------------------------------------------------\n")-1,
94 &dwWritten, NULL);
96 WriteFile(hStdOut, pdwData, dwLen, &dwWritten, NULL);
98 WriteFile(hStdOut,
99 "\n-----------------------------------------------------------------\n",
100 sizeof("\n-----------------------------------------------------------------\n")-1,
101 &dwWritten, NULL);
105 ////////////////////////////////////////////////////////////////////////////////
107 // IStreamImpl - stub IStream implementation class
109 ////////////////////////////////////////////////////////////////////////////////
111 class IStreamImpl : public IStream
113 public:
115 HRESULT __stdcall Read(void * /*pDest*/, ULONG /*nMaxLen*/, ULONG * /*pnRead*/)
117 return E_NOTIMPL;
120 HRESULT __stdcall Write(const void * /*pv*/, ULONG /*cb*/, ULONG * /*pcbWritten*/)
122 return E_NOTIMPL;
125 HRESULT __stdcall Seek(LARGE_INTEGER /*dlibMove*/, DWORD /*dwOrigin*/,
126 ULARGE_INTEGER * /*pLibNewPosition*/)
128 return E_NOTIMPL;
131 HRESULT __stdcall SetSize(ULARGE_INTEGER /*libNewSize*/)
133 return E_NOTIMPL;
136 HRESULT __stdcall CopyTo(IStream * /*pStream*/, ULARGE_INTEGER /*cb*/,
137 ULARGE_INTEGER * /*pcbRead*/, ULARGE_INTEGER * /*pcbWritten*/)
139 return E_NOTIMPL;
142 HRESULT __stdcall Commit(DWORD /*grfCommitFlags*/)
144 return E_NOTIMPL;
147 HRESULT __stdcall Revert()
149 return E_NOTIMPL;
152 HRESULT __stdcall LockRegion(ULARGE_INTEGER /*libOffset*/, ULARGE_INTEGER /*cb*/, DWORD /*dwLockType*/)
154 return E_NOTIMPL;
157 HRESULT __stdcall UnlockRegion(ULARGE_INTEGER /*libOffset*/, ULARGE_INTEGER /*cb*/, DWORD /*dwLockType*/)
159 return E_NOTIMPL;
162 HRESULT __stdcall Stat(STATSTG * /*pstatstg*/, DWORD /*grfStatFlag*/)
164 return E_NOTIMPL;
167 HRESULT __stdcall Clone(IStream ** /*ppstm*/)
169 return E_NOTIMPL;
171 }; // class IStreamImpl
173 ////////////////////////////////////////////////////////////////////////////////
175 // CStreamOnServerContext
177 ////////////////////////////////////////////////////////////////////////////////
179 class CStreamOnServerContext : public IStreamImpl
181 public:
183 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
185 if (ppv == NULL)
187 return E_POINTER;
190 *ppv = NULL;
192 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
193 InlineIsEqualGUID(riid, IID_IStream) ||
194 InlineIsEqualGUID(riid, IID_ISequentialStream))
196 *ppv = static_cast<IStream *>(this);
197 return S_OK;
200 return E_NOINTERFACE;
203 ULONG __stdcall AddRef()
205 return 1;
208 ULONG __stdcall Release()
210 return 1;
213 private:
215 IHttpServerContext * m_pServerContext;
216 DWORD m_dwBytesRead;
218 public:
220 CStreamOnServerContext(IHttpServerContext *pServerContext = NULL)
221 : m_pServerContext(pServerContext), m_dwBytesRead(0)
225 void SetServerContext(IHttpServerContext *pServerContext)
227 ATLASSUME( m_pServerContext == NULL );
229 m_pServerContext = pServerContext;
232 HRESULT __stdcall Read(void *pDest, ULONG nMaxLen, ULONG *pnRead)
234 ATLENSURE( pDest != NULL );
235 ATLASSUME( m_pServerContext != NULL );
237 DWORD dwToRead = __min(m_pServerContext->GetTotalBytes()-m_dwBytesRead, nMaxLen);
238 if (ReadClientData(m_pServerContext, (LPSTR) pDest, &dwToRead, m_dwBytesRead) != FALSE)
240 m_dwBytesRead+= dwToRead;
242 if (pnRead != NULL)
244 *pnRead = dwToRead;
247 return S_OK;
250 ATLTRACE( _T("ATLSOAP: CStreamOnServerContext::Read -- ReadClientData failed.\r\n") );
252 return E_FAIL;
254 }; // class CStreamOnServerContext
256 ////////////////////////////////////////////////////////////////////////////////
258 // CReadStreamOnSocket
260 ////////////////////////////////////////////////////////////////////////////////
262 template <typename TSocketClass>
263 class CReadStreamOnSocket : public IStreamImpl
265 public:
267 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
269 if (ppv == NULL)
271 return E_POINTER;
274 *ppv = NULL;
276 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
277 InlineIsEqualGUID(riid, IID_IStream) ||
278 InlineIsEqualGUID(riid, IID_ISequentialStream))
280 *ppv = static_cast<IStream *>(this);
281 return S_OK;
284 return E_NOINTERFACE;
287 ULONG __stdcall AddRef()
289 return 1;
292 ULONG __stdcall Release()
294 return 1;
297 private:
299 CAtlHttpClientT<TSocketClass> * m_pSocket;
300 LPCSTR m_szBuffer;
301 LPCSTR m_szCurr;
302 long m_nBodyLen;
304 public:
306 CReadStreamOnSocket()
307 : m_pSocket(NULL), m_szBuffer(NULL), m_szCurr(NULL), m_nBodyLen(0)
311 BOOL Init(CAtlHttpClientT<TSocketClass> *pSocket)
313 ATLENSURE( pSocket != NULL );
315 m_pSocket = pSocket;
316 m_szBuffer = (LPCSTR) pSocket->GetBody();
318 ATLSOAP_TRACE( (LPBYTE) pSocket->GetBody(), pSocket->GetBodyLength() );
320 if (m_szBuffer != NULL)
322 m_szCurr = m_szBuffer;
323 m_nBodyLen = pSocket->GetBodyLength();
324 if (m_nBodyLen != 0)
326 return TRUE;
330 ATLTRACE( _T("ATLSOAP: CReadStreamOnSocket::Init failed.\r\n") );
332 return FALSE;
335 HRESULT __stdcall Read(void *pDest, ULONG nMaxLen, ULONG *pnRead)
337 ATLASSERT( pDest != NULL );
338 ATLASSUME( m_pSocket != NULL );
339 ATLASSUME( m_szBuffer != NULL );
341 if (pnRead != NULL)
343 *pnRead = 0;
346 long nRead = (int) (m_szCurr-m_szBuffer);
347 if (nRead < m_nBodyLen)
349 long nLength = __min((int)(m_nBodyLen-nRead), (LONG) nMaxLen);
350 Checked::memcpy_s(pDest, nMaxLen, m_szCurr, nLength);
351 m_szCurr+= nLength;
353 if (pnRead != NULL)
355 *pnRead = (ULONG) nLength;
359 return S_OK;
361 }; // class CReadStreamOnSocket
363 ////////////////////////////////////////////////////////////////////////////////
365 // CWriteStreamOnCString
367 ////////////////////////////////////////////////////////////////////////////////
369 class CWriteStreamOnCString : public IWriteStream
372 public:
373 CStringA m_str;
375 virtual ~CWriteStreamOnCString()
379 HRESULT WriteStream(LPCSTR szOut, int nLen, LPDWORD pdwWritten)
381 ATLENSURE_RETURN( szOut != NULL );
383 if (nLen < 0)
385 nLen = (int) strlen(szOut);
388 _ATLTRY
390 m_str.Append(szOut, nLen);
392 _ATLCATCHALL()
394 return E_OUTOFMEMORY;
397 if (pdwWritten != NULL)
399 *pdwWritten = (DWORD) nLen;
402 return S_OK;
405 HRESULT FlushStream()
407 return S_OK;
410 void Cleanup()
412 m_str.Empty();
414 }; // class CWriteStreamOnCString
416 ////////////////////////////////////////////////////////////////////////////////
418 // Namespaces
420 ////////////////////////////////////////////////////////////////////////////////
422 #define SOAPENV_NAMESPACEA "http://schemas.xmlsoap.org/soap/envelope/"
423 #define SOAPENV_NAMESPACEW ATLSOAP_MAKEWIDESTR( SOAPENV_NAMESPACEA )
425 #define SOAPENC_NAMESPACEA "http://schemas.xmlsoap.org/soap/encoding/"
426 #define SOAPENC_NAMESPACEW ATLSOAP_MAKEWIDESTR( SOAPENC_NAMESPACEA )
428 #define XSI_NAMESPACEA "http://www.w3.org/2001/XMLSchema-instance"
429 #define XSI_NAMESPACEW ATLSOAP_MAKEWIDESTR( XSI_NAMESPACEA )
431 #define XSD_NAMESPACEA "http://www.w3.org/2001/XMLSchema"
432 #define XSD_NAMESPACEW ATLSOAP_MAKEWIDESTR( XSD_NAMESPACEA )
434 #ifndef ATLSOAP_GENERIC_NAMESPACE
435 #define ATLSOAP_GENERIC_NAMESPACE L"http://www.tempuri.org"
436 #endif
438 ////////////////////////////////////////////////////////////////////////////////
440 // Helpers
442 ////////////////////////////////////////////////////////////////////////////////
444 inline HRESULT GetAttribute(
445 __in ISAXAttributes *pAttributes,
446 __in_ecount(cchName) const wchar_t *wszAttrName, __in int cchName,
447 __out_ecount_part(*pcchValue, *pcchValue) const wchar_t **pwszValue, __inout int *pcchValue,
448 __in_ecount_opt(cchNamespace) wchar_t *wszNamespace = NULL, __in int cchNamespace = 0)
450 if (!pAttributes || !wszAttrName || !pwszValue || !pcchValue)
452 return E_INVALIDARG;
455 *pwszValue = NULL;
456 *pcchValue = 0;
457 if (!wszNamespace)
459 return (pAttributes->getValueFromQName(wszAttrName, cchName, pwszValue, pcchValue) == S_OK ? S_OK : E_FAIL);
461 return (pAttributes->getValueFromName(wszNamespace, cchNamespace,
462 wszAttrName, cchName, pwszValue, pcchValue) == S_OK ? S_OK : E_FAIL);
465 inline HRESULT GetAttribute(
466 __in ISAXAttributes *pAttributes,
467 __in_ecount(cchName) const wchar_t *wszAttrName, __in int cchName,
468 __inout CStringW &strValue,
469 __in_ecount_opt(cchNamespace) wchar_t *wszNamespace = NULL, __in int cchNamespace = 0)
471 const wchar_t *wszValue = NULL;
472 int cchValue = 0;
474 if (!pAttributes || !wszAttrName)
476 return E_INVALIDARG;
479 HRESULT hr;
480 if (!wszNamespace)
482 hr = (pAttributes->getValueFromQName(wszAttrName, cchName, &wszValue, &cchValue) == S_OK ? S_OK : E_FAIL);
484 else
486 hr = (pAttributes->getValueFromName(wszNamespace, cchNamespace,
487 wszAttrName, cchName, &wszValue, &cchValue) == S_OK ? S_OK : E_FAIL);
490 if (hr == S_OK)
492 _ATLTRY
494 strValue.SetString(wszValue, cchValue);
496 _ATLCATCHALL()
498 ATLTRACE( _T("ATLSOAP: GetAttribute -- out of memory.\r\n") );
500 hr = E_OUTOFMEMORY;
504 return hr;
507 inline const wchar_t *SkipWhitespace(const wchar_t *wsz)
509 while (*wsz && iswspace(*wsz))
510 ++wsz;
511 return wsz;
514 } // namespace ATL
515 #pragma pack(pop)
517 ////////////////////////////////////////////////////////////////////////////////
519 // BLOB data type - use this struct when you want to send BLOB data
520 // the attribute provider and proxy generator will only properly special
521 // case blob data when using this struct.
523 ////////////////////////////////////////////////////////////////////////////////
525 [ export ]
526 typedef struct _tagATLSOAP_BLOB
528 unsigned long size;
529 unsigned char *data;
530 } ATLSOAP_BLOB;
532 #ifndef _ATL_SOAP_NO_PARAMETER_VALIDATIONS
533 #define _ATL_VALIDATE_PARAMETER_END(p)\
534 do \
536 if(*(p) !='\0') \
537 return E_FAIL; \
538 } while(0)
539 #else
540 #define _ATL_VALIDATE_PARAMETER_END(p)
541 #endif
543 // All non-integral types have specializations which
544 // will be called. The following function will be called
545 // only for integral types
547 #pragma push_macro("max")
548 #pragma push_macro("min")
549 #undef max
550 #undef min
551 template <typename T>
552 inline HRESULT AtlGetSAXValue(T * pVal , const wchar_t * wsz , int cch )
554 __int64 nVal = *pVal;
555 if (FAILED(AtlGetSAXValue(&nVal, wsz, cch)))
556 return E_FAIL;
558 #ifndef _ATL_SOAP_NO_PARAMETER_VALIDATIONS
559 if(nVal < std::numeric_limits<T>::min() || nVal > std::numeric_limits<T>::max())
560 return E_FAIL;
561 #endif
563 *pVal = T(nVal);
564 return S_OK;
568 #pragma pop_macro("max")
569 #pragma pop_macro("min")
571 ////////////////////////////////////////////////////////////////////////////////
573 // AtlGetXMLValue (for IXMLDOMDocument) - get the real type from the XML data
575 ///////////////////////////////////////////////////////////////////////////////
578 // generic IXMLDOMNode template function
579 // delegates to AtlGetSAXValue
581 template <typename T>
582 inline HRESULT AtlGetXMLValue(IXMLDOMNode *pParam, T *pVal)
584 CComBSTR bstrVal;
585 HRESULT hr = AtlGetXMLValue(pParam, &bstrVal);
586 if (SUCCEEDED(hr))
588 hr = AtlGetSAXValue(pVal, bstrVal, bstrVal.Length());
591 return hr;
594 // specialization for BSTR
595 template <>
596 inline HRESULT AtlGetXMLValue<BSTR>(IXMLDOMNode *pParam, BSTR *pbstrVal)
598 if (pParam == NULL)
600 return E_INVALIDARG;
602 if (pbstrVal == NULL)
604 return E_POINTER;
607 CComPtr<IXMLDOMNode> spChild;
608 if (pParam->get_firstChild(&spChild) == S_OK)
610 CComPtr<IXMLDOMNode> spXmlChild;
611 if (spChild->get_firstChild(&spXmlChild) == S_OK)
613 return (pParam->get_xml(pbstrVal) == S_OK ? S_OK : E_FAIL);
617 return (pParam->get_text(pbstrVal) == S_OK) ? S_OK : E_FAIL;
620 ////////////////////////////////////////////////////////////////////////////////
622 // AtlGetSAXValue - (for SAX or generic) get the real type from the XML data
624 ////////////////////////////////////////////////////////////////////////////////
626 template <>
627 inline HRESULT AtlGetSAXValue<bool>(bool *pVal, __in_z const wchar_t *wsz, int cch)
629 ATLENSURE( wsz != NULL );
631 if (!pVal)
633 return E_POINTER;
636 *pVal = false;
638 HRESULT hr = E_FAIL;
639 switch (wsz[0])
641 case L'1':
643 if (cch==1)
645 *pVal = true;
646 hr = S_OK;
648 break;
650 case L'0':
652 if (cch==1)
654 *pVal = false;
655 hr = S_OK;
657 break;
659 case L't':
661 if (cch==sizeof("true")-1 && !wcsncmp(wsz, L"true", cch))
663 *pVal = true;
664 hr = S_OK;
666 break;
668 case L'f':
670 if (cch==sizeof("false")-1 && !wcsncmp(wsz, L"false", cch))
672 *pVal = false;
673 hr = S_OK;
675 break;
679 return hr;
682 template <>
683 inline HRESULT AtlGetSAXValue<__int64>(__int64 *pVal, __in_z const wchar_t *wsz, int cch)
685 ATLENSURE_RETURN( wsz != NULL );
687 if (!pVal)
689 return E_POINTER;
692 _ATLTRY
694 CFixedStringT<CStringW, 1024> wstr(wsz, cch);
695 const wchar_t *pStart = ATL::SkipWhitespace(static_cast<LPCWSTR>(wstr));
696 const wchar_t *pEnd;
698 __int64 i = 0;
699 errno_t errnoValue = AtlStrToNum(&i, pStart, const_cast<wchar_t **>(&pEnd), 10);
700 if (errnoValue == ERANGE)
702 return E_FAIL;//overflow or underflow case
704 pEnd = ATL::SkipWhitespace(pEnd);
705 _ATL_VALIDATE_PARAMETER_END(pEnd);
706 *pVal = i;
708 _ATLCATCHALL()
710 return E_OUTOFMEMORY;
713 return S_OK;
716 template <>
717 inline HRESULT AtlGetSAXValue<unsigned __int64>(unsigned __int64 *pVal, __in_z const wchar_t *wsz, int cch)
719 ATLENSURE_RETURN( wsz != NULL );
721 if (!pVal)
723 return E_POINTER;
726 _ATLTRY
728 CFixedStringT<CStringW, 1024> wstr(wsz, cch);
729 const wchar_t *pStart = ATL::SkipWhitespace(static_cast<LPCWSTR>(wstr));
730 const wchar_t *pEnd;
732 unsigned __int64 i = 0;
733 errno_t errnoValue = AtlStrToNum(&i, pStart, const_cast<wchar_t **>(&pEnd), 10);
734 if (errnoValue == ERANGE)
736 return E_FAIL;//overflow or underflow case
738 pEnd = ATL::SkipWhitespace(pEnd);
739 _ATL_VALIDATE_PARAMETER_END(pEnd);
740 *pVal = i;
742 _ATLCATCHALL()
744 return E_OUTOFMEMORY;
747 return S_OK;
749 template <>
750 inline HRESULT AtlGetSAXValue<double>(double *pVal, __in_z const wchar_t *wsz, int cch)
752 ATLENSURE_RETURN( wsz != NULL );
754 if (!pVal)
756 return E_POINTER;
759 if ((cch == 3) && (wsz[0]==L'I') && (!wcsncmp(wsz, L"INF", cch)))
761 *(((int *) pVal)+0) = 0x0000000;
762 *(((int *) pVal)+1) = 0x7FF00000;
764 else if ((cch == 3) && (wsz[0]==L'N') && (!wcsncmp(wsz, L"NaN", cch)))
766 *(((int *) pVal)+0) = 0x0000000;
767 *(((int *) pVal)+1) = 0xFFF80000;
769 else if ((cch == 4) && (wsz[1]==L'I') && (!wcsncmp(wsz, L"-INF", cch)))
771 *(((int *) pVal)+0) = 0x0000000;
772 *(((int *) pVal)+1) = 0xFFF00000;
774 else
776 errno_t errnoValue = 0;
778 _ATLTRY
780 CFixedStringT<CStringW, 1024> wstr(wsz, cch);
781 const wchar_t *pStart = ATL::SkipWhitespace(static_cast<LPCWSTR>(wstr));
782 const wchar_t *pEnd;
783 double d = 0.0;
784 errnoValue = AtlStrToNum(&d, pStart, const_cast<wchar_t **>(&pEnd));
785 pEnd = ATL::SkipWhitespace(pEnd);
786 _ATL_VALIDATE_PARAMETER_END(pEnd);
787 *pVal = d;
789 _ATLCATCHALL()
791 return E_OUTOFMEMORY;
794 if ((*pVal == -HUGE_VAL) || (*pVal == HUGE_VAL) || (errnoValue == ERANGE))
796 return E_FAIL;
800 return S_OK;
803 template <>
804 inline HRESULT AtlGetSAXValue<float>(float *pVal, __in_z const wchar_t *wsz, int cch)
806 ATLASSERT( wsz != NULL );
808 if (!pVal)
810 return E_POINTER;
813 double d = *pVal;
814 if (SUCCEEDED(AtlGetSAXValue(&d, wsz, cch)))
816 #ifdef _ATL_SOAP_PARAMETER_VALIDATIONS
817 if(d > FLT_MAX || d < -FLT_MAX)
818 return E_FAIL;
819 #endif
820 *pVal = (float) d;
821 return S_OK;
824 return E_FAIL;
827 template <>
828 inline HRESULT AtlGetSAXValue<BSTR>(BSTR *pVal, __in_z const wchar_t *wsz, int cch)
830 ATLASSERT( wsz != NULL );
832 if (pVal == NULL)
834 return E_POINTER;
837 *pVal = SysAllocStringLen(wsz, cch);
839 return ((*pVal != NULL) ? S_OK : E_OUTOFMEMORY);
842 inline HRESULT AtlGetSAXBlobValue(
843 ATLSOAP_BLOB *pVal,
844 const wchar_t *wsz,
845 int cch,
846 IAtlMemMgr *pMemMgr,
847 bool bHex = false)
849 ATLENSURE_RETURN( wsz != NULL );
850 ATLENSURE_RETURN( pMemMgr != NULL );
852 if (pVal == NULL)
854 return E_POINTER;
857 if (pVal->data != NULL)
859 return E_INVALIDARG;
862 pVal->data = NULL;
863 pVal->size = 0;
865 int nLength = AtlUnicodeToUTF8(wsz, cch, NULL, 0);
867 if (nLength != 0)
869 char * pSrc = (char *) pMemMgr->Allocate(nLength);
870 if (pSrc != NULL)
872 nLength = AtlUnicodeToUTF8(wsz, cch, pSrc, nLength);
873 if (nLength != 0)
875 pVal->data = (unsigned char *) pMemMgr->Allocate(nLength);
876 if (pVal->data != NULL)
878 BOOL bRet;
879 int nDataLength = nLength;
880 if (!bHex)
882 bRet = Base64Decode(pSrc, nLength, pVal->data, &nDataLength);
884 else
886 bRet = AtlHexDecode(pSrc, nLength, pVal->data, &nDataLength);
888 if (bRet)
890 pVal->size = nDataLength;
895 pMemMgr->Free(pSrc);
899 if (pVal->size == 0)
901 if (pVal->data != NULL)
903 pMemMgr->Free(pVal->data);
904 pVal->data = NULL;
908 return S_OK;
911 ////////////////////////////////////////////////////////////////////////////////
913 // AtlGenXMLValue template and specializations
915 ////////////////////////////////////////////////////////////////////////////////
917 template <typename T>
918 inline HRESULT AtlGenXMLValue(__in IWriteStream *pStream, __in T *pVal)
920 if ((pStream == NULL) || (pVal == NULL))
922 return E_INVALIDARG;
926 // delegate to CWriteStreamHelper
928 CWriteStreamHelper s(pStream);
930 return (s.Write(*pVal) == TRUE ? S_OK : E_FAIL);
933 #ifdef _NATIVE_WCHAR_T_DEFINED
934 template <>
935 inline HRESULT AtlGenXMLValue<wchar_t>(__in IWriteStream *pStream, __in wchar_t *pVal)
937 return AtlGenXMLValue(pStream, (unsigned short *)pVal);
939 #endif
941 template <>
942 inline HRESULT AtlGenXMLValue<wchar_t *>(__in IWriteStream *pStream, __deref_inout_z wchar_t **pVal)
944 if ((pStream == NULL) || (*pVal == NULL))
946 return E_INVALIDARG;
949 wchar_t *wszWrite = *pVal;
950 int nSrcLen = (int)wcslen(*pVal);
951 int nCnt = EscapeXML(*pVal, nSrcLen, NULL, 0);
952 if (nCnt > nSrcLen)
954 nCnt++;
955 wszWrite = (wchar_t *)calloc((nCnt),sizeof(wchar_t));
956 if (wszWrite == NULL)
958 return E_OUTOFMEMORY;
961 nCnt = EscapeXML(*pVal, nSrcLen, wszWrite, nCnt);
962 if (nCnt == 0)
964 free(wszWrite);
965 return E_FAIL;
967 wszWrite[nCnt] = L'\0';
968 nSrcLen = nCnt;
971 nCnt = AtlUnicodeToUTF8(wszWrite, nSrcLen, NULL, 0);
972 HRESULT hr = E_FAIL;
973 if ((nCnt == 0) || (nCnt == nSrcLen))
975 CWriteStreamHelper s(pStream);
977 hr = (s.Write(wszWrite) == TRUE ? S_OK : E_FAIL);
979 else
981 nCnt++;
982 CHeapPtr<char> szWrite;
983 szWrite.AllocateBytes((size_t)(nCnt));
984 if (szWrite != NULL)
986 nCnt = AtlUnicodeToUTF8(wszWrite, nSrcLen, szWrite, nCnt);
987 if (nCnt != 0)
989 hr = pStream->WriteStream(szWrite, nCnt, NULL);
992 else
994 ATLTRACE( _T("ATLSOAP: AtlGenXMLValue<wchar_t *> -- out of memory.\r\n") );
996 hr = E_OUTOFMEMORY;
1000 if (wszWrite != *pVal)
1002 free(wszWrite);
1005 return hr;
1008 template <>
1009 inline HRESULT AtlGenXMLValue<double>(IWriteStream *pStream, double *pVal)
1011 if ((pStream == NULL) || (pVal == NULL))
1013 return E_INVALIDARG;
1016 HRESULT hr;
1017 switch (_fpclass(*pVal))
1019 case _FPCLASS_SNAN:
1020 case _FPCLASS_QNAN:
1022 hr = pStream->WriteStream("NaN", 3, NULL);
1023 break;
1025 case _FPCLASS_NINF:
1027 hr = pStream->WriteStream("-INF", 4, NULL);
1028 break;
1030 case _FPCLASS_PINF:
1032 hr = pStream->WriteStream("INF", 3, NULL);
1033 break;
1035 case _FPCLASS_NZ:
1037 hr = pStream->WriteStream("-0", 2, NULL);
1038 break;
1040 default:
1042 /***
1043 * 2 = sign + decimal point
1044 * ndec = decimal digits
1045 * 5 = exponent letter (e or E), exponent sign, three digits exponent
1046 * 1 = extra space for rounding
1047 * 1 = string terminator '\0'
1048 ***/
1049 const int ndec = 512;
1050 CHAR szBuf[ndec+9];
1051 szBuf[0] = '\0';
1052 Checked::gcvt_s(szBuf, _countof(szBuf), *pVal, ndec);
1053 size_t nLen = strlen(szBuf);
1054 if (nLen && szBuf[nLen-1] == '.')
1056 szBuf[--nLen] = '\0';
1059 hr = pStream->WriteStream(szBuf, (int)nLen, NULL);
1060 break;
1064 return hr;
1067 template <>
1068 inline HRESULT AtlGenXMLValue<float>(IWriteStream *pStream, float *pVal)
1070 if ((pStream == NULL) || (pVal == NULL))
1072 return E_INVALIDARG;
1075 double d = *pVal;
1077 return AtlGenXMLValue(pStream, &d);
1080 template <>
1081 inline HRESULT AtlGenXMLValue<bool>(IWriteStream *pStream, bool *pVal)
1083 if ((pStream == NULL) || (pVal == NULL))
1085 return E_INVALIDARG;
1088 if (*pVal == true)
1090 return pStream->WriteStream("true", sizeof("true")-1, NULL);
1093 return pStream->WriteStream("false", sizeof("false")-1, NULL);
1096 inline HRESULT AtlGenXMLBlobValue(
1097 IWriteStream *pStream,
1098 ATLSOAP_BLOB *pVal,
1099 IAtlMemMgr *pMemMgr,
1100 bool bHex = false)
1102 if ((pStream == NULL) || (pVal == NULL) || (pMemMgr == NULL))
1104 return E_INVALIDARG;
1107 HRESULT hr = E_FAIL;
1108 int nLength;
1109 if (!bHex)
1111 nLength = Base64EncodeGetRequiredLength(pVal->size, ATLSOAP_BASE64_FLAGS);
1113 else
1115 nLength = AtlHexEncodeGetRequiredLength(pVal->size);
1118 char *pEnc = (char *) pMemMgr->Allocate(nLength);
1119 if (pEnc != NULL)
1121 BOOL bRet;
1122 if (!bHex)
1124 bRet = Base64Encode(pVal->data, pVal->size, pEnc, &nLength, ATLSOAP_BASE64_FLAGS);
1126 else
1128 bRet = AtlHexEncode(pVal->data, pVal->size, pEnc, &nLength);
1130 if (bRet)
1132 hr = pStream->WriteStream(pEnc, nLength, NULL);
1135 pMemMgr->Free(pEnc);
1138 return hr;
1141 template <typename T>
1142 inline HRESULT AtlCleanupValue(T * /*pVal*/)
1144 return S_OK;
1147 inline HRESULT AtlCleanupBlobValue(ATLSOAP_BLOB *pVal, IAtlMemMgr *pMemMgr)
1149 if ((pVal == NULL) || (pMemMgr == NULL))
1151 return E_INVALIDARG;
1154 if (pVal->data != NULL)
1156 pMemMgr->Free(pVal->data);
1157 pVal->data = NULL;
1158 pVal->size = 0;
1161 return S_OK;
1164 template <>
1165 inline HRESULT AtlCleanupValue<ATLSOAP_BLOB>(ATLSOAP_BLOB *pVal)
1167 ATLTRACE( _T("Warning: AtlCleanupValue<ATLSOAP_BLOB> was called -- assuming CRT allocator.\r\n") );
1169 if (pVal == NULL)
1171 return E_INVALIDARG;
1174 if (pVal->data != NULL)
1176 free(pVal->data);
1177 pVal->data = NULL;
1178 pVal->size = 0;
1181 return S_OK;
1184 template <>
1185 inline HRESULT AtlCleanupValue<BSTR>(BSTR *pVal)
1187 if (pVal == NULL)
1189 // should never happen
1190 ATLASSERT( FALSE );
1191 return E_INVALIDARG;
1194 if ((*pVal) != NULL)
1196 // null strings are okay
1197 SysFreeString(*pVal);
1198 *pVal = NULL;
1201 return S_OK;
1204 template <typename T>
1205 inline HRESULT AtlCleanupValueEx(T *pVal, IAtlMemMgr *pMemMgr)
1207 pMemMgr;
1209 return AtlCleanupValue(pVal);
1212 template <>
1213 inline HRESULT AtlCleanupValueEx<ATLSOAP_BLOB>(ATLSOAP_BLOB *pVal, IAtlMemMgr *pMemMgr)
1215 return AtlCleanupBlobValue(pVal, pMemMgr);
1218 // single dimensional arrays
1219 template <typename T>
1220 inline HRESULT AtlCleanupArray(T *pArray, int nCnt)
1222 if (pArray == NULL)
1224 return E_INVALIDARG;
1227 for (int i=0; i<nCnt; i++)
1229 AtlCleanupValue(&pArray[i]);
1232 return S_OK;
1236 template <typename T>
1237 inline HRESULT AtlCleanupArrayEx(T *pArray, int nCnt, IAtlMemMgr *pMemMgr)
1239 if (pArray == NULL)
1241 return E_INVALIDARG;
1244 for (int i=0; i<nCnt; i++)
1246 AtlCleanupValueEx(&pArray[i], pMemMgr);
1249 return S_OK;
1253 // multi-dimensional arrays
1254 template <typename T>
1255 inline HRESULT AtlCleanupArrayMD(T *pArray, const int *pDims)
1257 if ((pArray == NULL) || (pDims == NULL))
1259 return E_INVALIDARG;
1262 // calculate size
1263 int nCnt = 1;
1264 for (int i=1; i<=pDims[0]; i++)
1266 nCnt*= pDims[i];
1269 return AtlCleanupArray(pArray, nCnt);
1272 template <typename T>
1273 inline HRESULT AtlCleanupArrayMDEx(T *pArray, const int *pDims, IAtlMemMgr *pMemMgr)
1275 if ((pArray == NULL) || (pDims == NULL))
1277 return E_INVALIDARG;
1280 // calculate size
1281 int nCnt = 1;
1282 for (int i=1; i<=pDims[0]; i++)
1284 nCnt*= pDims[i];
1287 return AtlCleanupArrayEx(pArray, nCnt, pMemMgr);
1291 #pragma pack(push,_ATL_PACKING)
1292 namespace ATL
1295 ////////////////////////////////////////////////////////////////////////////////
1297 // CSAXSoapErrorHandler
1299 ////////////////////////////////////////////////////////////////////////////////
1301 class CSAXSoapErrorHandler : public ISAXErrorHandler
1303 private:
1305 CFixedStringT<CStringW, 256> m_strParseError;
1307 public:
1308 virtual ~CSAXSoapErrorHandler()
1312 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
1314 if (!ppv)
1316 return E_POINTER;
1319 if (InlineIsEqualGUID(riid, __uuidof(ISAXErrorHandler)) ||
1320 InlineIsEqualGUID(riid, __uuidof(IUnknown)))
1322 *ppv = static_cast<ISAXErrorHandler*>(this);
1323 return S_OK;
1325 return E_NOINTERFACE;
1328 ULONG __stdcall AddRef()
1330 return 1;
1333 ULONG __stdcall Release()
1335 return 1;
1338 const CStringW& GetParseError()
1340 return m_strParseError;
1343 HRESULT __stdcall error(
1344 ISAXLocator *pLocator,
1345 const wchar_t *wszErrorMessage,
1346 HRESULT hrErrorCode)
1348 (pLocator);
1349 (wszErrorMessage);
1350 (hrErrorCode);
1352 ATLTRACE( _T("ATLSOAP: parse error: %ws\r\n"), wszErrorMessage );
1354 _ATLTRY
1356 m_strParseError = wszErrorMessage;
1358 _ATLCATCHALL()
1360 return E_FAIL;
1363 return hrErrorCode;
1366 HRESULT __stdcall fatalError(
1367 ISAXLocator *pLocator,
1368 const wchar_t *wszErrorMessage,
1369 HRESULT hrErrorCode)
1371 (pLocator);
1372 (wszErrorMessage);
1373 (hrErrorCode);
1375 ATLTRACE( _T("ATLSOAP: fatal parse error: %ws\r\n"), wszErrorMessage );
1377 _ATLTRY
1379 m_strParseError = wszErrorMessage;
1381 _ATLCATCHALL()
1383 return E_FAIL;
1386 return hrErrorCode;
1389 HRESULT __stdcall ignorableWarning(
1390 ISAXLocator *pLocator,
1391 const wchar_t *wszErrorMessage,
1392 HRESULT hrErrorCode)
1394 (pLocator);
1395 (wszErrorMessage);
1396 (hrErrorCode);
1398 ATLTRACE( _T("ATLSOAP: ignorable warning: %ws\r\n"), wszErrorMessage );
1400 return hrErrorCode;
1404 ////////////////////////////////////////////////////////////////////////////////
1406 // ISAXContentHandlerImpl
1408 ////////////////////////////////////////////////////////////////////////////////
1410 class ISAXContentHandlerImpl :
1411 public ISAXContentHandler
1413 public:
1416 // ISAXContentHandler interface
1419 HRESULT __stdcall putDocumentLocator(ISAXLocator * /*pLocator*/)
1421 return S_OK;
1424 HRESULT __stdcall startDocument()
1426 return S_OK;
1429 HRESULT __stdcall endDocument()
1431 return S_OK;
1434 HRESULT __stdcall startPrefixMapping(
1435 const wchar_t * /*wszPrefix*/,
1436 int /*cchPrefix*/,
1437 const wchar_t * /*wszUri*/,
1438 int /*cchUri*/)
1440 return S_OK;
1443 HRESULT __stdcall endPrefixMapping(
1444 const wchar_t * /*wszPrefix*/,
1445 int /*cchPrefix*/)
1447 return S_OK;
1450 HRESULT __stdcall startElement(
1451 const wchar_t * /*wszNamespaceUri*/,
1452 int /*cchNamespaceUri*/,
1453 const wchar_t * /*wszLocalName*/,
1454 int /*cchLocalName*/,
1455 const wchar_t * /*wszQName*/,
1456 int /*cchQName*/,
1457 ISAXAttributes * /*pAttributes*/)
1459 return S_OK;
1462 HRESULT __stdcall endElement(
1463 const wchar_t * /*wszNamespaceUri*/,
1464 int /*cchNamespaceUri*/,
1465 const wchar_t * /*wszLocalName*/,
1466 int /*cchLocalName*/,
1467 const wchar_t * /*wszQName*/,
1468 int /*cchQName*/)
1470 return S_OK;
1473 HRESULT __stdcall characters(
1474 const wchar_t * /*wszChars*/,
1475 int /*cchChars*/)
1477 return S_OK;
1480 HRESULT __stdcall ignorableWhitespace(
1481 const wchar_t * /*wszChars*/,
1482 int /*cchChars*/)
1484 return S_OK;
1487 HRESULT __stdcall processingInstruction(
1488 const wchar_t * /*wszTarget*/,
1489 int /*cchTarget*/,
1490 const wchar_t * /*wszData*/,
1491 int /*cchData*/)
1493 return S_OK;
1496 HRESULT __stdcall skippedEntity(
1497 const wchar_t * /*wszName*/,
1498 int /*cchName*/)
1500 return S_OK;
1502 }; // class ISAXContentHandlerImpl
1504 ////////////////////////////////////////////////////////////////////////////////
1506 // SAX skip element handler utility class
1507 // (skip an element and all its child elements)
1509 ////////////////////////////////////////////////////////////////////////////////
1511 class CSkipHandler : public ISAXContentHandlerImpl
1513 public:
1514 virtual ~CSkipHandler()
1518 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
1520 if (ppv == NULL)
1522 return E_POINTER;
1525 *ppv = NULL;
1527 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
1528 InlineIsEqualGUID(riid, IID_ISAXContentHandler))
1530 *ppv = static_cast<ISAXContentHandler *>(this);
1531 return S_OK;
1534 return E_NOINTERFACE;
1537 ULONG __stdcall AddRef()
1539 return 1;
1542 ULONG __stdcall Release()
1544 return 1;
1547 private:
1549 DWORD m_dwReset;
1550 CComPtr<ISAXXMLReader> m_spReader;
1551 CComPtr<ISAXContentHandler> m_spParent;
1553 DWORD DisableReset(DWORD dwCnt = 1)
1555 m_dwReset += dwCnt;
1557 return m_dwReset;
1560 DWORD EnableReset()
1562 if (m_dwReset > 0)
1564 --m_dwReset;
1567 return m_dwReset;
1570 public:
1572 CSkipHandler(ISAXContentHandler *pParent = NULL, ISAXXMLReader *pReader = NULL)
1573 : m_spParent(pParent), m_spReader(pReader), m_dwReset(1)
1577 void SetParent(ISAXContentHandler *pParent)
1579 m_spParent = pParent;
1581 void DetachParent()
1583 m_spParent.Detach();
1586 void SetReader(ISAXXMLReader *pReader)
1588 m_spReader = pReader;
1591 HRESULT __stdcall startElement(
1592 const wchar_t * /*wszNamespaceUri*/,
1593 int /*cchNamespaceUri*/,
1594 const wchar_t * /*wszLocalName*/,
1595 int /*cchLocalName*/,
1596 const wchar_t * /*wszQName*/,
1597 int /*cchQName*/,
1598 ISAXAttributes * /*pAttributes*/)
1600 DisableReset();
1601 return S_OK;
1604 HRESULT __stdcall endElement(
1605 const wchar_t * /*wszNamespaceUri*/,
1606 int /*cchNamespaceUri*/,
1607 const wchar_t * /*wszLocalName*/,
1608 int /*cchLocalName*/,
1609 const wchar_t * /*wszQName*/,
1610 int /*cchQName*/)
1612 if (EnableReset() == 0)
1614 m_spReader->putContentHandler(m_spParent);
1617 return S_OK;
1619 }; // class CSkipHandler
1622 ////////////////////////////////////////////////////////////////////////////////
1624 // SAX string builder class
1626 ////////////////////////////////////////////////////////////////////////////////
1628 class CSAXStringBuilder : public ISAXContentHandlerImpl
1630 public:
1632 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
1634 if (ppv == NULL)
1636 return E_POINTER;
1639 *ppv = NULL;
1641 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
1642 InlineIsEqualGUID(riid, IID_ISAXContentHandler))
1644 *ppv = static_cast<ISAXContentHandler *>(this);
1645 return S_OK;
1648 return E_NOINTERFACE;
1651 ULONG __stdcall AddRef()
1653 return 1;
1656 ULONG __stdcall Release()
1658 return 1;
1661 private:
1663 ISAXContentHandler * m_pParent;
1664 ISAXXMLReader * m_pReader;
1665 DWORD m_dwReset;
1666 CFixedStringT<CStringW, 64> m_str;
1668 DWORD DisableReset(DWORD dwReset = 1)
1670 m_dwReset+= dwReset;
1672 return m_dwReset;
1675 DWORD EnableReset()
1677 if (m_dwReset > 0)
1679 --m_dwReset;
1682 return m_dwReset;
1685 public:
1687 CSAXStringBuilder(ISAXXMLReader *pReader = NULL, ISAXContentHandler *pParent = NULL)
1688 :m_pReader(pReader), m_pParent(pParent), m_dwReset(0)
1692 virtual ~CSAXStringBuilder()
1696 void SetReader(ISAXXMLReader *pReader)
1698 m_pReader = pReader;
1701 void SetParent(ISAXContentHandler *pParent)
1703 m_pParent = pParent;
1706 const CStringW& GetString()
1708 return m_str;
1711 void Clear()
1713 m_str.Empty();
1714 m_dwReset = 0;
1717 HRESULT __stdcall startElement(
1718 const wchar_t * /*wszNamespaceUri*/,
1719 int /*cchNamespaceUri*/,
1720 const wchar_t * /*wszLocalName*/,
1721 int /*cchLocalName*/,
1722 const wchar_t *wszQName,
1723 int cchQName,
1724 ISAXAttributes *pAttributes)
1726 if (m_dwReset == 0)
1728 // if there is unescaped, nested XML, must disable
1729 // an additional time for the first element
1730 DisableReset();
1732 DisableReset();
1734 int nAttrs = 0;
1735 HRESULT hr = pAttributes->getLength(&nAttrs);
1737 _ATLTRY
1739 if (SUCCEEDED(hr))
1741 m_str.Append(L"<", 1);
1742 m_str.Append(wszQName, cchQName);
1744 const wchar_t *wszAttrNamespaceUri = NULL;
1745 const wchar_t *wszAttrLocalName = NULL;
1746 const wchar_t *wszAttrQName = NULL;
1747 const wchar_t *wszAttrValue = NULL;
1748 int cchAttrUri = 0;
1749 int cchAttrLocalName = 0;
1750 int cchAttrQName = 0;
1751 int cchAttrValue = 0;
1753 for (int i=0; i<nAttrs; i++)
1755 hr = pAttributes->getName(i, &wszAttrNamespaceUri, &cchAttrUri,
1756 &wszAttrLocalName, &cchAttrLocalName, &wszAttrQName, &cchAttrQName);
1758 if (FAILED(hr))
1760 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::startElement -- MSXML error.\r\n") );
1762 break;
1765 m_str.Append(L" ", 1);
1766 m_str.Append(wszAttrQName, cchAttrQName);
1768 hr = pAttributes->getValue(i, &wszAttrValue, &cchAttrValue);
1770 if (FAILED(hr))
1772 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::startElement -- MSXML error.\r\n") );
1774 break;
1777 m_str.Append(L"=\"", sizeof("=\"")-1);
1778 if (cchAttrValue != 0)
1780 m_str.Append(wszAttrValue, cchAttrValue);
1782 m_str.Append(L"\"", 1);
1785 if (SUCCEEDED(hr))
1787 m_str.Append(L">", 1);
1791 _ATLCATCHALL()
1793 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::startElement -- out of memory.\r\n") );
1795 hr = E_OUTOFMEMORY;
1798 return hr;
1801 HRESULT __stdcall endElement(
1802 const wchar_t * wszNamespaceUri,
1803 int cchNamespaceUri,
1804 const wchar_t * wszLocalName,
1805 int cchLocalName,
1806 const wchar_t *wszQName,
1807 int cchQName)
1809 HRESULT hr = S_OK;
1810 _ATLTRY
1812 if (EnableReset() == 0)
1814 hr = m_pParent->characters((LPCWSTR) m_str, m_str.GetLength());
1815 if (SUCCEEDED(hr))
1817 hr = m_pParent->endElement(wszNamespaceUri, cchNamespaceUri,
1818 wszLocalName, cchLocalName, wszQName, cchQName);
1821 m_pReader->putContentHandler(m_pParent);
1824 if (m_dwReset > 0)
1826 m_str.Append(L"</", 2);
1827 m_str.Append(wszQName, cchQName);
1828 m_str.Append(L">", 1);
1831 _ATLCATCHALL()
1833 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::endElement -- out of memory.\r\n") );
1835 hr = E_OUTOFMEMORY;
1838 return hr;
1841 HRESULT __stdcall characters(
1842 const wchar_t *wszChars,
1843 int cchChars)
1845 _ATLTRY
1847 m_str.Append(wszChars, cchChars);
1849 _ATLCATCHALL()
1851 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::characters -- out of memory.\r\n") );
1853 return E_OUTOFMEMORY;
1856 return S_OK;
1859 HRESULT __stdcall ignorableWhitespace(
1860 const wchar_t *wszChars,
1861 int cchChars)
1863 _ATLTRY
1865 m_str.Append(wszChars, cchChars);
1867 _ATLCATCHALL()
1869 ATLTRACE( _T("ATLSOAP: CSAXStringBuilder::ignorableWhitespace -- out of memory.\r\n") );
1871 return E_OUTOFMEMORY;
1874 return S_OK;
1876 }; // class CSAXStringBuilder
1878 } // namespace ATL
1879 #pragma pack(pop)
1881 ////////////////////////////////////////////////////////////////////////////////
1883 // SOAP data structure definitions
1885 ////////////////////////////////////////////////////////////////////////////////
1888 // ***************************** WARNING *****************************
1889 // THESE STRUCTURES ARE INTERNAL ONLY, FOR USE WITH THE ATL SERVER SOAP
1890 // ATTRIBUTES. USERS SHOULD NOT USE THESE TYPES DIRECTLY. ABSOLUTELY NO
1891 // GUARANTEES ARE MADE ABOUT BACKWARD COMPATIBILITY FOR DIRECT USE OF
1892 // THESE TYPES.
1895 ////////////////////////////////////////////////////////////////////////////////
1897 // BEGIN PRIVATE DEFINITIONS
1899 ////////////////////////////////////////////////////////////////////////////////
1901 inline HRESULT AtlSoapGetArraySize(ISAXAttributes *pAttributes, size_t *pnSize,
1902 const wchar_t **pwszTypeStart = NULL, const wchar_t **pwszTypeEnd = NULL)
1904 if (pnSize == NULL)
1906 return E_POINTER;
1909 if (pAttributes == NULL)
1911 return E_INVALIDARG;
1914 *pnSize = 0;
1916 HRESULT hr = S_OK;
1918 _ATLTRY
1920 const wchar_t *wszTmp;
1921 int cch;
1923 hr = GetAttribute(pAttributes, L"arrayType", sizeof("arrayType")-1,
1924 &wszTmp, &cch, SOAPENC_NAMESPACEW, sizeof(SOAPENC_NAMESPACEA)-1);
1926 if ((SUCCEEDED(hr)) && (wszTmp != NULL))
1928 hr = E_FAIL;
1930 CFixedStringT<CStringW, 1024> wstrArrayType(wszTmp, cch);
1931 const wchar_t *wsz = static_cast<LPCWSTR>(wstrArrayType);
1933 const wchar_t *wszTypeStart = NULL;
1934 const wchar_t *wszTypeEnd = NULL;
1936 // skip spaces
1937 while (iswspace(*wsz) != 0)
1939 wsz++;
1942 // no need to walk the string if the caller is not interested
1943 if ((pwszTypeStart != NULL) && (pwszTypeEnd != NULL))
1945 wszTypeStart = wsz;
1946 wszTypeEnd = wcschr(wszTypeStart, L':');
1947 if (wszTypeEnd != NULL)
1949 wszTypeStart = wszTypeEnd+1;
1953 // SOAP Section 5 encodings are of the form:
1954 // <soap_enc namespace>:arrayType="<type_qname>[dim1(,dim_i)*]
1955 // for example: SOAP-ENC:arrayType="xsd:string[2,4]"
1957 wsz = wcschr(wsz, L'[');
1958 if (wsz != NULL)
1960 wszTypeEnd = wsz-1;
1961 if (wsz[1] == ']')
1963 return S_FALSE;
1966 *pnSize = 1;
1968 // get the size of each dimension
1969 while (wsz != NULL)
1971 wsz++;
1972 int nDim = _wtoi(wsz);
1973 if (nDim < 0)
1975 hr = E_FAIL;
1976 break;
1978 *pnSize *= (size_t) nDim;
1979 if (!nDim)
1981 break;
1984 wsz = wcschr(wsz, L',');
1987 if ((pwszTypeStart != NULL) && (pwszTypeEnd != NULL))
1989 *pwszTypeStart = wszTypeStart;
1990 *pwszTypeEnd = wszTypeEnd;
1993 hr = S_OK;
1996 else
1998 // not a section-5 encoding
1999 hr = S_FALSE;
2002 _ATLCATCHALL()
2004 hr = E_OUTOFMEMORY;
2007 return hr;
2010 inline size_t AtlSoapGetArrayDims(const int *pDims)
2012 if (pDims == NULL)
2014 return 0;
2017 size_t nRet = 1;
2018 for (int i=1; i<=pDims[0]; i++)
2020 nRet *= pDims[i];
2023 return nRet;
2026 enum SOAPFLAGS
2028 SOAPFLAG_NONE = 0x00000000,
2029 SOAPFLAG_IN = 0x00000001,
2030 SOAPFLAG_OUT = 0x00000002,
2031 SOAPFLAG_RETVAL = 0x00000004,
2032 SOAPFLAG_DYNARR = 0x00000008,
2033 SOAPFLAG_FIXEDARR = 0x00000010,
2034 SOAPFLAG_MUSTUNDERSTAND = 0x00000020,
2035 SOAPFLAG_UNKSIZE = 0x00000040,
2036 SOAPFLAG_READYSTATE = 0x00000080,
2037 SOAPFLAG_FIELD = 0x00000100,
2038 SOAPFLAG_NOMARSHAL = 0x00000200,
2039 SOAPFLAG_NULLABLE = 0x00000400,
2040 SOAPFLAG_DOCUMENT = 0x00000800,
2041 SOAPFLAG_RPC = 0x00001000,
2042 SOAPFLAG_LITERAL = 0x00002000,
2043 SOAPFLAG_ENCODED = 0x00004000,
2044 SOAPFLAG_PID = 0x00008000,
2045 SOAPFLAG_PAD = 0x00010000,
2046 SOAPFLAG_CHAIN = 0x00020000,
2047 SOAPFLAG_SIZEIS = 0x00040000,
2048 SOAPFLAG_DYNARRWRAPPER = 0x00080000
2051 enum SOAPMAPTYPE
2053 SOAPMAP_ERR = 0,
2054 SOAPMAP_ENUM,
2055 SOAPMAP_FUNC,
2056 SOAPMAP_STRUCT,
2057 SOAPMAP_UNION,
2058 SOAPMAP_HEADER,
2059 SOAPMAP_PARAM
2062 struct _soapmap;
2064 struct _soapmapentry
2066 ULONG nHash;
2067 const char * szField;
2068 const WCHAR * wszField;
2069 int cchField;
2070 int nVal;
2071 DWORD dwFlags;
2073 size_t nOffset;
2074 const int * pDims;
2076 const _soapmap * pChain;
2078 int nSizeIs;
2080 ULONG nNamespaceHash;
2081 const char *szNamespace;
2082 const wchar_t *wszNamespace;
2083 int cchNamespace;
2086 struct _soapmap
2088 ULONG nHash;
2089 const char * szName;
2090 const wchar_t * wszName;
2091 int cchName;
2092 int cchWName;
2093 SOAPMAPTYPE mapType;
2094 const _soapmapentry * pEntries;
2095 size_t nElementSize;
2096 size_t nElements;
2097 int nRetvalIndex;
2099 DWORD dwCallFlags;
2101 ULONG nNamespaceHash;
2102 const char *szNamespace;
2103 const wchar_t *wszNamespace;
2104 int cchNamespace;
2107 enum SOAPTYPES
2109 SOAPTYPE_ERR = -2,
2110 SOAPTYPE_UNK = -1,
2111 SOAPTYPE_STRING = 0,
2112 SOAPTYPE_BOOLEAN,
2113 SOAPTYPE_FLOAT,
2114 SOAPTYPE_DOUBLE,
2115 SOAPTYPE_DECIMAL,
2116 SOAPTYPE_DURATION,
2117 SOAPTYPE_HEXBINARY,
2118 SOAPTYPE_BASE64BINARY,
2119 SOAPTYPE_ANYURI,
2120 SOAPTYPE_ID,
2121 SOAPTYPE_IDREF,
2122 SOAPTYPE_ENTITY,
2123 SOAPTYPE_NOTATION,
2124 SOAPTYPE_QNAME,
2125 SOAPTYPE_NORMALIZEDSTRING,
2126 SOAPTYPE_TOKEN,
2127 SOAPTYPE_LANGUAGE,
2128 SOAPTYPE_IDREFS,
2129 SOAPTYPE_ENTITIES,
2130 SOAPTYPE_NMTOKEN,
2131 SOAPTYPE_NMTOKENS,
2132 SOAPTYPE_NAME,
2133 SOAPTYPE_NCNAME,
2134 SOAPTYPE_INTEGER,
2135 SOAPTYPE_NONPOSITIVEINTEGER,
2136 SOAPTYPE_NEGATIVEINTEGER,
2137 SOAPTYPE_LONG,
2138 SOAPTYPE_INT,
2139 SOAPTYPE_SHORT,
2140 SOAPTYPE_BYTE,
2141 SOAPTYPE_NONNEGATIVEINTEGER,
2142 SOAPTYPE_UNSIGNEDLONG,
2143 SOAPTYPE_UNSIGNEDINT,
2144 SOAPTYPE_UNSIGNEDSHORT,
2145 SOAPTYPE_UNSIGNEDBYTE,
2146 SOAPTYPE_POSITIVEINTEGER,
2147 SOAPTYPE_DATETIME,
2148 SOAPTYPE_TIME,
2149 SOAPTYPE_DATE,
2150 SOAPTYPE_GMONTH,
2151 SOAPTYPE_GYEARMONTH,
2152 SOAPTYPE_GYEAR,
2153 SOAPTYPE_GMONTHDAY,
2154 SOAPTYPE_GDAY,
2156 SOAPTYPE_USERBASE = 0x00001000
2159 inline ULONG AtlSoapHashStr(const char * sz)
2161 ULONG nHash = 0;
2162 while (*sz != 0)
2164 nHash = (nHash<<5)+nHash+(*sz);
2165 sz++;
2168 return nHash;
2171 inline ULONG AtlSoapHashStr(const wchar_t * sz)
2173 ULONG nHash = 0;
2174 while (*sz != 0)
2176 nHash = (nHash<<5)+nHash+(*sz);
2177 sz++;
2180 return nHash;
2183 inline ULONG AtlSoapHashStr(const char * sz, int cch)
2185 ULONG nHash = 0;
2186 for (int i=0; i<cch; i++)
2188 nHash = (nHash<<5)+nHash+(*sz);
2189 sz++;
2192 return nHash;
2195 inline ULONG AtlSoapHashStr(const wchar_t * sz, int cch)
2197 ULONG nHash = 0;
2198 for (int i=0; i<cch; i++)
2200 nHash = (nHash<<5)+nHash+(*sz);
2201 sz++;
2204 return nHash;
2207 inline size_t AtlSoapGetElementSize(SOAPTYPES type)
2209 size_t nRet;
2210 switch (type)
2212 case SOAPTYPE_BOOLEAN:
2213 nRet = sizeof(bool);
2214 break;
2215 case SOAPTYPE_FLOAT:
2216 nRet = sizeof(float);
2217 break;
2218 case SOAPTYPE_DOUBLE:
2219 case SOAPTYPE_DECIMAL:
2220 nRet = sizeof(double);
2221 break;
2222 case SOAPTYPE_HEXBINARY:
2223 case SOAPTYPE_BASE64BINARY:
2224 nRet = sizeof(ATLSOAP_BLOB);
2225 break;
2226 case SOAPTYPE_INTEGER:
2227 case SOAPTYPE_NONPOSITIVEINTEGER:
2228 case SOAPTYPE_NEGATIVEINTEGER:
2229 case SOAPTYPE_LONG:
2230 nRet = sizeof(__int64);
2231 break;
2232 case SOAPTYPE_INT:
2233 nRet = sizeof(int);
2234 break;
2235 case SOAPTYPE_SHORT:
2236 nRet = sizeof(short);
2237 break;
2238 case SOAPTYPE_BYTE:
2239 nRet = sizeof(char);
2240 break;
2241 case SOAPTYPE_POSITIVEINTEGER:
2242 case SOAPTYPE_NONNEGATIVEINTEGER:
2243 case SOAPTYPE_UNSIGNEDLONG:
2244 nRet = sizeof(unsigned __int64);
2245 break;
2246 case SOAPTYPE_UNSIGNEDINT:
2247 nRet = sizeof(unsigned int);
2248 break;
2249 case SOAPTYPE_UNSIGNEDSHORT:
2250 nRet = sizeof(unsigned short);
2251 break;
2252 case SOAPTYPE_UNSIGNEDBYTE:
2253 nRet = sizeof(unsigned char);
2254 break;
2255 default:
2256 if ((type != SOAPTYPE_ERR) && (type != SOAPTYPE_UNK) && (type != SOAPTYPE_USERBASE))
2258 // treat as string
2259 nRet = sizeof(BSTR);
2261 else
2263 ATLTRACE( _T("ATLSOAP: AtlSoapGetElementSize -- internal error.\r\n") );
2264 // should never get here
2265 ATLASSERT( FALSE );
2266 nRet = 0;
2268 break;
2271 return nRet;
2274 inline HRESULT AtlSoapGetElementValue(const wchar_t *wsz, int cch,
2275 void *pVal, SOAPTYPES type, IAtlMemMgr *pMemMgr)
2277 HRESULT hr = E_FAIL;
2279 switch (type)
2281 case SOAPTYPE_BOOLEAN:
2282 hr = AtlGetSAXValue((bool *)pVal, wsz, cch);
2283 break;
2284 case SOAPTYPE_FLOAT:
2285 hr = AtlGetSAXValue((float *)pVal, wsz, cch);
2286 break;
2287 case SOAPTYPE_DOUBLE:
2288 case SOAPTYPE_DECIMAL:
2289 hr = AtlGetSAXValue((double *)pVal, wsz, cch);
2290 break;
2291 case SOAPTYPE_HEXBINARY:
2292 hr = AtlGetSAXBlobValue((ATLSOAP_BLOB *)pVal, wsz, cch, pMemMgr, true);
2293 break;
2294 case SOAPTYPE_BASE64BINARY:
2295 hr = AtlGetSAXBlobValue((ATLSOAP_BLOB *)pVal, wsz, cch, pMemMgr, false);
2296 break;
2298 case SOAPTYPE_INTEGER:
2299 case SOAPTYPE_NONPOSITIVEINTEGER:
2300 case SOAPTYPE_NEGATIVEINTEGER:
2301 case SOAPTYPE_LONG:
2302 hr = AtlGetSAXValue((__int64 *)pVal, wsz, cch);
2303 break;
2304 case SOAPTYPE_INT:
2305 hr = AtlGetSAXValue((int *)pVal, wsz, cch);
2306 break;
2307 case SOAPTYPE_SHORT:
2308 hr = AtlGetSAXValue((short *)pVal, wsz, cch);
2309 break;
2310 case SOAPTYPE_BYTE:
2311 hr = AtlGetSAXValue((char *)pVal, wsz, cch);
2312 break;
2313 case SOAPTYPE_POSITIVEINTEGER:
2314 case SOAPTYPE_NONNEGATIVEINTEGER:
2315 case SOAPTYPE_UNSIGNEDLONG:
2316 hr = AtlGetSAXValue((unsigned __int64 *)pVal, wsz, cch);
2317 break;
2318 case SOAPTYPE_UNSIGNEDINT:
2319 hr = AtlGetSAXValue((unsigned int *)pVal, wsz, cch);
2320 break;
2321 case SOAPTYPE_UNSIGNEDSHORT:
2322 hr = AtlGetSAXValue((unsigned short *)pVal, wsz, cch);
2323 break;
2324 case SOAPTYPE_UNSIGNEDBYTE:
2325 hr = AtlGetSAXValue((unsigned char *)pVal, wsz, cch);
2326 break;
2327 default:
2328 if ((type != SOAPTYPE_ERR) && (type != SOAPTYPE_UNK) && (type != SOAPTYPE_USERBASE))
2330 hr = AtlGetSAXValue((BSTR *)pVal, wsz, cch);
2332 #ifdef _DEBUG
2333 else
2335 ATLTRACE( _T("ATLSOAP: AtlSoapGetElementValue -- internal error.\r\n") );
2337 // should never get here
2338 ATLASSERT( FALSE );
2340 #endif
2341 break;
2344 return hr;
2347 inline HRESULT AtlSoapGenElementValue(void *pVal, IWriteStream *pStream, SOAPTYPES type, IAtlMemMgr *pMemMgr)
2349 HRESULT hr = E_FAIL;
2351 switch (type)
2353 case SOAPTYPE_BOOLEAN:
2354 hr = AtlGenXMLValue(pStream, (bool *)pVal);
2355 break;
2356 case SOAPTYPE_FLOAT:
2357 hr = AtlGenXMLValue(pStream, (float *)pVal);
2358 break;
2359 case SOAPTYPE_DOUBLE:
2360 case SOAPTYPE_DECIMAL:
2361 hr = AtlGenXMLValue(pStream, (double *)pVal);
2362 break;
2363 case SOAPTYPE_HEXBINARY:
2364 hr = AtlGenXMLBlobValue(pStream, (ATLSOAP_BLOB *)pVal, pMemMgr, true);
2365 break;
2366 case SOAPTYPE_BASE64BINARY:
2367 hr = AtlGenXMLBlobValue(pStream, (ATLSOAP_BLOB *)pVal, pMemMgr, false);
2368 break;
2370 case SOAPTYPE_INTEGER:
2371 case SOAPTYPE_NONPOSITIVEINTEGER:
2372 case SOAPTYPE_NEGATIVEINTEGER:
2373 case SOAPTYPE_LONG:
2374 hr = AtlGenXMLValue(pStream, (__int64 *)pVal);
2375 break;
2376 case SOAPTYPE_INT:
2377 hr = AtlGenXMLValue(pStream, (int *)pVal);
2378 break;
2379 case SOAPTYPE_SHORT:
2380 hr = AtlGenXMLValue(pStream, (short *)pVal);
2381 break;
2382 case SOAPTYPE_BYTE:
2383 hr = AtlGenXMLValue(pStream, (char *)pVal);
2384 break;
2385 case SOAPTYPE_POSITIVEINTEGER:
2386 case SOAPTYPE_NONNEGATIVEINTEGER:
2387 case SOAPTYPE_UNSIGNEDLONG:
2388 hr = AtlGenXMLValue(pStream, (unsigned __int64 *)pVal);
2389 break;
2390 case SOAPTYPE_UNSIGNEDINT:
2391 hr = AtlGenXMLValue(pStream, (unsigned int *)pVal);
2392 break;
2393 case SOAPTYPE_UNSIGNEDSHORT:
2394 hr = AtlGenXMLValue(pStream, (unsigned short *)pVal);
2395 break;
2396 case SOAPTYPE_UNSIGNEDBYTE:
2397 hr = AtlGenXMLValue(pStream, (unsigned char *)pVal);
2398 break;
2399 default:
2400 if ((type != SOAPTYPE_ERR) && (type != SOAPTYPE_UNK) && (type != SOAPTYPE_USERBASE))
2402 hr = AtlGenXMLValue(pStream, (BSTR *)pVal);
2404 #ifdef _DEBUG
2405 else
2407 ATLTRACE( _T("ATLSOAP: AtlSoapGenElementValue -- internal error.\r\n" ) );
2409 // should never get here
2410 ATLASSERT( FALSE );
2412 #endif
2413 break;
2415 return hr;
2418 inline HRESULT AtlSoapCleanupElement(void *pVal, SOAPTYPES type, IAtlMemMgr *pMemMgr)
2420 HRESULT hr = S_OK;
2422 switch (type)
2424 case SOAPTYPE_BOOLEAN:
2425 case SOAPTYPE_FLOAT:
2426 case SOAPTYPE_DOUBLE:
2427 case SOAPTYPE_DECIMAL:
2428 case SOAPTYPE_INT:
2429 case SOAPTYPE_INTEGER:
2430 case SOAPTYPE_NONPOSITIVEINTEGER:
2431 case SOAPTYPE_NEGATIVEINTEGER:
2432 case SOAPTYPE_LONG:
2433 case SOAPTYPE_SHORT:
2434 case SOAPTYPE_BYTE:
2435 case SOAPTYPE_POSITIVEINTEGER:
2436 case SOAPTYPE_NONNEGATIVEINTEGER:
2437 case SOAPTYPE_UNSIGNEDLONG:
2438 case SOAPTYPE_UNSIGNEDINT:
2439 case SOAPTYPE_UNSIGNEDSHORT:
2440 case SOAPTYPE_UNSIGNEDBYTE:
2441 break;
2443 case SOAPTYPE_HEXBINARY:
2444 case SOAPTYPE_BASE64BINARY:
2445 hr = AtlCleanupBlobValue((ATLSOAP_BLOB *)pVal, pMemMgr);
2446 break;
2448 default:
2449 if ((type != SOAPTYPE_ERR) && (type != SOAPTYPE_UNK) && (type != SOAPTYPE_USERBASE))
2451 // treat as string
2452 hr = AtlCleanupValue((BSTR *)pVal);
2454 #ifdef _DEBUG
2455 else
2457 ATLTRACE( _T("ATLSOAP: AtlSoapCleanupElement -- internal error.\r\n" ) );
2459 // should never get here
2460 ATLASSERT( FALSE );
2462 #endif
2463 break;
2466 return hr;
2469 ////////////////////////////////////////////////////////////////////////////////
2471 // END PRIVATE DEFINITIONS
2473 ////////////////////////////////////////////////////////////////////////////////
2475 #define SOAP_ENVELOPEA "Envelope"
2476 #define SOAP_ENVELOPEW ATLSOAP_MAKEWIDESTR( SOAP_ENVELOPEA )
2478 #define SOAP_HEADERA "Header"
2479 #define SOAP_HEADERW ATLSOAP_MAKEWIDESTR( SOAP_HEADERA )
2481 #define SOAP_BODYA "Body"
2482 #define SOAP_BODYW ATLSOAP_MAKEWIDESTR( SOAP_BODYA )
2485 #pragma pack(push,_ATL_PACKING)
2486 namespace ATL
2490 // SOAP fault helpers
2493 enum SOAP_ERROR_CODE
2495 SOAP_E_UNK=0,
2496 SOAP_E_VERSION_MISMATCH=100,
2497 SOAP_E_MUST_UNDERSTAND=200,
2498 SOAP_E_CLIENT=300,
2499 SOAP_E_SERVER=400
2502 // forward declaration of CSoapFault
2503 class CSoapFault;
2505 class CSoapFaultParser : public ISAXContentHandlerImpl
2507 private:
2509 CSoapFault *m_pFault;
2511 DWORD m_dwState;
2513 const static DWORD STATE_ERROR = 0;
2514 const static DWORD STATE_ENVELOPE = 1;
2515 const static DWORD STATE_BODY = 2;
2516 const static DWORD STATE_START = 4;
2517 const static DWORD STATE_FAULTCODE = 8;
2518 const static DWORD STATE_FAULTSTRING = 16;
2519 const static DWORD STATE_FAULTACTOR = 32;
2520 const static DWORD STATE_DETAIL = 64;
2521 const static DWORD STATE_RESET = 128;
2522 const static DWORD STATE_SKIP = 256;
2525 CComPtr<ISAXXMLReader> m_spReader;
2526 CSAXStringBuilder m_stringBuilder;
2527 CSkipHandler m_skipHandler;
2529 const wchar_t *m_wszSoapPrefix;
2530 int m_cchSoapPrefix;
2532 public:
2533 virtual ~CSoapFaultParser()
2535 m_skipHandler.DetachParent();
2538 // IUnknown interface
2539 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
2541 if (ppv == NULL)
2543 return E_POINTER;
2546 *ppv = NULL;
2548 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
2549 InlineIsEqualGUID(riid, IID_ISAXContentHandler))
2551 *ppv = static_cast<ISAXContentHandler *>(this);
2552 return S_OK;
2555 return E_NOINTERFACE;
2558 ULONG __stdcall AddRef()
2560 return 1;
2563 ULONG __stdcall Release()
2565 return 1;
2568 // constructor
2570 CSoapFaultParser(CSoapFault *pFault, ISAXXMLReader *pReader)
2571 :m_pFault(pFault), m_dwState(STATE_ERROR), m_spReader(pReader)
2573 ATLASSERT( pFault != NULL );
2574 ATLASSERT( pReader != NULL );
2577 // ISAXContentHandler interface
2578 HRESULT __stdcall startElement(
2579 const wchar_t * wszNamespaceUri,
2580 int cchNamespaceUri,
2581 const wchar_t * wszLocalName,
2582 int cchLocalName,
2583 const wchar_t * /*wszQName*/,
2584 int /*cchQName*/,
2585 ISAXAttributes * /*pAttributes*/)
2587 struct _faultmap
2589 const wchar_t *wszTag;
2590 int cchTag;
2591 DWORD dwState;
2594 const static _faultmap s_faultParseMap[] =
2596 { L"Envelope", sizeof("Envelope")-1, CSoapFaultParser::STATE_ENVELOPE },
2597 { L"Body", sizeof("Body")-1, CSoapFaultParser::STATE_BODY },
2598 { L"Header", sizeof("Header")-1, CSoapFaultParser::STATE_BODY },
2599 { L"Fault", sizeof("Fault")-1, CSoapFaultParser::STATE_START },
2600 { L"faultcode", sizeof("faultcode")-1, CSoapFaultParser::STATE_FAULTCODE },
2601 { L"faultstring", sizeof("faultstring")-1, CSoapFaultParser::STATE_FAULTSTRING },
2602 { L"faultactor", sizeof("faultactor")-1, CSoapFaultParser::STATE_FAULTACTOR },
2603 { L"detail", sizeof("detail")-1, CSoapFaultParser::STATE_DETAIL }
2606 if (m_spReader.p == NULL)
2608 ATLTRACE( _T("ATLSOAP: CSoapFaultParser::startElement -- ISAXXMLReader is NULL.\r\n" ) );
2610 return E_INVALIDARG;
2613 m_dwState &= ~STATE_RESET;
2614 for (int i=0; i<(sizeof(s_faultParseMap)/sizeof(s_faultParseMap[0])); i++)
2616 if ((cchLocalName == s_faultParseMap[i].cchTag) &&
2617 (!wcsncmp(wszLocalName, s_faultParseMap[i].wszTag, cchLocalName)))
2619 DWORD dwState = s_faultParseMap[i].dwState;
2620 if ((dwState & (STATE_START | STATE_ENVELOPE | STATE_BODY)) == 0)
2622 m_stringBuilder.SetReader(m_spReader);
2623 m_stringBuilder.SetParent(this);
2625 m_stringBuilder.Clear();
2626 m_spReader->putContentHandler( &m_stringBuilder );
2628 else
2630 if ((dwState <= m_dwState) ||
2631 (cchNamespaceUri != sizeof(SOAPENV_NAMESPACEA)-1) ||
2632 (wcsncmp(wszNamespaceUri, SOAPENV_NAMESPACEW, cchNamespaceUri)))
2634 ATLTRACE( _T("ATLSOAP: CSoapFaultParser::startElement -- malformed SOAP fault.\r\n" ) );
2636 return E_FAIL;
2640 m_dwState = dwState;
2641 return S_OK;
2644 if (m_dwState > STATE_START)
2646 m_dwState = STATE_SKIP;
2647 m_skipHandler.SetReader(m_spReader);
2648 m_skipHandler.SetParent(this);
2650 m_spReader->putContentHandler( &m_skipHandler );
2651 return S_OK;
2654 ATLTRACE( _T("ATLSOAP: CSoapFaultParser::startElement -- malformed SOAP fault.\r\n" ) );
2656 return E_FAIL;
2659 HRESULT __stdcall startPrefixMapping(
2660 const wchar_t * wszPrefix,
2661 int cchPrefix,
2662 const wchar_t * wszUri,
2663 int cchUri)
2665 if ((cchUri == sizeof(SOAPENV_NAMESPACEA)-1) &&
2666 (!wcsncmp(wszUri, SOAPENV_NAMESPACEW, cchUri)))
2668 m_wszSoapPrefix = wszPrefix;
2669 m_cchSoapPrefix = cchPrefix;
2672 return S_OK;
2675 HRESULT __stdcall characters(
2676 const wchar_t * wszChars,
2677 int cchChars);
2680 extern __declspec(selectany) const int ATLS_SOAPFAULT_CNT = 4;
2682 class CSoapFault
2684 private:
2686 struct _faultcode
2688 const wchar_t *wsz;
2689 int cch;
2690 const wchar_t *wszFaultString;
2691 int cchFaultString;
2692 SOAP_ERROR_CODE errCode;
2695 static const _faultcode s_faultCodes[];
2697 public:
2699 // members
2700 SOAP_ERROR_CODE m_soapErrCode;
2701 CStringW m_strFaultCode;
2702 CStringW m_strFaultString;
2703 CStringW m_strFaultActor;
2704 CStringW m_strDetail;
2706 CSoapFault()
2707 : m_soapErrCode(SOAP_E_UNK)
2711 HRESULT SetErrorCode(
2712 const wchar_t *wsz,
2713 const wchar_t *wszSoapPrefix,
2714 int cch = -1,
2715 int cchSoapPrefix = -1,
2716 bool bSetFaultString = true)
2718 if ((wsz == NULL) || (wszSoapPrefix == NULL))
2720 return E_INVALIDARG;
2723 if (cch == -1)
2725 cch = (int) wcslen(wsz);
2728 while (*wsz && iswspace(*wsz))
2730 ++wsz;
2731 --cch;
2734 if (cchSoapPrefix == -1)
2736 cchSoapPrefix = (int) wcslen(wszSoapPrefix);
2739 const wchar_t *wszLocalName = wcschr(wsz, L':');
2740 if (wszLocalName == NULL)
2742 // faultCode must be QName
2744 ATLTRACE( _T("ATLSOAP: CSoapFault::SetErrorCode -- faultCode is not a QName.\r\n" ) );
2746 return E_FAIL;
2749 // make sure the namespace of the fault is the
2750 // SOAPENV namespace
2751 if ((cchSoapPrefix != (int)(wszLocalName-wsz)) ||
2752 (wcsncmp(wsz, wszSoapPrefix, cchSoapPrefix)))
2754 ATLTRACE( _T("ATLSOAP: CSoapFault::SetErrorCode -- fault namespace is incorrect.\r\n" ) );
2756 return E_FAIL;
2759 wszLocalName++;
2760 cch -= (int) (wszLocalName-wsz);
2762 _ATLTRY
2764 for (int i=0; i<ATLS_SOAPFAULT_CNT; i++)
2766 if ((cch == s_faultCodes[i].cch) &&
2767 (!wcsncmp(wszLocalName, s_faultCodes[i].wsz, cch)))
2769 m_soapErrCode = s_faultCodes[i].errCode;
2770 if (bSetFaultString != false)
2772 m_strFaultString.SetString(s_faultCodes[i].wszFaultString, s_faultCodes[i].cchFaultString);
2773 break;
2777 if (m_strFaultString.GetLength() == 0)
2779 m_strFaultCode.SetString(wszLocalName, cch);
2782 _ATLCATCHALL()
2784 ATLTRACE( _T("ATLSOAP: CSoapFault::SetErrorCode -- out of memory.\r\n" ) );
2786 return E_OUTOFMEMORY;
2789 return S_OK;
2792 HRESULT ParseFault(IStream *pStream, ISAXXMLReader *pReader = NULL)
2794 if (pStream == NULL)
2796 ATLTRACE( _T("ATLSOAP: CSoapFault::ParseFault -- NULL IStream was passed.\r\n" ) );
2798 return E_INVALIDARG;
2801 CComPtr<ISAXXMLReader> spReader;
2802 if (pReader != NULL)
2804 spReader = pReader;
2806 else
2808 if (FAILED(spReader.CoCreateInstance(ATLS_SAXXMLREADER_CLSID, NULL, CLSCTX_INPROC_SERVER)))
2810 ATLTRACE( _T("ATLSOAP: CSoapFault::ParseFault -- CoCreateInstance of SAXXMLReader failed.\r\n" ) );
2812 return E_FAIL;
2816 Clear();
2817 CSoapFaultParser parser(const_cast<CSoapFault *>(this), spReader);
2818 spReader->putContentHandler(&parser);
2820 CComVariant varStream;
2821 varStream = static_cast<IUnknown*>(pStream);
2823 HRESULT hr = spReader->parse(varStream);
2824 spReader->putContentHandler(NULL);
2825 return hr;
2828 HRESULT GenerateFault(IWriteStream *pWriteStream)
2830 if ((pWriteStream == NULL) || (m_soapErrCode == SOAP_E_UNK))
2832 return E_INVALIDARG;
2835 ATLASSERT( (m_soapErrCode == SOAP_E_UNK) ||
2836 (m_soapErrCode == SOAP_E_VERSION_MISMATCH) ||
2837 (m_soapErrCode == SOAP_E_MUST_UNDERSTAND) ||
2838 (m_soapErrCode == SOAP_E_CLIENT) ||
2839 (m_soapErrCode == SOAP_E_SERVER) );
2841 HRESULT hr = S_OK;
2842 _ATLTRY
2844 const wchar_t *wszFaultCode = NULL;
2845 if (m_strFaultCode.GetLength() == 0)
2847 for (int i=0; i<4; i++)
2849 if (s_faultCodes[i].errCode == m_soapErrCode)
2851 if (m_strFaultString.GetLength() == 0)
2853 m_strFaultString.SetString(s_faultCodes[i].wszFaultString,
2854 s_faultCodes[i].cchFaultString);
2857 wszFaultCode = s_faultCodes[i].wsz;
2858 break;
2863 if (wszFaultCode == NULL)
2865 if (m_strFaultCode.GetLength() != 0)
2867 wszFaultCode = m_strFaultCode;
2869 else
2871 ATLTRACE( _T("CSoapFault::GenerateFault -- missing/invalid fault code.\r\n") );
2872 return E_FAIL;
2876 const LPCSTR s_szErrorFormat =
2877 "<SOAP:Envelope xmlns:SOAP=\"" SOAPENV_NAMESPACEA "\">"
2878 "<SOAP:Body>"
2879 "<SOAP:Fault>"
2880 "<faultcode>SOAP:%ws</faultcode>"
2881 "<faultstring>%ws</faultstring>"
2882 "%s%ws%s"
2883 "<detail>%ws</detail>"
2884 "</SOAP:Fault>"
2885 "</SOAP:Body>"
2886 "</SOAP:Envelope>";
2888 CStringA strFault;
2889 strFault.Format(s_szErrorFormat, wszFaultCode, m_strFaultString,
2890 m_strFaultActor.GetLength() ? "<faultactor>" : "", m_strFaultActor,
2891 m_strFaultActor.GetLength() ? "</faultactor>" : "",
2892 m_strDetail);
2894 hr = pWriteStream->WriteStream(strFault, strFault.GetLength(), NULL);
2896 _ATLCATCHALL()
2898 ATLTRACE( _T("ATLSOAP: CSoapFault::GenerateFault -- out of memory.\r\n" ) );
2899 hr = E_OUTOFMEMORY;
2902 return hr;
2905 void Clear()
2907 m_soapErrCode = SOAP_E_UNK;
2908 m_strFaultCode.Empty();
2909 m_strFaultString.Empty();
2910 m_strFaultActor.Empty();
2911 m_strDetail.Empty();
2913 }; // class CSoapFault
2915 #define DECLARE_SOAP_FAULT(__name, __faultstring, __errcode) \
2916 { L ## __name, sizeof(__name)-1, L ## __faultstring, sizeof(__faultstring), __errcode },
2918 __declspec(selectany) const CSoapFault::_faultcode CSoapFault::s_faultCodes[] =
2920 DECLARE_SOAP_FAULT("VersionMismatch", "SOAP Version Mismatch Error", SOAP_E_VERSION_MISMATCH)
2921 DECLARE_SOAP_FAULT("MustUnderstand", "SOAP Must Understand Error", SOAP_E_MUST_UNDERSTAND)
2922 DECLARE_SOAP_FAULT("Client", "SOAP Invalid Request", SOAP_E_CLIENT)
2923 DECLARE_SOAP_FAULT("Server", "SOAP Server Application Faulted", SOAP_E_SERVER)
2926 ATL_NOINLINE inline HRESULT __stdcall CSoapFaultParser::characters(
2927 const wchar_t * wszChars,
2928 int cchChars)
2930 if (m_pFault == NULL)
2932 return E_INVALIDARG;
2935 if (m_dwState & STATE_RESET)
2937 return S_OK;
2940 HRESULT hr = E_FAIL;
2941 _ATLTRY
2943 switch (m_dwState)
2945 case STATE_FAULTCODE:
2946 if (m_pFault->m_soapErrCode == SOAP_E_UNK)
2948 hr = m_pFault->SetErrorCode(wszChars, m_wszSoapPrefix,
2949 cchChars, m_cchSoapPrefix, false);
2951 break;
2952 case STATE_FAULTSTRING:
2953 if (m_pFault->m_strFaultString.GetLength() == 0)
2955 m_pFault->m_strFaultString.SetString(wszChars, cchChars);
2956 hr = S_OK;
2958 break;
2959 case STATE_FAULTACTOR:
2960 if (m_pFault->m_strFaultActor.GetLength() == 0)
2962 m_pFault->m_strFaultActor.SetString(wszChars, cchChars);
2963 hr = S_OK;
2965 break;
2966 case STATE_DETAIL:
2967 if (m_pFault->m_strDetail.GetLength() == 0)
2969 m_pFault->m_strDetail.SetString(wszChars, cchChars);
2970 hr = S_OK;
2972 break;
2973 case STATE_START: case STATE_ENVELOPE : case STATE_BODY : case STATE_SKIP:
2974 hr = S_OK;
2975 break;
2976 default:
2977 // should never get here
2978 ATLASSERT( FALSE );
2979 break;
2982 _ATLCATCHALL()
2984 ATLTRACE( _T("ATLSOAP: CSoapFaultParser::characters -- out of memory.\r\n" ) );
2986 hr = E_OUTOFMEMORY;
2989 m_dwState |= STATE_RESET;
2991 return hr;
2994 ////////////////////////////////////////////////////////////////////////////////
2996 // CSoapRootHandler - the class that does most of the work
2998 ////////////////////////////////////////////////////////////////////////////////
3000 #ifndef ATLSOAP_STACKSIZE
3001 // 16 will be plenty for the 99% case
3002 #define ATLSOAP_STACKSIZE 16
3003 #endif
3005 #ifndef ATLSOAP_GROWARRAY
3006 #define ATLSOAP_GROWARRAY 10
3007 #endif
3009 class CSoapRootHandler : public ISAXContentHandlerImpl
3011 private:
3013 friend class _CSDLGenerator;
3016 // state constants
3018 const static DWORD SOAP_START = 0;
3019 const static DWORD SOAP_ENVELOPE = 1;
3020 const static DWORD SOAP_HEADERS = 2;
3021 const static DWORD SOAP_BODY = 3;
3022 const static DWORD SOAP_PARAMS = 4;
3023 const static DWORD SOAP_CALLED = 5;
3024 const static DWORD SOAP_RESPONSE = 6;
3025 const static DWORD SOAP_HEADERS_DONE = 7;
3028 // hash values for SOAP namespaces and elements
3030 const static ULONG SOAP_ENV = 0x5D3574E2;
3031 const static ULONG SOAP_ENC = 0xBD62724B;
3032 const static ULONG ENVELOPE = 0xDBE6009E;
3033 const static ULONG HEADER = 0xAF4DFFC9;
3034 const static ULONG BODY = 0x0026168E;
3037 // XSD Names
3039 struct XSDEntry
3041 wchar_t * wszName;
3042 char * szName;
3043 int cchName;
3046 const static XSDEntry s_xsdNames[];
3049 // CBitVector - a dynamically sized bit vector class
3051 class CBitVector
3053 private:
3055 // 64 bits will handle the 99% case
3056 unsigned __int64 m_nBits;
3058 // when we need to grow
3059 unsigned __int64 * m_pBits;
3061 size_t m_nSize;
3063 bool Grow(size_t nIndex)
3065 // Think carefully
3066 // In our current implementation, CHAR_BIT==8, and sizeof(m_nBits)==8. Easy to confuse the two.
3068 // We do math in bits, so this is our max size
3069 ATLENSURE(nIndex<SIZE_MAX/((sizeof(m_nBits)*CHAR_BIT)));
3071 // round up to nearest 64 bits
3072 size_t nAllocSizeBits = nIndex+((sizeof(m_nBits)*CHAR_BIT)-(nIndex%(sizeof(m_nBits)*CHAR_BIT)));
3073 size_t nAllocSizeBytes = nAllocSizeBits/CHAR_BIT;
3075 if (m_pBits != &m_nBits)
3077 unsigned __int64 * pNewBits=NULL;
3078 pNewBits = (unsigned __int64 *) realloc(m_pBits, nAllocSizeBytes );
3079 if(!pNewBits)
3081 return false;
3083 m_pBits=pNewBits;
3085 else
3087 m_pBits = (unsigned __int64 *) malloc(nAllocSizeBytes );
3088 if (m_pBits != NULL)
3090 Checked::memcpy_s(m_pBits, nAllocSizeBytes, &m_nBits, sizeof(m_nBits));
3094 if (m_pBits != NULL)
3096 // set new bits to 0
3097 memset(m_pBits+(m_nSize/(CHAR_BIT*sizeof(m_nBits))), 0x00, (nAllocSizeBits-m_nSize)/CHAR_BIT);
3098 m_nSize = nAllocSizeBits;
3099 return true;
3102 ATLTRACE( _T("ATLSOAP: CBitVector::Grow -- out of memory.\r\n" ) );
3104 return false;
3107 public:
3109 CBitVector()
3110 : m_nBits(0), m_nSize(sizeof(m_nBits)*CHAR_BIT)
3112 m_pBits = &m_nBits;
3115 CBitVector(const CBitVector&)
3117 m_pBits = &m_nBits;
3120 const CBitVector& operator=(const CBitVector& that)
3122 if (this != &that)
3124 m_pBits = &m_nBits;
3127 return *this;
3130 bool GetBit(size_t nIndex) const
3132 if (nIndex >= m_nSize)
3134 return false;
3137 size_t i = nIndex/(sizeof(m_nBits)*CHAR_BIT);
3138 size_t nBits = nIndex-i*(sizeof(m_nBits)*CHAR_BIT);
3139 return ((m_pBits[i] >> nBits) & 0x01);
3142 bool SetBit(size_t nIndex)
3144 if (nIndex >= m_nSize)
3146 if (!Grow(nIndex))
3148 return false;
3152 size_t i = nIndex/(sizeof(m_nBits)*CHAR_BIT);
3153 size_t nBits = nIndex-i*(sizeof(m_nBits)*CHAR_BIT);
3154 m_pBits[i] |= (((unsigned __int64) 1) << nBits);
3156 return true;
3159 void Clear()
3161 if (m_pBits == &m_nBits)
3163 m_nBits = 0;
3165 else
3167 memset(m_pBits, 0x00, (m_nSize/CHAR_BIT));
3171 ~CBitVector()
3173 if (m_pBits != &m_nBits)
3175 free(m_pBits);
3178 m_pBits = &m_nBits;
3179 m_nSize = sizeof(m_nBits)*CHAR_BIT;
3182 void RelocateFixup()
3184 if (m_nSize <= sizeof(m_nBits)*CHAR_BIT)
3186 m_pBits = &m_nBits;
3189 }; // class CBitVector
3192 // Parsing State
3194 struct ParseState
3196 void *pvElement;
3197 DWORD dwFlags;
3198 size_t nAllocSize;
3199 size_t nExpectedElements;
3200 size_t nElement;
3201 const _soapmap *pMap;
3202 const _soapmapentry *pEntry;
3204 // mark when we get an item
3205 CBitVector vec;
3207 size_t nDepth;
3209 ParseState(void *pvElement_ = NULL, DWORD dwFlags_ = 0,
3210 size_t nAllocSize_ = 0, size_t nExpectedElements_ = 0,
3211 size_t nElement_ = 0, const _soapmap *pMap_ = NULL,
3212 const _soapmapentry *pEntry_ = NULL)
3213 : pvElement(pvElement_), dwFlags(dwFlags_), nAllocSize(nAllocSize_),
3214 nExpectedElements(nExpectedElements_), nElement(nElement_), pMap(pMap_),
3215 pEntry(pEntry_), nDepth(0)
3217 vec.Clear();
3220 ParseState(const ParseState& that)
3222 pvElement = that.pvElement;
3223 dwFlags = that.dwFlags;
3224 nAllocSize = that.nAllocSize;
3225 nExpectedElements = that.nExpectedElements;
3226 nElement = that.nElement;
3227 pMap = that.pMap;
3228 pEntry = that.pEntry;
3229 nDepth = that.nDepth;
3230 vec.Clear();
3233 ~ParseState()
3235 pvElement = NULL;
3236 dwFlags = 0;
3237 nAllocSize = 0;
3238 nExpectedElements = 0;
3239 nElement = 0;
3240 pMap = NULL;
3241 pEntry = NULL;
3242 nDepth = 0;
3243 vec.Clear();
3246 void RelocateFixup()
3248 vec.RelocateFixup();
3250 }; // struct ParseState
3252 class CParseStateElementTraits : public CDefaultElementTraits<ParseState>
3254 public:
3255 // CBitVector relocate fixup
3256 static void RelocateElements( ParseState* pDest, ParseState* pSrc, size_t nElements )
3258 CDefaultElementTraits<ParseState>::RelocateElements(pDest, pSrc, nElements);
3260 // fixup CBitVector
3261 for (size_t i=0; i<nElements; i++)
3263 pDest[i].RelocateFixup();
3268 class CResponseGenerator
3270 public:
3271 HRESULT StartEnvelope(IWriteStream *pStream)
3273 ATLENSURE_RETURN( pStream != NULL );
3275 return pStream->WriteStream("<soap:Envelope "
3276 "xmlns:soap=\"" SOAPENV_NAMESPACEA "\" "
3277 "xmlns:xsi=\"" XSI_NAMESPACEA "\" "
3278 "xmlns:xsd=\"" XSD_NAMESPACEA "\" "
3279 "xmlns:soapenc=\"" SOAPENC_NAMESPACEA "\">",
3281 sizeof("<soap:Envelope "
3282 "xmlns:soap=\"" SOAPENV_NAMESPACEA "\" "
3283 "xmlns:xsi=\"" XSI_NAMESPACEA "\" "
3284 "xmlns:xsd=\"" XSD_NAMESPACEA "\" "
3285 "xmlns:soapenc=\"" SOAPENC_NAMESPACEA "\">")-1,
3287 NULL);
3290 HRESULT StartHeaders(IWriteStream *pStream, const _soapmap *pMap)
3292 ATLENSURE_RETURN( pStream != NULL );
3293 ATLENSURE_RETURN( pMap != NULL );
3295 HRESULT hr = pStream->WriteStream("<soap:Header", sizeof("<soap:Header")-1, NULL);
3296 if (SUCCEEDED(hr))
3298 if ((pMap->dwCallFlags & (SOAPFLAG_RPC | SOAPFLAG_ENCODED)) !=
3299 (SOAPFLAG_RPC | SOAPFLAG_ENCODED))
3301 // qualify document/literal by default
3302 // For this version, ATL Server will not respect
3303 // the elementForm* attributes in an XSD schema
3305 hr = pStream->WriteStream(" xmlns=\"", sizeof(" xmlns=\"")-1, NULL);
3306 if (SUCCEEDED(hr))
3308 hr = pStream->WriteStream(pMap->szNamespace, pMap->cchNamespace, NULL);
3309 if (SUCCEEDED(hr))
3311 hr = pStream->WriteStream("\">", sizeof("\">")-1, NULL);
3315 else
3317 // rpc/encoded
3318 hr = pStream->WriteStream(">", sizeof(">")-1, NULL);
3321 return hr;
3324 HRESULT EndHeaders(IWriteStream *pStream)
3326 ATLENSURE_RETURN( pStream != NULL );
3328 return pStream->WriteStream("</soap:Header>", sizeof("</soap:Header>")-1, NULL);
3331 virtual HRESULT StartBody(IWriteStream *pStream)
3333 ATLENSURE_RETURN( pStream != NULL );
3335 return pStream->WriteStream(
3336 "<soap:Body>", sizeof("<soap:Body>")-1, NULL);
3339 HRESULT EndBody(IWriteStream *pStream)
3341 ATLENSURE_RETURN( pStream != NULL );
3343 return pStream->WriteStream("</soap:Body>", sizeof("</soap:Body>")-1, NULL);
3346 HRESULT EndEnvelope(IWriteStream *pStream)
3348 ATLENSURE_RETURN( pStream != NULL );
3350 return pStream->WriteStream("</soap:Envelope>", sizeof("</soap:Envelope>")-1, NULL);
3353 virtual HRESULT StartMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient) = 0;
3354 virtual HRESULT EndMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient) = 0;
3356 virtual HRESULT StartEntry(IWriteStream *pStream, const _soapmap *pMap, const _soapmapentry *pEntry)
3358 ATLENSURE_RETURN( pStream != NULL );
3359 ATLENSURE_RETURN( pEntry != NULL );
3361 // output name
3362 HRESULT hr = pStream->WriteStream("<", 1, NULL);
3363 if (SUCCEEDED(hr))
3365 const char *szHeaderNamespace = NULL;
3366 int cchHeaderNamespace = 0;
3368 if ((pMap != NULL) && (pMap->mapType == SOAPMAP_HEADER) &&
3369 ((pEntry->pChain != NULL) &&
3370 (pEntry->pChain->szNamespace !=NULL)) ||
3371 (pEntry->szNamespace != NULL))
3373 hr = pStream->WriteStream("snp:", sizeof("snp:")-1, NULL);
3374 if (SUCCEEDED(hr))
3376 szHeaderNamespace = pEntry->pChain ?
3377 pEntry->pChain->szNamespace : pEntry->szNamespace;
3379 cchHeaderNamespace = pEntry->pChain ?
3380 pEntry->pChain->cchNamespace : pEntry->cchNamespace;
3384 if (SUCCEEDED(hr))
3386 if ((pEntry->dwFlags & SOAPFLAG_RETVAL)==0)
3388 hr = pStream->WriteStream(pEntry->szField, pEntry->cchField, NULL);
3390 else
3392 hr = pStream->WriteStream("return", sizeof("return")-1, NULL);
3394 if (SUCCEEDED(hr))
3396 if (szHeaderNamespace != NULL)
3398 ATLASSERT( cchHeaderNamespace != 0 );
3400 hr = pStream->WriteStream(" xmlns:snp=\"", sizeof(" xmlns:snp=\"")-1, NULL);
3401 if (SUCCEEDED(hr))
3403 hr = pStream->WriteStream(szHeaderNamespace, cchHeaderNamespace, NULL);
3404 if (SUCCEEDED(hr))
3406 hr = pStream->WriteStream("\"", sizeof("\"")-1, NULL);
3413 if (SUCCEEDED(hr))
3415 if (pEntry->dwFlags & SOAPFLAG_MUSTUNDERSTAND)
3417 // output mustUnderstand
3418 hr = pStream->WriteStream(" soap:mustUnderstand=\"1\"", sizeof(" soap:mustUnderstand=\"1\"")-1, NULL);
3421 return hr;
3424 HRESULT EndEntry(IWriteStream *pStream, const _soapmap *pMap, const _soapmapentry *pEntry)
3426 ATLENSURE_RETURN( pStream != NULL );
3427 ATLENSURE_RETURN( pEntry != NULL );
3429 HRESULT hr = pStream->WriteStream("</", 2, NULL);
3430 if (SUCCEEDED(hr))
3432 if ((pMap != NULL) &&
3433 (pMap->mapType == SOAPMAP_HEADER) &&
3434 ((pEntry->pChain != NULL) &&
3435 (pEntry->pChain->szNamespace !=NULL)) ||
3436 (pEntry->szNamespace != NULL))
3438 hr = pStream->WriteStream("snp:", sizeof("snp:")-1, NULL);
3440 if ((pEntry->dwFlags & SOAPFLAG_RETVAL)==0)
3442 hr = pStream->WriteStream(pEntry->szField, pEntry->cchField, NULL);
3444 else
3446 hr = pStream->WriteStream("return", sizeof("return")-1, NULL);
3448 if (SUCCEEDED(hr))
3450 hr = pStream->WriteStream(">", 1, NULL);
3453 return hr;
3455 }; // class CResponseGenerator
3457 class CDocLiteralGenerator : public CResponseGenerator
3459 public:
3461 HRESULT StartMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient)
3463 ATLENSURE_RETURN( pStream != NULL );
3464 ATLENSURE_RETURN( pMap != NULL );
3466 HRESULT hr = S_OK;
3467 // output type name
3468 hr = pStream->WriteStream("<", 1, NULL);
3469 if (SUCCEEDED(hr))
3471 hr = pStream->WriteStream(pMap->szName, pMap->cchName, NULL);
3472 if (SUCCEEDED(hr))
3474 if ((pMap->mapType == SOAPMAP_FUNC) &&
3475 (bClient == false) &&
3476 (pMap->dwCallFlags & SOAPFLAG_PID))
3478 hr = pStream->WriteStream("Response", sizeof("Response")-1, NULL);
3479 if (FAILED(hr))
3481 return hr;
3485 if (pMap->mapType == SOAPMAP_FUNC)
3487 hr = pStream->WriteStream(" xmlns=\"", sizeof(" xmlns=\"")-1, NULL);
3488 if (SUCCEEDED(hr))
3490 hr = pStream->WriteStream(pMap->szNamespace, pMap->cchNamespace, NULL);
3491 if (SUCCEEDED(hr))
3493 hr = pStream->WriteStream("\">", sizeof("\">")-1, NULL);
3497 else
3499 hr = pStream->WriteStream(">", 1, NULL);
3503 return hr;
3506 HRESULT EndMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient)
3508 ATLENSURE_RETURN( pStream != NULL );
3509 ATLENSURE_RETURN( pMap != NULL );
3511 HRESULT hr = pStream->WriteStream("</", sizeof("</")-1, NULL);
3512 if (SUCCEEDED(hr))
3514 hr = pStream->WriteStream(pMap->szName, pMap->cchName, NULL);
3515 if (SUCCEEDED(hr))
3517 if ((pMap->mapType == SOAPMAP_FUNC) &&
3518 (bClient == false) &&
3519 (pMap->dwCallFlags & SOAPFLAG_PID))
3521 hr = pStream->WriteStream("Response", sizeof("Response")-1, NULL);
3522 if (FAILED(hr))
3524 return hr;
3527 hr = pStream->WriteStream(">", 1, NULL);
3531 return hr;
3534 }; // class CDocLiteralGenerator
3536 class CPIDGenerator : public CDocLiteralGenerator
3540 class CPADGenerator : public CDocLiteralGenerator
3542 public:
3544 virtual HRESULT StartEntry(IWriteStream *pStream, const _soapmap *pMap, const _soapmapentry *pEntry)
3546 ATLENSURE_RETURN( pStream != NULL );
3547 ATLENSURE_RETURN( pEntry != NULL );
3549 HRESULT hr = __super::StartEntry(pStream, pMap, pEntry);
3550 if (SUCCEEDED(hr) && (pMap->dwCallFlags & SOAPFLAG_PAD))
3552 hr = pStream->WriteStream(" xmlns=\"", sizeof(" xmlns=\"")-1, NULL);
3553 if (SUCCEEDED(hr))
3555 hr = pStream->WriteStream(pMap->szNamespace, pMap->cchNamespace, NULL);
3556 if (SUCCEEDED(hr))
3558 hr = pStream->WriteStream("\"", sizeof("\"")-1, NULL);
3563 return hr;
3565 }; // class CPADGenerator
3567 class CRpcEncodedGenerator : public CResponseGenerator
3569 public:
3571 HRESULT StartBody(IWriteStream *pStream)
3573 ATLENSURE_RETURN( pStream != NULL );
3575 return pStream->WriteStream(
3576 "<soap:Body soap:encodingStyle=\"" SOAPENC_NAMESPACEA "\">",
3577 sizeof("<soap:Body soap:encodingStyle=\"" SOAPENC_NAMESPACEA "\">")-1, NULL);
3580 HRESULT StartMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient)
3582 ATLENSURE_RETURN( pStream != NULL );
3583 ATLENSURE_RETURN( pMap != NULL );
3585 (bClient); // unused for rpc/encoded
3587 HRESULT hr = pStream->WriteStream("<snp:", sizeof("<snp:")-1, NULL);
3588 if (SUCCEEDED(hr))
3590 hr = pStream->WriteStream(pMap->szName, pMap->cchName, NULL);
3591 if (SUCCEEDED(hr))
3593 if (pMap->mapType == SOAPMAP_FUNC)
3595 hr = pStream->WriteStream(" xmlns:snp=\"", sizeof(" xmlns:snp=\"")-1, NULL);
3596 if (SUCCEEDED(hr))
3598 ATLASSERT( pMap->szNamespace != NULL );
3599 hr = pStream->WriteStream(pMap->szNamespace, pMap->cchNamespace, NULL);
3600 if (SUCCEEDED(hr))
3602 hr = pStream->WriteStream("\">", sizeof("\">")-1, NULL);
3606 else
3608 hr = pStream->WriteStream(">", 1, NULL);
3612 return hr;
3615 HRESULT EndMap(IWriteStream *pStream, const _soapmap *pMap, bool bClient)
3617 ATLENSURE_RETURN( pStream != NULL );
3618 ATLENSURE_RETURN( pMap != NULL );
3620 (bClient); // unused for rpc/encoded
3622 HRESULT hr = pStream->WriteStream("</snp:", sizeof("</snp:")-1, NULL);
3623 if (SUCCEEDED(hr))
3625 hr = pStream->WriteStream(pMap->szName, pMap->cchName, NULL);
3626 if (SUCCEEDED(hr))
3628 hr = pStream->WriteStream(">", 1, NULL);
3632 return hr;
3634 }; // class CRpcEncodedGenerator
3637 // members
3639 CAtlArray<ParseState, CParseStateElementTraits> m_stateStack;
3640 size_t m_nState;
3642 DWORD m_dwState;
3644 CComPtr<ISAXXMLReader> m_spReader;
3646 CSAXStringBuilder m_stringBuilder;
3647 CSkipHandler m_skipHandler;
3649 IAtlMemMgr * m_pMemMgr;
3651 static CCRTHeap m_crtHeap;
3653 bool m_bClient;
3655 void *m_pvParam;
3657 bool m_bNullCheck;
3658 bool m_bChildCheck;
3659 bool m_bCharacters;
3660 size_t m_nDepth;
3662 typedef CFixedStringT<CStringW, 16> REFSTRING;
3664 // used for rpc/encoded messages with href's
3665 typedef CAtlMap<REFSTRING, ParseState, CStringRefElementTraits<REFSTRING> > REFMAP;
3666 REFMAP m_refMap;
3669 // Implementation helpers
3672 HRESULT PushState(void *pvElement = NULL, const _soapmap *pMap = NULL,
3673 const _soapmapentry *pEntry = NULL, DWORD dwFlags = 0, size_t nAllocSize = 0,
3674 size_t nExpectedElements = 0, size_t nElement = 0)
3676 if (m_stateStack.IsEmpty())
3678 // 16 will be plenty for the 99% case
3679 if (!m_stateStack.SetCount(0, 16))
3681 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::PushState -- out of memory.\r\n" ) );
3683 return E_OUTOFMEMORY;
3687 size_t nCnt = m_stateStack.GetCount();
3688 m_nState = m_stateStack.Add();
3689 if (m_stateStack.GetCount() <= nCnt)
3691 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::PushState -- out of memory.\r\n" ) );
3693 return E_OUTOFMEMORY;
3696 ParseState &state = m_stateStack[m_nState];
3698 state.pvElement = pvElement;
3699 state.dwFlags = dwFlags;
3700 state.nAllocSize = nAllocSize;
3701 state.nExpectedElements = nExpectedElements;
3702 state.nElement = nElement;
3703 state.pMap = pMap;
3704 state.pEntry = pEntry;
3705 state.nDepth = m_nDepth;
3707 return S_OK;
3710 ParseState& GetState()
3712 return m_stateStack[m_nState];
3715 void PopState(bool bForce = false)
3717 if ((m_nState != 0) || (bForce != false))
3719 m_stateStack.RemoveAt(m_nState);
3720 --m_nState;
3724 BOOL IsEqualElement(int cchLocalNameCheck, const wchar_t *wszLocalNameCheck,
3725 int cchNamespaceUriCheck, const wchar_t *wszNamespaceUriCheck,
3726 int cchLocalName, const wchar_t *wszLocalName,
3727 int cchNamespaceUri, const wchar_t *wszNamespaceUri)
3729 ATLENSURE(wszLocalName);
3730 ATLENSURE(wszLocalNameCheck);
3731 ATLENSURE(wszNamespaceUri);
3732 ATLENSURE(wszNamespaceUriCheck);
3734 if (cchLocalName == cchLocalNameCheck &&
3735 cchNamespaceUri == cchNamespaceUriCheck &&
3736 !wcsncmp(wszLocalName, wszLocalNameCheck, cchLocalName) &&
3737 !wcsncmp(wszNamespaceUri, wszNamespaceUriCheck, cchNamespaceUri))
3739 return TRUE;
3742 return FALSE;
3745 ATL_FORCEINLINE BOOL IsEqualString(const wchar_t *wszStr1, int cchStr1, const wchar_t *wszStr2, int cchStr2)
3747 ATLENSURE( wszStr1 != NULL );
3748 ATLENSURE( wszStr2 != NULL );
3749 ATLENSURE( cchStr1 >= 0 );
3750 ATLENSURE( cchStr2 >= 0 );
3752 if (cchStr1 == cchStr2)
3754 return !wcsncmp(wszStr1, wszStr2, cchStr2);
3756 return FALSE;
3759 ATL_FORCEINLINE BOOL IsEqualStringHash(const wchar_t *wszStr1, int cchStr1, ULONG nHash1,
3760 const wchar_t *wszStr2, int cchStr2, ULONG nHash2)
3762 ATLENSURE( wszStr1 != NULL );
3763 ATLENSURE( wszStr2 != NULL );
3764 ATLENSURE( cchStr1 >= 0 );
3765 ATLENSURE( cchStr2 >= 0 );
3767 if (nHash1 == nHash2)
3769 return IsEqualString(wszStr1, cchStr1, wszStr2, cchStr2);
3772 return FALSE;
3775 BOOL IsEqualElement(int cchLocalNameCheck, const wchar_t *wszLocalNameCheck,
3776 int cchLocalName, const wchar_t *wszLocalName)
3778 if (cchLocalName == cchLocalNameCheck &&
3779 !wcsncmp(wszLocalName, wszLocalNameCheck, cchLocalName))
3781 return TRUE;
3784 return FALSE;
3787 void SetOffsetValue(void *pBase, void *pSrc, size_t nOffset)
3789 void **ppDest = (void **)(((unsigned char *)pBase)+nOffset);
3790 *ppDest = pSrc;
3793 bool IsRpcEncoded()
3795 if ((m_stateStack[0].pMap->dwCallFlags & (SOAPFLAG_RPC | SOAPFLAG_ENCODED)) ==
3796 (SOAPFLAG_RPC | SOAPFLAG_ENCODED))
3798 return true;
3800 return false;
3804 HRESULT ValidateArrayEntry(
3805 ParseState& state,
3806 const wchar_t *wszLocalName,
3807 int cchLocalName)
3809 (cchLocalName);
3810 (wszLocalName);
3812 ATLASSERT( state.pEntry != NULL );
3814 // SOAP Section 5.4.2
3816 // check number of elements
3817 if (state.nElement == state.nExpectedElements)
3819 // too many elements
3820 if ((state.dwFlags & SOAPFLAG_UNKSIZE)==0)
3822 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::ValidateArrayEntry -- too many elements.\r\n" ) );
3823 return E_FAIL;
3826 ATLASSERT( IsRpcEncoded() == false );
3828 // see if we need to allocate more
3829 if (state.nElement == state.nAllocSize)
3831 unsigned char **ppArr = (unsigned char **)state.pvElement;
3832 size_t nNewElement=0;
3833 HRESULT hr=E_FAIL;
3834 if(FAILED(hr=::ATL::AtlMultiply(&nNewElement, state.nElement, static_cast<size_t>(2))))
3836 return hr;
3838 hr = AllocateArray(state.pEntry, (void **)ppArr, __max(nNewElement, ATLSOAP_GROWARRAY), state.nElement);
3840 if (SUCCEEDED(hr))
3842 state.nAllocSize = __max((state.nElement)*2, ATLSOAP_GROWARRAY);
3845 return hr;
3849 return S_OK;
3852 HRESULT CheckID(
3853 const wchar_t *wszNamespaceUri,
3854 const wchar_t *wszLocalName,
3855 int cchLocalName,
3856 ISAXAttributes *pAttributes)
3858 (cchLocalName);
3859 (wszLocalName);
3860 (wszNamespaceUri);
3861 ATLASSERT( pAttributes != NULL );
3863 const wchar_t *wsz = NULL;
3864 int cch = 0;
3866 HRESULT hr = GetAttribute(pAttributes, L"id", sizeof("id")-1, &wsz, &cch);
3867 if ((hr == S_OK) && (wsz != NULL))
3869 const REFMAP::CPair *p = NULL;
3870 _ATLTRY
3872 REFSTRING strRef(wsz, cch);
3873 p = m_refMap.Lookup(strRef);
3874 if (p == NULL)
3876 return S_FALSE;
3879 _ATLCATCHALL()
3881 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckID -- out of memory.\r\n" ) );
3883 return E_OUTOFMEMORY;
3886 ATLASSERT( IsRpcEncoded() == true );
3888 const ParseState& state = p->m_value;
3890 // disallow href-chaining
3891 hr = CheckHref(state.pEntry, state.pvElement, pAttributes);
3892 if (hr != S_FALSE)
3894 return E_FAIL;
3897 hr = S_OK;
3899 // do array stuff
3900 if (state.dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))
3902 hr = GetSection5Info(state, state.pEntry, pAttributes);
3904 else
3906 // only structs and arrays are allowed for hrefs
3907 ATLASSERT( state.pEntry->pChain != NULL );
3908 ATLASSERT( state.pEntry->pChain->mapType == SOAPMAP_STRUCT );
3910 // structs must have child entries
3911 m_bChildCheck = state.pEntry->pChain->nElements != 0;
3913 if (S_OK != PushState(state.pvElement, state.pEntry->pChain, state.pEntry,
3914 state.dwFlags, 0, state.pEntry->pChain->nElements))
3916 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckID -- out of memory.\n" ) );
3917 hr = E_OUTOFMEMORY;
3921 m_refMap.DisableAutoRehash();
3922 m_refMap.RemoveAtPos(const_cast<REFMAP::CPair*>(p));
3923 m_refMap.EnableAutoRehash();
3925 return hr;
3928 return S_FALSE;
3931 HRESULT GetElementEntry(
3932 ParseState& state,
3933 const wchar_t *wszNamespaceUri,
3934 const wchar_t *wszLocalName,
3935 int cchLocalName,
3936 ISAXAttributes *pAttributes,
3937 const _soapmapentry **ppEntry)
3939 ATLENSURE_RETURN( state.pMap != NULL );
3940 ATLENSURE_RETURN( ppEntry != NULL );
3942 *ppEntry = NULL;
3943 const _soapmapentry *pEntries = state.pMap->pEntries;
3944 DWORD dwIncludeFlags;
3945 DWORD dwExcludeFlags;
3947 HRESULT hr = CheckID(wszNamespaceUri, wszLocalName, cchLocalName, pAttributes);
3948 if (hr != S_FALSE)
3950 if (hr == S_OK)
3952 hr = S_FALSE;
3954 return hr;
3957 if (m_bClient != false)
3959 dwIncludeFlags = SOAPFLAG_OUT;
3960 dwExcludeFlags = SOAPFLAG_IN;
3962 else
3964 dwIncludeFlags = SOAPFLAG_IN;
3965 dwExcludeFlags = SOAPFLAG_OUT;
3968 ULONG nHash = AtlSoapHashStr(wszLocalName, cchLocalName);
3970 for (size_t i=0; pEntries[i].nHash != 0; i++)
3972 if (nHash == pEntries[i].nHash &&
3973 ((pEntries[i].dwFlags & dwIncludeFlags) ||
3974 ((pEntries[i].dwFlags & dwExcludeFlags) == 0)) &&
3975 IsEqualElement(pEntries[i].cchField, pEntries[i].wszField,
3976 cchLocalName, wszLocalName)/* &&
3977 !wcscmp(wszNamespaceUri, wszNamespace)*/)
3979 // check bit vector
3981 if (state.vec.GetBit(i) == false)
3983 if (state.vec.SetBit(i) == false)
3985 return E_OUTOFMEMORY;
3988 else
3990 // already received this element
3991 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::GetElementEntry -- duplicate element was sent.\r\n" ) );
3993 return E_FAIL;
3996 state.nElement++;
3997 *ppEntry = &pEntries[i];
3999 return S_OK;
4003 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::GetElementEntry -- element not found: %.*ws.\r\n" ), cchLocalName, wszLocalName );
4005 return E_FAIL;
4008 HRESULT CheckMustUnderstandHeader(ISAXAttributes *pAttributes)
4010 ATLASSERT( pAttributes != NULL );
4012 const wchar_t* wszMustUnderstand;
4013 int cchMustUnderstand;
4014 bool bMustUnderstand= false;
4016 if (SUCCEEDED(GetAttribute(pAttributes, L"mustUnderstand", sizeof("mustUnderstand")-1,
4017 &wszMustUnderstand, &cchMustUnderstand,
4018 SOAPENV_NAMESPACEW, sizeof(SOAPENV_NAMESPACEA)-1)) &&
4019 (wszMustUnderstand != NULL))
4021 if (FAILED(AtlGetSAXValue(&bMustUnderstand, wszMustUnderstand, cchMustUnderstand)))
4023 bMustUnderstand = true;
4027 if (bMustUnderstand == false)
4029 ATLASSERT( GetReader() != NULL );
4031 m_skipHandler.SetReader(GetReader());
4032 m_skipHandler.SetParent(this);
4034 return GetReader()->putContentHandler( &m_skipHandler );
4036 else
4038 SoapFault(SOAP_E_MUST_UNDERSTAND, NULL, 0);
4041 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckMustUnderstandHeader -- unknown \"mustUnderstand\" SOAP Header was received.\r\n" ) );
4043 return E_FAIL;
4046 HRESULT AllocateArray(
4047 const _soapmapentry *pEntry,
4048 void **ppArr, size_t nElements,
4049 size_t nCurrElements = 0)
4051 ATLENSURE_RETURN( ppArr != NULL );
4052 ATLENSURE_RETURN( pEntry != NULL );
4054 size_t nElementSize;
4055 if (pEntry->nVal != SOAPTYPE_UNK)
4057 nElementSize = AtlSoapGetElementSize((SOAPTYPES) pEntry->nVal);
4059 else // UDT
4061 ATLENSURE_RETURN( pEntry->pChain != NULL );
4062 nElementSize = pEntry->pChain->nElementSize;
4064 if (nElementSize != 0)
4066 if (*ppArr == NULL)
4068 ATLASSERT( nCurrElements == 0 );
4069 size_t nBytes=0;
4070 HRESULT hr=S_OK;
4071 if( FAILED(hr=::ATL::AtlMultiply(&nBytes, nElementSize, nElements)))
4073 return hr;
4075 *ppArr = m_pMemMgr->Allocate(nBytes);
4077 else // *ppArr != NULL
4079 ATLASSERT( nCurrElements != 0 );
4080 size_t nBytes=0;
4081 HRESULT hr=S_OK;
4082 if( FAILED(hr=::ATL::AtlAdd(&nBytes, nElements, nCurrElements)) ||
4083 FAILED(hr=::ATL::AtlMultiply(&nBytes, nElementSize, nBytes)))
4085 return hr;
4087 *ppArr = m_pMemMgr->Reallocate(*ppArr, nBytes);
4090 else
4092 // internal error
4093 ATLASSERT( FALSE );
4094 return E_FAIL;
4097 if (*ppArr == NULL)
4099 return E_OUTOFMEMORY;
4102 memset(((unsigned char *)(*ppArr))+(nCurrElements*nElementSize), 0x00, nElements*nElementSize);
4104 return S_OK;
4107 HRESULT GetSection5Info(
4108 const ParseState& state,
4109 const _soapmapentry *pEntry,
4110 ISAXAttributes *pAttributes)
4112 ATLENSURE_RETURN( pEntry != NULL );
4113 ATLENSURE_RETURN( pAttributes != NULL );
4115 HRESULT hr;
4116 if (IsRpcEncoded() != false)
4118 // check for href
4119 // we ONLY do this for rpc/encoded (required for interop)
4120 // NOTE: ATL Server does not support object graphs, so
4121 // only single-reference elements are allowed
4122 hr = CheckHref(pEntry, state.pvElement, pAttributes,
4123 pEntry->dwFlags, SOAPFLAG_READYSTATE);
4124 if (hr != S_FALSE)
4126 return hr;
4130 size_t nElements;
4131 DWORD dwFlags = 0;
4132 hr = AtlSoapGetArraySize(pAttributes, &nElements);
4133 if (FAILED(hr))
4135 return hr;
4138 size_t nAllocSize = 0;
4139 size_t nElementsPush = 0;
4141 if (pEntry->dwFlags & SOAPFLAG_DYNARR)
4143 // set size_is value
4144 ATLENSURE_RETURN( state.pMap != NULL );
4145 int *pnSizeIs = (int *)(((unsigned char *)state.pvElement)+
4146 (state.pMap->pEntries[pEntry->nSizeIs].nOffset));
4148 if (hr != S_OK)
4150 if (IsRpcEncoded())
4152 // rpc/encoded requires soapenc:arrayType attribute
4153 return E_FAIL;
4156 nElements = ATLSOAP_GROWARRAY;
4157 nAllocSize = ATLSOAP_GROWARRAY;
4158 dwFlags |= SOAPFLAG_UNKSIZE;
4159 *pnSizeIs = 0;
4161 else
4163 *pnSizeIs = (int)nElements;
4164 if (nElements == 0)
4166 // soapenc:arrayType="type[0]"
4167 // treat as null array
4169 m_bNullCheck = true;
4171 // push an emtpy state
4172 return PushState();
4175 nElementsPush = nElements;
4177 void *p = NULL;
4178 hr = AllocateArray(pEntry, &p, nElements);
4179 if (hr != S_OK)
4181 return hr;
4184 SetOffsetValue(state.pvElement, p, pEntry->nOffset);
4186 else
4188 // for fixed-size arrays, we know the number of elements
4189 ATLASSERT( pEntry->dwFlags & SOAPFLAG_FIXEDARR );
4190 if (hr == S_OK)
4192 if (nElements != AtlSoapGetArrayDims(pEntry->pDims))
4194 return E_FAIL;
4197 else
4199 hr = S_OK;
4200 nElements = AtlSoapGetArrayDims(pEntry->pDims);
4202 nElementsPush = nElements;
4205 dwFlags |= pEntry->dwFlags;
4207 // push element with array flag
4209 if (S_OK != PushState(((unsigned char *)state.pvElement)+pEntry->nOffset,
4210 state.pMap, pEntry, dwFlags & ~SOAPFLAG_READYSTATE, nAllocSize, nElementsPush))
4212 return E_OUTOFMEMORY;
4215 m_bChildCheck = true;
4217 return S_OK;
4220 void * UpdateArray(ParseState& state, const _soapmapentry *pEntry)
4222 ATLENSURE(pEntry);
4224 size_t nSize;
4225 void *pVal = NULL;
4227 if (pEntry->nVal != SOAPTYPE_UNK)
4229 nSize = AtlSoapGetElementSize((SOAPTYPES) pEntry->nVal);
4231 else
4233 ATLENSURE( pEntry->pChain != NULL );
4235 nSize = pEntry->pChain->nElementSize;
4238 if (state.dwFlags & SOAPFLAG_FIXEDARR)
4240 unsigned char *ppArr = (unsigned char *)state.pvElement;
4241 pVal = ppArr+(state.nElement*nSize);
4243 else
4245 ATLASSERT( state.dwFlags & SOAPFLAG_DYNARR );
4247 unsigned char **ppArr = (unsigned char **)state.pvElement;
4248 pVal = (*ppArr)+(state.nElement*nSize);
4249 if (state.dwFlags & SOAPFLAG_UNKSIZE)
4251 ATLASSERT( IsRpcEncoded() == false );
4253 // need to use the previous state's pvElement to update the size_is value
4254 ATLASSUME( m_nState > 0 );
4255 int *pnSizeIs = (int *)(((unsigned char *)m_stateStack[m_nState-1].pvElement)+
4256 (state.pMap->pEntries[pEntry->nSizeIs].nOffset));
4258 // update size_is parameter
4259 *pnSizeIs = (int)(state.nElement+1);
4260 state.nExpectedElements++;
4263 state.nElement++;
4265 return pVal;
4268 HRESULT ProcessString(const _soapmapentry *pEntry, void *pVal)
4270 ATLENSURE_RETURN( pEntry != NULL );
4272 // set to the string builder class
4274 ATLASSERT( GetReader() != NULL );
4276 m_stringBuilder.SetReader(GetReader());
4277 m_stringBuilder.SetParent(this);
4279 m_stringBuilder.Clear();
4280 GetReader()->putContentHandler( &m_stringBuilder );
4282 if (S_OK != PushState(pVal, NULL, pEntry, SOAPFLAG_READYSTATE | pEntry->dwFlags))
4284 return E_OUTOFMEMORY;
4287 return S_OK;
4291 HRESULT CheckHref(
4292 const _soapmapentry *pEntry,
4293 void *pVal,
4294 ISAXAttributes *pAttributes,
4295 DWORD dwIncludeFlags = 0,
4296 DWORD dwExcludeFlags = 0)
4298 ATLASSERT( pEntry != NULL );
4299 ATLASSERT( pVal != NULL );
4300 ATLASSERT( pAttributes != NULL );
4302 const wchar_t *wsz = NULL;
4303 int cch = 0;
4305 HRESULT hr = GetAttribute(pAttributes, L"href", sizeof("href")-1, &wsz, &cch);
4306 if ((hr == S_OK) && (wsz != NULL))
4308 // only allow hrefs on structs and arrays
4309 if (((pEntry->dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))==0) &&
4310 (pEntry->pChain == NULL || pEntry->pChain->mapType != SOAPMAP_STRUCT))
4312 ATLTRACE( _T("ATL Server only allows href's on arrays and structs.\r\n") );
4314 return E_FAIL;
4317 ATLASSERT( IsRpcEncoded() == true );
4319 _ATLTRY
4321 if (*wsz == L'#')
4323 wsz++;
4324 cch--;
4327 REFSTRING strRef(wsz, cch);
4328 if (m_refMap.Lookup(strRef) != NULL)
4330 // ATL Server does not support multi-reference objects
4331 ATLASSERT( FALSE );
4332 return E_FAIL;
4335 ParseState& currState = GetState();
4336 if ((currState.pEntry != NULL) && (currState.pEntry->dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR)))
4338 // it is an array item
4339 ATLASSERT( currState.nElement != 0 );
4341 // exclude array flags for href'd array elements
4342 dwExcludeFlags |= SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR;
4345 ParseState state;
4346 state.pvElement = pVal;
4347 state.dwFlags = (pEntry->dwFlags | dwIncludeFlags) & ~dwExcludeFlags;
4348 state.nExpectedElements = 0;
4350 state.nElement = 0;
4351 state.pMap = GetState().pMap;
4352 state.pEntry = pEntry;
4354 if (!m_refMap.SetAt(strRef, state))
4356 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckHref -- out of memory.\r\n" ) );
4358 return E_OUTOFMEMORY;
4361 // make sure there are no child elements
4362 m_bNullCheck = true;
4364 // push an emtpy state
4365 return PushState();
4367 _ATLCATCHALL()
4369 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckHref -- out of memory.\r\n" ) );
4371 return E_OUTOFMEMORY;
4375 return S_FALSE;
4378 HRESULT ProcessUDT(
4379 const _soapmapentry *pEntry,
4380 void *pVal)
4382 ATLENSURE_RETURN( pEntry != NULL );
4383 ATLENSURE_RETURN( pVal != NULL );
4384 ATLENSURE_RETURN( pEntry->nVal != SOAPTYPE_ERR );
4385 ATLENSURE_RETURN( pEntry->nVal != SOAPTYPE_USERBASE );
4387 // if it is a complex type, get the chain entry
4388 // and push the new state on the stack
4390 DWORD dwFlags = pEntry->dwFlags;
4391 if (pEntry->pChain->mapType != SOAPMAP_ENUM)
4393 // struct
4394 dwFlags &= ~(SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR);
4395 m_bChildCheck = pEntry->pChain->nElements != 0;
4397 else
4399 // enum
4400 dwFlags |= SOAPFLAG_READYSTATE;
4402 // enums must not have child elements
4403 m_bNullCheck = true;
4405 // enums must be specified
4406 m_bCharacters = true;
4409 if (S_OK != PushState(pVal, pEntry->pChain, pEntry, dwFlags, 0, pEntry->pChain->nElements))
4411 return E_OUTOFMEMORY;
4414 return S_OK;
4417 HRESULT ChainEntry(
4418 const ParseState& state,
4419 const wchar_t *wszNamespaceUri,
4420 int cchNamespaceUri,
4421 const wchar_t *wszLocalName,
4422 int cchLocalName,
4423 ISAXAttributes *pAttributes)
4425 ATLENSURE_RETURN( state.pMap != NULL );
4427 // PAD is only supported on the client
4428 const _soapmap *pMap = state.pMap;
4429 if ((pMap->dwCallFlags & SOAPFLAG_CHAIN)==0)
4431 return S_FALSE;
4434 ATLENSURE_RETURN( pMap->dwCallFlags & SOAPFLAG_PAD );
4435 ATLASSUME( m_bClient == true );
4436 ATLENSURE_RETURN( pMap->nElements == 1 );
4437 const _soapmapentry *pEntries = pMap->pEntries;
4438 ATLENSURE_RETURN( pEntries != NULL );
4440 int nIndex;
4441 if (pEntries[0].dwFlags & SOAPFLAG_OUT)
4443 nIndex = 0;
4445 else
4447 nIndex = 1;
4450 const _soapmapentry *pEntry = &pEntries[nIndex];
4451 ATLENSURE_RETURN( pEntry->nHash != 0 );
4452 ATLENSURE_RETURN( pEntry->pChain != NULL );
4454 if (S_OK != PushState(state.pvElement, pEntry->pChain, pEntry, pEntry->dwFlags, 0, pEntry->pChain->nElements))
4456 return E_OUTOFMEMORY;
4459 return ProcessParams(wszNamespaceUri, cchNamespaceUri, wszLocalName, cchLocalName, pAttributes);
4462 HRESULT IsNullEntry(const _soapmapentry *pEntry, ISAXAttributes *pAttributes)
4464 ATLASSERT( pEntry != NULL );
4465 ATLASSERT( pAttributes != NULL );
4467 HRESULT hr = E_FAIL;
4468 bool bNull = false;
4469 const wchar_t *wszNull = NULL;
4470 int cchNull = 0;
4471 hr = GetAttribute(pAttributes, L"nil", sizeof("nil")-1, &wszNull, &cchNull,
4472 XSI_NAMESPACEW, sizeof(XSI_NAMESPACEA)-1);
4473 if ((hr == S_OK) && (wszNull != NULL))
4475 hr = AtlGetSAXValue(&bNull, wszNull, cchNull);
4476 if (hr == S_OK)
4478 if (bNull != false)
4480 if (pEntry->dwFlags & SOAPFLAG_NULLABLE)
4482 m_bNullCheck = true;
4484 // push an emtpy state
4485 return PushState();
4488 // non-nullable element
4489 return E_FAIL;
4494 return S_FALSE;
4497 HRESULT ProcessParams(
4498 const wchar_t *wszNamespaceUri,
4499 int cchNamespaceUri,
4500 const wchar_t *wszLocalName,
4501 int cchLocalName,
4502 ISAXAttributes *pAttributes)
4504 (wszNamespaceUri);
4505 (cchNamespaceUri);
4507 if (m_stateStack.IsEmpty())
4509 if (m_dwState == SOAP_HEADERS)
4511 return CheckMustUnderstandHeader(pAttributes);
4514 return E_FAIL;
4517 ParseState &state = GetState();
4519 ATLASSERT( state.pvElement != NULL );
4520 HRESULT hr = E_FAIL;
4521 const _soapmapentry *pEntry = NULL;
4523 // if array element
4524 if (state.dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))
4526 hr = ValidateArrayEntry(state, wszLocalName, cchLocalName);
4528 if (SUCCEEDED(hr))
4530 pEntry = state.pEntry;
4532 else
4534 return hr;
4537 else // not an array element
4539 // special-case for PAD with type=
4540 hr = ChainEntry(state, wszNamespaceUri, cchNamespaceUri,
4541 wszLocalName, cchLocalName, pAttributes);
4543 if (hr == S_FALSE)
4545 hr = GetElementEntry(state, wszNamespaceUri, wszLocalName, cchLocalName, pAttributes, &pEntry);
4546 if (hr != S_OK)
4548 if (hr == S_FALSE)
4550 hr = S_OK;
4552 else if (m_dwState == SOAP_HEADERS)
4554 hr = CheckMustUnderstandHeader(pAttributes);
4556 return hr;
4559 ATLASSERT( pEntry != NULL );
4561 else
4563 return hr;
4567 hr = IsNullEntry(pEntry, pAttributes);
4568 if (hr != S_FALSE)
4570 return hr;
4572 hr = S_OK;
4573 ATLENSURE_RETURN(pEntry);
4574 // if is array
4575 if (((pEntry->pDims != NULL) || (pEntry->dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))) &&
4576 ((state.dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR)) == 0))
4578 // get SOAP section-5 info (if it is there)
4579 return GetSection5Info(state, pEntry, pAttributes);
4581 else
4583 // if it is a simple type, push a new (ready) state on the stack
4584 void *pVal;
4585 if (state.dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))
4587 pVal = UpdateArray(state, pEntry);
4588 ATLASSERT( pVal != NULL );
4590 else
4592 pVal = (((unsigned char *)state.pvElement)+pEntry->nOffset);
4595 if (IsRpcEncoded() != false)
4597 // check for href
4598 // we ONLY do this for rpc/encoded (required for interop)
4599 // NOTE: ATL Server does not support object graphs, so
4600 // only single-reference elements are allowed
4601 hr = CheckHref(pEntry, pVal, pAttributes);
4602 if (hr != S_FALSE)
4604 return hr;
4606 hr = S_OK;
4609 if (pEntry->nVal != SOAPTYPE_UNK)
4611 // simple types should not have child elements
4612 m_bNullCheck = true;
4614 // if it is a string
4615 if ((pEntry->nVal == SOAPTYPE_STRING) || (pEntry->nVal == SOAPTYPE_BASE64BINARY))
4617 hr = ProcessString(pEntry, pVal);
4619 else
4621 // expect characters for all non-string simple types
4622 m_bCharacters = true;
4624 // basic simple type
4625 if (S_OK != PushState(pVal, NULL, pEntry, SOAPFLAG_READYSTATE | pEntry->dwFlags))
4627 hr = E_OUTOFMEMORY;
4631 else
4633 hr = ProcessUDT(pEntry, pVal);
4634 if (pEntry->dwFlags & (SOAPFLAG_DYNARRWRAPPER))
4636 // We're moving to the **first** entry in the dynamic array wrapper.
4637 // We know it is the first entry because the dynamic array wrapper is created
4638 // by sproxy and it guarantees this layouts.
4639 ++m_nDepth;
4640 ProcessParams (wszNamespaceUri, cchNamespaceUri, pEntry->pChain->pEntries[0].wszField,
4641 pEntry->pChain->pEntries[0].cchField, pAttributes);
4646 return hr;
4649 size_t GetSizeIsValue(void *pvParam, const _soapmap *pMap, const _soapmapentry *pEntry)
4651 ATLENSURE( pvParam != NULL );
4652 ATLENSURE( pMap != NULL );
4653 ATLENSURE( pEntry != NULL );
4655 int nSizeIs = pEntry->nSizeIs;
4656 size_t nOffset = pMap->pEntries[nSizeIs].nOffset;
4657 void *pVal = ((unsigned char *)pvParam)+nOffset;
4659 __int64 nVal = 0;
4660 switch(pMap->pEntries[nSizeIs].nVal)
4662 case SOAPTYPE_INTEGER:
4663 case SOAPTYPE_NONPOSITIVEINTEGER:
4664 case SOAPTYPE_NEGATIVEINTEGER:
4665 case SOAPTYPE_LONG:
4666 nVal = *((__int64 *)pVal);
4667 break;
4668 case SOAPTYPE_INT:
4669 nVal = *((int *)pVal);
4670 break;
4671 case SOAPTYPE_SHORT:
4672 nVal = *((short *)pVal);
4673 break;
4674 case SOAPTYPE_BYTE:
4675 nVal = *((char *)pVal);
4676 break;
4677 case SOAPTYPE_POSITIVEINTEGER:
4678 case SOAPTYPE_NONNEGATIVEINTEGER:
4679 case SOAPTYPE_UNSIGNEDLONG:
4680 unsigned __int64 n;
4681 n = *((unsigned __int64 *)pVal);
4682 if (n > _I64_MAX)
4684 // come on ...
4685 nVal = 0;
4687 else
4689 nVal = (__int64)n;
4691 break;
4692 case SOAPTYPE_UNSIGNEDINT:
4693 nVal = *((unsigned int *)pVal);
4694 break;
4695 case SOAPTYPE_UNSIGNEDSHORT:
4696 nVal = *((unsigned short *)pVal);
4697 break;
4698 case SOAPTYPE_UNSIGNEDBYTE:
4699 nVal = *((unsigned char *)pVal);
4700 break;
4701 default:
4702 nVal = 0;
4705 if (nVal < 0)
4707 nVal = 0;
4710 return (size_t) nVal;
4713 HRESULT GenerateArrayInfo(const _soapmapentry *pEntry, const int *pDims, IWriteStream *pStream)
4715 ATLENSURE_RETURN( pEntry != NULL );
4716 ATLENSURE_RETURN( pStream != NULL );
4718 HRESULT hr = S_OK;
4719 if (pEntry->nVal != SOAPTYPE_UNK)
4721 // xsd type
4722 hr = pStream->WriteStream(" soapenc:arrayType=\"xsd:",
4723 sizeof(" soapenc:arrayType=\"xsd:")-1, NULL);
4725 else
4727 ATLENSURE_RETURN( pEntry->pChain != NULL );
4729 hr = pStream->WriteStream(" xmlns:q1=\"", sizeof(" xmlns:q1=\"")-1, NULL);
4730 if (SUCCEEDED(hr))
4732 if (pEntry->pChain->szNamespace != NULL)
4734 hr = pStream->WriteStream(pEntry->pChain->szNamespace, pEntry->pChain->cchNamespace, NULL);
4736 else
4738 hr = pStream->WriteStream(GetNamespaceUriA(), -1, NULL);
4740 if (SUCCEEDED(hr))
4742 hr = pStream->WriteStream("\"", 1, NULL);
4743 if (SUCCEEDED(hr))
4745 hr = pStream->WriteStream(" soapenc:arrayType=\"q1:",
4746 sizeof(" soapenc:arrayType=\"q1:")-1, NULL);
4752 if (FAILED(hr))
4754 return hr;
4757 if (pEntry->nVal != SOAPTYPE_UNK)
4759 hr = pStream->WriteStream(s_xsdNames[pEntry->nVal].szName ,
4760 s_xsdNames[pEntry->nVal].cchName, NULL);
4762 else
4764 ATLASSERT( pEntry->pChain != NULL );
4766 hr = pStream->WriteStream(pEntry->pChain->szName, pEntry->pChain->cchName, NULL);
4769 if (FAILED(hr))
4771 return hr;
4774 hr = pStream->WriteStream("[", 1, NULL);
4775 if (FAILED(hr))
4777 return hr;
4780 CWriteStreamHelper s( pStream );
4781 for (int i=1; i<=pDims[0]; i++)
4783 if (!s.Write(pDims[i]) ||
4784 ((i < pDims[0]) && (S_OK != pStream->WriteStream(", ", 2, NULL))))
4786 return E_FAIL;
4790 hr = pStream->WriteStream("]\"", 2, NULL);
4791 if (FAILED(hr))
4793 return hr;
4796 return S_OK;
4799 HRESULT GenerateXSDWrapper(bool bStart, int nVal, bool bNull, IWriteStream *pStream)
4801 ATLENSURE_RETURN( pStream != NULL );
4803 HRESULT hr = pStream->WriteStream((bStart != false) ? "<" : "</",
4804 (bStart != false) ? 1 : 2, NULL);
4805 if (SUCCEEDED(hr))
4807 hr = pStream->WriteStream(s_xsdNames[nVal].szName,
4808 s_xsdNames[nVal].cchName, NULL);
4809 if ((bNull != false) && (SUCCEEDED(hr)))
4811 hr = pStream->WriteStream(" xsi:nil=\"1\"", sizeof(" xsi:nil=\"1\"")-1, NULL);
4813 if (SUCCEEDED(hr))
4815 hr = pStream->WriteStream(">", 1, NULL);
4819 return hr;
4822 HRESULT GenerateGenericWrapper(bool bStart, const _soapmap *pMap, IWriteStream *pStream)
4824 ATLENSURE_RETURN( pStream != NULL );
4825 ATLENSURE_RETURN( pMap != NULL );
4827 HRESULT hr = pStream->WriteStream((bStart != false) ? "<" : "</",
4828 (bStart != false) ? 1 : 2, NULL);
4829 if (SUCCEEDED(hr))
4831 hr = pStream->WriteStream(pMap->szName, pMap->cchName, NULL);
4832 if (SUCCEEDED(hr))
4834 hr = pStream->WriteStream(">", 1, NULL);
4838 return hr;
4841 HRESULT GetArrayInformation(
4842 IWriteStream *pStream,
4843 const _soapmap *pMap,
4844 const _soapmapentry *pEntry,
4845 void *pvParam,
4846 size_t &nCnt,
4847 size_t &nElementSize)
4849 ATLENSURE_RETURN( pStream != NULL );
4850 ATLENSURE_RETURN( pMap != NULL );
4851 ATLENSURE_RETURN( pEntry != NULL );
4852 ATLENSURE_RETURN( pvParam != NULL );
4854 const int *pDims = NULL;
4855 int arrDims[2] = { 0 };
4857 if (pEntry->dwFlags & SOAPFLAG_FIXEDARR)
4859 pDims = pEntry->pDims;
4861 else
4863 ATLASSERT( pEntry->dwFlags & SOAPFLAG_DYNARR );
4864 nCnt = GetSizeIsValue(pvParam, pMap, pEntry);
4866 if (nCnt == 0)
4868 // array size should only be zero if array is NULL
4869 // did you forget to set the array size?
4870 ATLASSERT( FALSE );
4871 return E_FAIL;
4874 arrDims[0] = 1;
4875 arrDims[1] = (int) nCnt;
4877 pDims = arrDims;
4880 // output array information
4881 HRESULT hr = GenerateArrayInfo(pEntry, pDims, pStream);
4882 if (FAILED(hr))
4884 return hr;
4886 if (SUCCEEDED(hr))
4888 nCnt = AtlSoapGetArrayDims(pDims);
4890 // did you forget to set the size_is value?
4891 ATLASSERT( nCnt != 0 );
4893 if (pEntry->nVal != SOAPTYPE_UNK)
4895 nElementSize = AtlSoapGetElementSize((SOAPTYPES) pEntry->nVal);
4897 else
4899 ATLENSURE_RETURN( pEntry->pChain != NULL );
4901 nElementSize = pEntry->pChain->nElementSize;
4905 return hr;
4908 HRESULT GenerateEnum(IWriteStream *pStream, void *pVal, const _soapmapentry *pEntry, bool bArray)
4910 ATLENSURE_RETURN( pStream != NULL );
4911 ATLENSURE_RETURN( pVal != NULL );
4912 ATLENSURE_RETURN( pEntry != NULL );
4914 int nVal = *((int *)pVal);
4915 const _soapmapentry *pEnumEntries = pEntry->pChain->pEntries;
4917 ATLENSURE_RETURN( pEnumEntries != NULL );
4918 size_t j;
4919 HRESULT hr = E_FAIL;
4920 for (j=0; pEnumEntries[j].nHash != 0; j++)
4922 if (nVal == pEnumEntries[j].nVal)
4924 hr = pStream->WriteStream(pEnumEntries[j].szField, pEnumEntries[j].cchField, NULL);
4925 if ((bArray != false) && (SUCCEEDED(hr)))
4927 hr = GenerateGenericWrapper(false, pEntry->pChain, pStream);
4929 break;
4933 return hr;
4936 HRESULT GenerateHeaders(CResponseGenerator *pGenerator, const _soapmap *pMap, IWriteStream *pStream)
4938 ATLENSURE_RETURN( pStream != NULL );
4939 ATLENSURE_RETURN( pMap != NULL );
4941 ATLENSURE_RETURN( pGenerator != NULL );
4943 DWORD dwIncludeFlags = SOAPFLAG_OUT;
4944 if (m_bClient != false)
4946 dwIncludeFlags = SOAPFLAG_IN;
4949 size_t nCnt = 0;
4950 for (size_t i=0; pMap->pEntries[i].nHash != 0; i++)
4952 if (pMap->pEntries[i].dwFlags & dwIncludeFlags)
4954 nCnt++;
4958 // no headers to be sent
4959 if (nCnt == 0)
4961 return S_OK;
4964 HRESULT hr = pGenerator->StartHeaders(pStream, pMap);
4965 if (SUCCEEDED(hr))
4967 hr = GenerateResponseHelper(pGenerator, pMap, GetHeaderValue(), pStream);
4968 if (SUCCEEDED(hr))
4970 hr = pGenerator->EndHeaders(pStream);
4974 return hr;
4977 bool IsNullElement(const _soapmapentry *pEntry, void *pVal, DWORD dwExcludeFlags=0)
4979 ATLENSURE( pEntry != NULL );
4980 ATLENSURE( pVal != NULL );
4982 bool bNull = false;
4984 DWORD dwFlags = pEntry->dwFlags & ~dwExcludeFlags;
4986 if (dwFlags & SOAPFLAG_DYNARR)
4988 unsigned char **ppArr = (unsigned char **)pVal;
4989 if (*ppArr == NULL)
4991 bNull = true;
4994 else if (pEntry->nVal == SOAPTYPE_STRING)
4996 BSTR *pBSTR = (BSTR *)pVal;
4997 if (*pBSTR == NULL)
4999 bNull = true;
5002 else if ((pEntry->nVal == SOAPTYPE_BASE64BINARY) || (pEntry->nVal == SOAPTYPE_HEXBINARY))
5004 if (((ATLSOAP_BLOB *)pVal)->data == NULL)
5006 bNull = true;
5010 return bNull;
5013 HRESULT GenerateNull(IWriteStream *pStream)
5015 ATLENSURE_RETURN( pStream != NULL );
5016 return pStream->WriteStream(" xsi:nil=\"1\"/>", sizeof(" xsi:nil=\"1\"/>")-1, NULL);
5019 HRESULT GenerateResponseHelper(CResponseGenerator *pGenerator, const _soapmap *pMap, void *pvParam, IWriteStream *pStream,
5020 bool bArrayElement = false)
5022 ATLENSURE_RETURN( pGenerator != NULL );
5023 ATLENSURE_RETURN( pMap != NULL );
5024 ATLENSURE_RETURN( pStream != NULL );
5026 HRESULT hr = S_OK;
5028 if ((bArrayElement != false) &&
5029 ((pMap->dwCallFlags & SOAPFLAG_PAD)==0))
5031 hr = pGenerator->StartMap(pStream, pMap, m_bClient);
5032 if (FAILED(hr))
5034 return hr;
5038 ATLENSURE_RETURN( pMap->pEntries != NULL );
5040 const _soapmapentry *pEntries = pMap->pEntries;
5041 size_t i;
5043 DWORD dwIncludeFlags;
5044 DWORD dwExcludeFlags;
5045 if (m_bClient != false)
5047 dwIncludeFlags = SOAPFLAG_IN;
5048 dwExcludeFlags = SOAPFLAG_OUT;
5050 else
5052 dwIncludeFlags = SOAPFLAG_OUT;
5053 dwExcludeFlags = SOAPFLAG_IN;
5056 for (i=0; pEntries[i].nHash != 0; i++)
5058 if (((pEntries[i].dwFlags & dwIncludeFlags) ||
5059 ((pEntries[i].dwFlags & dwExcludeFlags)==0)) &&
5060 ((pEntries[i].dwFlags & SOAPFLAG_NOMARSHAL)==0))
5062 hr = pGenerator->StartEntry(pStream, pMap, &pEntries[i]);
5063 if (FAILED(hr))
5065 return hr;
5068 size_t nElementSize = 0;
5069 size_t nCnt = 1;
5071 ATLASSERT( pvParam != NULL );
5073 void *pvCurrent = ((unsigned char *)pvParam)+pEntries[i].nOffset;
5075 if (IsNullElement(&pEntries[i], pvCurrent))
5077 hr = GenerateNull(pStream);
5078 if (SUCCEEDED(hr))
5080 continue;
5082 return hr;
5085 bool bArray = (pEntries[i].dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR)) != 0;
5086 if (bArray != false)
5088 hr = GetArrayInformation(pStream, pMap, &pEntries[i], pvParam, nCnt, nElementSize);
5091 hr = pStream->WriteStream(">", 1, NULL);
5092 if (FAILED(hr))
5094 return hr;
5097 for (size_t nElement=0; nElement<nCnt; nElement++)
5099 void *pVal;
5101 // get updated value
5102 if (bArray != false)
5104 if (pEntries[i].dwFlags & SOAPFLAG_FIXEDARR)
5106 unsigned char *ppArr = (unsigned char *)pvCurrent;
5107 pVal = ppArr+(nElement*nElementSize);
5109 else
5111 ATLASSERT( pEntries[i].dwFlags & SOAPFLAG_DYNARR );
5113 unsigned char **ppArr = (unsigned char **)pvCurrent;
5114 pVal = (*ppArr)+(nElement*nElementSize);
5117 else
5119 pVal = pvCurrent;
5122 if (pEntries[i].nVal != SOAPTYPE_UNK)
5124 bool bNull = false;
5125 if (bArray != false)
5127 bNull = IsNullElement(&pEntries[i], pVal, SOAPFLAG_DYNARR | SOAPFLAG_FIXEDARR);
5128 hr = GenerateXSDWrapper(true, pEntries[i].nVal, bNull, pStream);
5129 if (FAILED(hr))
5131 return hr;
5134 if (bNull == false)
5136 hr = AtlSoapGenElementValue(pVal, pStream, (SOAPTYPES) pEntries[i].nVal, GetMemMgr());
5138 if ((SUCCEEDED(hr)) && (bArray != false))
5140 hr = GenerateXSDWrapper(false, pEntries[i].nVal, false, pStream);
5143 if (FAILED(hr))
5145 return hr;
5148 else
5150 ATLASSERT( pEntries[i].pChain != NULL );
5152 if (pEntries[i].pChain->mapType != SOAPMAP_ENUM)
5154 // struct
5155 hr = GenerateResponseHelper(pGenerator, pEntries[i].pChain, pVal, pStream, bArray);
5157 else
5159 if (bArray != false)
5161 hr = GenerateGenericWrapper(true, pEntries[i].pChain, pStream);
5162 if (FAILED(hr))
5164 return hr;
5168 hr = GenerateEnum(pStream, pVal, &pEntries[i], bArray);
5173 // output element close
5174 if (SUCCEEDED(hr))
5176 hr = pGenerator->EndEntry(pStream, pMap, &pEntries[i]);
5180 if (FAILED(hr))
5182 return hr;
5186 if ((bArrayElement != false) &&
5187 ((pMap->dwCallFlags & SOAPFLAG_PAD)==0))
5189 // output type name
5190 hr = pGenerator->EndMap(pStream, pMap, m_bClient);
5193 return hr;
5196 void CleanupHelper(const _soapmap *pMap, void *pvParam)
5198 ATLENSURE( pMap != NULL );
5199 ATLENSURE( pMap->pEntries != NULL );
5201 if (pvParam == NULL)
5203 return;
5206 const _soapmapentry *pEntries = pMap->pEntries;
5207 size_t i;
5209 for (i=0; pEntries[i].nHash != 0; i++)
5211 if ((m_bClient != false) && ((pEntries[i].dwFlags & SOAPFLAG_OUT)==0))
5213 // skip in-only headers on the client
5214 continue;
5217 void *pvCheck = ((unsigned char *)pvParam)+pEntries[i].nOffset;
5218 if (IsNullElement(&pEntries[i], pvCheck))
5220 continue;
5223 size_t nElementSize = 0;
5224 size_t nCnt = 1;
5226 const int *pDims = NULL;
5227 int arrDims[2] = { 0 };
5229 bool bArray = (pEntries[i].dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR)) != 0;
5231 if (bArray != false)
5233 if (pEntries[i].dwFlags & SOAPFLAG_FIXEDARR)
5235 pDims = pEntries[i].pDims;
5237 else
5239 ATLASSERT( pEntries[i].dwFlags & SOAPFLAG_DYNARR );
5240 nCnt = GetSizeIsValue(pvParam, pMap, &pEntries[i]);
5242 arrDims[0] = 1;
5243 arrDims[1] = (int) nCnt;
5245 pDims = arrDims;
5248 nCnt = AtlSoapGetArrayDims(pDims);
5250 if (pEntries[i].nVal != SOAPTYPE_UNK)
5252 nElementSize = AtlSoapGetElementSize((SOAPTYPES) pEntries[i].nVal);
5254 else
5256 ATLENSURE( pEntries[i].pChain != NULL );
5258 nElementSize = pEntries[i].pChain->nElementSize;
5262 void *pvCurrent = ((unsigned char *)pvParam)+pEntries[i].nOffset;
5264 for (size_t nElement=0; nElement<nCnt; nElement++)
5266 void *pVal;
5268 // get updated value
5269 if (bArray != false)
5271 if (pEntries[i].dwFlags & SOAPFLAG_FIXEDARR)
5273 unsigned char *ppArr = (unsigned char *)pvCurrent;
5274 pVal = ppArr+(nElement*nElementSize);
5276 else
5278 ATLASSERT( pEntries[i].dwFlags & SOAPFLAG_DYNARR );
5280 unsigned char **ppArr = (unsigned char **)pvCurrent;
5281 if (*ppArr == NULL)
5283 break;
5285 pVal = (*ppArr)+(nElement*nElementSize);
5288 else
5290 pVal = pvCurrent;
5293 if (pEntries[i].nVal != SOAPTYPE_UNK)
5295 AtlSoapCleanupElement(pVal, (SOAPTYPES) pEntries[i].nVal, GetMemMgr());
5297 else
5299 ATLENSURE( pEntries[i].pChain != NULL );
5301 if (pEntries[i].pChain->mapType != SOAPMAP_ENUM)
5303 CleanupHelper(pEntries[i].pChain, pVal);
5308 if (pEntries[i].dwFlags & SOAPFLAG_DYNARR)
5310 // free it
5311 unsigned char **ppArr = (unsigned char **)pvCurrent;
5313 ATLENSURE( ppArr != NULL );
5315 if (*ppArr != NULL)
5317 m_pMemMgr->Free(*ppArr);
5318 *ppArr = NULL;
5324 const _soapmap * GetSoapMapFromName(
5325 const wchar_t * wszName,
5326 int cchName = -1,
5327 const wchar_t * wszNamespaceUri = NULL,
5328 int cchNamespaceUri = -1,
5329 int *pnVal = NULL,
5330 bool bHeader = false)
5332 (cchNamespaceUri);
5334 const _soapmap ** pEntry = NULL;
5336 if (bHeader == false)
5338 pEntry = GetFunctionMap();
5340 else
5342 pEntry = GetHeaderMap();
5345 if (pEntry == NULL)
5347 return NULL;
5350 if (cchName < 0)
5352 cchName = (int)wcslen(wszName);
5354 if ((cchNamespaceUri < 0) && (wszNamespaceUri != NULL))
5356 cchNamespaceUri = (int)wcslen(wszNamespaceUri);
5359 ULONG nFunctionHash = AtlSoapHashStr(wszName, cchName);
5360 ULONG nNamespaceHash = wszNamespaceUri ? AtlSoapHashStr(wszNamespaceUri, cchNamespaceUri) : 0;
5362 int i;
5363 for (i=0; pEntry[i] != NULL; i++)
5365 if ((IsEqualStringHash(wszName, cchName, nFunctionHash,
5366 pEntry[i]->wszName, pEntry[i]->cchWName, pEntry[i]->nHash) != FALSE) &&
5367 (!wszNamespaceUri ||
5368 IsEqualStringHash(wszNamespaceUri, cchNamespaceUri, nNamespaceHash,
5369 pEntry[i]->wszNamespace, pEntry[i]->cchNamespace, pEntry[i]->nNamespaceHash) != FALSE))
5371 break;
5375 if (pnVal != NULL)
5377 *pnVal = i;
5379 return pEntry[i];
5382 HRESULT CheckEndElement(const ParseState& state)
5384 // check for all elements
5385 if (state.nElement == state.nExpectedElements)
5387 return S_OK;
5390 // error check for fixed arrays
5391 if (state.dwFlags & SOAPFLAG_FIXEDARR)
5393 return E_FAIL;
5396 // check for dynamic arrays
5397 if (state.dwFlags & SOAPFLAG_DYNARR)
5399 // check for dynamic arrays with known size
5400 // (from soap:arrayType attribute)
5401 if ((state.dwFlags & SOAPFLAG_UNKSIZE)==0)
5403 return E_FAIL;
5407 DWORD dwIncludeFlags;
5408 DWORD dwExcludeFlags;
5410 if (m_bClient != false)
5412 dwIncludeFlags = SOAPFLAG_OUT;
5413 dwExcludeFlags = SOAPFLAG_IN;
5415 else
5417 dwIncludeFlags = SOAPFLAG_IN;
5418 dwExcludeFlags = SOAPFLAG_OUT;
5421 if (state.pMap != NULL)
5423 // ensure all omitted elements were nullable elements or nomarshal elements
5424 const _soapmapentry *pEntries = state.pMap->pEntries;
5425 for (size_t i=0; pEntries[i].nHash != 0; i++)
5427 if ((pEntries[i].dwFlags & dwIncludeFlags) ||
5428 ((pEntries[i].dwFlags & dwExcludeFlags)==0))
5430 if (state.vec.GetBit(i) == false)
5432 if (((pEntries[i].dwFlags & (SOAPFLAG_NULLABLE | SOAPFLAG_NOMARSHAL))==0) && (pEntries[i].nVal != SOAPTYPE_UNK))
5434 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckEndElement -- invalid number of elements for parameter/field\r\n") );
5435 return E_FAIL;
5442 return S_OK;
5445 HRESULT CheckSoapHeaders(const ParseState &state)
5447 DWORD dwIncludeFlags;
5448 DWORD dwExcludeFlags;
5450 if (m_bClient != false)
5452 dwIncludeFlags = SOAPFLAG_OUT;
5453 dwExcludeFlags = SOAPFLAG_IN;
5455 else
5457 dwIncludeFlags = SOAPFLAG_IN;
5458 dwExcludeFlags = SOAPFLAG_OUT;
5461 if (state.pMap != NULL)
5463 ATLASSERT( state.pMap->mapType == SOAPMAP_HEADER );
5465 // ensure all omitted elements were nullable elements, nomarshal elements, or non-required elements
5466 const _soapmapentry *pEntries = state.pMap->pEntries;
5467 for (size_t i=0; pEntries[i].nHash != 0; i++)
5469 if ((pEntries[i].dwFlags & dwIncludeFlags) ||
5470 ((pEntries[i].dwFlags & dwExcludeFlags)==0))
5472 if (state.vec.GetBit(i) == false)
5474 bool bNoOmit = (pEntries[i].dwFlags & (SOAPFLAG_NULLABLE | SOAPFLAG_NOMARSHAL))==0;
5476 if ((bNoOmit != false) ||
5477 ((bNoOmit != false) && (pEntries[i].dwFlags & SOAPFLAG_MUSTUNDERSTAND)))
5479 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::CheckSoapHeaders -- missing header\r\n") );
5480 return E_FAIL;
5487 return S_OK;
5490 HRESULT CheckEndHeaders(
5491 const wchar_t * wszNamespaceUri,
5492 int cchNamespaceUri,
5493 const wchar_t * wszLocalName,
5494 int cchLocalName)
5496 if (IsEqualElement(sizeof(SOAP_HEADERA)-1, SOAP_HEADERW,
5497 sizeof(SOAPENV_NAMESPACEA)-1, SOAPENV_NAMESPACEW,
5498 cchLocalName, wszLocalName,
5499 cchNamespaceUri, wszNamespaceUri))
5501 m_dwState = SOAP_HEADERS_DONE;
5502 return S_OK;
5505 // some sort of error
5506 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::endElement -- invalid SOAP message format while processing headers.\r\n" ) );
5508 return E_FAIL;
5511 protected:
5513 ISAXXMLReader * SetReader(ISAXXMLReader *pReader)
5515 ISAXXMLReader *pPrevRdr = m_spReader;
5516 m_spReader = pReader;
5518 return pPrevRdr;
5521 ISAXXMLReader * GetReader()
5523 return m_spReader;
5526 HRESULT SetSoapMapFromName(
5527 const wchar_t * wszName,
5528 int cchName = -1,
5529 const wchar_t * wszNamespaceUri = NULL,
5530 int cchNamespaceUri = -1,
5531 bool bHeader = false)
5533 ATLENSURE_RETURN( wszName != NULL );
5535 int nVal;
5536 const _soapmap *pMap = NULL;
5537 if (m_stateStack.GetCount() != 0)
5539 ATLASSUME( m_stateStack[0].pMap != NULL );
5540 nVal = (int) m_stateStack[0].nAllocSize;
5541 ATLASSERT( GetFunctionMap() != NULL );
5542 pMap = GetFunctionMap()[nVal];
5544 else
5546 pMap = GetSoapMapFromName(wszName, cchName,
5547 wszNamespaceUri, cchNamespaceUri, &nVal, bHeader);
5550 if (pMap == NULL)
5552 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::SetSoapMapFromName -- _soapmap not found for: %.*ws, with namespace %.*ws\r\n"),
5553 (int)wcslen(wszName), wszName, wszNamespaceUri ? (int)wcslen(wszNamespaceUri) : 0, wszNamespaceUri ? wszNamespaceUri : L"");
5555 return E_FAIL;
5558 HRESULT hr = E_OUTOFMEMORY;
5560 // allocate the parameter struct
5562 void *pvParam = NULL;
5563 if (bHeader != false)
5565 pvParam = GetHeaderValue();
5567 else
5569 if (m_bClient == false)
5571 m_pvParam = m_pMemMgr->Allocate(pMap->nElementSize);
5573 pvParam = m_pvParam;
5576 if (pvParam != NULL)
5578 if (bHeader == false)
5580 memset(pvParam, 0x00, pMap->nElementSize);
5583 // push initial state
5585 if (m_stateStack.GetCount() != 0)
5587 m_stateStack.RemoveAll();
5590 hr = PushState(pvParam, pMap, NULL, 0, nVal, pMap->nElements);
5592 if (FAILED(hr))
5594 if ((m_bClient == false) && (bHeader == false))
5596 m_pMemMgr->Free(pvParam);
5601 #ifdef _DEBUG
5602 if (hr == E_OUTOFMEMORY)
5604 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::SetSoapMapFromName -- out of memory.\r\n" ) );
5606 #endif // _DEBUG
5608 return hr;
5611 // implementation
5612 virtual const _soapmap ** GetFunctionMap() = 0;
5613 virtual const _soapmap ** GetHeaderMap() = 0;
5614 virtual const wchar_t * GetNamespaceUri() = 0;
5615 virtual const char * GetServiceName() = 0;
5616 virtual const char * GetNamespaceUriA() = 0;
5617 virtual HRESULT CallFunction(
5618 void *pvParam,
5619 const wchar_t *wszLocalName, int cchLocalName,
5620 size_t nItem) = 0;
5621 virtual void * GetHeaderValue() = 0;
5623 public:
5625 CSoapRootHandler(ISAXXMLReader *pReader = NULL)
5626 : m_pMemMgr(&m_crtHeap), m_spReader(pReader), m_bClient(false),
5627 m_nState(0), m_pvParam(NULL), m_nDepth(0)
5629 InitHandlerState();
5631 virtual ~CSoapRootHandler()
5633 m_skipHandler.DetachParent();
5636 IAtlMemMgr * SetMemMgr(IAtlMemMgr *pMemMgr)
5638 IAtlMemMgr *pPrevMgr = m_pMemMgr;
5639 m_pMemMgr = pMemMgr;
5641 return pPrevMgr;
5644 IAtlMemMgr * GetMemMgr()
5646 return m_pMemMgr;
5649 // override this function to do SOAP Fault handling
5650 virtual HRESULT SoapFault(
5651 SOAP_ERROR_CODE /*errCode*/,
5652 const wchar_t * /*wszDetail*/,
5653 int /*cchDetail*/)
5655 if (m_bClient != false)
5657 return S_OK;
5660 // SOAP servers must implement this function
5661 ATLASSERT( FALSE );
5662 return E_FAIL;
5666 // implementation
5669 void InitHandlerState()
5671 m_bNullCheck = false;
5672 m_bCharacters = false;
5673 m_bChildCheck = false;
5674 m_dwState = SOAP_START;
5676 HRESULT __stdcall startDocument()
5678 InitHandlerState();
5679 return S_OK;
5682 HRESULT __stdcall startElement(
5683 const wchar_t *wszNamespaceUri,
5684 int cchNamespaceUri,
5685 const wchar_t *wszLocalName,
5686 int cchLocalName,
5687 const wchar_t * wszQName,
5688 int cchQName,
5689 ISAXAttributes *pAttributes)
5691 if (m_bNullCheck || m_bCharacters)
5693 // make sure elements that aren't supposed to have child elements
5694 // do not have child elements, and where we were expecting
5695 // characters, we got them
5696 return E_FAIL;
5699 m_bChildCheck = false;
5700 ++m_nDepth;
5702 HRESULT hr = S_OK;
5703 switch (m_dwState)
5705 case SOAP_PARAMS: case SOAP_HEADERS:
5707 hr = ProcessParams(wszNamespaceUri, cchNamespaceUri, wszLocalName,
5708 cchLocalName, pAttributes);
5710 break;
5712 case SOAP_START: case SOAP_ENVELOPE: case SOAP_HEADERS_DONE:
5714 ULONG nNamespaceHash = AtlSoapHashStr(wszNamespaceUri,
5715 cchNamespaceUri);
5716 if (nNamespaceHash != SOAP_ENV)
5718 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::startElement -- incorrect SOAP-ENV namespace.\r\n" ) );
5720 return E_FAIL;
5723 ULONG nElementHash = AtlSoapHashStr(wszLocalName, cchLocalName);
5725 if (nElementHash == ENVELOPE &&
5726 IsEqualElement(
5727 sizeof(SOAP_ENVELOPEA)-1, SOAP_ENVELOPEW,
5728 sizeof(SOAPENV_NAMESPACEA)-1, SOAPENV_NAMESPACEW,
5729 cchLocalName, wszLocalName,
5730 cchNamespaceUri, wszNamespaceUri))
5732 // Envelope must be first element in package
5734 if (m_dwState != SOAP_START)
5736 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::startElement -- invalid SOAP message format: \"Envelope\" in unexpected location.\r\n" ) );
5738 hr = E_FAIL;
5740 m_dwState = SOAP_ENVELOPE;
5742 else if (nElementHash == HEADER &&
5743 IsEqualElement(sizeof(SOAP_HEADERA)-1, SOAP_HEADERW,
5744 sizeof(SOAPENV_NAMESPACEA)-1, SOAPENV_NAMESPACEW,
5745 cchLocalName, wszLocalName,
5746 cchNamespaceUri, wszNamespaceUri))
5748 if (m_dwState != SOAP_ENVELOPE)
5750 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::startElement -- invalid SOAP message format: \"Headers\" in unexpected location.\r\n" ) );
5752 hr = E_FAIL;
5755 m_dwState = SOAP_HEADERS;
5757 else if (nElementHash == BODY &&
5758 IsEqualElement(sizeof(SOAP_BODYA)-1, SOAP_BODYW,
5759 sizeof(SOAPENV_NAMESPACEA)-1, SOAPENV_NAMESPACEW,
5760 cchLocalName, wszLocalName,
5761 cchNamespaceUri, wszNamespaceUri))
5763 if (m_dwState == SOAP_START)
5765 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::startElement -- invalid SOAP message format: \"Body\" in unexpected location.\r\n" ) );
5767 hr = E_FAIL;
5769 m_dwState = SOAP_BODY;
5772 break;
5774 case SOAP_BODY:
5776 hr = DispatchSoapCall(wszNamespaceUri, cchNamespaceUri,
5777 wszLocalName, cchLocalName);
5779 m_dwState = SOAP_PARAMS;
5781 if (SUCCEEDED(hr))
5783 if (GetState().pMap->dwCallFlags & SOAPFLAG_PAD)
5785 hr = startElement(wszNamespaceUri, cchNamespaceUri,
5786 wszLocalName, cchLocalName, wszQName, cchQName,
5787 pAttributes);
5791 break;
5794 #ifdef _DEBUG
5796 default:
5798 // should never get here -- internal error
5799 ATLASSERT( FALSE );
5802 #endif // _DEBUG
5805 return hr;
5808 HRESULT __stdcall characters(
5809 const wchar_t *wszChars,
5810 int cchChars)
5812 m_bCharacters = false;
5814 // if it is a ready state, get the value
5815 if (m_stateStack.IsEmpty() == false)
5817 ParseState& state = GetState();
5818 if ((state.dwFlags & SOAPFLAG_READYSTATE) &&
5819 ((state.dwFlags & SOAPFLAG_SIZEIS)==0)) // don't marshal struct size_is elements -- should be filled in by array marshaling code
5821 if ((state.pMap == NULL) || (state.pMap->mapType != SOAPMAP_ENUM))
5823 return AtlSoapGetElementValue(wszChars, cchChars,
5824 state.pvElement, (SOAPTYPES)state.pEntry->nVal, GetMemMgr());
5826 else
5828 // enum
5830 ATLASSERT( state.pMap != NULL );
5831 ATLASSERT( state.pMap->pEntries != NULL );
5833 ULONG nHash = AtlSoapHashStr(wszChars, cchChars);
5834 const _soapmapentry *pEntries = state.pMap->pEntries;
5836 size_t i;
5837 for (i=0; pEntries[i].nHash != 0; i++)
5839 if ((nHash == pEntries[i].nHash) &&
5840 (cchChars == pEntries[i].cchField) &&
5841 (!wcsncmp(wszChars, pEntries[i].wszField, cchChars)))
5843 break;
5847 if (pEntries[i].nHash != 0)
5849 *((int *)state.pvElement) = pEntries[i].nVal;
5850 state.nElement++;
5851 return S_OK;
5854 // no matching enum entry found
5855 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::characters -- no matching enum entry found for: %.*ws.\r\n" ), cchChars, wszChars );
5857 return E_FAIL;
5862 // otherwise, ignore
5864 return S_OK;
5867 HRESULT __stdcall endElement(
5868 const wchar_t * wszNamespaceUri,
5869 int cchNamespaceUri,
5870 const wchar_t * wszLocalName,
5871 int cchLocalName,
5872 const wchar_t * /*wszQName*/,
5873 int /*cchQName*/)
5875 static bool bDynArrWrapper = false;
5876 if (m_bCharacters)
5878 return E_FAIL;
5881 m_bNullCheck = false;
5883 if (m_stateStack.IsEmpty() != false)
5885 return S_OK;
5888 if (!bDynArrWrapper && (m_nState > 1))
5890 ParseState prevState = m_stateStack.GetAt(m_nState - 1);
5891 ParseState curState = m_stateStack.GetAt(m_nState);
5892 if (prevState.dwFlags & SOAPFLAG_DYNARRWRAPPER)
5894 bDynArrWrapper = true;
5895 endElement (wszNamespaceUri, cchNamespaceUri, curState.pEntry->wszField,
5896 curState.pEntry->cchField, NULL, 0);
5899 else
5901 bDynArrWrapper = false;
5904 --m_nDepth;
5906 const ParseState& state = GetState();
5908 if ((m_dwState == SOAP_HEADERS) && (m_stateStack.GetCount() == 1))
5910 return CheckEndHeaders(wszNamespaceUri, cchNamespaceUri, wszLocalName, cchLocalName);
5913 if (state.dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))
5915 if (state.dwFlags & SOAPFLAG_READYSTATE)
5917 PopState();
5920 const ParseState& currstate = GetState();
5921 ATLENSURE_RETURN( currstate.pEntry != NULL );
5923 if (m_nDepth == (currstate.nDepth-1))
5925 if (S_OK != CheckEndElement(currstate))
5927 // invalid number of elements
5928 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::endElement -- invalid number of array elements for array parameter %.*ws.\r\n"),
5929 currstate.pEntry->cchField, currstate.pEntry->wszField );
5931 return E_FAIL;
5934 PopState();
5937 else
5939 if (S_OK != CheckEndElement(state))
5941 return E_FAIL;
5944 PopState();
5947 return S_OK;
5950 HRESULT SetClientStruct(void *pvParam, int nMapIndex)
5952 ATLENSURE_RETURN( pvParam != NULL );
5953 ATLENSURE_RETURN( nMapIndex >= 0 );
5955 // this is the params struct
5956 // store for later use
5957 m_pvParam = pvParam;
5959 const _soapmap ** pEntries = GetHeaderMap();
5960 ATLENSURE_RETURN( pEntries != NULL );
5962 // push header value
5963 return PushState(GetHeaderValue(), pEntries[nMapIndex], NULL, 0, nMapIndex, pEntries[nMapIndex]->nElements);
5966 void ResetClientState(bool bFull = false)
5968 m_stateStack.RemoveAll();
5969 m_nState = 0;
5970 if (bFull != false)
5972 m_dwState = SOAP_START;
5973 m_pvParam = NULL;
5977 HRESULT CreateReader()
5979 return m_spReader.CoCreateInstance(ATLS_SAXXMLREADER_CLSID, NULL, CLSCTX_INPROC_SERVER);
5982 HRESULT InitializeSOAP(IServiceProvider *pProvider)
5984 HRESULT hr = S_OK;
5986 if (m_spReader.p == NULL)
5988 hr = E_FAIL;
5989 if (pProvider != NULL)
5991 IAtlMemMgr *pMemMgr = NULL;
5992 hr = pProvider->QueryService(__uuidof(IAtlMemMgr),
5993 __uuidof(IAtlMemMgr), (void **)&pMemMgr);
5994 if ((SUCCEEDED(hr)) && (pMemMgr != NULL))
5996 SetMemMgr(pMemMgr);
5999 hr = pProvider->QueryService(__uuidof(ISAXXMLReader),
6000 __uuidof(ISAXXMLReader), (void **)&m_spReader);
6003 if (FAILED(hr))
6005 hr = CreateReader();
6009 if (SUCCEEDED(hr))
6011 hr = m_spReader->putContentHandler(this);
6014 #ifdef _DEBUG
6015 else
6017 ATLTRACE( _T("ATLSOAP: CSoapRootHandler::InitializeSOAP -- failed to get SAXXMLReader.\r\n" ) );
6019 #endif // _DEBUG
6021 return hr;
6024 void UninitializeSOAP()
6026 if (m_spReader.p != NULL)
6028 m_spReader->putContentHandler(NULL);
6029 m_spReader.Release();
6033 virtual HRESULT DispatchSoapCall(const wchar_t *wszNamespaceUri,
6034 int cchNamespaceUri, const wchar_t *wszLocalName,
6035 int cchLocalName)
6037 HRESULT hr = S_OK;
6039 if (m_stateStack.IsEmpty() == false)
6041 ATLASSUME( m_stateStack[0].pMap != NULL );
6043 // check to see if all required and non-nullable SOAP headers were sent
6044 if (m_stateStack[0].pMap->mapType == SOAPMAP_HEADER)
6046 hr = CheckSoapHeaders(m_stateStack[0]);
6048 if (SUCCEEDED(hr))
6050 hr = SetSoapMapFromName(wszLocalName, cchLocalName,
6051 wszNamespaceUri, cchNamespaceUri);
6054 else
6056 // get the appropriate function map
6057 hr = SetSoapMapFromName(wszLocalName, cchLocalName,
6058 wszNamespaceUri, cchNamespaceUri);
6060 if (SUCCEEDED(hr))
6062 // set the SOAP Header map for the function
6063 ATLASSUME( m_stateStack.IsEmpty() == false );
6065 const _soapmap **ppHeaderMap = GetHeaderMap();
6066 ATLENSURE_RETURN( ppHeaderMap != NULL );
6068 // create a temporary parse state for checking headers
6069 ParseState state;
6070 state.pMap = ppHeaderMap[m_stateStack[0].nAllocSize];
6071 ATLENSURE_RETURN( state.pMap != NULL );
6073 // check to see if all required and non-nullable SOAP headers were sent
6074 hr = CheckSoapHeaders(state);
6078 return hr;
6081 virtual HRESULT BeginParse(IStream *pStream)
6083 ATLASSERT( pStream != NULL );
6085 CComVariant varStream;
6086 varStream = static_cast<IUnknown*>(pStream);
6088 HRESULT hr = m_spReader->parse(varStream);
6089 if (SUCCEEDED(hr))
6091 if (m_refMap.GetCount() != 0)
6093 hr = E_FAIL;
6096 return hr;
6099 HRESULT CallFunctionInternal()
6101 HRESULT hr = E_FAIL;
6102 const ParseState& state = m_stateStack[0];
6103 hr = CallFunction(
6104 state.pvElement,
6105 state.pMap->wszName,
6106 state.pMap->cchWName,
6107 state.nAllocSize);
6109 return hr;
6112 virtual HRESULT GenerateResponse(IWriteStream *pStream)
6114 ATLASSUME( m_stateStack.IsEmpty() == false );
6115 ATLASSUME( m_stateStack[0].pMap != NULL );
6116 ATLASSUME( m_stateStack[0].pvElement != NULL );
6118 const ParseState& state = m_stateStack[0];
6120 const _soapmap *pHeaderMap = NULL;
6121 if (m_bClient == false)
6123 const _soapmap **ppHeaderMap = GetHeaderMap();
6124 if (ppHeaderMap != NULL)
6126 pHeaderMap = ppHeaderMap[state.nAllocSize];
6129 else
6131 pHeaderMap = state.pMap;
6134 const _soapmap *pFuncMap = NULL;
6135 if (m_bClient == false)
6137 pFuncMap = state.pMap;
6139 else
6141 const _soapmap **ppFuncMap = GetFunctionMap();
6142 ATLENSURE_RETURN( ppFuncMap != NULL );
6143 pFuncMap = ppFuncMap[state.nAllocSize];
6146 ATLENSURE_RETURN( pFuncMap != NULL );
6148 CRpcEncodedGenerator rpcGen;
6149 CPADGenerator padGen;
6150 CPIDGenerator pidGen;
6152 CResponseGenerator *pGenerator = NULL;
6154 if ((pFuncMap->dwCallFlags & (SOAPFLAG_RPC | SOAPFLAG_ENCODED)) == (SOAPFLAG_RPC | SOAPFLAG_ENCODED))
6156 pGenerator = &rpcGen;
6158 else if (pFuncMap->dwCallFlags & SOAPFLAG_PID)
6160 ATLASSERT( (pFuncMap->dwCallFlags & (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL)) == (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL) );
6161 pGenerator = &pidGen;
6163 else
6165 ATLASSERT( (pFuncMap->dwCallFlags & (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL)) == (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL) );
6166 ATLASSERT( pFuncMap->dwCallFlags & SOAPFLAG_PAD );
6167 pGenerator = &padGen;
6170 HRESULT hr = pGenerator->StartEnvelope(pStream);
6171 if (SUCCEEDED(hr))
6173 // generate headers if necessary
6174 hr = GenerateHeaders(pGenerator, pHeaderMap, pStream);
6175 if (SUCCEEDED(hr))
6177 hr = pGenerator->StartBody(pStream);
6178 if (SUCCEEDED(hr))
6180 hr = GenerateResponseHelper(pGenerator, pFuncMap, m_pvParam, pStream, true);
6181 if (SUCCEEDED(hr))
6183 hr = pGenerator->EndBody(pStream);
6184 if (SUCCEEDED(hr))
6186 hr = pGenerator->EndEnvelope(pStream);
6193 return hr;
6196 virtual void Cleanup()
6198 // cleanup headers
6199 CleanupHeaders();
6201 if ((m_stateStack.IsEmpty() == false) && (m_pvParam != NULL))
6203 const _soapmap **ppFuncMap = GetFunctionMap();
6204 ATLENSURE( ppFuncMap != NULL );
6206 const _soapmap *pFuncMap = ppFuncMap[m_stateStack[0].nAllocSize];
6207 ATLENSURE( pFuncMap != NULL );
6209 CleanupHelper(pFuncMap, m_pvParam);
6210 if (m_bClient == false)
6212 m_pMemMgr->Free(m_pvParam);
6213 m_stateStack.RemoveAll();
6218 virtual void CleanupHeaders()
6220 if (m_stateStack.IsEmpty() == false)
6222 const _soapmap **ppHeaderMap = GetHeaderMap();
6223 ATLENSURE( ppHeaderMap != NULL );
6225 const _soapmap *pHeaderMap = ppHeaderMap[m_stateStack[0].nAllocSize];
6226 ATLENSURE( pHeaderMap != NULL );
6228 CleanupHelper(pHeaderMap, GetHeaderValue());
6232 void SetClient(bool bClient)
6234 m_bClient = bClient;
6237 }; // class CSoapRootHandler
6239 #define DECLARE_XSD_ENTRY( __name ) \
6240 { L ## __name, __name, sizeof(__name)-1 },
6242 __declspec(selectany) const CSoapRootHandler::XSDEntry CSoapRootHandler::s_xsdNames[] =
6244 DECLARE_XSD_ENTRY("string")
6245 DECLARE_XSD_ENTRY("boolean")
6246 DECLARE_XSD_ENTRY("float")
6247 DECLARE_XSD_ENTRY("double")
6248 DECLARE_XSD_ENTRY("decimal")
6249 DECLARE_XSD_ENTRY("duration")
6250 DECLARE_XSD_ENTRY("hexBinary")
6251 DECLARE_XSD_ENTRY("base64Binary")
6252 DECLARE_XSD_ENTRY("anyURI")
6253 DECLARE_XSD_ENTRY("ID")
6254 DECLARE_XSD_ENTRY("IDREF")
6255 DECLARE_XSD_ENTRY("ENTITY")
6256 DECLARE_XSD_ENTRY("NOTATION")
6257 DECLARE_XSD_ENTRY("QName")
6258 DECLARE_XSD_ENTRY("normalizedString")
6259 DECLARE_XSD_ENTRY("token")
6260 DECLARE_XSD_ENTRY("language")
6261 DECLARE_XSD_ENTRY("IDREFS")
6262 DECLARE_XSD_ENTRY("ENTITIES")
6263 DECLARE_XSD_ENTRY("NMTOKEN")
6264 DECLARE_XSD_ENTRY("NMTOKENS")
6265 DECLARE_XSD_ENTRY("Name")
6266 DECLARE_XSD_ENTRY("NCName")
6267 DECLARE_XSD_ENTRY("integer")
6268 DECLARE_XSD_ENTRY("nonPositiveInteger")
6269 DECLARE_XSD_ENTRY("negativeInteger")
6270 DECLARE_XSD_ENTRY("long")
6271 DECLARE_XSD_ENTRY("int")
6272 DECLARE_XSD_ENTRY("short")
6273 DECLARE_XSD_ENTRY("byte")
6274 DECLARE_XSD_ENTRY("nonNegativeInteger")
6275 DECLARE_XSD_ENTRY("unsignedLong")
6276 DECLARE_XSD_ENTRY("unsignedInt")
6277 DECLARE_XSD_ENTRY("unsignedShort")
6278 DECLARE_XSD_ENTRY("unsignedByte")
6279 DECLARE_XSD_ENTRY("positiveInteger")
6280 DECLARE_XSD_ENTRY("dateTime")
6281 DECLARE_XSD_ENTRY("time")
6282 DECLARE_XSD_ENTRY("date")
6283 DECLARE_XSD_ENTRY("gMonth")
6284 DECLARE_XSD_ENTRY("gYearMonth")
6285 DECLARE_XSD_ENTRY("gYear")
6286 DECLARE_XSD_ENTRY("gMonthDay")
6287 DECLARE_XSD_ENTRY("gDay")
6290 __declspec(selectany) CCRTHeap CSoapRootHandler::m_crtHeap;
6292 template <typename THandler>
6293 class CSoapHandler :
6294 public CSoapRootHandler,
6295 public CComObjectRootEx<CComMultiThreadModel>,
6296 public IRequestHandlerImpl<THandler>
6298 protected:
6300 HTTP_CODE m_hcErr;
6301 CHttpResponse *m_pHttpResponse;
6303 // heap for SOAP requests
6304 CWin32Heap m_heap;
6306 // default heap is COM heap (SOAP Servers can double as COM objects)
6307 CComHeap m_comHeap;
6309 public:
6311 BEGIN_COM_MAP(CSoapHandler<THandler>)
6312 COM_INTERFACE_ENTRY(ISAXContentHandler)
6313 COM_INTERFACE_ENTRY(IRequestHandler)
6314 END_COM_MAP()
6316 CSoapHandler()
6317 :m_pHttpResponse(NULL), m_hcErr(HTTP_SUCCESS)
6319 SetMemMgr(&m_comHeap);
6322 void SetHttpError(HTTP_CODE hcErr)
6324 m_hcErr = hcErr;
6327 HRESULT SoapFault(
6328 SOAP_ERROR_CODE errCode,
6329 const wchar_t *wszDetail,
6330 int cchDetail)
6332 ATLASSUME( m_pHttpResponse != NULL );
6334 SetHttpError(AtlsHttpError(500, SUBERR_NO_PROCESS));
6336 m_pHttpResponse->ClearHeaders();
6337 m_pHttpResponse->ClearContent();
6338 m_pHttpResponse->SetContentType("text/xml");
6339 m_pHttpResponse->SetStatusCode(500);
6341 CSoapFault fault;
6342 if (wszDetail != NULL)
6344 if (cchDetail < 0)
6346 cchDetail = (int) wcslen(wszDetail);
6349 _ATLTRY
6351 fault.m_strDetail.SetString(wszDetail, cchDetail);
6353 _ATLCATCHALL()
6355 ATLTRACE( _T("CSoapHandler::SoapFault -- out of memory.\r\n" ) );
6357 return E_OUTOFMEMORY;
6361 fault.m_soapErrCode = errCode;
6362 fault.GenerateFault(m_pHttpResponse);
6363 return S_OK;
6366 HTTP_CODE InitializeHandler(AtlServerRequest *pRequestInfo, IServiceProvider *pProvider)
6368 m_hcErr = IRequestHandlerImpl<THandler>::InitializeHandler(pRequestInfo, pProvider);
6369 if (m_hcErr == HTTP_SUCCESS)
6371 HRESULT hr = InitializeSOAP(m_spServiceProvider);
6372 if (SUCCEEDED(hr))
6374 // try to use the per-thread heap
6375 CIsapiWorker *pWorker = pRequestInfo->pExtension->GetThreadWorker();
6376 if (pWorker != NULL)
6378 m_heap.Attach(pWorker->m_hHeap, false);
6379 SetMemMgr(&m_heap);
6382 return m_hcErr;
6386 // some initialization failure
6387 CHttpResponse HttpResponse(pRequestInfo->pServerContext);
6388 m_pHttpResponse = &HttpResponse;
6390 SoapFault(SOAP_E_SERVER, NULL, 0);
6392 m_pHttpResponse = NULL;
6394 return m_hcErr;
6397 HTTP_CODE HandleRequest(AtlServerRequest *pRequestInfo, IServiceProvider * /*pProvider*/)
6399 // SOAPACTION header is required per the SOAP 1.1
6400 // mainly so firewalls can filter on it.
6401 char szBuf[ATL_URL_MAX_URL_LENGTH+1];
6402 szBuf[0] = '\0';
6403 DWORD dwLen = ATL_URL_MAX_URL_LENGTH;
6404 if ( m_spServerContext->GetServerVariable("HTTP_SOAPACTION", szBuf, &dwLen) != FALSE )
6406 if ( dwLen >= 2 )
6408 // drop the last "
6409 szBuf[dwLen-2] = '\0';
6410 char *szMethod = strrchr(szBuf, '#');
6411 if (szMethod != NULL)
6413 _ATLTRY
6415 // ignore return code here
6416 SetSoapMapFromName(CA2W( szMethod+1 ), -1, GetNamespaceUri(), -1, true);
6418 _ATLCATCHALL()
6420 return AtlsHttpError(500, ISE_SUBERR_OUTOFMEM);
6425 else
6427 // SOAP requestion that use the HTTP transport
6428 // must have a SOAPACTION header.
6429 return HTTP_ERROR(500, ISE_SUBERR_SOAPNOSOAPACTION);
6432 // set the header map
6433 CHttpResponse HttpResponse(pRequestInfo->pServerContext);
6434 m_pHttpResponse = &HttpResponse;
6436 CStreamOnServerContext s(pRequestInfo->pServerContext);
6438 #ifdef _DEBUG
6440 CSAXSoapErrorHandler err;
6441 GetReader()->putErrorHandler(&err);
6443 #endif // _DEBUG
6445 HRESULT hr = BeginParse(&s);
6447 #ifdef _DEBUG
6448 // release the error handler
6449 GetReader()->putErrorHandler(NULL);
6450 #endif // _DEBUG
6452 if (FAILED(hr))
6454 Cleanup();
6455 if (m_hcErr == HTTP_SUCCESS)
6457 SoapFault(SOAP_E_CLIENT, NULL, NULL);
6460 return m_hcErr;
6463 _ATLTRY
6465 hr = CallFunctionInternal();
6467 _ATLCATCHALL()
6469 // cleanup before propagating user exception
6470 Cleanup();
6471 HttpResponse.Detach();
6472 _ATLRETHROW;
6475 if (FAILED(hr))
6477 Cleanup();
6478 HttpResponse.ClearHeaders();
6479 HttpResponse.ClearContent();
6480 if (m_hcErr != HTTP_SUCCESS)
6482 HttpResponse.SetStatusCode(HTTP_ERROR_CODE(m_hcErr));
6483 return HTTP_SUCCESS_NO_PROCESS;
6485 HttpResponse.SetStatusCode(500);
6486 GenerateAppError(&HttpResponse, hr);
6487 return AtlsHttpError(500, SUBERR_NO_PROCESS);
6490 HttpResponse.SetContentType("text/xml");
6491 hr = GenerateResponse(&HttpResponse);
6492 Cleanup();
6493 if (FAILED(hr))
6495 SoapFault(SOAP_E_SERVER, NULL, 0);
6496 return m_hcErr;
6499 return HTTP_SUCCESS;
6502 virtual ATL_NOINLINE HRESULT GenerateAppError(IWriteStream *pStream, HRESULT hr)
6504 if (pStream == NULL)
6506 return E_INVALIDARG;
6509 LPWSTR pwszMessage = NULL;
6510 DWORD dwLen = ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
6511 NULL, hr, 0, (LPWSTR) &pwszMessage, 0, NULL);
6513 if (dwLen == 0)
6515 pwszMessage = L"Application Error";
6518 hr = SoapFault(SOAP_E_SERVER, pwszMessage, dwLen ? dwLen : -1);
6519 if (dwLen != 0)
6521 ::LocalFree(pwszMessage);
6524 return hr;
6527 void UninitializeHandler()
6529 UninitializeSOAP();
6534 // client error states
6535 enum SOAPCLIENT_ERROR
6537 SOAPCLIENT_SUCCESS=0, // everything succeeded
6538 SOAPCLIENT_INITIALIZE_ERROR, // initialization failed -- most likely an MSXML installation problem
6539 SOAPCLIENT_OUTOFMEMORY, // out of memory
6540 SOAPCLIENT_GENERATE_ERROR, // failed in generating the response
6541 SOAPCLIENT_CONNECT_ERROR, // failed connecting to server
6542 SOAPCLIENT_SEND_ERROR, // failed in sending message
6543 SOAPCLIENT_SERVER_ERROR, // server error
6544 SOAPCLIENT_SOAPFAULT, // a SOAP Fault was returned by the server
6545 SOAPCLIENT_PARSEFAULT_ERROR, // failed in parsing SOAP fault
6546 SOAPCLIENT_READ_ERROR, // failed in reading response
6547 SOAPCLIENT_PARSE_ERROR // failed in parsing response
6550 template <typename TSocketClass = ZEvtSyncSocket>
6551 class CSoapSocketClientT
6553 private:
6555 CUrl m_url;
6556 CWriteStreamOnCString m_writeStream;
6557 CReadStreamOnSocket<TSocketClass> m_readStream;
6558 DWORD m_dwTimeout;
6560 SOAPCLIENT_ERROR m_errorState;
6562 protected:
6564 virtual HRESULT GetClientReader(ISAXXMLReader **pReader)
6566 if (pReader == NULL)
6568 return E_POINTER;
6570 *pReader = NULL;
6572 CComPtr<ISAXXMLReader> spReader;
6573 HRESULT hr = spReader.CoCreateInstance(ATLS_SAXXMLREADER_CLSID, NULL, CLSCTX_INPROC_SERVER);
6574 if (SUCCEEDED(hr))
6576 *pReader = spReader.Detach();
6578 return hr;
6581 public:
6583 // note : not shared across stock client implementations
6584 CAtlHttpClientT<TSocketClass> m_socket;
6586 CSoapFault m_fault;
6588 // constructor
6589 CSoapSocketClientT(LPCTSTR szUrl)
6590 : m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
6592 TCHAR szTmp[ATL_URL_MAX_URL_LENGTH];
6593 if(AtlEscapeUrl(szUrl,szTmp,0,ATL_URL_MAX_URL_LENGTH-1,ATL_URL_BROWSER_MODE))
6594 m_url.CrackUrl(szTmp);
6597 CSoapSocketClientT(LPCTSTR szServer, LPCTSTR szUri, ATL_URL_PORT nPort=80)
6598 : m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
6600 ATLASSERT( szServer != NULL );
6601 ATLASSERT( szUri != NULL );
6603 m_url.SetUrlPath(szUri);
6604 m_url.SetHostName(szServer);
6605 m_url.SetPortNumber(nPort);
6608 ~CSoapSocketClientT()
6610 CleanupClient();
6613 SOAPCLIENT_ERROR GetClientError()
6615 return m_errorState;
6618 void SetClientError(SOAPCLIENT_ERROR errorState)
6620 m_errorState = errorState;
6623 IWriteStream * GetWriteStream()
6625 return &m_writeStream;
6628 HRESULT GetReadStream(IStream **ppStream)
6630 if (ppStream == NULL)
6632 return E_POINTER;
6635 *ppStream = &m_readStream;
6636 return S_OK;
6639 void CleanupClient()
6641 m_writeStream.Cleanup();
6642 m_fault.Clear();
6643 SetClientError(SOAPCLIENT_SUCCESS);
6646 HRESULT SendRequest(LPCTSTR szAction)
6648 HRESULT hr = E_FAIL;
6649 _ATLTRY
6651 // create extra headers to send with request
6652 CFixedStringT<CString, 256> strExtraHeaders(szAction);
6653 strExtraHeaders.Append(_T("Accept: text/xml\r\n"), sizeof("Accept: text/xml\r\n")-1);
6654 CAtlNavigateData navData;
6655 navData.SetMethod(ATL_HTTP_METHOD_POST);
6656 navData.SetPort(m_url.GetPortNumber());
6657 navData.SetExtraHeaders(strExtraHeaders);
6658 navData.SetPostData((LPBYTE)(LPCSTR) m_writeStream.m_str, m_writeStream.m_str.GetLength(), _T("text/xml; charset=utf-8"));
6660 ATLSOAP_TRACE( (LPBYTE)(LPCSTR)m_writeStream.m_str, m_writeStream.m_str.GetLength() );
6662 if (m_dwTimeout != 0)
6664 navData.SetSocketTimeout(m_dwTimeout);
6667 if (m_socket.Navigate(&m_url, &navData) != false)
6669 if (GetStatusCode() == 200)
6671 hr = (m_readStream.Init(&m_socket) != FALSE ? S_OK : E_FAIL);
6672 if (hr != S_OK)
6674 SetClientError(SOAPCLIENT_READ_ERROR);
6677 else if (GetStatusCode() == 202)
6679 // for one-way methods
6680 hr = S_OK;
6682 else
6684 SetClientError(SOAPCLIENT_SERVER_ERROR);
6687 else if (GetStatusCode() == 500)
6689 SetClientError(SOAPCLIENT_SOAPFAULT);
6691 // if returned 500, get the SOAP fault
6692 if (m_readStream.Init(&m_socket) != FALSE)
6694 CComPtr<ISAXXMLReader> spReader;
6695 if (SUCCEEDED(GetClientReader(&spReader)))
6697 CComPtr<IStream> spReadStream;
6698 if (SUCCEEDED(GetReadStream(&spReadStream)))
6700 if (FAILED(m_fault.ParseFault(spReadStream, spReader)))
6702 SetClientError(SOAPCLIENT_PARSEFAULT_ERROR);
6708 else
6710 SetClientError(SOAPCLIENT_SEND_ERROR);
6713 _ATLCATCHALL()
6715 hr = E_FAIL;
6718 return hr;
6721 HRESULT SetUrl(LPCTSTR szUrl)
6723 TCHAR szTmp[ATL_URL_MAX_URL_LENGTH];
6724 if(!AtlEscapeUrl(szUrl,szTmp,0,ATL_URL_MAX_URL_LENGTH-1,ATL_URL_BROWSER_MODE))
6726 return E_FAIL;
6729 return (m_url.CrackUrl(szTmp) != FALSE) ? S_OK : E_FAIL;
6732 HRESULT GetUrl(__out_ecount_part_z(*pdwLen, *pdwLen) LPTSTR szUrl, __inout LPDWORD pdwLen)
6734 if ((szUrl == NULL) || (pdwLen == NULL))
6736 return E_INVALIDARG;
6739 return (m_url.CreateUrl(szUrl, pdwLen) != FALSE) ? S_OK : E_FAIL;
6742 HRESULT SetProxy(LPCTSTR szProxy = NULL, short nProxyPort = 80)
6744 BOOL bRet = m_socket.SetProxy(szProxy, nProxyPort);
6745 return (bRet != FALSE) ? S_OK : E_FAIL;
6748 void SetTimeout(DWORD dwTimeout)
6750 m_dwTimeout = dwTimeout;
6753 int GetStatusCode()
6755 return m_socket.GetStatus();
6758 }; // CSoapSocketClientT
6760 #ifndef ATLSOAP_NOWININET
6762 class CReadStreamOnInet : public IStreamImpl
6764 public:
6766 HRESULT __stdcall QueryInterface(REFIID riid, void **ppv)
6768 if (ppv == NULL)
6770 return E_POINTER;
6773 *ppv = NULL;
6775 if (InlineIsEqualGUID(riid, IID_IUnknown) ||
6776 InlineIsEqualGUID(riid, IID_IStream) ||
6777 InlineIsEqualGUID(riid, IID_ISequentialStream))
6779 *ppv = static_cast<IStream *>(this);
6780 return S_OK;
6783 return E_NOINTERFACE;
6786 ULONG __stdcall AddRef()
6788 return 1;
6791 ULONG __stdcall Release()
6793 return 1;
6796 private:
6798 HINTERNET m_hFile;
6800 public:
6802 CReadStreamOnInet()
6803 :m_hFile(NULL)
6807 void Init(HINTERNET hFile)
6809 m_hFile = hFile;
6812 HRESULT STDMETHODCALLTYPE Read(void *pDest, ULONG dwMaxLen, ULONG *pdwRead)
6814 BOOL bRet = InternetReadFile(m_hFile, pDest, dwMaxLen, pdwRead);
6815 return (bRet != FALSE) ? S_OK : E_FAIL;
6818 }; // CStreamOnInet
6820 class CSoapWininetClient
6822 private:
6824 CUrl m_url;
6825 CWriteStreamOnCString m_writeStream;
6826 CReadStreamOnInet m_readStream;
6827 CString m_strProxy;
6828 DWORD m_dwTimeout;
6829 CFixedStringT<CString, ATL_URL_MAX_URL_LENGTH+1> m_strUrl;
6830 SOAPCLIENT_ERROR m_errorState;
6832 void CloseAll()
6834 if (m_hRequest != NULL)
6836 InternetCloseHandle(m_hRequest);
6837 m_hRequest = NULL;
6839 if (m_hConnection != NULL)
6841 InternetCloseHandle(m_hConnection);
6842 m_hConnection = NULL;
6844 if (m_hInternet != NULL)
6846 InternetCloseHandle(m_hInternet);
6847 m_hInternet = NULL;
6851 HRESULT ConnectToServer()
6853 if (m_hConnection != NULL)
6855 return S_OK;
6858 m_hInternet = InternetOpen(
6859 ATLSOAPINET_CLIENT,
6860 m_strProxy.GetLength() ? (INTERNET_OPEN_TYPE_PRECONFIG | INTERNET_OPEN_TYPE_PROXY) : INTERNET_OPEN_TYPE_PRECONFIG,
6861 m_strProxy.GetLength() ? (LPCTSTR) m_strProxy : NULL,
6862 NULL, 0);
6864 if (m_hInternet != NULL)
6866 if (m_dwTimeout != 0)
6868 InternetSetOption(m_hInternet, INTERNET_OPTION_CONNECT_TIMEOUT,
6869 &m_dwTimeout, sizeof(m_dwTimeout));
6870 InternetSetOption(m_hInternet, INTERNET_OPTION_RECEIVE_TIMEOUT,
6871 &m_dwTimeout, sizeof(m_dwTimeout));
6872 InternetSetOption(m_hInternet, INTERNET_OPTION_SEND_TIMEOUT,
6873 &m_dwTimeout, sizeof(m_dwTimeout));
6875 m_hConnection = InternetConnect(m_hInternet, m_url.GetHostName(),
6876 (INTERNET_PORT) m_url.GetPortNumber(), NULL, NULL,
6877 INTERNET_SERVICE_HTTP, 0, NULL);
6879 if (m_hConnection != NULL)
6881 return S_OK;
6884 CloseAll();
6885 return E_FAIL;
6888 protected:
6890 virtual HRESULT GetClientReader(ISAXXMLReader **pReader)
6892 if (pReader == NULL)
6894 return E_POINTER;
6896 *pReader = NULL;
6898 CComPtr<ISAXXMLReader> spReader;
6899 HRESULT hr = spReader.CoCreateInstance(ATLS_SAXXMLREADER_CLSID, NULL, CLSCTX_INPROC_SERVER);
6900 if (SUCCEEDED(hr))
6902 *pReader = spReader.Detach();
6904 return hr;
6907 public:
6909 // note : not shared across stock client implementations
6910 HINTERNET m_hInternet;
6911 HINTERNET m_hConnection;
6912 HINTERNET m_hRequest;
6914 CSoapFault m_fault;
6916 CSoapWininetClient(LPCTSTR szUrl)
6917 :m_hInternet(NULL), m_hConnection(NULL), m_hRequest(NULL), m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
6919 TCHAR szTmp[ATL_URL_MAX_URL_LENGTH];
6920 if(AtlEscapeUrl(szUrl,szTmp,0,ATL_URL_MAX_URL_LENGTH-1,ATL_URL_BROWSER_MODE))
6922 if (m_url.CrackUrl(szTmp) != FALSE)
6924 SetProxy();
6925 _ATLTRY
6927 m_strUrl.SetString(m_url.GetUrlPath(), m_url.GetUrlPathLength());
6928 m_strUrl.Append(m_url.GetExtraInfo(), m_url.GetExtraInfoLength());
6930 _ATLCATCHALL()
6937 CSoapWininetClient(LPCTSTR szServer, LPCTSTR szUri, short nPort=80)
6938 :m_hInternet(NULL), m_hConnection(NULL), m_hRequest(NULL), m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
6940 if (m_url.SetHostName(szServer) != FALSE)
6942 if (m_url.SetUrlPath(szUri) != FALSE)
6944 if (m_url.SetPortNumber((ATL_URL_PORT) nPort) != FALSE)
6946 _ATLTRY
6948 m_strUrl.SetString(m_url.GetUrlPath(), m_url.GetUrlPathLength());
6949 m_strUrl.Append(m_url.GetExtraInfo(), m_url.GetExtraInfoLength());
6951 _ATLCATCHALL()
6959 virtual ~CSoapWininetClient()
6961 CleanupClient();
6962 CloseAll();
6965 SOAPCLIENT_ERROR GetClientError()
6967 return m_errorState;
6970 void SetClientError(SOAPCLIENT_ERROR errorState)
6972 m_errorState = errorState;
6975 IWriteStream * GetWriteStream()
6977 return &m_writeStream;
6980 HRESULT GetReadStream(IStream **ppStream)
6982 if (ppStream == NULL)
6984 return E_POINTER;
6987 *ppStream = &m_readStream;
6988 return S_OK;
6991 void CleanupClient()
6993 m_writeStream.Cleanup();
6994 if (m_hRequest != NULL)
6996 InternetCloseHandle(m_hRequest);
6997 m_hRequest = NULL;
6999 m_fault.Clear();
7000 SetClientError(SOAPCLIENT_SUCCESS);
7003 HRESULT SendRequest(LPCTSTR szAction)
7005 if (ConnectToServer() != S_OK)
7007 SetClientError(SOAPCLIENT_CONNECT_ERROR);
7008 return E_FAIL;
7011 CString strHeaders;
7012 _ATLTRY
7014 strHeaders.Append(szAction);
7015 strHeaders.Append(_T("Content-Type: text/xml; charset=utf-8\r\n"));
7017 _ATLCATCHALL()
7019 return E_OUTOFMEMORY;
7022 static LPCTSTR s_szAcceptTypes[] = { _T("text/*"), NULL };
7023 m_hRequest = HttpOpenRequest(m_hConnection, _T("POST"),
7024 m_strUrl, _T("HTTP/1.0"), NULL,
7025 s_szAcceptTypes,
7026 INTERNET_FLAG_NO_UI | INTERNET_FLAG_KEEP_CONNECTION | ((m_url.GetScheme() == ATL_URL_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0)
7027 , NULL);
7029 if (m_hRequest != NULL)
7031 if (FALSE != HttpSendRequest(m_hRequest, strHeaders, (DWORD) strHeaders.GetLength(),
7032 (void *)(LPCSTR)m_writeStream.m_str, m_writeStream.m_str.GetLength()))
7034 m_readStream.Init(m_hRequest);
7035 if (GetStatusCode() != HTTP_STATUS_SERVER_ERROR)
7037 return S_OK;
7039 else
7041 SetClientError(SOAPCLIENT_SOAPFAULT);
7043 CComPtr<ISAXXMLReader> spReader;
7044 if (SUCCEEDED(GetClientReader(&spReader)))
7046 CComPtr<IStream> spReadStream;
7047 if (SUCCEEDED(GetReadStream(&spReadStream)))
7049 if (FAILED(m_fault.ParseFault(spReadStream, spReader)))
7051 SetClientError(SOAPCLIENT_PARSEFAULT_ERROR);
7058 else
7060 SetClientError(SOAPCLIENT_SEND_ERROR);
7063 return E_FAIL;
7066 HRESULT SetUrl(LPCTSTR szUrl)
7068 CloseAll();
7069 TCHAR szTmp[ATL_URL_MAX_URL_LENGTH];
7070 if(!AtlEscapeUrl(szUrl,szTmp,0,ATL_URL_MAX_URL_LENGTH-1,ATL_URL_BROWSER_MODE))
7072 return E_FAIL;
7075 if (m_url.CrackUrl(szTmp) != FALSE)
7077 _ATLTRY
7079 m_strUrl.SetString(m_url.GetUrlPath(), m_url.GetUrlPathLength());
7080 m_strUrl.Append(m_url.GetExtraInfo(), m_url.GetExtraInfoLength());
7082 _ATLCATCHALL()
7084 return E_OUTOFMEMORY;
7086 return S_OK;
7088 return E_FAIL;
7091 HRESULT GetUrl(LPTSTR szUrl, LPDWORD pdwLen)
7093 if ((szUrl == NULL) || (pdwLen == NULL))
7095 return E_INVALIDARG;
7098 return (m_url.CreateUrl(szUrl, pdwLen) != FALSE) ? S_OK : E_FAIL;
7101 HRESULT SetProxy(LPCTSTR szProxy = NULL, short nProxyPort = 80)
7103 _ATLTRY
7105 if (szProxy && szProxy[0])
7107 m_strProxy.Format(_T("http=http://%s:%d https=http://%s:%d"), szProxy, nProxyPort, szProxy, nProxyPort);
7109 else
7111 m_strProxy.Empty();
7114 _ATLCATCHALL()
7116 return E_OUTOFMEMORY;
7119 return S_OK;
7122 void SetTimeout(DWORD dwTimeout)
7124 m_dwTimeout = dwTimeout;
7127 int GetStatusCode()
7129 DWORD dwLen = 255;
7130 TCHAR szBuf[256];
7131 if (HttpQueryInfo(m_hRequest, HTTP_QUERY_STATUS_CODE, szBuf, &dwLen, NULL))
7133 szBuf[dwLen] = '\0';
7134 return _ttoi(szBuf);
7136 return 0;
7138 }; // CSoapWininetClient
7139 #endif
7141 #ifndef ATLSOAP_NOMSXML_INET
7142 class CSoapMSXMLInetClient
7144 private:
7146 CUrl m_url;
7147 CWriteStreamOnCString m_writeStream;
7148 DWORD m_dwTimeout;
7149 SOAPCLIENT_ERROR m_errorState;
7151 HRESULT ConnectToServer()
7153 TCHAR szURL[ATL_URL_MAX_URL_LENGTH];
7154 DWORD dwLen = ATL_URL_MAX_URL_LENGTH;
7155 HRESULT hr = E_FAIL;
7157 if (m_spHttpRequest)
7158 return S_OK;
7160 if (!m_url.CreateUrl(szURL, &dwLen))
7161 return E_FAIL;
7164 hr = m_spHttpRequest.CoCreateInstance(__uuidof(ServerXMLHTTP30));
7165 if (hr != S_OK)
7166 return hr;
7168 CComVariant vEmpty;
7169 hr = m_spHttpRequest->open( CComBSTR(L"POST"),
7170 CComBSTR(szURL),
7171 CComVariant(VARIANT_BOOL(VARIANT_FALSE)),
7172 vEmpty,
7173 vEmpty );
7174 if (hr != S_OK)
7176 m_spHttpRequest.Release();
7177 return hr;
7180 return S_OK;
7183 protected:
7185 virtual HRESULT GetClientReader(ISAXXMLReader **pReader)
7187 if (pReader == NULL)
7189 return E_POINTER;
7191 *pReader = NULL;
7193 CComPtr<ISAXXMLReader> spReader;
7194 HRESULT hr = spReader.CoCreateInstance(ATLS_SAXXMLREADER_CLSID, NULL, CLSCTX_INPROC_SERVER);
7195 if (SUCCEEDED(hr))
7197 *pReader = spReader.Detach();
7199 return hr;
7202 public:
7204 // note : not shared across stock client implementations
7205 CComPtr<IServerXMLHTTPRequest> m_spHttpRequest;
7207 CSoapFault m_fault;
7209 CSoapMSXMLInetClient(LPCTSTR szUrl)
7210 :m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
7212 m_url.CrackUrl(szUrl);
7215 CSoapMSXMLInetClient(LPCTSTR szServer, LPCTSTR szUri, short nPort=80)
7216 : m_dwTimeout(0), m_errorState(SOAPCLIENT_SUCCESS)
7218 m_url.SetHostName(szServer);
7219 m_url.SetUrlPath(szUri);
7220 m_url.SetPortNumber((ATL_URL_PORT) nPort);
7223 virtual ~CSoapMSXMLInetClient()
7225 CleanupClient();
7228 SOAPCLIENT_ERROR GetClientError()
7230 return m_errorState;
7233 void SetClientError(SOAPCLIENT_ERROR errorState)
7235 m_errorState = errorState;
7238 IWriteStream * GetWriteStream()
7240 return &m_writeStream;
7243 HRESULT GetReadStream(IStream **ppStream)
7245 if (ppStream == NULL)
7247 return E_POINTER;
7250 *ppStream = NULL;
7251 HRESULT hr = E_FAIL;
7253 if (m_spHttpRequest)
7255 VARIANT vResponseStream;
7256 VariantInit(&vResponseStream);
7257 hr = m_spHttpRequest->get_responseStream(&vResponseStream);
7258 if (S_OK == hr)
7260 hr = E_FAIL;
7261 if ((vResponseStream.vt == VT_UNKNOWN) && (vResponseStream.punkVal != NULL))
7263 // we return the refcount with the pointer!
7264 hr = vResponseStream.punkVal->QueryInterface(__uuidof(IStream), (void **)ppStream);
7266 else
7268 SetClientError(SOAPCLIENT_READ_ERROR);
7271 VariantClear(&vResponseStream);
7273 return hr;
7276 void CleanupClient()
7278 m_writeStream.Cleanup();
7279 m_spHttpRequest.Release();
7280 m_fault.Clear();
7281 SetClientError(SOAPCLIENT_SUCCESS);
7284 HRESULT SendRequest(LPCTSTR szAction)
7286 if (ConnectToServer() != S_OK)
7288 SetClientError(SOAPCLIENT_CONNECT_ERROR);
7289 return E_FAIL;
7292 // set the action header
7293 LPCTSTR szColon = _tcschr(szAction, _T(':'));
7294 if (szColon != NULL)
7298 szColon++;
7299 } while (_istspace(static_cast<unsigned char>(*szColon)));
7301 if (FAILED(m_spHttpRequest->setRequestHeader(
7302 CComBSTR( L"SOAPAction" ), CComBSTR( szColon ))))
7304 SetClientError(SOAPCLIENT_SEND_ERROR);
7305 return E_FAIL;
7307 } // if SOAPAction header not properly formed, attempt to send anyway
7309 if (FAILED(m_spHttpRequest->setRequestHeader(CComBSTR( L"Content-Type" ), CComBSTR(L"text/xml; charset=utf-8"))))
7311 SetClientError(SOAPCLIENT_SEND_ERROR);
7312 return E_FAIL;
7315 // set timeout
7316 if (m_dwTimeout != 0)
7318 long nTimeout = (long) m_dwTimeout;
7319 m_spHttpRequest->setTimeouts(nTimeout, nTimeout, nTimeout, nTimeout);
7320 // reset timeout
7321 m_dwTimeout = 0;
7324 CComVariant vBody(m_writeStream.m_str);
7325 HRESULT hr = m_spHttpRequest->send(vBody);
7326 if ((SUCCEEDED(hr)) && (GetStatusCode() == 500))
7328 hr = E_FAIL;
7329 CComPtr<ISAXXMLReader> spReader;
7330 if (SUCCEEDED(GetClientReader(&spReader)))
7332 SetClientError(SOAPCLIENT_SOAPFAULT);
7334 CComPtr<IStream> spReadStream;
7335 if (SUCCEEDED(GetReadStream(&spReadStream)))
7337 if (FAILED(m_fault.ParseFault(spReadStream, spReader)))
7339 SetClientError(SOAPCLIENT_PARSEFAULT_ERROR);
7344 else if (FAILED(hr))
7346 SetClientError(SOAPCLIENT_SEND_ERROR);
7349 return hr;
7352 HRESULT SetUrl(LPCTSTR szUrl)
7354 CleanupClient();
7355 return (m_url.CrackUrl(szUrl) != FALSE ? S_OK : E_FAIL);
7358 HRESULT GetUrl(LPTSTR szUrl, LPDWORD pdwLen)
7360 if ((szUrl == NULL) || (pdwLen == NULL))
7362 return E_INVALIDARG;
7365 return (m_url.CreateUrl(szUrl, pdwLen) != FALSE) ? S_OK : E_FAIL;
7368 void SetTimeout(DWORD dwTimeout)
7370 m_dwTimeout = dwTimeout;
7373 int GetStatusCode()
7375 long lStatus;
7376 if (m_spHttpRequest->get_status(&lStatus) == S_OK)
7378 return (int) lStatus;
7380 return 0;
7383 HRESULT SetProxy(LPCTSTR szProxy = NULL, short nProxyPort = 80)
7385 (szProxy);
7386 (nProxyPort);
7388 ATLTRACE( _T("CSoapMSXMLInetClient does not support SetProxy") );
7390 return S_OK;
7392 }; // CSoapMSXMLInetClient
7393 #endif
7396 class _CSDLGenerator : public ITagReplacerImpl<_CSDLGenerator>
7398 private:
7400 typedef CAtlMap<CStringA, const _soapmap *, CStringElementTraits<CStringA> > WSDLMAP;
7401 typedef CAtlMap<CStringA, const _soapmapentry *, CStringElementTraits<CStringA> > HEADERMAP;
7403 HRESULT GenerateWSDLHelper(const _soapmap *pMap, WSDLMAP& structMap, WSDLMAP& enumMap)
7405 ATLENSURE_RETURN( pMap != NULL );
7407 const _soapmapentry *pEntries = pMap->pEntries;
7408 ATLENSURE_RETURN( pEntries != NULL );
7410 HRESULT hr = S_OK;
7412 for (int i=0; pEntries[i].nHash != 0; i++)
7414 if (pEntries[i].nVal == SOAPTYPE_UNK)
7416 ATLENSURE_RETURN( pEntries[i].pChain != NULL );
7418 _ATLTRY
7420 POSITION pos = NULL;
7421 CStringA strName(pEntries[i].pChain->szName, pEntries[i].pChain->cchName);
7422 if (pEntries[i].pChain->mapType == SOAPMAP_STRUCT)
7424 pos = structMap.SetAt(strName, pEntries[i].pChain);
7426 else if (pEntries[i].pChain->mapType == SOAPMAP_ENUM)
7428 pos = enumMap.SetAt(strName, pEntries[i].pChain);
7430 if (pos == NULL)
7432 hr = E_OUTOFMEMORY;
7433 break;
7436 _ATLCATCHALL()
7438 hr = E_OUTOFMEMORY;
7439 break;
7442 hr = GenerateWSDLHelper(pEntries[i].pChain, structMap, enumMap);
7443 if (FAILED(hr))
7445 break;
7450 return hr;
7453 HTTP_CODE IsUDT(const _soapmapentry *pEntry)
7455 ATLENSURE( pEntry != NULL );
7456 return (pEntry->nVal != SOAPTYPE_UNK) ? HTTP_S_FALSE : HTTP_SUCCESS;
7459 HTTP_CODE GetSoapDims(const _soapmapentry *pEntry)
7461 ATLENSURE( pEntry != NULL );
7462 if (pEntry->pDims[0] != 0)
7464 if (SUCCEEDED(m_pWriteStream->WriteStream("[", 1, NULL)))
7466 for (int i=1; i<=pEntry->pDims[0]; i++)
7468 if (m_writeHelper.Write(pEntry->pDims[i]) != FALSE)
7470 if (i < pEntry->pDims[0])
7472 if (FAILED(m_pWriteStream->WriteStream(", ", 2, NULL)))
7474 return HTTP_FAIL;
7479 if (SUCCEEDED(m_pWriteStream->WriteStream("]", 1, NULL)))
7481 return HTTP_SUCCESS;
7485 return HTTP_FAIL;
7488 const _soapmap **m_pFuncs;
7489 const _soapmap **m_pHeaders;
7490 int m_nFunc;
7491 int m_nParam;
7492 int m_nHeader;
7493 WSDLMAP m_structMap;
7494 WSDLMAP m_enumMap;
7495 POSITION m_currUDTPos;
7496 int m_nCurrUDTField;
7498 HEADERMAP m_headerMap;
7499 POSITION m_currHeaderPos;
7501 CWriteStreamHelper m_writeHelper;
7503 CStringA m_strServiceName;
7504 CStringA m_strNamespaceUri;
7506 IWriteStream *m_pWriteStream;
7508 CComPtr<IHttpServerContext> m_spHttpServerContext;
7510 DWORD m_dwCallFlags;
7512 protected:
7514 void SetWriteStream(IWriteStream *pStream)
7516 m_pWriteStream = pStream;
7517 m_writeHelper.Attach(m_pWriteStream);
7520 void SetHttpServerContext(IHttpServerContext *pServerContext)
7522 m_spHttpServerContext = pServerContext;
7525 static HTTP_CODE GetSoapType(int nVal, IWriteStream *pStream)
7527 return (pStream->WriteStream(CSoapRootHandler::s_xsdNames[nVal].szName,
7528 CSoapRootHandler::s_xsdNames[nVal].cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
7532 HRESULT InitializeSDL(CSoapRootHandler *pHdlr)
7534 m_pFuncs = pHdlr->GetFunctionMap();
7536 if (m_pFuncs == NULL)
7538 return E_FAIL;
7541 ATLASSUME( m_pFuncs[0] != NULL );
7543 m_dwCallFlags = m_pFuncs[0]->dwCallFlags;
7545 size_t i;
7546 for (i=0; m_pFuncs[i] != NULL; i++)
7548 const _soapmap *pMap = m_pFuncs[i];
7549 HRESULT hr = GenerateWSDLHelper(pMap, m_structMap, m_enumMap);
7550 if (FAILED(hr))
7552 return hr;
7556 m_pHeaders = pHdlr->GetHeaderMap();
7557 if (m_pHeaders != NULL)
7559 for (i=0; m_pHeaders[i] != NULL; i++)
7561 const _soapmap *pMap = m_pHeaders[i];
7562 HRESULT hr = GenerateWSDLHelper(pMap, m_structMap, m_enumMap);
7563 if (FAILED(hr))
7565 return hr;
7569 for (i=0; m_pHeaders[i] != NULL; i++)
7571 const _soapmap *pMap = m_pHeaders[i];
7572 for (size_t j=0; pMap->pEntries[j].nHash != 0; j++)
7574 HRESULT hr = S_OK;
7575 _ATLTRY
7577 if (m_headerMap.SetAt(pMap->pEntries[j].szField, &pMap->pEntries[j]) == NULL)
7579 hr = E_OUTOFMEMORY;
7582 _ATLCATCHALL()
7584 hr = E_OUTOFMEMORY;
7586 if (FAILED(hr))
7588 return hr;
7594 _ATLTRY
7596 m_strServiceName = pHdlr->GetServiceName();
7597 m_strNamespaceUri = pHdlr->GetNamespaceUriA();
7599 _ATLCATCHALL()
7601 return E_OUTOFMEMORY;
7603 return S_OK;
7606 virtual const char * GetHandlerName() = 0;
7608 public:
7610 _CSDLGenerator()
7611 :m_pFuncs(NULL), m_nFunc(-1), m_nParam(-1),
7612 m_currUDTPos(NULL), m_nCurrUDTField(-1),
7613 m_pWriteStream(NULL), m_nHeader(-1), m_currHeaderPos(NULL)
7616 virtual ~_CSDLGenerator()
7620 HTTP_CODE OnGetURL()
7622 char szURL[ATL_URL_MAX_URL_LENGTH];
7623 DWORD dwUrlSize = sizeof(szURL);
7624 char szServer[ATL_URL_MAX_HOST_NAME_LENGTH];
7625 DWORD dwServerSize = sizeof(szServer);
7626 char szHttps[16];
7627 DWORD dwHttpsLen = sizeof(szHttps);
7628 char szPort[ATL_URL_MAX_PORT_NUMBER_LENGTH+1];
7629 DWORD dwPortLen = sizeof(szPort);
7631 if (m_spHttpServerContext->GetServerVariable("URL", szURL, &dwUrlSize) != FALSE)
7633 if (m_spHttpServerContext->GetServerVariable("SERVER_NAME", szServer, &dwServerSize) != FALSE)
7635 bool bHttps = false;
7636 if ((m_spHttpServerContext->GetServerVariable("HTTPS", szHttps, &dwHttpsLen) != FALSE) &&
7637 (!_stricmp(szHttps, "ON")))
7639 bHttps = true;
7642 if (m_spHttpServerContext->GetServerVariable("SERVER_PORT", szPort, &dwPortLen) != FALSE)
7644 _ATLTRY
7646 CStringA strUrl;
7647 strUrl.Format("http%s://%s:%s%s?Handler=%s", bHttps ? "s" : "", szServer, szPort, szURL, GetHandlerName());
7649 CA2W wszUrl(strUrl);
7650 wchar_t *pwszUrl = wszUrl;
7651 HRESULT hr = AtlGenXMLValue(m_pWriteStream, &pwszUrl);
7652 return SUCCEEDED(hr) ? HTTP_SUCCESS : HTTP_FAIL;
7654 _ATLCATCHALL()
7656 return HTTP_FAIL;
7661 return HTTP_FAIL;
7664 HTTP_CODE OnGetNamespace()
7666 return (m_pWriteStream->WriteStream(m_strNamespaceUri,
7667 m_strNamespaceUri.GetLength(), NULL) == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
7670 HTTP_CODE OnGetNextFunction()
7672 m_nFunc++;
7673 if (m_pFuncs[m_nFunc] == NULL)
7675 m_nFunc = -1;
7676 return HTTP_S_FALSE;
7678 return HTTP_SUCCESS;
7681 HTTP_CODE OnGetFunctionName()
7683 return (m_pWriteStream->WriteStream(m_pFuncs[m_nFunc]->szName,
7684 m_pFuncs[m_nFunc]->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7687 HTTP_CODE OnGetNextParameter()
7689 ++m_nParam;
7690 if (m_pFuncs[m_nFunc]->pEntries[m_nParam].nHash != 0)
7692 if (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & SOAPFLAG_NOMARSHAL)
7694 return OnGetNextParameter();
7696 return HTTP_SUCCESS;
7698 m_nParam = -1;
7699 return HTTP_S_FALSE;
7702 HTTP_CODE OnIsInParameter()
7704 return (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & SOAPFLAG_IN) ? HTTP_SUCCESS : HTTP_S_FALSE;
7707 HTTP_CODE OnGetParameterName()
7709 HRESULT hr = S_OK;
7710 if (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & SOAPFLAG_RETVAL)
7712 hr = m_pWriteStream->WriteStream("return", sizeof("return")-1, NULL);
7714 else
7716 hr = m_pWriteStream->WriteStream(m_pFuncs[m_nFunc]->pEntries[m_nParam].szField,
7717 m_pFuncs[m_nFunc]->pEntries[m_nParam].cchField, NULL);
7720 return (hr == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
7723 HTTP_CODE OnNotIsArrayParameter()
7725 return (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR))
7726 ? HTTP_S_FALSE: HTTP_SUCCESS;
7729 HTTP_CODE OnIsParameterUDT()
7731 return IsUDT(&m_pFuncs[m_nFunc]->pEntries[m_nParam]);
7734 HTTP_CODE OnGetParameterSoapType()
7736 if (m_pFuncs[m_nFunc]->pEntries[m_nParam].nVal != SOAPTYPE_UNK)
7738 return GetSoapType(m_pFuncs[m_nFunc]->pEntries[m_nParam].nVal, m_pWriteStream);
7740 ATLASSUME( m_pFuncs[m_nFunc]->pEntries[m_nParam].pChain != NULL );
7741 return (m_pWriteStream->WriteStream(m_pFuncs[m_nFunc]->pEntries[m_nParam].pChain->szName,
7742 m_pFuncs[m_nFunc]->pEntries[m_nParam].pChain->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7745 HTTP_CODE OnIsParameterDynamicArray()
7747 return (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & SOAPFLAG_DYNARR) ? HTTP_SUCCESS: HTTP_S_FALSE;
7750 HTTP_CODE OnIsArrayParameter()
7752 return (OnNotIsArrayParameter() != HTTP_SUCCESS) ? HTTP_SUCCESS : HTTP_S_FALSE;
7755 HTTP_CODE OnIsParameterOneDimensional()
7757 return (m_pFuncs[m_nFunc]->pEntries[m_nParam].pDims[0] == 1) ? HTTP_SUCCESS : HTTP_S_FALSE;
7760 HTTP_CODE OnGetParameterArraySize()
7762 return (m_writeHelper.Write(m_pFuncs[m_nFunc]->pEntries[m_nParam].pDims[1]) != FALSE)
7763 ? HTTP_SUCCESS : HTTP_FAIL;
7766 HTTP_CODE OnGetParameterArraySoapDims()
7768 return GetSoapDims(&m_pFuncs[m_nFunc]->pEntries[m_nParam]);
7771 HTTP_CODE OnIsOutParameter()
7773 return (m_pFuncs[m_nFunc]->pEntries[m_nParam].dwFlags & SOAPFLAG_OUT) ? HTTP_SUCCESS : HTTP_S_FALSE;
7776 HTTP_CODE OnGetNextEnum()
7778 if (m_currUDTPos == NULL)
7780 m_currUDTPos = m_enumMap.GetStartPosition();
7782 else
7784 m_enumMap.GetNext(m_currUDTPos);
7787 return (m_currUDTPos != NULL) ? HTTP_SUCCESS : HTTP_S_FALSE;
7790 HTTP_CODE OnGetEnumName()
7792 const _soapmap *pMap = m_enumMap.GetValueAt(m_currUDTPos);
7793 return (m_pWriteStream->WriteStream(pMap->szName, pMap->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7796 HTTP_CODE OnGetNextEnumElement()
7798 const _soapmap *pMap = m_enumMap.GetValueAt(m_currUDTPos);
7799 ++m_nCurrUDTField;
7800 if (pMap->pEntries[m_nCurrUDTField].nHash != 0)
7802 return HTTP_SUCCESS;
7804 m_nCurrUDTField = -1;
7805 return HTTP_S_FALSE;
7808 HTTP_CODE OnGetEnumElementName()
7810 const _soapmap *pMap = m_enumMap.GetValueAt(m_currUDTPos);
7811 return (m_pWriteStream->WriteStream(pMap->pEntries[m_nCurrUDTField].szField,
7812 pMap->pEntries[m_nCurrUDTField].cchField, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7815 HTTP_CODE OnGetNextStruct()
7817 if (m_currUDTPos == NULL)
7819 m_currUDTPos = m_structMap.GetStartPosition();
7821 else
7823 m_structMap.GetNext(m_currUDTPos);
7826 return (m_currUDTPos != NULL) ? HTTP_SUCCESS : HTTP_S_FALSE;
7829 HTTP_CODE OnGetStructName()
7831 const _soapmap *pMap = m_enumMap.GetValueAt(m_currUDTPos);
7832 return (m_pWriteStream->WriteStream(pMap->szName, pMap->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7835 HTTP_CODE OnGetNextStructField()
7837 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7838 ++m_nCurrUDTField;
7839 if (pMap->pEntries[m_nCurrUDTField].nHash != 0)
7841 return HTTP_SUCCESS;
7843 m_nCurrUDTField = -1;
7844 return HTTP_S_FALSE;
7847 HTTP_CODE OnGetStructFieldName()
7849 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7850 return (m_pWriteStream->WriteStream(pMap->pEntries[m_nCurrUDTField].szField,
7851 pMap->pEntries[m_nCurrUDTField].cchField, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7854 HTTP_CODE OnNotIsArrayField()
7856 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7857 return (pMap->pEntries[m_nCurrUDTField].dwFlags & (SOAPFLAG_FIXEDARR | SOAPFLAG_DYNARR)) ? HTTP_S_FALSE : HTTP_SUCCESS;
7860 HTTP_CODE OnIsFieldUDT()
7862 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7863 return IsUDT(&pMap->pEntries[m_nCurrUDTField]);
7866 HTTP_CODE OnGetStructFieldSoapType()
7868 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7869 if (pMap->pEntries[m_nCurrUDTField].nVal != SOAPTYPE_UNK)
7871 return GetSoapType(pMap->pEntries[m_nCurrUDTField].nVal, m_pWriteStream);
7873 ATLASSERT( pMap->pEntries[m_nCurrUDTField].pChain != NULL );
7874 return (m_pWriteStream->WriteStream(pMap->pEntries[m_nCurrUDTField].pChain->szName,
7875 pMap->pEntries[m_nCurrUDTField].pChain->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7878 HTTP_CODE OnIsArrayField()
7880 return (OnNotIsArrayField() != HTTP_SUCCESS) ? HTTP_SUCCESS : HTTP_S_FALSE;
7883 HTTP_CODE OnIsFieldDynamicArray()
7885 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7886 return (pMap->pEntries[m_nCurrUDTField].dwFlags & SOAPFLAG_DYNARR) ? HTTP_SUCCESS : HTTP_S_FALSE;
7889 HTTP_CODE OnGetFieldSizeIsName()
7891 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7892 int nIndex = pMap->pEntries[m_nCurrUDTField].nSizeIs;
7893 ATLASSERT( nIndex >= 0 );
7894 return (m_pStream->WriteStream(pMap->pEntries[nIndex].szField,
7895 pMap->pEntries[nIndex].cchField, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7898 HTTP_CODE OnIsFieldOneDimensional()
7900 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7901 return (pMap->pEntries[m_nCurrUDTField].pDims[0] == 1) ? HTTP_SUCCESS : HTTP_S_FALSE;
7904 HTTP_CODE OnGetFieldArraySize()
7906 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7907 return (m_writeHelper.Write(pMap->pEntries[m_nCurrUDTField].pDims[1]) != FALSE) ?
7908 HTTP_SUCCESS : HTTP_S_FALSE;
7911 HTTP_CODE OnGetFieldArraySoapDims()
7913 const _soapmap *pMap = m_structMap.GetValueAt(m_currUDTPos);
7914 return GetSoapDims(&pMap->pEntries[m_nCurrUDTField]);
7917 HTTP_CODE OnGetServiceName()
7919 return (m_pWriteStream->WriteStream(m_strServiceName,
7920 m_strServiceName.GetLength(), NULL) == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
7923 HTTP_CODE OnGetNextHeader()
7925 if (m_currHeaderPos == NULL)
7927 m_currHeaderPos = m_headerMap.GetStartPosition();
7929 else
7931 m_headerMap.GetNext(m_currHeaderPos);
7934 return (m_currHeaderPos != NULL) ? HTTP_SUCCESS : HTTP_S_FALSE;
7937 HTTP_CODE OnIsInHeader()
7939 return (m_pHeaders[m_nFunc]->pEntries[m_nHeader].dwFlags & SOAPFLAG_IN)
7940 ? HTTP_SUCCESS : HTTP_S_FALSE;
7943 HTTP_CODE OnIsOutHeader()
7945 return (m_pHeaders[m_nFunc]->pEntries[m_nHeader].dwFlags & SOAPFLAG_OUT)
7946 ? HTTP_SUCCESS : HTTP_S_FALSE;
7949 HTTP_CODE OnIsRequiredHeader()
7951 return (m_pHeaders[m_nFunc]->pEntries[m_nHeader].dwFlags & SOAPFLAG_MUSTUNDERSTAND)
7952 ? HTTP_SUCCESS : HTTP_S_FALSE;
7955 HTTP_CODE OnGetHeaderName()
7957 const _soapmapentry *pEntry = m_headerMap.GetValueAt(m_currHeaderPos);
7958 return (m_pWriteStream->WriteStream(pEntry->szField,
7959 pEntry->cchField, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
7962 HTTP_CODE OnNotIsArrayHeader()
7964 const _soapmapentry *pEntry = m_headerMap.GetValueAt(m_currHeaderPos);
7965 return (pEntry->dwFlags & SOAPFLAG_FIXEDARR) ? HTTP_S_FALSE : HTTP_SUCCESS;
7968 HTTP_CODE OnIsHeaderUDT()
7970 return IsUDT(m_headerMap.GetValueAt(m_currHeaderPos));
7973 HTTP_CODE OnGetHeaderSoapType()
7975 const _soapmapentry *pEntry = m_headerMap.GetValueAt(m_currHeaderPos);
7976 if (pEntry->nVal != SOAPTYPE_UNK)
7978 return GetSoapType(pEntry->nVal, m_pWriteStream);
7980 ATLENSURE( pEntry->pChain != NULL );
7981 return (m_pWriteStream->WriteStream(pEntry->pChain->szName,
7982 pEntry->pChain->cchName, NULL) == S_OK) ? HTTP_SUCCESS : HTTP_S_FALSE;
7985 HTTP_CODE OnIsHeaderOneDimensional()
7987 const _soapmapentry *pEntry = m_headerMap.GetValueAt(m_currHeaderPos);
7988 return (pEntry->pDims[0] == 1) ? HTTP_SUCCESS : HTTP_S_FALSE;
7991 HTTP_CODE OnGetHeaderArraySize()
7993 const _soapmapentry *pEntry = m_headerMap.GetValueAt(m_currHeaderPos);
7994 return (m_writeHelper.Write(pEntry->pDims[1]) != FALSE) ?
7995 HTTP_SUCCESS : HTTP_S_FALSE;
7998 HTTP_CODE OnGetHeaderArraySoapDims()
8000 return GetSoapDims(m_headerMap.GetValueAt(m_currHeaderPos));
8003 HTTP_CODE OnGetNextFunctionHeader()
8005 ++m_nHeader;
8006 if (m_pHeaders[m_nFunc]->pEntries[m_nHeader].nHash != 0)
8008 if (m_pHeaders[m_nFunc]->pEntries[m_nHeader].dwFlags & SOAPFLAG_NOMARSHAL)
8010 return OnGetNextHeader();
8012 return HTTP_SUCCESS;
8014 m_nHeader = -1;
8015 return HTTP_S_FALSE;
8018 HTTP_CODE OnGetFunctionHeaderName()
8020 return (m_pWriteStream->WriteStream(
8021 m_pHeaders[m_nFunc]->pEntries[m_nHeader].szField,
8022 m_pHeaders[m_nFunc]->pEntries[m_nHeader].cchField,
8023 NULL) == S_OK) ? HTTP_SUCCESS : HTTP_FAIL;
8026 HTTP_CODE OnIsArrayHeader()
8028 return (OnNotIsArrayHeader() == HTTP_SUCCESS) ? HTTP_S_FALSE : HTTP_SUCCESS;
8031 HTTP_CODE OnIsDocumentLiteral()
8033 if ((m_dwCallFlags & (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL)) ==
8034 (SOAPFLAG_DOCUMENT | SOAPFLAG_LITERAL))
8036 return HTTP_SUCCESS;
8038 return HTTP_S_FALSE;
8041 HTTP_CODE OnIsRpcEncoded()
8043 if ((m_dwCallFlags & (SOAPFLAG_RPC | SOAPFLAG_ENCODED)) ==
8044 (SOAPFLAG_RPC | SOAPFLAG_ENCODED))
8046 return HTTP_SUCCESS;
8048 return HTTP_S_FALSE;
8051 #pragma warning (push)
8052 #pragma warning (disable : 4640) // construction of local static object is not thread-safe
8054 BEGIN_REPLACEMENT_METHOD_MAP(_CSDLGenerator)
8055 REPLACEMENT_METHOD_ENTRY("GetNamespace", OnGetNamespace)
8056 REPLACEMENT_METHOD_ENTRY("GetNextFunction", OnGetNextFunction)
8057 REPLACEMENT_METHOD_ENTRY("GetFunctionName", OnGetFunctionName)
8058 REPLACEMENT_METHOD_ENTRY("GetNextParameter", OnGetNextParameter)
8059 REPLACEMENT_METHOD_ENTRY("IsInParameter", OnIsInParameter)
8060 REPLACEMENT_METHOD_ENTRY("GetParameterName", OnGetParameterName)
8061 REPLACEMENT_METHOD_ENTRY("NotIsArrayParameter", OnNotIsArrayParameter)
8062 REPLACEMENT_METHOD_ENTRY("IsParameterUDT", OnIsParameterUDT)
8063 REPLACEMENT_METHOD_ENTRY("GetParameterSoapType", OnGetParameterSoapType)
8064 REPLACEMENT_METHOD_ENTRY("IsParameterDynamicArray", OnIsParameterDynamicArray)
8065 REPLACEMENT_METHOD_ENTRY("IsArrayParameter", OnIsArrayParameter)
8066 REPLACEMENT_METHOD_ENTRY("IsParameterOneDimensional", OnIsParameterOneDimensional)
8067 REPLACEMENT_METHOD_ENTRY("GetParameterArraySize", OnGetParameterArraySize)
8068 REPLACEMENT_METHOD_ENTRY("GetParameterArraySoapDims", OnGetParameterArraySoapDims)
8069 REPLACEMENT_METHOD_ENTRY("IsOutParameter", OnIsOutParameter)
8070 REPLACEMENT_METHOD_ENTRY("GetNextEnum", OnGetNextEnum)
8071 REPLACEMENT_METHOD_ENTRY("GetEnumName", OnGetEnumName)
8072 REPLACEMENT_METHOD_ENTRY("GetNextEnumElement", OnGetNextEnumElement)
8073 REPLACEMENT_METHOD_ENTRY("GetEnumElementName", OnGetEnumElementName)
8074 REPLACEMENT_METHOD_ENTRY("GetNextStruct", OnGetNextStruct)
8075 REPLACEMENT_METHOD_ENTRY("GetStructName", OnGetStructName)
8076 REPLACEMENT_METHOD_ENTRY("GetNextStructField", OnGetNextStructField)
8077 REPLACEMENT_METHOD_ENTRY("GetStructFieldName", OnGetStructFieldName)
8078 REPLACEMENT_METHOD_ENTRY("NotIsArrayField", OnNotIsArrayField)
8079 REPLACEMENT_METHOD_ENTRY("IsFieldUDT", OnIsFieldUDT)
8080 REPLACEMENT_METHOD_ENTRY("GetStructFieldSoapType", OnGetStructFieldSoapType)
8081 REPLACEMENT_METHOD_ENTRY("IsArrayField", OnIsArrayField)
8082 REPLACEMENT_METHOD_ENTRY("IsFieldOneDimensional", OnIsFieldOneDimensional)
8083 REPLACEMENT_METHOD_ENTRY("GetFieldArraySize", OnGetFieldArraySize)
8084 REPLACEMENT_METHOD_ENTRY("GetFieldArraySoapDims", OnGetFieldArraySoapDims)
8085 REPLACEMENT_METHOD_ENTRY("GetServiceName", OnGetServiceName)
8086 REPLACEMENT_METHOD_ENTRY("GetURL", OnGetURL)
8088 REPLACEMENT_METHOD_ENTRY("GetNextHeader", OnGetNextHeader)
8089 REPLACEMENT_METHOD_ENTRY("GetHeaderName", OnGetHeaderName)
8090 REPLACEMENT_METHOD_ENTRY("NotIsArrayHeader", OnNotIsArrayHeader)
8091 REPLACEMENT_METHOD_ENTRY("IsArrayHeader", OnIsArrayHeader)
8092 REPLACEMENT_METHOD_ENTRY("IsHeaderUDT", OnIsHeaderUDT)
8093 REPLACEMENT_METHOD_ENTRY("GetHeaderSoapType", OnGetHeaderSoapType)
8094 REPLACEMENT_METHOD_ENTRY("IsHeaderOneDimensional", OnIsHeaderOneDimensional)
8095 REPLACEMENT_METHOD_ENTRY("GetHeaderArraySize", OnGetHeaderArraySize)
8096 REPLACEMENT_METHOD_ENTRY("GetHeaderArraySoapDims", OnGetHeaderArraySoapDims)
8097 REPLACEMENT_METHOD_ENTRY("GetNextFunctionHeader", OnGetNextFunctionHeader)
8098 REPLACEMENT_METHOD_ENTRY("GetFunctionHeaderName", OnGetFunctionHeaderName)
8099 REPLACEMENT_METHOD_ENTRY("IsInHeader", OnIsInHeader)
8100 REPLACEMENT_METHOD_ENTRY("IsOutHeader", OnIsOutHeader)
8101 REPLACEMENT_METHOD_ENTRY("IsRequiredHeader", OnIsRequiredHeader)
8103 REPLACEMENT_METHOD_ENTRY("IsDocumentLiteral", OnIsDocumentLiteral)
8104 REPLACEMENT_METHOD_ENTRY("IsRpcEncoded", OnIsRpcEncoded)
8105 REPLACEMENT_METHOD_ENTRY("IsFieldDynamicArray", OnIsFieldDynamicArray)
8106 REPLACEMENT_METHOD_ENTRY("GetFieldSizeIsName", OnGetFieldSizeIsName)
8107 END_REPLACEMENT_METHOD_MAP()
8109 #pragma warning (pop)
8111 }; // class _CSDLGenerator
8113 template <class THandler, const char *szHandlerName>
8114 class CSDLGenerator :
8115 public _CSDLGenerator,
8116 public IRequestHandlerImpl< CSDLGenerator<THandler,szHandlerName> >,
8117 public CComObjectRootEx<CComSingleThreadModel>
8119 private:
8121 public:
8122 typedef CSDLGenerator<THandler, szHandlerName> _sdlGenerator;
8124 BEGIN_COM_MAP(_sdlGenerator)
8125 COM_INTERFACE_ENTRY(IRequestHandler)
8126 COM_INTERFACE_ENTRY(ITagReplacer)
8127 END_COM_MAP()
8129 HTTP_CODE InitializeHandler(AtlServerRequest *pRequestInfo, IServiceProvider *pServiceProvider)
8131 IRequestHandlerImpl<CSDLGenerator>::InitializeHandler(pRequestInfo, pServiceProvider);
8133 CComObjectStack<THandler> handler;
8134 if (FAILED(InitializeSDL(&handler)))
8136 return HTTP_FAIL;
8139 CStencil s;
8140 HTTP_CODE hcErr = s.LoadFromString(s_szAtlsWSDLSrf, (DWORD) strlen(s_szAtlsWSDLSrf));
8141 if (hcErr == HTTP_SUCCESS)
8143 hcErr = HTTP_FAIL;
8144 CHttpResponse HttpResponse(pRequestInfo->pServerContext);
8145 HttpResponse.SetContentType("text/xml");
8146 if (s.ParseReplacements(this) != false)
8148 s.FinishParseReplacements();
8150 SetStream(&HttpResponse);
8151 SetWriteStream(&HttpResponse);
8152 SetHttpServerContext(m_spServerContext);
8154 ATLASSERT( s.ParseSuccessful() != false );
8156 hcErr = s.Render(this, &HttpResponse);
8160 return hcErr;
8163 const char * GetHandlerName()
8165 return szHandlerName;
8167 }; // class CSDLGenerator
8169 } // namespace ATL
8170 #pragma pack(pop)
8172 #pragma warning(pop)
8174 #endif // __ATLSOAP_H__