|
|
#ifndef _W3CONTEXT_HXX_
#define _W3CONTEXT_HXX_
#define W3_PARAMETERS_KEY \
L"System\\CurrentControlSet\\Services\\w3svc\\Parameters"
// Is it a UNC Path?
#define ISUNC(a) ((a)[0]==L'\\' && (a)[1]==L'\\')
#define W3_FLAG_ASYNC 0x00000001
#define W3_FLAG_SYNC 0x00000002
#define W3_FLAG_NO_CUSTOM_ERROR 0x00000004
#define W3_FLAG_MORE_DATA 0x00000008
#define W3_FLAG_PAST_END_OF_REQ 0x00000010
#define W3_FLAG_NO_HEADERS 0x00000020
#define W3_FLAG_NO_CONTENT_LENGTH 0x00000040
#define W3_FLAG_NO_ERROR_BODY 0x00000080
#define W3_FLAG_VALID ( W3_FLAG_ASYNC | \
W3_FLAG_SYNC | \ W3_FLAG_NO_CUSTOM_ERROR | \ W3_FLAG_MORE_DATA | \ W3_FLAG_PAST_END_OF_REQ | \ W3_FLAG_NO_HEADERS | \ W3_FLAG_NO_ERROR_BODY | \ W3_FLAG_NO_CONTENT_LENGTH )
#define VALID_W3_FLAGS(x) ( (x) == ((x) & (W3_FLAG_VALID)) )
class URL_CONTEXT; class W3_HANDLER; class COMPRESSION_CONTEXT;
//
// Access check state
//
// We potentially do two asynchronous operations in determining whether
// a given request is valid
// 1) Do an RDNS lookup if restrictions are configured in metabase
// 2) Request a client certificate if configured in metabase
//
enum W3_CONTEXT_ACCESS_STATE { ACCESS_STATE_START, ACCESS_STATE_RDNS, ACCESS_STATE_CLIENT_CERT_PRELOAD_ENTITY, ACCESS_STATE_CLIENT_CERT, ACCESS_STATE_AUTHENTICATION, ACCESS_STATE_SENDING_ERROR, ACCESS_STATE_DONE };
//
// W3_CONTEXT - Object representing an execution of the state machine to
// handle a given request from UL
//
#define W3_CONTEXT_LIST_SPINS 200
//
// maximum number of nested child execute calls that are supported
//
#define W3_CONTEXT_MAX_RECURSION_LEVEL 100
#define W3_CONTEXT_SIGNATURE ((DWORD) 'XC3W')
#define W3_CONTEXT_SIGNATURE_FREE ((DWORD) 'xc3w')
class W3_CONTEXT { private:
DWORD _dwSignature;
//
// Handler for this context
//
W3_HANDLER * _pHandler;
//
// Error Status for request
//
HRESULT _errorStatus;
//
// Completion indication (for synchronous execution of handlers)
//
HANDLE _hCompletion;
//
// Custom error file to cleanup
//
W3_FILE_INFO * _pCustomErrorFile;
//
// Maintain list of contexts
//
LIST_ENTRY _listEntry;
//
// Where are we with checking access rights for this request
//
W3_CONTEXT_ACCESS_STATE _accessState; BOOL _fDNSRequiredForAccess; // argh
//
// The status of last child request executed by this context
//
USHORT _childStatusCode; USHORT _childSubErrorCode; HRESULT _childError;
//
// Is authentication access check required or not
//
BOOL _fAuthAccessCheckRequired;
//
// Are we suppressing the response entity (normally if it is a HEAD
// request to something other than an ISAPI)
//
BOOL _fSuppressEntity;
//
// Recursion level for the ExecuteUrl() used to prevent infinite recursion
// If recursion level reaches W3_CONTEXT_MAX_RECURSION_LEVEL value
// then no more IsapiExecuteUrl() or ExecuteChildRequest() calls are allowed
//
DWORD _dwRecursionLevel;
//
// Keep a reference to the VrToken so it won't get deleted somewhere else
//
TOKEN_CACHE_ENTRY * _pctVrToken;
//
// Chunk buffer
//
CHUNK_BUFFER _ChunkBuffer;
CONTEXT_STATUS ExecuteCurrentHandler( VOID );
protected:
//
// The flags determining how to execute this request
// (we let child contexts alter these flags if needed)
//
DWORD _dwExecFlags;
public:
static CHAR sm_achRedirectMessage[ 512 ]; static DWORD sm_cbRedirectMessage; static CHAR * sm_pszAccessDeniedMessage; W3_CONTEXT( DWORD dwExecFlags, DWORD dwRecursionLevel ); virtual ~W3_CONTEXT(); virtual BOOL QueryResponseSent( VOID ) = 0; virtual BOOL QuerySendLocation( VOID ) { return FALSE; } virtual BOOL QueryNeedFinalDone( VOID ) = 0;
virtual VOID SetNeedFinalDone( VOID ) = 0; virtual W3_REQUEST * QueryRequest( VOID ) = 0;
virtual W3_RESPONSE * QueryResponse( VOID ) = 0;
virtual W3_SITE * QuerySite( VOID ) = 0;
virtual W3_CONTEXT * QueryParentContext( VOID ) = 0; virtual W3_MAIN_CONTEXT * QueryMainContext( VOID ) = 0; virtual URL_CONTEXT * QueryUrlContext( VOID ) = 0; virtual W3_USER_CONTEXT * QueryUserContext( VOID ) = 0; virtual W3_FILTER_CONTEXT * QueryFilterContext( BOOL fCreateIfNotFound = TRUE ) = 0;
virtual ULATQ_CONTEXT QueryUlatqContext( VOID ) = 0; virtual BOOL QueryProviderHandled( VOID ) = 0; virtual BOOL NotifyFilters( DWORD dwNotification, VOID * pvFilterInfo, BOOL * pfFinished ) = 0;
virtual BOOL IsNotificationNeeded( DWORD dwNotification ) = 0; virtual VOID SetDisconnect( BOOL fDisconnect ) = 0; virtual BOOL QueryDisconnect( VOID ) = 0;
virtual VOID SetDoneWithCompression( VOID ) = 0;
virtual BOOL QueryDoneWithCompression( VOID ) = 0;
virtual VOID SetCompressionContext( COMPRESSION_CONTEXT * pCompressionContext ) = 0;
virtual COMPRESSION_CONTEXT * QueryCompressionContext( VOID ) = 0;
virtual HTTP_LOG_FIELDS_DATA * QueryUlLogData( VOID ) = 0;
virtual VOID SetLastIOPending( LAST_IO_PENDING ioPending ) = 0;
virtual VOID IncrementBytesRecvd( DWORD dwRead ) = 0;
virtual VOID IncrementBytesSent( DWORD dwSent ) = 0; virtual BOOL QueryIsUlCacheable( VOID ) = 0; virtual VOID DisableUlCache( VOID ) = 0; //
// Other fixed W3_CONTEXT methods
//
VOID * ContextAlloc( DWORD cbSize );
W3_HANDLER * QueryHandler( VOID ) const { return _pHandler; } VOID SetChildStatusAndError( USHORT ChildStatusCode, USHORT ChildSubError, HRESULT ChildError ) { _childStatusCode = ChildStatusCode; _childSubErrorCode = ChildSubError; _childError = ChildError; } VOID QueryChildStatusAndError( USHORT * pChildStatusCode, USHORT * pChildSubError, DWORD * pChildError ) const { DBG_ASSERT( pChildStatusCode != NULL ); DBG_ASSERT( pChildSubError != NULL ); DBG_ASSERT( pChildError != NULL ); *pChildStatusCode = _childStatusCode; *pChildSubError = _childSubErrorCode; if ( FAILED( _childError ) ) { *pChildError = WIN32_FROM_HRESULT( _childError ); } else { *pChildError = ERROR_SUCCESS; } } BOOL QuerySendCustomError( VOID ) const { if ( _dwExecFlags & W3_FLAG_NO_CUSTOM_ERROR ) { return FALSE; } else { return TRUE; } } BOOL QuerySendErrorBody( VOID ) const { if ( _dwExecFlags & W3_FLAG_NO_ERROR_BODY ) { return FALSE; } else { return TRUE; } } BOOL QuerySendHeaders( VOID ) const { if ( _dwExecFlags & W3_FLAG_NO_HEADERS ) { return FALSE; } else { return TRUE; } } VOID SetAuthAccessCheckRequired( BOOL fAuthAccessCheckRequired ) { _fAuthAccessCheckRequired = fAuthAccessCheckRequired; }
BOOL QueryAuthAccessCheckRequired( VOID ) const { return _fAuthAccessCheckRequired; }
VOID SetSSICommandHandler( W3_HANDLER * pHandler );
BOOL QueryDoUlLogging( VOID );
BOOL QueryDoCustomLogging( VOID ); HRESULT SetupCustomErrorFileResponse( STRU & strErrorFile );
HRESULT SendResponse( DWORD dwFlags ); HRESULT GetCertificateInfoEx( IN DWORD cbAllocated, OUT DWORD * pdwCertEncodingType, OUT unsigned char * pbCertEncoded, OUT DWORD * pcbCertEncoded, OUT DWORD * pdwCertificateFlags ); HANDLE QueryImpersonationToken( BOOL * pfIsVrToken = NULL ); HANDLE QueryPrimaryToken( VOID ); TOKEN_CACHE_ENTRY * QueryVrToken( VOID ) { return _pctVrToken; }
VOID QueryFileCacheUser( CACHE_USER * pFileUser ); CONTEXT_STATUS CheckAccess( BOOL fCompletion, DWORD cbCompletion, DWORD dwCompletionStatus, BOOL * pfAccessAllowed ); CERTIFICATE_CONTEXT * QueryCertificateContext( VOID ); CHUNK_BUFFER * QueryHeaderBuffer( VOID ) { return &_ChunkBuffer; } BOOL CheckClientCertificateAccess( VOID ); HRESULT SendEntity( DWORD dwFlags );
HRESULT ReceiveEntity( DWORD dwFlags, VOID * pBuffer, DWORD cbBuffer, DWORD * pBytesReceived ); DWORD QueryRemainingEntityFromUl( VOID );
VOID SetRemainingEntityFromUl( DWORD cbRemaining );
VOID QueryAlreadyAvailableEntity( VOID ** ppvBuffer, DWORD * pcbBuffer ); HRESULT QueryErrorStatus( VOID ) const { return _errorStatus; }
VOID SetErrorStatus( HRESULT errorStatus ) { _errorStatus = errorStatus; }
HRESULT CheckUrlRedirection( BOOL *pfRedirected, STRU *pstrDestination, HTTP_STATUS *pStatusCode );
HRESULT SetupHttpRedirect( STRA & strPath, BOOL fIncludeParameters, HTTP_STATUS & httpStatus );
HRESULT SetupHttpRedirect( STRU & strPath, BOOL fIncludeParameters, HTTP_STATUS & httpStatus );
HRESULT SetupAllowHeader( VOID ); BOOL CheckSignature( VOID ) const { return _dwSignature == W3_CONTEXT_SIGNATURE; } BOOL QueryAccessChecked( VOID ) const { return _accessState == ACCESS_STATE_DONE; } VOID ResetAccessCheck( VOID ) { _accessState = ACCESS_STATE_START; } HRESULT SetupCompletionEvent( VOID ) { _hCompletion = IIS_CREATE_EVENT( "W3_CONTEXT::_hCompletion", this, FALSE, FALSE ); if ( _hCompletion == NULL ) { return HRESULT_FROM_WIN32( GetLastError() ); } else { return NO_ERROR; } } VOID WaitForCompletion( VOID ) { if ( _hCompletion ) { WaitForSingleObject( _hCompletion, INFINITE ); } } VOID IndicateCompletion( VOID ) { if ( _hCompletion ) { SetEvent( _hCompletion ); } } BOOL QueryIsSynchronous( VOID ) const { return _hCompletion != NULL; } HRESULT IsapiExecuteUrl( EXEC_URL_INFO * pExecUrlInfo );
HRESULT CleanIsapiExecuteUrl( EXEC_URL_INFO * pExecUrlInfo ); HRESULT IsapiSendCustomError( HSE_CUSTOM_ERROR_INFO * pCustomErrorInfo );
HRESULT CleanIsapiSendCustomError( HSE_CUSTOM_ERROR_INFO * pCustomErrorInfo ); HRESULT ExecuteChildRequest( W3_REQUEST * pNewRequest, BOOL fOwnRequest, DWORD dwFlags );
HRESULT ExecuteHandler( DWORD dwFlags, BOOL * pfDidImmediateFinish = NULL ); CONTEXT_STATUS ExecuteHandlerCompletion( DWORD cbCompletion, DWORD dwCompletionStatus );
HRESULT CheckPathInfoExists( W3_HANDLER ** ppHandler );
HRESULT InternalDetermineHandler( W3_HANDLER ** ppHandler, BOOL fDoExistenceCheck ); HRESULT DetermineHandler( VOID ) { return InternalDetermineHandler( &_pHandler, TRUE ); }
HRESULT ValidateAppPool( BOOL * pfAppPoolValid );
virtual DWORD QueryCurrentStarScriptMapIndex( VOID ) = 0;
static HRESULT Initialize( VOID ); static VOID Terminate( VOID ); static VOID OnCleanIsapiExecuteUrl( DWORD dwCompletionStatus, DWORD cbWritten, LPOVERLAPPED lpo ); static VOID OnCleanIsapiSendCustomError( DWORD dwCompletionStatus, DWORD cbWritten, LPOVERLAPPED lpo ); };
//
// EXECUTE_CONTEXT Used to marshall an IsapiExecuteUrl() or
// IsapiSendCustomError() on a clean (non-coinited) thread
//
#define EXECUTE_CONTEXT_SIGNATURE ((DWORD) 'TCXE')
#define EXECUTE_CONTEXT_SIGNATURE_FREE ((DWORD) 'xcxe')
class EXECUTE_CONTEXT { public: EXECUTE_CONTEXT( W3_CONTEXT * pW3Context ) { DBG_ASSERT( pW3Context != NULL ); _hEvent = NULL; _pW3Context = pW3Context; ZeroMemory( &_ExecUrlInfo, sizeof( _ExecUrlInfo ) ); ZeroMemory( &_UserInfo, sizeof( _UserInfo ) ); ZeroMemory( &_EntityInfo, sizeof( _EntityInfo ) ); _dwSignature = EXECUTE_CONTEXT_SIGNATURE; } virtual ~EXECUTE_CONTEXT() { _dwSignature = EXECUTE_CONTEXT_SIGNATURE_FREE; if ( _hEvent != NULL ) { SetEvent( _hEvent ); } } HRESULT InitializeFromExecUrlInfo( EXEC_URL_INFO * pExecUrlInfo ); EXEC_URL_INFO * QueryExecUrlInfo( VOID ) { return &_ExecUrlInfo; } VOID SetCompleteEvent( HANDLE hEvent ) { _hEvent = hEvent; } BOOL CheckSignature( VOID ) const { return _dwSignature == EXECUTE_CONTEXT_SIGNATURE; } HANDLE QueryCompleteEvent( VOID ) const { return _hEvent; } W3_CONTEXT * QueryW3Context( VOID ) const { return _pW3Context; } VOID * operator new( #if DBG
size_t size #else
size_t #endif
) { DBG_ASSERT( size == sizeof( EXECUTE_CONTEXT ) ); DBG_ASSERT( sm_pachExecuteContexts != NULL ); return sm_pachExecuteContexts->Alloc(); } VOID operator delete( VOID * pExecuteContext ) { DBG_ASSERT( pExecuteContext != NULL ); DBG_ASSERT( sm_pachExecuteContexts != NULL ); DBG_REQUIRE( sm_pachExecuteContexts->Free( pExecuteContext ) ); } static HRESULT Initialize( VOID ); static VOID Terminate( VOID );
private: DWORD _dwSignature; W3_CONTEXT * _pW3Context; EXEC_URL_INFO _ExecUrlInfo; EXEC_URL_USER_INFO _UserInfo; EXEC_URL_ENTITY_INFO _EntityInfo; CHUNK_BUFFER _HeaderBuffer; HANDLE _hEvent; static ALLOC_CACHE_HANDLER * sm_pachExecuteContexts; };
#endif
|