742 lines
15 KiB
C++
742 lines
15 KiB
C++
#ifndef _W3REQUEST_HXX_
|
|
#define _W3REQUEST_HXX_
|
|
|
|
#define W3_REQUEST_SIGNATURE ((DWORD) 'QR3W')
|
|
#define W3_REQUEST_SIGNATURE_FREE ((DWORD) 'qr3w')
|
|
|
|
class W3_CONTEXT;
|
|
|
|
class W3_REQUEST
|
|
{
|
|
protected:
|
|
|
|
DWORD _dwSignature;
|
|
|
|
//
|
|
// We provide a friendly wrapper of the UL_HTTP_REQUEST from UL
|
|
//
|
|
|
|
HTTP_REQUEST * _pUlHttpRequest;
|
|
HTTP_UNKNOWN_HEADER * _pExtraUnknown;
|
|
|
|
//
|
|
// If a filter changes the URL, unknown verb, etc., we need a new buffer
|
|
// pointed into by UL_HTTP_REQUEST
|
|
//
|
|
|
|
CHUNK_BUFFER _HeaderBuffer;
|
|
|
|
//
|
|
// If we are going to insert entity body (child requests) then we'll
|
|
// need a HTTP_DATA_CHUNK to store the pointer
|
|
//
|
|
|
|
HTTP_DATA_CHUNK _InsertedEntityBodyChunk;
|
|
|
|
//
|
|
// Preloaded entity
|
|
//
|
|
|
|
BUFFER _buffEntityBodyPreload;
|
|
|
|
//
|
|
// Keep track of the "wire user" for this request
|
|
//
|
|
|
|
STRA _strRequestUserName;
|
|
|
|
//
|
|
// Keep track of original full URL of request (can be changed by filter)
|
|
//
|
|
|
|
WCHAR * _pszOriginalFullUrl;
|
|
DWORD _cchOriginalFullUrl;
|
|
|
|
static PHOSTENT sm_pHostEnt;
|
|
|
|
|
|
public:
|
|
W3_REQUEST()
|
|
: _dwSignature( W3_REQUEST_SIGNATURE ),
|
|
_pUlHttpRequest( NULL ),
|
|
_pExtraUnknown( NULL ),
|
|
_pszOriginalFullUrl( NULL ),
|
|
_cchOriginalFullUrl( 0 )
|
|
{
|
|
_InsertedEntityBodyChunk.DataChunkType = HttpDataChunkFromMemory;
|
|
}
|
|
|
|
virtual ~W3_REQUEST()
|
|
{
|
|
if ( _pExtraUnknown != NULL )
|
|
{
|
|
LocalFree( _pExtraUnknown );
|
|
_pExtraUnknown = NULL;
|
|
}
|
|
|
|
_dwSignature = W3_REQUEST_SIGNATURE_FREE;
|
|
}
|
|
|
|
VOID
|
|
SetHttpRequest(
|
|
HTTP_REQUEST * pRequest
|
|
)
|
|
{
|
|
_pUlHttpRequest = pRequest;
|
|
|
|
_pszOriginalFullUrl = pRequest->CookedUrl.pFullUrl;
|
|
_cchOriginalFullUrl = pRequest->CookedUrl.FullUrlLength / sizeof(WCHAR);
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
Initialize(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
VOID
|
|
Terminate(
|
|
VOID
|
|
);
|
|
|
|
HRESULT
|
|
SetNewPreloadedEntityBody(
|
|
VOID * pvBuffer,
|
|
DWORD cbBuffer
|
|
);
|
|
|
|
HRESULT AppendEntityBody(
|
|
VOID * pvBuffer,
|
|
DWORD cbBuffer
|
|
);
|
|
|
|
HRESULT PreloadEntityBody(
|
|
W3_CONTEXT * pW3Context,
|
|
BOOL * pfComplete
|
|
);
|
|
|
|
HRESULT
|
|
PreloadCompletion(
|
|
W3_CONTEXT * pW3Context,
|
|
DWORD cbRead,
|
|
DWORD dwStatus,
|
|
BOOL * pfComplete
|
|
);
|
|
|
|
VOID
|
|
RemoveDav(
|
|
VOID
|
|
);
|
|
|
|
HRESULT
|
|
SetUrl(
|
|
STRU & strNewUrl,
|
|
BOOL fResetQueryString = TRUE
|
|
);
|
|
|
|
HRESULT
|
|
SetUrlA(
|
|
STRA & strNewUrl,
|
|
BOOL fResetQueryString = TRUE
|
|
);
|
|
|
|
HTTP_CONNECTION_ID
|
|
QueryConnectionId(
|
|
VOID
|
|
) const
|
|
{
|
|
return _pUlHttpRequest->ConnectionId;
|
|
}
|
|
|
|
BOOL
|
|
QueryMoreEntityBodyExists(
|
|
VOID
|
|
)
|
|
{
|
|
return _pUlHttpRequest->MoreEntityBodyExists;
|
|
}
|
|
|
|
HTTP_REQUEST_ID
|
|
QueryRequestId(
|
|
VOID
|
|
) const
|
|
{
|
|
return _pUlHttpRequest->RequestId;
|
|
}
|
|
|
|
DWORD
|
|
QuerySiteId(
|
|
VOID
|
|
) const
|
|
{
|
|
return (DWORD)(_pUlHttpRequest->UrlContext >> 32);
|
|
}
|
|
|
|
DWORD
|
|
QueryLocalAddress(
|
|
VOID
|
|
) const;
|
|
|
|
DWORD
|
|
QueryRemoteAddress(
|
|
VOID
|
|
) const;
|
|
|
|
USHORT
|
|
QueryLocalPort(
|
|
VOID
|
|
) const;
|
|
|
|
USHORT
|
|
QueryRemotePort(
|
|
VOID
|
|
) const;
|
|
|
|
BOOL
|
|
IsProxyRequest(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
IsChunkedRequest(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
IsLocalRequest(
|
|
VOID
|
|
) const;
|
|
|
|
BOOL
|
|
IsSecureRequest(
|
|
VOID
|
|
) const
|
|
{
|
|
DBG_ASSERT( _pUlHttpRequest != NULL );
|
|
return _pUlHttpRequest->pSslInfo != NULL;
|
|
}
|
|
|
|
HTTP_SSL_INFO *
|
|
QuerySslInfo(
|
|
VOID
|
|
) const
|
|
{
|
|
DBG_ASSERT( _pUlHttpRequest != NULL );
|
|
return _pUlHttpRequest->pSslInfo;
|
|
}
|
|
|
|
HTTP_SSL_CLIENT_CERT_INFO *
|
|
QueryClientCertInfo(
|
|
VOID
|
|
) const
|
|
{
|
|
DBG_ASSERT( _pUlHttpRequest != NULL );
|
|
if ( _pUlHttpRequest->pSslInfo != NULL )
|
|
{
|
|
return _pUlHttpRequest->pSslInfo->pClientCertInfo;
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
SetClientCertInfo(
|
|
HTTP_SSL_CLIENT_CERT_INFO * pClientCertInfo
|
|
)
|
|
{
|
|
DBG_ASSERT( pClientCertInfo != NULL );
|
|
DBG_ASSERT( _pUlHttpRequest != NULL );
|
|
DBG_ASSERT( _pUlHttpRequest->pSslInfo != NULL );
|
|
|
|
_pUlHttpRequest->pSslInfo->pClientCertInfo = pClientCertInfo;
|
|
}
|
|
|
|
HTTP_RAW_CONNECTION_ID
|
|
QueryRawConnectionId(
|
|
VOID
|
|
) const
|
|
{
|
|
DBG_ASSERT( _pUlHttpRequest != NULL );
|
|
return _pUlHttpRequest->RawConnectionId;
|
|
}
|
|
|
|
HRESULT
|
|
GetRawUrl(
|
|
STRA * pstrRawUrl
|
|
)
|
|
{
|
|
if ( pstrRawUrl == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
return pstrRawUrl->Copy( _pUlHttpRequest->pRawUrl,
|
|
_pUlHttpRequest->RawUrlLength );
|
|
}
|
|
|
|
HRESULT
|
|
GetOriginalFullUrl(
|
|
STRU * pstrFullUrl
|
|
)
|
|
{
|
|
if ( pstrFullUrl == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
return pstrFullUrl->Copy( _pszOriginalFullUrl, _cchOriginalFullUrl );
|
|
}
|
|
|
|
HRESULT
|
|
GetFullUrl(
|
|
STRU * pstrFullUrl
|
|
)
|
|
{
|
|
if ( pstrFullUrl == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
return pstrFullUrl->Copy( _pUlHttpRequest->CookedUrl.pFullUrl,
|
|
_pUlHttpRequest->CookedUrl.FullUrlLength / sizeof(WCHAR) );
|
|
}
|
|
|
|
HRESULT
|
|
GetAllHeaders(
|
|
STRA * pstrHeaders,
|
|
BOOL fISAPIStyle
|
|
);
|
|
|
|
BOOL
|
|
IsSuspectUrl(
|
|
VOID
|
|
);
|
|
|
|
HRESULT
|
|
GetUrl(
|
|
STRU * pstrUrl
|
|
)
|
|
{
|
|
if ( pstrUrl == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
return pstrUrl->Copy( _pUlHttpRequest->CookedUrl.pAbsPath,
|
|
_pUlHttpRequest->CookedUrl.AbsPathLength / sizeof(WCHAR) );
|
|
}
|
|
|
|
VOID
|
|
QueryUrl(
|
|
WCHAR ** ppszUrl,
|
|
USHORT * pcbUrl)
|
|
{
|
|
*ppszUrl = _pUlHttpRequest->CookedUrl.pAbsPath;
|
|
*pcbUrl = _pUlHttpRequest->CookedUrl.AbsPathLength;
|
|
}
|
|
|
|
HRESULT
|
|
GetHostAddr(
|
|
IN OUT STRU *pstrHostAddr
|
|
)
|
|
{
|
|
WCHAR * pchTail;
|
|
|
|
if ( pstrHostAddr == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
pchTail = wcspbrk( _pUlHttpRequest->CookedUrl.pHost, L":" );
|
|
if( !pchTail )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
return pstrHostAddr->Copy( _pUlHttpRequest->CookedUrl.pHost,
|
|
DIFF(pchTail - _pUlHttpRequest->CookedUrl.pHost) );
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
QueryClientWantsDisconnect(
|
|
VOID
|
|
);
|
|
|
|
HRESULT
|
|
GetVerbString(
|
|
STRA * pstrVerb
|
|
);
|
|
|
|
|
|
VOID
|
|
QueryVerb(
|
|
CHAR ** ppszVerb,
|
|
USHORT * pcchVerb
|
|
);
|
|
|
|
HRESULT
|
|
GetVersionString(
|
|
STRA * pstrVersion
|
|
);
|
|
|
|
HRESULT
|
|
GetAuthType(
|
|
STRA * pstrAuthType
|
|
);
|
|
|
|
HRESULT
|
|
GetRequestUserName(
|
|
STRA * pstrUserName
|
|
)
|
|
{
|
|
if ( pstrUserName == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
return pstrUserName->Copy( _strRequestUserName );
|
|
}
|
|
|
|
HRESULT
|
|
SetRequestUserName(
|
|
STRA & strUserName
|
|
)
|
|
{
|
|
return _strRequestUserName.Copy( strUserName );
|
|
}
|
|
|
|
STRA *
|
|
QueryRequestUserName()
|
|
{
|
|
return &_strRequestUserName;
|
|
}
|
|
|
|
HTTP_VERSION
|
|
QueryVersion(
|
|
VOID
|
|
)
|
|
{
|
|
return _pUlHttpRequest->Version;
|
|
}
|
|
|
|
HRESULT
|
|
GetQueryString(
|
|
STRU * pstrQueryString
|
|
)
|
|
{
|
|
DBG_ASSERT ( pstrQueryString != NULL );
|
|
|
|
if ( _pUlHttpRequest->CookedUrl.QueryStringLength )
|
|
{
|
|
return pstrQueryString->Copy( _pUlHttpRequest->CookedUrl.pQueryString + 1,
|
|
_pUlHttpRequest->CookedUrl.QueryStringLength / sizeof(WCHAR) - 1 );
|
|
}
|
|
else
|
|
{
|
|
return pstrQueryString->Copy( L"", 0 );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetQueryStringA(
|
|
STRA * pstrQueryString
|
|
)
|
|
{
|
|
DBG_ASSERT ( pstrQueryString != NULL );
|
|
|
|
if ( _pUlHttpRequest->CookedUrl.QueryStringLength )
|
|
{
|
|
return pstrQueryString->CopyWTruncate( _pUlHttpRequest->CookedUrl.pQueryString + 1);
|
|
}
|
|
else
|
|
{
|
|
return pstrQueryString->Copy( "", 0 );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
SetVerb(
|
|
STRA & strVerb
|
|
);
|
|
|
|
HRESULT
|
|
SetVersion(
|
|
STRA & strVersion
|
|
);
|
|
|
|
HRESULT
|
|
BuildFullUrl(
|
|
STRA& strPath,
|
|
STRA * pstrRedirect,
|
|
BOOL fIncludeParameters = TRUE
|
|
);
|
|
|
|
HRESULT
|
|
BuildFullUrl(
|
|
STRU& strPath,
|
|
STRU * pstrRedirect,
|
|
BOOL fIncludeParameters = TRUE
|
|
);
|
|
|
|
HTTP_VERB
|
|
QueryVerbType(
|
|
VOID
|
|
) const
|
|
{
|
|
return _pUlHttpRequest->Verb;
|
|
}
|
|
|
|
VOID
|
|
SetVerbType(
|
|
HTTP_VERB NewVerb
|
|
)
|
|
{
|
|
_pUlHttpRequest->Verb = NewVerb;
|
|
}
|
|
|
|
CHAR *
|
|
GetHeader(
|
|
ULONG index,
|
|
USHORT * pcchLength = NULL
|
|
)
|
|
{
|
|
if (pcchLength)
|
|
{
|
|
*pcchLength = _pUlHttpRequest->Headers.pKnownHeaders[ index ].RawValueLength;
|
|
}
|
|
|
|
return _pUlHttpRequest->Headers.pKnownHeaders[ index ].pRawValue;
|
|
}
|
|
|
|
CHAR *
|
|
GetHeader(
|
|
CHAR * pszHeaderName
|
|
);
|
|
|
|
HRESULT
|
|
GetHeader(
|
|
STRA & strHeaderName,
|
|
STRA * pstrValue,
|
|
BOOL fIsUnknownHeader = FALSE
|
|
)
|
|
{
|
|
return GetHeader( strHeaderName.QueryStr(),
|
|
strHeaderName.QueryCCH(),
|
|
pstrValue,
|
|
fIsUnknownHeader );
|
|
}
|
|
|
|
HRESULT
|
|
GetHeader(
|
|
CHAR * pszHeaderName,
|
|
DWORD cchHeaderName,
|
|
STRA * pstrValue,
|
|
BOOL fIsUnknownHeader = FALSE
|
|
);
|
|
|
|
HRESULT
|
|
CloneRequest(
|
|
DWORD dwCloneFlags,
|
|
W3_REQUEST ** ppRequest
|
|
);
|
|
|
|
HRESULT
|
|
DeleteHeader(
|
|
CHAR * pszHeaderName
|
|
);
|
|
|
|
HRESULT
|
|
SetHeader(
|
|
STRA & strHeaderName,
|
|
STRA & strHeaderValue,
|
|
BOOL fAppend = FALSE
|
|
);
|
|
|
|
HRESULT
|
|
SetHeadersByStream(
|
|
CHAR * pszHeaderStream
|
|
);
|
|
|
|
CHAR *
|
|
QueryRawUrl(
|
|
USHORT *pcchUrl
|
|
) const
|
|
{
|
|
*pcchUrl = _pUlHttpRequest->RawUrlLength;
|
|
return _pUlHttpRequest->pRawUrl;
|
|
}
|
|
|
|
LPVOID
|
|
QueryEntityBody(
|
|
VOID
|
|
)
|
|
{
|
|
if ( _pUlHttpRequest->EntityChunkCount == 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// we only expect one memory type chunk
|
|
//
|
|
|
|
DBG_ASSERT( _pUlHttpRequest->EntityChunkCount == 1 );
|
|
DBG_ASSERT( _pUlHttpRequest->pEntityChunks[0].DataChunkType == HttpDataChunkFromMemory );
|
|
|
|
return _pUlHttpRequest->pEntityChunks[0].FromMemory.pBuffer;
|
|
}
|
|
|
|
DWORD
|
|
QueryAvailableBytes(
|
|
VOID
|
|
)
|
|
{
|
|
if ( _pUlHttpRequest->EntityChunkCount == 0 )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// we only expect one memory type chunk
|
|
//
|
|
|
|
DBG_ASSERT( _pUlHttpRequest->EntityChunkCount == 1 );
|
|
DBG_ASSERT( _pUlHttpRequest->pEntityChunks[0].DataChunkType == HttpDataChunkFromMemory );
|
|
|
|
return _pUlHttpRequest->pEntityChunks[0].FromMemory.BufferLength;
|
|
}
|
|
|
|
private:
|
|
HRESULT
|
|
BuildISAPIHeaderLine(
|
|
CHAR * pszHeaderName,
|
|
DWORD cchHeaderName,
|
|
CHAR * pszHeaderValue,
|
|
DWORD cchHeaderValue,
|
|
STRA * pstrHeaderLine
|
|
);
|
|
|
|
HRESULT
|
|
BuildRawHeaderLine(
|
|
CHAR * pszHeaderName,
|
|
DWORD cchHeaderName,
|
|
CHAR * pszHeaderValue,
|
|
DWORD cchHeaderValue,
|
|
STRA * pstrHeaderLine
|
|
);
|
|
};
|
|
|
|
//
|
|
// Cloned request used for executing child requests
|
|
//
|
|
|
|
#define W3_REQUEST_CLONE_BASICS 0x01
|
|
#define W3_REQUEST_CLONE_HEADERS 0x02
|
|
#define W3_REQUEST_CLONE_ENTITY 0x04
|
|
#define W3_REQUEST_CLONE_NO_PRECONDITION 0x08
|
|
#define W3_REQUEST_CLONE_NO_DAV 0x10
|
|
|
|
class W3_CLONE_REQUEST : public W3_REQUEST
|
|
{
|
|
public:
|
|
|
|
W3_CLONE_REQUEST()
|
|
{
|
|
_pUlHttpRequest = &_ulHttpRequest;
|
|
}
|
|
|
|
virtual ~W3_CLONE_REQUEST()
|
|
{
|
|
}
|
|
|
|
HRESULT
|
|
CopyMinimum(
|
|
HTTP_REQUEST * pRequestToClone
|
|
);
|
|
|
|
HRESULT
|
|
CopyHeaders(
|
|
HTTP_REQUEST * pRequestToClone
|
|
);
|
|
|
|
HRESULT
|
|
CopyBasics(
|
|
HTTP_REQUEST * pRequestToClone
|
|
);
|
|
|
|
HRESULT
|
|
CopyEntity(
|
|
HTTP_REQUEST * pRequestToClone
|
|
);
|
|
|
|
VOID
|
|
RemoveConditionals(
|
|
VOID
|
|
);
|
|
|
|
VOID *
|
|
operator new(
|
|
size_t size
|
|
)
|
|
{
|
|
DBG_ASSERT( size == sizeof( W3_CLONE_REQUEST ) );
|
|
DBG_ASSERT( sm_pachCloneRequests != NULL );
|
|
return sm_pachCloneRequests->Alloc();
|
|
}
|
|
|
|
VOID
|
|
operator delete(
|
|
VOID * pCloneRequest
|
|
)
|
|
{
|
|
DBG_ASSERT( pCloneRequest != NULL );
|
|
DBG_ASSERT( sm_pachCloneRequests != NULL );
|
|
|
|
DBG_REQUIRE( sm_pachCloneRequests->Free( pCloneRequest ) );
|
|
}
|
|
|
|
static
|
|
HRESULT
|
|
Initialize(
|
|
VOID
|
|
);
|
|
|
|
static
|
|
VOID
|
|
Terminate(
|
|
VOID
|
|
);
|
|
|
|
private:
|
|
HTTP_REQUEST _ulHttpRequest;
|
|
|
|
//
|
|
// Lookaside for main contexts
|
|
//
|
|
|
|
static ALLOC_CACHE_HANDLER * sm_pachCloneRequests;
|
|
};
|
|
|
|
HRESULT
|
|
UlCleanAndCopyUrl(
|
|
IN PUCHAR pSource,
|
|
IN ULONG SourceLength,
|
|
OUT PULONG pBytesCopied,
|
|
IN OUT PWSTR pDestination,
|
|
OUT PWSTR * ppQueryString
|
|
);
|
|
|
|
#endif
|