// This is a part of the Active Template Library. // Copyright (C) Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Active Template Library Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Active Template Library product. #ifndef __ATLSPRIV_H__ #define __ATLSPRIV_H__ #pragma once #include #ifndef _WINSOCK2API_ #error Winsock2.h has to be included before including windows.h or use atlbase.h instead of windows.h #endif #ifndef _ATL_NO_DEFAULT_LIBS #pragma comment(lib, "ws2_32.lib") #endif // !_ATL_NO_DEFAULT_LIBS #include #include #include #include // ATL_SOCK_TIMEOUT defines the amount of time // this socket will block the calling thread waiting // for the socket before the call times out. #ifndef ATL_SOCK_TIMEOUT #define ATL_SOCK_TIMEOUT 10000 #endif #define ATL_WINSOCK_VER MAKELONG(2,0) // This file contains unsupported code used in ATL implementation files. Most of // this code is support code for various ATL Server functions. #pragma pack(push,_ATL_PACKING) namespace ATL{ // One of these objects can be created globally to turn // on the socket stuff at CRT startup and shut it down // on CRT term. class _AtlWSAInit { public: _AtlWSAInit() throw() { m_dwErr = WSAEFAULT; } bool Init() { if (!IsStarted()) m_dwErr = WSAStartup(ATL_WINSOCK_VER, &m_stData); return m_dwErr == 0; } bool IsStarted(){ return m_dwErr == 0; } ~_AtlWSAInit() throw() { if (!m_dwErr) WSACleanup(); } WSADATA m_stData; DWORD m_dwErr; }; #ifndef _ATL_NO_GLOBAL_SOCKET_STARTUP __declspec(selectany)_AtlWSAInit g_HttpInit; #endif class ZEvtSyncSocket { public: ZEvtSyncSocket() throw(); ~ZEvtSyncSocket() throw(); operator SOCKET() throw(); void Close() throw(); void Term() throw(); bool Create(const ADDRINFOT* pAI, WORD wFlags=0) throw(); bool Create(int af, int st, int proto, WORD wFlags=0) throw(); bool Connect(LPCTSTR szAddr, unsigned short nPort) throw(); bool Connect(const SOCKADDR* psa, int len) throw(); bool Connect(const ADDRINFOT *pAI) throw(); bool Write(WSABUF *pBuffers, int nCount, DWORD *pdwSize) throw(); bool Write(const unsigned char *pBuffIn, DWORD *pdwSize) throw(); bool Read(const unsigned char *pBuff, DWORD *pdwSize) throw(); bool Init(SOCKET hSocket, void * /*pData=NULL*/) throw(); DWORD GetSocketTimeout() throw(); DWORD SetSocketTimeout(DWORD dwNewTimeout) throw(); bool SupportsScheme(ATL_URL_SCHEME scheme) throw(); protected: DWORD m_dwCreateFlags; WSAEVENT m_hEventRead; WSAEVENT m_hEventWrite; WSAEVENT m_hEventConnect; CComAutoCriticalSection m_csRead; CComAutoCriticalSection m_csWrite; SOCKET m_socket; bool m_bConnected; DWORD m_dwLastError; DWORD m_dwSocketTimeout; }; inline bool _AtlIsHttpSpace(TCHAR c) { return (c == 0x09 || c == 0x0A || c == 0x0D || c == 0x20); } // MIME helper functions extern __declspec(selectany) const DWORD ATL_MIME_DEFAULT_CP = 28591; // This function is used to create an CSMTPConnection-compatible recipient string // from a recipient string that is in a CMimeMessage object. inline BOOL AtlMimeMakeRecipientsString(__in LPCSTR szNames, __out_ecount_part_z(*pdwLen, *pdwLen) LPSTR szRecipients, __inout_opt LPDWORD pdwLen = NULL) { ATLENSURE(szNames != NULL); ATLENSURE(szRecipients != NULL); char ch; DWORD dwLen = 0; while ((ch = *szNames++) != '\0') { // Skip everything that is in double quotes if (ch == '"') { while (*szNames && *szNames++ != '"'); } if (ch == '<') { // Extract the address from within the <> while (*szNames && *szNames != '>') { *szRecipients++ = *szNames++; dwLen++; } // End it with a comma *szRecipients++ = ','; dwLen++; } if (ch == '=') { // Skip any BEncoded or QEncoded parts while (*szNames) { if (*szNames == '?' && *(szNames+1) == '=') { szNames+=2; break; } szNames++; } } szNames++; } if (dwLen != 0) { szRecipients--; dwLen--; } *szRecipients = '\0'; if (pdwLen) *pdwLen = dwLen; return TRUE; } // AtlMimeCharsetFromCodePage, AtlMimeConvertString // are MIME multilanguage support functions. // Get the MIME character set of the of the code page. The character set is copied // into szCharset. #ifndef ATLSMTP_DEFAULT_CSET #define ATLSMTP_DEFAULT_CSET "iso-8859-1" #endif inline BOOL AtlMimeCharsetFromCodePage(__out_ecount_z(cch) LPSTR szCharset, __in UINT uiCodePage, __in_opt IMultiLanguage* pMultiLanguage, __in size_t cch) throw() { ATLASSERT(szCharset != NULL); if (!pMultiLanguage) { if ((uiCodePage == 0) || (uiCodePage == ATL_MIME_DEFAULT_CP)) { ATLASSERT(_countof(ATLSMTP_DEFAULT_CSET) <= cch); Checked::strcpy_s(szCharset, cch, ATLSMTP_DEFAULT_CSET); } else { return FALSE; } } else { if (uiCodePage == 0) uiCodePage = GetACP(); HRESULT hr; MIMECPINFO cpInfo; memset(&cpInfo, 0x00, sizeof(cpInfo)); #ifdef __IMultiLanguage2_INTERFACE_DEFINED__ // if IMultiLanguage2 is available, use it CComPtr spMultiLanguage2; hr = pMultiLanguage->QueryInterface(__uuidof(IMultiLanguage2), (void **)&spMultiLanguage2); if (FAILED(hr) || !spMultiLanguage2.p) hr = pMultiLanguage->GetCodePageInfo(uiCodePage, &cpInfo); else hr = spMultiLanguage2->GetCodePageInfo(uiCodePage, LANGIDFROMLCID(GetThreadLocale()), &cpInfo); #else // __IMultiLanguage2_INTERFACE_DEFINED__ hr = pMultiLanguage->GetCodePageInfo(uiCodePage, &cpInfo); #endif // __IMultiLanguage2_INTERFACE_DEFINED__ if (hr != S_OK) return FALSE; _ATLTRY { CW2A charSet(cpInfo.wszWebCharset); if (strlen(charSet) >= cch) return FALSE; Checked::strcpy_s(szCharset, cch, charSet); } _ATLCATCHALL() { return FALSE; } } return TRUE; } inline BOOL AtlMimeConvertStringW( __in IMultiLanguage *pMultiLanguage, __in UINT uiCodePage, __in LPCWSTR wszIn, __out_ecount_part_z(*pnLen, *pnLen) LPSTR *ppszOut, __inout UINT *pnLen) throw() { ATLENSURE( pMultiLanguage != NULL ); ATLENSURE( wszIn != NULL ); ATLENSURE( ppszOut != NULL ); ATLENSURE( pnLen != NULL ); *ppszOut = NULL; *pnLen = 0; if (uiCodePage == 0) { uiCodePage = GetACP(); } DWORD dwMode = 0; CHeapPtr pszOut; // get the length HRESULT hr = pMultiLanguage->ConvertStringFromUnicode(&dwMode, uiCodePage, const_cast(wszIn), NULL, NULL, pnLen); if (SUCCEEDED(hr)) { // allocate the buffer if (pszOut.Allocate(*pnLen)) { dwMode = 0; // do the conversion hr = pMultiLanguage->ConvertStringFromUnicode(&dwMode, uiCodePage, const_cast(wszIn), NULL, pszOut, pnLen); if (SUCCEEDED(hr)) { *ppszOut = pszOut.Detach(); return TRUE; } } } return FALSE; } inline BOOL AtlMimeConvertStringA( __in IMultiLanguage *pMultiLanguage, __in UINT uiCodePage, __in LPCSTR szIn, __out_ecount_part_z(*pnLen, *pnLen) LPSTR *ppszOut, __inout UINT *pnLen) throw() { _ATLTRY { return AtlMimeConvertStringW(pMultiLanguage, uiCodePage, CA2W(szIn), ppszOut, pnLen); } _ATLCATCHALL() { return FALSE; } } #ifdef _UNICODE #define AtlMimeConvertString AtlMimeConvertStringW #else #define AtlMimeConvertString AtlMimeConvertStringA #endif class CStreamOnSequentialStream : public IStream { CComPtr m_spStream; public: CStreamOnSequentialStream(ISequentialStream *pStream) throw() { ATLASSERT(pStream); m_spStream = pStream; } virtual ~CStreamOnSequentialStream() { } STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw() { if (!m_spStream) return E_UNEXPECTED; return m_spStream->Read(pv, cb, pcbRead); } STDMETHOD(Write)(const void *pv, ULONG cb, ULONG *pcbWritten) throw() { if (!m_spStream) return E_UNEXPECTED; return m_spStream->Write(pv, cb, pcbWritten); } STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(SetSize)(ULARGE_INTEGER ) throw() { return E_NOTIMPL; } STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *, ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(Commit)(DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Revert)( void) throw() { return E_NOTIMPL; } STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Stat)(STATSTG *, DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Clone)(IStream **) throw() { return E_NOTIMPL; } STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw() { *ppUnk = NULL; if (::InlineIsEqualGUID(iid, IID_IUnknown) || ::InlineIsEqualGUID(iid, IID_ISequentialStream) || ::InlineIsEqualGUID(iid, IID_IStream)) { *ppUnk = (void*)(IStream*)this; AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef( void) throw() { return (ULONG)1; } ULONG STDMETHODCALLTYPE Release( void) throw() { return (ULONG)1; } }; class CStreamOnByteArray : public IStream { public: BYTE *m_pArray; DWORD m_dwRead; CStreamOnByteArray(BYTE *pBytes) throw() { ATLASSERT(pBytes); m_pArray = pBytes; m_dwRead = 0; } STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw() { if (!pv) return E_INVALIDARG; if (cb == 0) return S_OK; if (!m_pArray) return E_UNEXPECTED; BYTE *pCurr = m_pArray; pCurr += m_dwRead; Checked::memcpy_s(pv, cb, pCurr, cb); if (pcbRead) *pcbRead = cb; m_dwRead += cb; return S_OK; } STDMETHOD(Write)(const void* , ULONG , ULONG* ) throw() { return E_UNEXPECTED; } STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(SetSize)(ULARGE_INTEGER ) throw() { return E_NOTIMPL; } STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *, ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(Commit)(DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Revert)( void) throw() { return E_NOTIMPL; } STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Stat)(STATSTG *, DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Clone)(IStream **) throw() { return E_NOTIMPL; } STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw() { *ppUnk = NULL; if (::InlineIsEqualGUID(iid, IID_IUnknown) || ::InlineIsEqualGUID(iid, IID_ISequentialStream) || ::InlineIsEqualGUID(iid, IID_IStream)) { *ppUnk = (void*)(IStream*)this; AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef( void) throw() { return (ULONG)1; } ULONG STDMETHODCALLTYPE Release( void) throw() { return (ULONG)1; } }; class CVariantStream : public IStream { public: CVariantStream() throw() { m_nCurrRead = 0; m_nVariantSize = 0; m_nRef = 1; } virtual ~CVariantStream() { } // input variant is put into contained BYTE array. HRESULT InsertVariant(const VARIANT *pVarIn) throw() { CComVariant vIn; HRESULT hr = E_FAIL; m_nCurrRead = 0; m_nVariantSize = 0; hr = vIn.Attach(const_cast(pVarIn)); if (hr == S_OK) { hr = vIn.WriteToStream(static_cast(this)); vIn.Detach(const_cast(pVarIn)); } return hr; } // variant is read from contained byte array into // out variant. HRESULT RetrieveVariant(VARIANT *pVarOut) throw() { CComVariant vOut; HRESULT hr = vOut.ReadFromStream(static_cast(this)); if (hr == S_OK) hr = vOut.Detach(pVarOut); m_nCurrRead = 0; return hr; } HRESULT LoadFromStream(ISequentialStream *stream) throw() { m_nCurrRead = 0; CStreamOnSequentialStream stm(stream); CComVariant v; HRESULT hr = v.ReadFromStream(&stm); if (hr == S_OK) hr = v.WriteToStream(static_cast(this)); return hr; } ISequentialStream* GetStream() throw() { return static_cast(this); } size_t GetVariantSize() throw() { return m_nVariantSize; } // Implementation // IStream implementation; STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw() { if (!pv) return E_INVALIDARG; if (cb == 0) return S_OK; if (pcbRead) *pcbRead = 0; if (!m_nVariantSize) return S_OK; // nothing to do. size_t nLeft = m_nVariantSize - m_nCurrRead; if (nLeft > 0) { size_t nRead = __min(nLeft, cb); BYTE *pCurr = m_stream; pCurr += m_nCurrRead; Checked::memcpy_s(pv, cb, pCurr, nRead); m_nCurrRead += nRead; if (pcbRead) *pcbRead = (ULONG)nRead; } return S_OK; } STDMETHOD(Write)(const void *pv, ULONG cb, ULONG *pcbWritten) throw() { HRESULT hr = E_OUTOFMEMORY; if (!pv) return E_INVALIDARG; if (cb == 0) return S_OK; if (pcbWritten) *pcbWritten = 0; ULONG newsz = cb + (ULONG)m_nVariantSize; if (newsz < cb || newsz < m_nVariantSize) { return E_OUTOFMEMORY; } BYTE *pBytes = NULL; ATLTRY(pBytes = m_stream.Reallocate(newsz)); if (pBytes) { pBytes += m_nVariantSize; Checked::memcpy_s(pBytes, cb, pv, cb); if (pcbWritten) *pcbWritten = cb; m_nVariantSize += cb; hr = S_OK; } return hr; } STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(SetSize)(ULARGE_INTEGER ) throw() { return E_NOTIMPL; } STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *, ULARGE_INTEGER *) throw() { return E_NOTIMPL; } STDMETHOD(Commit)(DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Revert)( void) throw() { return E_NOTIMPL; } STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Stat)(STATSTG *, DWORD ) throw() { return E_NOTIMPL; } STDMETHOD(Clone)(IStream **) throw() { return E_NOTIMPL; } STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw() { *ppUnk = NULL; if (::InlineIsEqualGUID(iid, IID_IUnknown)) { *ppUnk = (void*)(IUnknown*)this; } else if (::InlineIsEqualGUID(iid, IID_ISequentialStream)) { *ppUnk = (void*)(ISequentialStream*)this; } else if (::InlineIsEqualGUID(iid, IID_IStream)) { *ppUnk = (void*)(IStream*)this; } if (*ppUnk) { AddRef(); return S_OK; } return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef( void) throw() { return (ULONG)1; } ULONG STDMETHODCALLTYPE Release( void) throw() { return (ULONG)1; } CTempBuffer m_stream; size_t m_nVariantSize; size_t m_nCurrRead; long m_nRef; }; // given a nCurrent and a pointer to a value representing the // maximum value that has been seen in nCurrent, // will update pnMax if nCurrent is greater inline void AtlInterlockedUpdateMax(long nCurrent, long* pnMax) { ATLENSURE(pnMax != NULL); long nMax; long nOrigMax; do { nMax = *pnMax; nOrigMax = 0; if (nCurrent > nMax) nOrigMax = InterlockedCompareExchange(pnMax, nCurrent, nMax); } while (nOrigMax != 0 && nOrigMax != nMax); } // wrapper around InterlockedExchangeAdd inline LONG AtlInterlockedExchangeAdd(__inout long volatile* pAddend, __in long nValue) { #if defined(_WIN64) && defined(_M_CEE) // We use System::Threading::Interlocked::Add because InterlockedExchangeAdd is an intrisinc not supported in managed code with 64bits compilers. // System::Threading::Interlocked::Add returns the value after the addition, but we maintain the same semantics as InterlockedExchangeAdd. _STATIC_ASSERT(sizeof(int) == sizeof(long)); return (System::Threading::Interlocked::Add(*((int*)pAddend), nValue) - nValue); #else return InterlockedExchangeAdd(pAddend, nValue); #endif } // SOAP helpers #define _ATLSOAP_DECLARE_WSDL_SRF() \ __if_not_exists(s_szAtlsWSDLSrf) \ { \ extern __declspec(selectany) const char * const s_szAtlsWSDLSrf = \ "\r\n" \ "\r\n" \ "\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{if IsRpcEncoded}}\r\n" \ "{{while GetNextFunction}}\r\n" \ "{{while GetNextParameter}}\r\n" \ "{{if IsArrayParameter}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ "{{endwhile}}\r\n" \ "{{endif}}\r\n" \ "{{while GetNextHeader}}\r\n" \ "{{if IsHeaderUDT}}\r\n" \ "{{else}}\r\n" \ "{{if IsArrayHeader}}\r\n" \ "{{else}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endif}}\r\n" \ "{{if IsRpcEncoded}}\r\n" \ "{{if IsArrayHeader}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ "{{if IsDocumentLiteral}}\r\n" \ "{{while GetNextFunction}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextParameter}}\r\n" \ "{{if IsInParameter}}\r\n" \ " \r\n" \ "{{if IsArrayParameter}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextParameter}}\r\n" \ "{{if IsOutParameter}}\r\n" \ " \r\n" \ "{{if IsArrayParameter}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ "{{endif}}\r\n" \ "{{while GetNextEnum}}\r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextEnumElement}}\r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ "{{while GetNextStruct}}\r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextStructField}}\r\n" \ " \r\n" \ "{{if IsArrayField}}\r\n" \ " \r\n" \ "{{if IsRpcEncoded}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{else}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ "{{if IsDocumentLiteral}}\r\n" \ "{{while GetNextHeader}}\r\n" \ " \r\n" \ "{{if IsArrayHeader}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ "{{endif}}\r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextFunction}}\r\n" \ " \r\n" \ "{{if IsDocumentLiteral}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{if IsRpcEncoded}}\r\n" \ "{{while GetNextParameter}}\r\n" \ "{{if IsInParameter}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ "{{endif}}\r\n" \ " \r\n" \ " \r\n" \ "{{if IsDocumentLiteral}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{if IsRpcEncoded}}\r\n" \ "{{while GetNextParameter}}\r\n" \ "{{if IsOutParameter}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ "{{endif}}\r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ "{{while GetNextHeader}}\r\n" \ " \r\n" \ "{{if IsDocumentLiteral}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{if IsRpcEncoded}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ "{{while GetNextFunction}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextFunction}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextFunctionHeader}}\r\n" \ "{{if IsInHeader}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ "{{while GetNextFunctionHeader}}\r\n" \ "{{if IsOutHeader}}\r\n" \ " \r\n" \ "{{endif}}\r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ "{{endwhile}}\r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ " \r\n" \ ""; \ } #include }; // namespace ATL #pragma pack(pop) #endif // __ATLSPRIV_H__