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.
 
 
 
 
 
 

592 lines
14 KiB

#ifndef W3RESPONSE_HXX_INCLUDED
#define W3RESPONSE_HXX_INCLUDED
//
// HTTP status codes
//
#define REASON(x) (x),sizeof(x)-sizeof(CHAR)
struct HTTP_STATUS
{
USHORT statusCode;
PCHAR pszReason;
USHORT cbReason;
};
extern HTTP_STATUS HttpStatusOk;
extern HTTP_STATUS HttpStatusPartialContent;
extern HTTP_STATUS HttpStatusMultiStatus;
extern HTTP_STATUS HttpStatusMovedPermanently;
extern HTTP_STATUS HttpStatusRedirect;
extern HTTP_STATUS HttpStatusMovedTemporarily;
extern HTTP_STATUS HttpStatusNotModified;
extern HTTP_STATUS HttpStatusBadRequest;
extern HTTP_STATUS HttpStatusUnauthorized;
extern HTTP_STATUS HttpStatusForbidden;
extern HTTP_STATUS HttpStatusNotFound;
extern HTTP_STATUS HttpStatusMethodNotAllowed;
extern HTTP_STATUS HttpStatusNotAcceptable;
extern HTTP_STATUS HttpStatusProxyAuthRequired;
extern HTTP_STATUS HttpStatusPreconditionFailed;
extern HTTP_STATUS HttpStatusEntityTooLarge;
extern HTTP_STATUS HttpStatusUrlTooLong;
extern HTTP_STATUS HttpStatusRangeNotSatisfiable;
extern HTTP_STATUS HttpStatusExpectationFailed;
extern HTTP_STATUS HttpStatusLockedError;
extern HTTP_STATUS HttpStatusServerError;
extern HTTP_STATUS HttpStatusNotImplemented;
extern HTTP_STATUS HttpStatusBadGateway;
extern HTTP_STATUS HttpStatusServiceUnavailable;
extern HTTP_STATUS HttpStatusGatewayTimeout;
//
// HTTP Sub Errors
//
struct HTTP_SUB_ERROR
{
USHORT mdSubError;
DWORD dwStringId;
};
extern HTTP_SUB_ERROR HttpNoSubError;
extern HTTP_SUB_ERROR Http401BadLogon;
extern HTTP_SUB_ERROR Http401Config;
extern HTTP_SUB_ERROR Http401Resource;
extern HTTP_SUB_ERROR Http401Filter;
extern HTTP_SUB_ERROR Http401Application;
extern HTTP_SUB_ERROR Http403ExecAccessDenied;
extern HTTP_SUB_ERROR Http403ReadAccessDenied;
extern HTTP_SUB_ERROR Http403WriteAccessDenied;
extern HTTP_SUB_ERROR Http403SSLRequired;
extern HTTP_SUB_ERROR Http403SSL128Required;
extern HTTP_SUB_ERROR Http403IPAddressReject;
extern HTTP_SUB_ERROR Http403CertRequired;
extern HTTP_SUB_ERROR Http403SiteAccessDenied;
extern HTTP_SUB_ERROR Http403TooManyUsers;
extern HTTP_SUB_ERROR Http403InvalidateConfig;
extern HTTP_SUB_ERROR Http403PasswordChange;
extern HTTP_SUB_ERROR Http403MapperDenyAccess;
extern HTTP_SUB_ERROR Http403CertRevoked;
extern HTTP_SUB_ERROR Http403DirBrowsingDenied;
extern HTTP_SUB_ERROR Http403CertInvalid;
extern HTTP_SUB_ERROR Http403CertTimeInvalid;
extern HTTP_SUB_ERROR Http403AppPoolDenied;
extern HTTP_SUB_ERROR Http403InsufficientPrivilegeForCgi;
extern HTTP_SUB_ERROR Http403PassportLoginFailure;
extern HTTP_SUB_ERROR Http404SiteNotFound;
extern HTTP_SUB_ERROR Http404DeniedByPolicy;
extern HTTP_SUB_ERROR Http404DeniedByMimeMap;
extern HTTP_SUB_ERROR Http500UNCAccess;
extern HTTP_SUB_ERROR Http500BadMetadata;
extern HTTP_SUB_ERROR Http502Timeout;
extern HTTP_SUB_ERROR Http502PrematureExit;
#define W3_RESPONSE_INLINE_HEADERS 10
#define W3_RESPONSE_INLINE_CHUNKS 5
#define W3_RESPONSE_SIGNATURE ((DWORD) 'PR3W')
#define W3_RESPONSE_SIGNATURE_FREE ((DWORD) 'pr3w')
#define W3_RESPONSE_ASYNC 0x01
#define W3_RESPONSE_MORE_DATA 0x02
#define W3_RESPONSE_DISCONNECT 0x04
#define W3_RESPONSE_SUPPRESS_ENTITY 0x10
#define W3_RESPONSE_SUPPRESS_HEADERS 0x20
enum W3_RESPONSE_MODE
{
RESPONSE_MODE_PARSED,
RESPONSE_MODE_RAW
};
class W3_RESPONSE
{
private:
DWORD _dwSignature;
HTTP_RESPONSE _ulHttpResponse;
HTTP_SUB_ERROR _subError;
//
// Buffer to store any strings for header values/names which are
// referenced in the _ulHttpResponse
//
CHUNK_BUFFER _HeaderBuffer;
HTTP_UNKNOWN_HEADER _rgUnknownHeaders[ W3_RESPONSE_INLINE_HEADERS ];
BUFFER _bufUnknownHeaders;
//
// Buffer to store chunk data structures referenced in calls
// to UlSendHttpResponse or UlSendEntityBody
//
HTTP_DATA_CHUNK _rgChunks[ W3_RESPONSE_INLINE_CHUNKS ];
BUFFER _bufChunks;
USHORT _cChunks;
ULONGLONG _cbContentLength;
//
// Has this response been touched at all?
//
BOOL _fResponseTouched;
//
// Has a response been sent
//
BOOL _fResponseSent;
//
// Some buffers used when in raw mode
//
STRA _strRawCoreHeaders;
CHAR _achRawCoreHeaders[ 200 ];
//
// Are we in raw mode or parsed mode?
//
W3_RESPONSE_MODE _responseMode;
//
// Does an ISAPI expect to complete headers with WriteClient()
//
BOOL _fIncompleteHeaders;
//
// Which chunk is the first of actual entity
//
USHORT _cFirstEntityChunk;
//
// Manage where we are as it relates to chunks to be filtered
//
USHORT _cCurrentChunk;
ULONGLONG _cbCurrentOffset;
BUFFER _bufRawChunk;
DWORD _dwSendFlags;
BOOL _fHandleCompletion;
DWORD _cbTotalCompletion;
static DWORD sm_dwSendRawDataBufferSize;
HRESULT
BuildRawCoreHeaders(
VOID
);
HRESULT
SwitchToRawMode(
CHAR * pszAdditionalHeaders,
DWORD cchAdditionalHeaders
);
HRESULT
ParseHeadersFromStream(
CHAR * pszStream
);
HRESULT
InsertDataChunk(
HTTP_DATA_CHUNK * pNewChunk,
LONG cPosition
);
HTTP_DATA_CHUNK *
QueryChunks(
VOID
)
{
return (HTTP_DATA_CHUNK*) _bufChunks.QueryPtr();
}
VOID
Reset(
VOID
);
public:
W3_RESPONSE()
: _bufUnknownHeaders( (BYTE*) _rgUnknownHeaders,
sizeof( _rgUnknownHeaders ) ),
_bufChunks( (BYTE*) _rgChunks,
sizeof( _rgChunks ) ),
_strRawCoreHeaders( _achRawCoreHeaders, sizeof( _achRawCoreHeaders ) )
{
Reset();
_dwSignature = W3_RESPONSE_SIGNATURE;
}
~W3_RESPONSE()
{
_dwSignature = W3_RESPONSE_SIGNATURE_FREE;
}
static
HRESULT
Initialize(
VOID
);
static
VOID
Terminate(
VOID
);
BOOL
CheckSignature(
VOID
) const
{
return _dwSignature == W3_RESPONSE_SIGNATURE;
}
//
// Core header adding/deleting functions
//
HRESULT
SwitchToParsedMode(
VOID
);
HRESULT
DeleteHeader(
CHAR * pszHeaderName
);
HRESULT
SetHeader(
DWORD headerIndex,
CHAR * pszHeaderValue,
USHORT cchHeaderValue,
BOOL fAppend = FALSE
);
HRESULT
SetHeaderByReference(
DWORD headerIndex,
CHAR * pszHeaderValue,
USHORT cchHeaderValue,
BOOL fForceParsedMode = FALSE
);
HRESULT
SetHeader(
CHAR * pszHeaderName,
USHORT cchHeaderName,
CHAR * pszHeaderValue,
USHORT cchHeaderValue,
BOOL fAppend = FALSE,
BOOL fForceParsedMode = FALSE,
BOOL fAlwaysAddUnknown = FALSE,
BOOL fAppendAsDupHeader = FALSE
);
//
// Some friendly SetHeader helpers
//
const CHAR *
GetHeader(
DWORD headerIndex
)
{
HRESULT hr;
if ( _responseMode == RESPONSE_MODE_RAW )
{
hr = SwitchToParsedMode();
if ( FAILED( hr ) )
{
return NULL;
}
}
DBG_ASSERT( _responseMode == RESPONSE_MODE_PARSED );
DBG_ASSERT(headerIndex < HttpHeaderResponseMaximum);
return _ulHttpResponse.Headers.KnownHeaders[headerIndex].pRawValue;
}
HRESULT
GetHeader(
CHAR * pszHeaderName,
STRA * pstrHeaderValue
);
VOID
ClearHeaders(
VOID
);
//
// Chunk management
//
HRESULT
AddFileHandleChunk(
HANDLE hFile,
ULONGLONG cbOffset,
ULONGLONG cbLength
);
HRESULT
AddMemoryChunkByReference(
PVOID pvBuffer,
DWORD cbBuffer
);
HRESULT
AddFragmentChunk(
WCHAR * pszFragmentName,
USHORT dwNameLength
);
HRESULT
Clear(
BOOL fClearEntityOnly = FALSE
);
HRESULT
GenerateAutomaticHeaders(
W3_CONTEXT * pW3Context,
DWORD * pdwFlags
);
//
// ULATQ send APIs
//
HRESULT
SendResponse(
W3_CONTEXT * pW3Context,
DWORD dwResponseFlags,
HTTP_CACHE_POLICY *pCachePolicy,
DWORD * pcbSent
);
HRESULT
SendEntity(
W3_CONTEXT * pW3Context,
DWORD dwResponseFlags,
DWORD * pcbSent
);
HRESULT
ResumeResponseTransfer(
W3_CONTEXT * pW3Context,
BOOL fCompletion,
DWORD cbCompletion,
DWORD dwCompletionStatus,
BOOL fAsync,
DWORD * pcbSent
);
HRESULT
OnIoCompletion(
W3_CONTEXT * pW3Context,
DWORD cbCompletion,
DWORD dwCompletionStatus
)
{
DWORD cbSent;
if ( _fHandleCompletion == FALSE )
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
}
else
{
ResumeResponseTransfer( pW3Context,
TRUE,
cbCompletion,
dwCompletionStatus,
TRUE,
&cbSent );
return NO_ERROR;
}
}
//
// Setup and send an ISAPI response
//
HRESULT
FilterWriteClient(
W3_CONTEXT * pW3Context,
PVOID pvData,
DWORD cbData
);
HRESULT
BuildResponseFromIsapi(
W3_CONTEXT * pW3Context,
LPSTR pszStatusLine,
LPSTR pszHeaderStream,
DWORD cchHeaderStream
);
HRESULT
BuildStatusFromIsapi(
LPSTR pszStatusLine
);
HRESULT
AppendResponseHeaders(
STRA & strHeaders
);
//
// Get the raw response stream for use by raw data filter
//
HRESULT
GetRawResponseStream(
STRA * pstrResponseStream
);
//
// Status code and reason
//
VOID
SetStatus(
HTTP_STATUS & httpStatus,
HTTP_SUB_ERROR & httpSubError = HttpNoSubError
)
{
_ulHttpResponse.StatusCode = httpStatus.statusCode;
_ulHttpResponse.pReason = httpStatus.pszReason;
_ulHttpResponse.ReasonLength = httpStatus.cbReason;
_subError = httpSubError;
_fResponseTouched = TRUE;
}
VOID
SetStatusCode(
USHORT StatusCode
)
{
_ulHttpResponse.StatusCode = StatusCode;
}
VOID
GetStatus(
HTTP_STATUS *phttpStatus
)
{
phttpStatus->statusCode = _ulHttpResponse.StatusCode;
phttpStatus->pszReason = (PSTR) _ulHttpResponse.pReason;
phttpStatus->cbReason = _ulHttpResponse.ReasonLength;
}
HRESULT
SetStatus(
USHORT StatusCode,
STRA & strReason,
HTTP_SUB_ERROR & subError = HttpNoSubError
);
HRESULT
GetStatusLine(
STRA * pstrStatusLine
);
USHORT
QueryStatusCode(
VOID
) const
{
return _ulHttpResponse.StatusCode;
}
HRESULT
QuerySubError(
HTTP_SUB_ERROR * pSubError
)
{
if ( pSubError == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
pSubError->mdSubError = _subError.mdSubError;
pSubError->dwStringId = _subError.dwStringId;
return NO_ERROR;
}
VOID
SetSubError(
HTTP_SUB_ERROR * pSubError
)
{
if ( pSubError == NULL )
{
DBG_ASSERT( FALSE );
return;
}
_subError.mdSubError = pSubError->mdSubError;
_subError.dwStringId = pSubError->dwStringId;
}
VOID
FindStringId(
VOID
);
//
// Touched state. Used to determine whether the system needs to send
// an error (500) response due to not state handler creating a response
//
BOOL
QueryResponseTouched(
VOID
) const
{
return _fResponseTouched;
}
BOOL
QueryResponseSent(
VOID
) const
{
return _fResponseSent;
}
ULONGLONG
QueryContentLength(
VOID
) const
{
return _cbContentLength;
}
//
// Is there any entity in this response (used by custom error logic)
//
BOOL
QueryEntityExists(
VOID
)
{
return _cChunks > 0 && _cChunks > _cFirstEntityChunk;
}
};
#endif