Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1081 lines
20 KiB

#ifndef _MAINCONTEXT_HXX_
#define _MAINCONTEXT_HXX_
class W3_CONNECTION;
class RAW_CONNECTION;
class W3_MAIN_CONTEXT;
//
// Different states
//
enum CONTEXT_STATE
{
CONTEXT_STATE_START,
CONTEXT_STATE_URLINFO,
CONTEXT_STATE_AUTHENTICATION,
CONTEXT_STATE_AUTHORIZATION,
CONTEXT_STATE_HANDLE_REQUEST,
CONTEXT_STATE_RESPONSE,
CONTEXT_STATE_LOG,
CONTEXT_STATE_DONE,
//
// This should be the last value
//
STATE_COUNT
};
//
// W3_CONNECTION_STATE - Abstract class representing state associated with
// connection (W3_CONNECTION)
//
class W3_CONNECTION_STATE
{
public:
virtual BOOL
Cleanup(
VOID
) = 0;
};
//
// W3_CONTEXT_STATE - Abstract class representing context information for a
// given state, stored for a given W3_MAIN_CONTEXT
// At the end of the state machine, objects implementing
// this class will be cleaned up (using Cleanup()).
//
class W3_MAIN_CONTEXT_STATE
{
public:
virtual
~W3_MAIN_CONTEXT_STATE()
{
}
virtual BOOL
Cleanup(
W3_MAIN_CONTEXT * pContext
) = 0;
VOID *
operator new(
size_t uiSize,
VOID * pPlacement
);
VOID
operator delete(
VOID * pContext
);
};
//
// W3_MAIN_CONTEXT
//
// This class represents the mainline (non-child) context representing the
// the execution of a single HTTP request. This class contains and manages
// the HTTP state machine
//
class W3_MAIN_CONTEXT : public W3_CONTEXT
{
private:
//
// Reference count used to manage fact that this context can be attached
// to a RAW_CONNECTION
//
LONG _cRefs;
//
// Request information
//
W3_REQUEST _request;
//
// Response object (not necessarily used in sending a response)
//
W3_RESPONSE _response;
//
// The associated connection for this given request
//
W3_CONNECTION * _pConnection;
BOOL _fAssociationChecked;
//
// The associated Site for this request
//
W3_SITE * _pSite;
//
// Metadata for request
//
URL_CONTEXT * _pUrlContext;
//
// User for the context. For now, the user cannot be reset for a child
// context and is therefore stored only in the main context. That could
// change later if we allow child requests to take on different
// user identity
//
W3_USER_CONTEXT * _pUserContext;
//
// Did an authentication provider already handle sending
// access denied headers?
//
BOOL _fProviderHandled;
//
// Do we need to check if Anonymous auth type is supported when
// we call ANONYMOUS_AUTH_PROVIDER::DoAuthenticate
//
BOOL _fCheckAnonAuthTypeSupported;
//
// Certificate context representing client certificate if negotiated
//
CERTIFICATE_CONTEXT * _pCertificateContext;
//
// ULATQ context used to communicate with UL
//
ULATQ_CONTEXT _ulatqContext;
//
// Filter state
//
W3_FILTER_CONTEXT * _pFilterContext;
//
// Inline filter context used for almost all cases (except
// when we need to persist filter context beyond
// main context lifetime)
//
W3_FILTER_CONTEXT _FilterContext;
//
// State machine
//
DWORD _currentState;
DWORD _nextState;
//
// State context objects
//
W3_MAIN_CONTEXT_STATE * _rgStateContexts[ STATE_COUNT ];
//
// Should we disconnect at the end of this request?
//
BOOL _fDisconnect;
//
// Are we done with compression for this request?
//
BOOL _fDoneWithCompression;
//
// The COMPRESSION_CONTEXT for the current request
//
COMPRESSION_CONTEXT *_pCompressionContext;
//
// Logging data to be passed on to UL
//
LOG_CONTEXT _LogContext;
//
// Do we need to send a final done?
//
BOOL _fNeedFinalDone;
//
// The current context to receive IO completions
//
W3_CONTEXT * _pCurrentContext;
//
// Is this response cacheble in UL?
//
BOOL _fIsUlCacheable;
//
// Access check (put here only since a child request cannot/should not
// change the remote address)
//
ADDRESS_CHECK _IpAddressCheck;
//
// Keep track of available entity body to be read thru UL.
//
DWORD _cbRemainingEntityFromUL;
//
// Keep track of the entity that we've read so far so that
// we can enforce MaxRequestEntityAllowed.
//
DWORD _cbEntityReadSoFar;
//
// For HEAD requests, UL will not send a content-length so we'll have
// to do for HEAD requests. The reason we keep this state
// is because filters/child-requests can reset the verb -> a resetting
// which still doesn't change the fact that UL will not be setting
// Content-Length
//
BOOL _fGenerateContentLength;
//
// Raw connection. Needed since we need to tell the raw connection when
// it should no longer reference us
//
RAW_CONNECTION * _pRawConnection;
//
// List of *-ScriptMaps which do not want to be notified at all anymore
// about this particular chain of request
//
MULTISZ _mszIgnoredInterceptors;
//
// Call information about last posted completion
//
CHAR * _pszLastPostFileName;
DWORD _dwLastPostLineNumber;
//
// Handle for TIMER callback when a W3_MAIN_CONTEXT has existed for too long
//
HANDLE _hTimer;
//
// Per request trace log
//
W3_TRACE_LOG * _pTraceLog;
//
// Can we ignore the apppool check (done when WAS routes us to an
// AppPool we aren't configured by URL-wise
//
BOOL _fIgnoreAppPoolCheck;
//
// static TraceLogFactory
//
static W3_TRACE_LOG_FACTORY * sm_pLogFactory;
//
// static File to trace to
//
static HANDLE sm_hTraceFile;
static
HRESULT
SetupTraceLogging(
VOID
);
static
VOID
CleanupTraceLogging(
VOID
);
//
// timeout in milliseconds before DebugBreak() is called
// read from registry at static Initialization
//
static DWORD sm_dwTimeout;
//
// Callback function that does the DebugBreak for overtime W3_MAIN_CONTEXT
//
static
VOID
TimerCallback(
PVOID pvParam,
BOOLEAN fReason
);
W3_MAIN_CONTEXT(const W3_MAIN_CONTEXT &);
void operator=(const W3_MAIN_CONTEXT &);
public:
//
// Lookaside for main contexts
//
static ALLOC_CACHE_HANDLER * sm_pachMainContexts;
//
// The states
//
static W3_STATE * sm_pStates[ STATE_COUNT ];
static SHORT sm_rgInline[ STATE_COUNT ];
static USHORT sm_cbInlineBytes;
W3_MAIN_CONTEXT(
HTTP_REQUEST * pUlHttpRequest,
ULATQ_CONTEXT pUlAtqContext
);
~W3_MAIN_CONTEXT();
VOID *
operator new(
size_t uiSize,
VOID * pPlacement
);
VOID
operator delete(
VOID * pMainContext
);
VOID *
AllocateFromInlineMemory(
DWORD cbSize
);
//
// Overridden W3_CONTEXT methods
//
ULATQ_CONTEXT
QueryUlatqContext(
VOID
)
{
return _ulatqContext;
}
W3_REQUEST *
QueryRequest(
VOID
)
{
return &_request;
}
W3_RESPONSE *
QueryResponse(
VOID
)
{
return &_response;
}
BOOL
QueryResponseSent(
VOID
)
{
return _response.QueryResponseSent();
}
BOOL
QueryIsUlCacheable(
VOID
)
{
return _fIsUlCacheable;
}
VOID
DisableUlCache(
VOID
)
{
_fIsUlCacheable = FALSE;
}
BOOL
QueryProviderHandled(
VOID
)
{
return _fProviderHandled;
}
BOOL
QueryNeedFinalDone(
VOID
)
{
return _fNeedFinalDone;
}
VOID
SetNeedFinalDone(
VOID
)
{
_fNeedFinalDone = TRUE;
}
BOOL
QueryCheckAnonAuthTypeSupported(
VOID
)
{
return _fCheckAnonAuthTypeSupported;
}
VOID
SetCheckAnonAuthTypeSupported(
BOOL fCheckAnonAuthTypeSupported
)
{
_fCheckAnonAuthTypeSupported = fCheckAnonAuthTypeSupported;
}
BOOL
QueryShouldGenerateContentLength(
VOID
) const
{
return _fGenerateContentLength;
}
VOID
SetShouldGenerateContentLength(
BOOL fShouldGenerate
)
{
_fGenerateContentLength = fShouldGenerate;
}
W3_USER_CONTEXT *
QueryUserContext(
VOID
)
{
return _pUserContext;
}
W3_USER_CONTEXT *
QueryConnectionUserContext(
VOID
);
VOID
SetConnectionUserContext(
W3_USER_CONTEXT * pUserContext
);
VOID
SetUserContext(
W3_USER_CONTEXT * pUserContext
)
{
// perf ctr
if (pUserContext->QueryAuthType() == MD_AUTH_ANONYMOUS)
{
_pSite->IncAnonUsers();
}
else
{
_pSite->IncNonAnonUsers();
}
_pUserContext = pUserContext;
}
CERTIFICATE_CONTEXT *
QueryCertificateContext(
VOID
) const
{
return _pCertificateContext;
}
VOID
UpdateSkipped(
HTTP_DATA_CHUNK * pChunks,
DWORD cChunks
);
VOID
DetermineRemainingEntity(
VOID
);
VOID
SetCertificateContext(
CERTIFICATE_CONTEXT * pCertificateContext
)
{
_pCertificateContext = pCertificateContext;
}
W3_FILTER_CONTEXT *
QueryFilterContext(
BOOL fCreateIfNotFound = TRUE
);
URL_CONTEXT *
QueryUrlContext(
VOID
)
{
return _pUrlContext;
}
W3_SITE *
QuerySite(
VOID
)
{
return _pSite;
}
W3_CONTEXT *
QueryCurrentContext(
VOID
)
{
return _pCurrentContext;
}
VOID
PopCurrentContext(
VOID
)
{
_pCurrentContext = _pCurrentContext->QueryParentContext();
if ( _pCurrentContext == NULL )
{
_pCurrentContext = this;
}
}
VOID
PushCurrentContext(
W3_CONTEXT * pW3Context
)
{
_pCurrentContext = pW3Context;
}
W3_CONTEXT *
QueryParentContext(
VOID
)
{
return NULL;
}
W3_MAIN_CONTEXT *
QueryMainContext(
VOID
)
{
return this;
}
BOOL
QueryDisconnect(
VOID
);
VOID
SetDisconnect(
BOOL fDisconnect
)
{
_fDisconnect = fDisconnect;
}
VOID
SetDeniedFlags(
DWORD dwDeniedFlags
)
{
if( _pFilterContext )
{
_pFilterContext->SetDeniedFlags( dwDeniedFlags );
}
}
BOOL
NotifyFilters(
DWORD dwNotification,
VOID * pvFilterInfo,
BOOL * pfFinished
);
BOOL
IsNotificationNeeded(
DWORD dwNotification
);
//
// W3_MAIN_CONTEXT specific methods. These methods are not callable
// when we are in the state of invoking a handler
//
VOID
ReferenceMainContext(
VOID
)
{
InterlockedIncrement( &_cRefs );
}
VOID
DereferenceMainContext(
VOID
)
{
ULATQ_CONTEXT ulatqContext;
if ( !InterlockedDecrement( &_cRefs ) )
{
//
// Remember the ULATQ context. Once we've deleted the object
// we will free the context
//
ulatqContext = _ulatqContext;
delete this;
UlAtqFreeContext( ulatqContext );
}
}
BOOL
QueryIgnoreAppPoolCheck(
VOID
) const
{
return _fIgnoreAppPoolCheck;
}
VOID
SetIgnoreAppPoolCheck(
VOID
)
{
_fIgnoreAppPoolCheck = TRUE;
}
RAW_CONNECTION *
QueryRawConnection(
VOID
) const
{
return _pRawConnection;
}
VOID
SetRawConnection(
RAW_CONNECTION * pRawConnection
);
VOID
SetRawConnectionClientContext(
DWORD dwCurrentFilter,
VOID * pvContext
);
BOOL
QueryRawConnectionNotificationChanged(
VOID
);
BOOL
IsRawConnectionDisableNotificationNeeded(
DWORD dwFilter,
DWORD dwNotification
);
BOOL
QueryExpiry(
LARGE_INTEGER * pExpiry
);
HRESULT
ExecuteExpiredUrl(
STRU & strExpUrl
);
HRESULT
PasswdExpireNotify(
VOID
);
HRESULT
PasswdChangeExecute(
VOID
);
HRESULT
ReceiveEntityBody(
BOOL fAsync,
VOID * pBuffer,
DWORD cbBuffer,
DWORD * pBytesReceived
);
DWORD
QueryRemainingEntityFromUl(
VOID
) const
{
return _cbRemainingEntityFromUL;
}
VOID
SetRemainingEntityFromUl(
DWORD cbRemaining
)
{
_cbRemainingEntityFromUL = cbRemaining;
}
HRESULT
GetRemoteDNSName(
STRA * pstrDNSName
);
ADDRESS_CHECK *
QueryAddressCheck(
VOID
)
{
return &_IpAddressCheck;
}
VOID
SetProviderHandled(
BOOL fProviderHandled
)
{
_fProviderHandled = fProviderHandled;
}
HRESULT
OnAccessDenied(
VOID
)
{
return NO_ERROR;
}
VOID
SetUrlContext(
URL_CONTEXT * pUrlContext
)
{
_pUrlContext = pUrlContext;
}
VOID
AssociateSite(
W3_SITE * site
)
{
_pSite = site;
}
W3_CONNECTION *
QueryConnection(
BOOL fCreateIfNotFound = TRUE
);
//
// Retrieve context for specified/current state
//
W3_MAIN_CONTEXT_STATE *
QueryContextState(
DWORD contextState = -1
)
{
if ( contextState == -1 )
{
contextState = _currentState;
}
return _rgStateContexts[ contextState ];
}
//
// Set context for current state
//
VOID
SetContextState(
W3_MAIN_CONTEXT_STATE * pStateContext
)
{
_rgStateContexts[ _currentState ] = pStateContext;
}
W3_CONNECTION_STATE *
QueryConnectionState(
VOID
);
VOID
SetConnectionState(
W3_CONNECTION_STATE * pConnectionState
);
HRESULT AppendIgnoreInterceptor(STRU &strName)
{
if (!_mszIgnoredInterceptors.Append(strName))
{
return HRESULT_FROM_WIN32(GetLastError());
}
return S_OK;
}
BOOL IsIgnoredInterceptor(STRU &strName)
{
return _mszIgnoredInterceptors.FindString(strName);
}
VOID SetDoneWithCompression()
{
_fDoneWithCompression = TRUE;
}
BOOL QueryDoneWithCompression()
{
return _fDoneWithCompression;
}
VOID SetCompressionContext(IN COMPRESSION_CONTEXT *pCompressionContext)
{
DBG_ASSERT(_pCompressionContext == NULL);
_pCompressionContext = pCompressionContext;
}
COMPRESSION_CONTEXT *QueryCompressionContext()
{
return _pCompressionContext;
}
HTTP_LOG_FIELDS_DATA *QueryUlLogData()
{
return _LogContext.QueryUlLogData();
}
LOG_CONTEXT *QueryLogContext()
{
return &_LogContext;
}
HRESULT CollectLoggingData(BOOL fCollectForULLogging);
void SetLastIOPending(LAST_IO_PENDING ioPending)
{
_LogContext.m_ioPending = ioPending;
}
LAST_IO_PENDING QueryLastIOPending()
{
return _LogContext.m_ioPending;
}
VOID IncrementBytesRecvd(DWORD dwRecvd)
{
_LogContext.m_dwBytesRecvd += dwRecvd;
_cbEntityReadSoFar += dwRecvd;
}
VOID IncrementBytesSent(DWORD dwSent)
{
_LogContext.m_dwBytesSent += dwSent;
}
VOID SetInitialEntityReadSize(DWORD dwBytes)
{
_cbEntityReadSoFar = dwBytes;
}
DWORD QueryEntityReadSoFar()
{
return _cbEntityReadSoFar;
}
VOID
DoWork(
DWORD cbCompletion,
DWORD dwCompletionStatus,
BOOL fIoCompletion
);
BOOL
SetupContext(
HTTP_REQUEST * pUlHttpRequest,
ULATQ_CONTEXT pUlAtqContext
);
VOID
CleanupContext(
VOID
);
VOID
SetFinishedResponse(
VOID
)
{
_nextState = CONTEXT_STATE_RESPONSE;
}
VOID
SetDone(
VOID
)
{
_nextState = CONTEXT_STATE_LOG;
}
VOID
BackupStateMachine(
VOID
);
HRESULT
SetupCertificateContext(
HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo
);
DWORD
QueryCurrentStarScriptMapIndex(
VOID
)
{
return 0;
}
static
HRESULT
SetupStateMachine(
VOID
);
static
VOID
CleanupStateMachine(
VOID
);
static
HRESULT
Initialize(
VOID
);
static
VOID
Terminate(
VOID
);
static
VOID
AddressResolutionCallback(
ADDRCHECKARG pContext,
BOOL fUnused,
LPSTR pszUnused
);
//
// Completion routines called from ULATQ
//
static
VOID
OnIoCompletion(
PVOID pvContext,
DWORD cbWritten,
DWORD dwCompletionStatus,
OVERLAPPED * lpo
);
static
VOID
OnNewRequest(
ULATQ_CONTEXT pContext
);
static
VOID
OnPostedCompletion(
DWORD dwCompletionStatus,
DWORD cbWritten,
LPOVERLAPPED lpo
);
static
VOID
PostMainCompletion(
CHAR * pszFileName,
DWORD dwLineNumber,
W3_MAIN_CONTEXT * pMainContext
);
W3_TRACE_LOG*
QueryTraceLog(
VOID
)
{
return _pTraceLog;
}
};
#define POST_MAIN_COMPLETION(x) \
W3_MAIN_CONTEXT::PostMainCompletion( __FILE__, __LINE__, (x) )
#endif