You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
538 lines
14 KiB
538 lines
14 KiB
#ifndef _ECB_H_
|
|
#define _ECB_H_
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// ECB.H
|
|
//
|
|
// Header for IEcb interface class.
|
|
//
|
|
// Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
|
|
#include <autoptr.h> // For CMTRefCounted parent
|
|
#include <cvroot.h>
|
|
#include <davmb.h> // For IMDData
|
|
#include <url.h> // 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<LPWSTR>(pwszUrl),
|
|
reinterpret_cast<DWORD*>(&cbPath),
|
|
reinterpret_cast<DWORD*>(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<CHAR, MAX_PATH> 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<UINT>(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<DWORD*>(&cbPath),
|
|
reinterpret_cast<DWORD*>(&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_)
|