#ifndef _ECB_H_ #define _ECB_H_ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // ECB.H // // Header for IEcb interface class. // // Copyright 1986-1997 Microsoft Corporation, All Rights Reserved // #include // For CMTRefCounted parent #include #include // For IMDData #include // For HttpUriEscape // ======================================================================== // // ENUM TRANSFER_CODINGS // // Valid transfer codings. See HTTP/1.1 draft section 3.5. // // TC_UNKNOWN - Unknown value. // TC_IDENTITY - Identity encoding (i.e. no encoding). // TC_CHUNKED - Chunked encoding. // enum TRANSFER_CODINGS { TC_UNKNOWN, TC_IDENTITY, TC_CHUNKED }; typedef struct _HSE_EXEC_URL_INFO_WIDE { LPCWSTR pwszUrl; // URL to execute DWORD dwExecUrlFlags; // Flags } HSE_EXEC_URL_INFO_WIDE, * LPHSE_EXEC_URL_INFO_WIDE; // ======================================================================== // // CLASS IIISAsyncIOCompleteObserver // // Passed to IEcb async I/O methods // class IIISAsyncIOCompleteObserver { // NOT IMPLEMENTED // IIISAsyncIOCompleteObserver& operator=( const IIISAsyncIOCompleteObserver& ); public: // CREATORS // virtual ~IIISAsyncIOCompleteObserver() = 0; // MANIPULATORS // virtual VOID IISIOComplete( DWORD dwcbIO, DWORD dwLastError ) = 0; }; // ======================================================================== // // CLASS IEcb // // Provides a clean interface to the EXTENSION_CONTROL_BLOCK passed // to us by IIS. // class CInstData; class IEcbBase : public CMTRefCounted { private: // NOT IMPLEMENTED // IEcbBase( const IEcbBase& ); IEcbBase& operator=( const IEcbBase& ); // Private URL mapping helpers // SCODE ScReqMapUrlToPathEx60After( /* [in] */ LPCWSTR pwszUrl, /* [out] */ HSE_UNICODE_URL_MAPEX_INFO * pmi ) const { SCODE sc = S_OK; UINT cbPath = sizeof(pmi->lpszPath); Assert( m_pecb ); Assert( pwszUrl ); Assert( pmi ); if (!m_pecb->ServerSupportFunction( m_pecb->ConnID, HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX, const_cast(pwszUrl), reinterpret_cast(&cbPath), reinterpret_cast(pmi) )) { // There is a fix for Windows Bugs 156176 that we need to do the // following check for. It applies to IIS 6.0 (+) path only. In IIS 5.0 // the maping functions were silently succeeding, and truncating the // buffer that contained the mapped path if it exceeded MAX_PATH. // That behaviour suited us, but is not very nice, so IIS 6.0 chose // to still fill in the buffer as before, but fail with special error // (ERROR_INSUFFICIENT_BUFFER). That error still means success to us, // so fail only if we see something different // if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { // Function does not allow to return failures, so the only option // is to throw. We cannot proceed if we did not get the data anyway. // If this function succeeds once, subsequent calls to it are non // failing. // sc = HRESULT_FROM_WIN32(GetLastError()); Assert(FAILED(sc)); DebugTrace("IEcbBase::ScReqMapUrlToPathEx60After() - ServerSupportFunction(HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX) failed 0x%08lX\n", sc); goto ret; } } DebugTrace ("IEcbBase::ScReqMapUrlToPathEx60After() - ServerSupportFunction" "(HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX) succeded!\n" "mapinfo:\n" "- url \"%ls\" maps to \"%ls\"\n" "- dwFlags = 0x%08x\n" "- cchMatchingPath = %d\n" "- cchMatchingURL = %d\n", pwszUrl, pmi->lpszPath, pmi->dwFlags, pmi->cchMatchingPath, pmi->cchMatchingURL); // The value for cbPath, at this point, should include the L'\0' // termination, and for that reason cbPath will always be more // than the length of the matching path. // Assert (0 == cbPath % sizeof(WCHAR)); Assert (pmi->cchMatchingPath < cbPath/sizeof(WCHAR)); ret: return sc; } SCODE ScReqMapUrlToPathEx60Before( /* [in] */ LPCWSTR pwszUrl, /* [out] */ HSE_UNICODE_URL_MAPEX_INFO * pmi ) const { SCODE sc = S_OK; HSE_URL_MAPEX_INFO mi; CStackBuffer pszUrl; UINT cchUrl; UINT cbUrl; UINT cbPath; UINT cchPath; Assert( m_pecb ); Assert( pwszUrl ); Assert( pmi ); // Find out the length of the URL // cchUrl = static_cast(wcslen(pwszUrl)); cbUrl = cchUrl * 3; // Resize the buffer to the sufficient size, leave place for '\0' termination // if (!pszUrl.resize(cbUrl + 1)) { sc = E_OUTOFMEMORY; DebugTrace("IEcbBase::ScReqMapUrlToPathEx60Before() - Error while allocating memory 0x%08lX\n", sc); goto ret; } // Convert to skinny including '\0' termination // cbUrl = WideCharToMultiByte(CP_ACP, 0, pwszUrl, cchUrl + 1, pszUrl.get(), cbUrl + 1, 0, 0); if (0 == cbUrl) { sc = HRESULT_FROM_WIN32(GetLastError()); DebugTrace("IEcbBase::ScSSFReqMapUrlToPathEx() - WideCharToMultiByte() failed 0x%08lX\n", sc); goto ret; } cbPath = MAX_PATH; // Get the skinny mappings from IIS // if (!m_pecb->ServerSupportFunction( m_pecb->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, pszUrl.get(), reinterpret_cast(&cbPath), reinterpret_cast(&mi))) { sc = HRESULT_FROM_WIN32(GetLastError()); DebugTrace("IEcbBase::ScSSFReqMapUrlToPathEx() - ServerSupportFunction() failed 0x%08lX\n", sc); goto ret; } DebugTrace ("IEcbBase::ScSSFReqMapUrlToPathEx() - ServerSupportFunction" "(HSE_REQ_MAP_URL_TO_PATH_EX) succeded!\n" "mapinfo:\n" "- url \"%hs\" maps to \"%hs\"\n" "- dwFlags = 0x%08x\n" "- cchMatchingPath = %d\n" "- cchMatchingURL = %d\n", pszUrl.get(), mi.lpszPath, mi.dwFlags, mi.cchMatchingPath, mi.cchMatchingURL); // The value for cbPath, at this point, should include the null // termination, and for that reason cbPath will always be more // than the length of the matching path. // Assert (mi.cchMatchingPath < cbPath); Assert (mi.cchMatchingURL < cbUrl); // First translate the matching path so we would know its // length and would be able to pass it back // if (mi.cchMatchingPath) { // Converting will never yield the buffer bigger than one we already have // pmi->cchMatchingPath = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, mi.lpszPath, mi.cchMatchingPath, pmi->lpszPath, MAX_PATH); if (0 == pmi->cchMatchingPath) { sc = HRESULT_FROM_WIN32(GetLastError()); DebugTrace("IEcbBase::ScSSFReqMapUrlToPathEx() - MultiByteToWideChar() failed 0x%08lX\n", sc); goto ret; } } else { pmi->cchMatchingPath = 0; } // Convert the remainder of the path including the '\0' termination // cchPath = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, mi.lpszPath + mi.cchMatchingPath, min(cbPath, MAX_PATH) - mi.cchMatchingPath, pmi->lpszPath + pmi->cchMatchingPath, MAX_PATH - pmi->cchMatchingPath); if (0 == cchPath) { sc = HRESULT_FROM_WIN32(GetLastError()); DebugTrace("IEcbBase::ScReqMapUrlToPathEx() - MultiByteToWideChar() failed 0x%08lX\n", sc); goto ret; } // Find the matching URL length for wide version // if (mi.cchMatchingURL) { pmi->cchMatchingURL = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, pszUrl.get(), mi.cchMatchingURL, 0, 0); if (0 == pmi->cchMatchingURL) { sc = HRESULT_FROM_WIN32(GetLastError()); DebugTrace("IEcbBase::ScReqMapUrlToPathEx() - MultiByteToWideChar() failed 0x%08lX\n", sc); goto ret; } } else { pmi->cchMatchingURL = 0; } ret: return sc; } protected: // Declare the version constant // enum { IIS_VERSION_6_0 = 0x60000 }; // A POINTER to the original EXTENSION_CONTROL_BLOCK. // Using a reference would make it impossible for us // to tell if IIS ever requires that we use the // EXTENSION_CONTROL_BLOCK passed into async I/O // completion routines for subsequent I/O. // EXTENSION_CONTROL_BLOCK * m_pecb; IEcbBase( EXTENSION_CONTROL_BLOCK& ecb) : m_pecb(&ecb) { m_cRef = 1; //$HACK Until we have 1-based refcounting } public: virtual BOOL FSsl() const = 0; virtual BOOL FFrontEndSecured() const = 0; virtual BOOL FBrief() const = 0; virtual ULONG LcidAccepted() const = 0; virtual VOID SetLcidAccepted(LCID lcid) = 0; virtual LPCSTR LpszRequestUrl() const = 0; virtual LPCWSTR LpwszRequestUrl() const = 0; virtual UINT CchUrlPrefix( LPCSTR * ppszPrefix ) const = 0; virtual UINT CchUrlPrefixW( LPCWSTR * ppwszPrefix ) const = 0; virtual UINT CchGetServerName( LPCSTR * ppszServer ) const = 0; virtual UINT CchGetServerNameW( LPCWSTR * ppwszServer ) const = 0; virtual UINT CchGetVirtualRoot( LPCSTR * ppszVroot ) const = 0; virtual UINT CchGetVirtualRootW( LPCWSTR * ppwszVroot ) const = 0; virtual UINT CchGetMatchingPathW( LPCWSTR * ppwszMatching ) const = 0; virtual LPCWSTR LpwszPathTranslated() const = 0; virtual CInstData& InstData() const = 0; virtual BOOL FGetServerVariable( LPCSTR lpszName, LPSTR lpszValue, DWORD * pcbValue ) const = 0; virtual BOOL FGetServerVariable( LPCSTR lpszName, LPWSTR lpwszValue, DWORD * pcchValue ) const = 0; BOOL WriteClient( LPVOID lpvBuf, LPDWORD lpdwcbBuf, DWORD dwFlags ) const { Assert( m_pecb ); return m_pecb->WriteClient( m_pecb->ConnID, lpvBuf, lpdwcbBuf, dwFlags ); } BOOL ReadClient( LPVOID lpvBuf, LPDWORD lpdwcbBuf ) const { Assert( m_pecb ); return m_pecb->ReadClient( m_pecb->ConnID, lpvBuf, lpdwcbBuf ); } BOOL ServerSupportFunction( DWORD dwHSERequest, LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType ) const { Assert( m_pecb ); return m_pecb->ServerSupportFunction( m_pecb->ConnID, dwHSERequest, lpvBuffer, lpdwSize, lpdwDataType ); } SCODE ScReqMapUrlToPathEx( LPCWSTR pwszUrl, HSE_UNICODE_URL_MAPEX_INFO * pmi ) const { Assert (m_pecb); if ( m_pecb->dwVersion >= IIS_VERSION_6_0 ) return ScReqMapUrlToPathEx60After( pwszUrl, pmi ); return ScReqMapUrlToPathEx60Before( pwszUrl, pmi ); } }; class IEcb : public IEcbBase { // NOT IMPLEMENTED // IEcb( const IEcb& ); IEcb& operator=( const IEcb& ); protected: // CREATORS // Only create this object through it's descendents! // IEcb( EXTENSION_CONTROL_BLOCK& ecb ) : IEcbBase(ecb) {} ~IEcb(); public: // ACCESSORS // LPCSTR LpszMethod() const { Assert( m_pecb ); return m_pecb->lpszMethod; } LPCSTR LpszQueryString() const { Assert( m_pecb ); return m_pecb->lpszQueryString; } DWORD CbTotalBytes() const { Assert( m_pecb ); return m_pecb->cbTotalBytes; } DWORD CbAvailable() const { Assert( m_pecb ); return m_pecb->cbAvailable; } const BYTE * LpbData() const { Assert( m_pecb ); return m_pecb->lpbData; } virtual LPCWSTR LpwszMethod() const = 0; virtual UINT CbGetRawURL( LPCSTR * ppszRawURL ) const = 0; virtual LPCSTR LpszUrlPrefix() const = 0; virtual LPCWSTR LpwszUrlPrefix() const = 0; virtual UINT CchUrlPortW( LPCWSTR * ppwszPort ) const = 0; virtual HANDLE HitUser() const = 0; virtual BOOL FKeepAlive() const = 0; virtual BOOL FCanChunkResponse() const = 0; virtual BOOL FAuthenticated() const = 0; virtual BOOL FProcessingCEUrl() const = 0; virtual BOOL FIIS60OrAfter() const = 0; virtual LPCSTR LpszVersion() const = 0; virtual BOOL FSyncTransmitHeaders( const HSE_SEND_HEADER_EX_INFO& shei ) = 0; virtual SCODE ScAsyncRead( BYTE * pbBuf, UINT * pcbBuf, IIISAsyncIOCompleteObserver& obs ) = 0; virtual SCODE ScAsyncWrite( BYTE * pbBuf, DWORD dwcbBuf, IIISAsyncIOCompleteObserver& obs ) = 0; virtual SCODE ScAsyncTransmitFile( const HSE_TF_INFO& tfi, IIISAsyncIOCompleteObserver& obs ) = 0; virtual SCODE ScAsyncCustomError60After( const HSE_CUSTOM_ERROR_INFO& cei, LPSTR pszStatus ) = 0; virtual SCODE ScExecuteChild( LPCWSTR pwszURI, LPCSTR pszQueryString, BOOL fCustomErrorUrl ) = 0; virtual SCODE ScSendRedirect( LPCSTR lpszURI ) = 0; virtual IMDData& MetaData() const = 0; virtual LPCWSTR PwszMDPathVroot() const = 0; #ifdef DBG virtual void LogString( LPCSTR szLocation ) const = 0; #else void LogString( LPCSTR ) const {}; #endif // MANIPULATORS // virtual VOID SendAsyncErrorResponse( DWORD dwStatusCode, LPCSTR pszBody, DWORD cchzBody, LPCSTR pszStatusDescription, DWORD cchzStatusDescription ) = 0; virtual DWORD HSEHandleException() = 0; // To be used ONLY by request/response. // virtual void SetStatusCode( UINT iStatusCode ) = 0; virtual void SetConnectionHeader( LPCWSTR pwszValue ) = 0; virtual void SetAcceptLanguageHeader( LPCSTR pszValue ) = 0; virtual void CloseConnection() = 0; }; IEcb * NewEcb( EXTENSION_CONTROL_BLOCK& ecb, BOOL fUseRawUrlMappings, DWORD * pdwHSEStatusRet ); #ifdef DBG void InitECBLogging(); void DeinitECBLogging(); #endif // // Routines to manipulate metadata (metabase) paths // ULONG CbMDPathW( const IEcb& ecb, LPCWSTR pwszURI ); VOID MDPathFromURIW( const IEcb& ecb, LPCWSTR pwszURI, LPWSTR pwszMDPath ); #endif // !defined(_ECB_H_)