838 lines
16 KiB
C++
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
|