windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/ulw3/w3context.hxx
2020-09-26 16:20:57 +08:00

838 lines
16 KiB
C++

#ifndef _W3CONTEXT_HXX_
#define _W3CONTEXT_HXX_
#define W3_PARAMETERS_KEY \
L"System\\CurrentControlSet\\Services\\w3svc\\Parameters"
#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_GENERATE_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_GENERATE_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,
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
#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;
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
);
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
//
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
);
VOID
QueryFileCacheUser(
FILE_CACHE_USER * pFileUser
);
CONTEXT_STATUS
CheckAccess(
BOOL fCompletion,
DWORD dwCompletionStatus,
BOOL * pfAccessAllowed
);
CERTIFICATE_CONTEXT *
QueryCertificateContext(
VOID
);
CHUNK_BUFFER *
QueryHeaderBuffer(
VOID
);
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
DoUrlRedirection(
BOOL *pfRedirected
);
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(
HSE_EXEC_URL_INFO * pExecUrlInfo
);
HRESULT
CleanIsapiExecuteUrl(
HSE_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
DetermineHandler(
BOOL fAllowWildcardMapping
);
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(
HSE_EXEC_URL_INFO * pExecUrlInfo
);
HSE_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(
size_t size
)
{
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;
HSE_EXEC_URL_INFO _ExecUrlInfo;
HSE_EXEC_URL_USER_INFO _UserInfo;
HSE_EXEC_URL_ENTITY_INFO _EntityInfo;
CHUNK_BUFFER _HeaderBuffer;
HANDLE _hEvent;
static ALLOC_CACHE_HANDLER * sm_pachExecuteContexts;
};
#endif