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.
 
 
 
 
 
 

4566 lines
134 KiB

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Module Name :
server_support.cxx
Abstract:
IIS Plus ServerSupportFunction command implementations
Author:
Wade Hilmo (wadeh) 05-Apr-2000
Project:
w3isapi.dll
--*/
#include "precomp.hxx"
#include "isapi_context.hxx"
#include "server_support.hxx"
//
// BUGBUG - stristr is declared in iisrearc\core\inc\irtlmisc.h,
// but doesn't appear to be implemented anywhere. Because of the
// way it's declared in that file, we have to use a different
// function name here...
//
const char*
stristr2(
const char* pszString,
const char* pszSubString
);
HRESULT
SSFSendResponseHeader(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szStatus,
LPSTR szHeaders
)
/*++
Routine Description:
Sends HTTP status and headers to the client.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szStatus - The status to send to the client (ie. "200 OK")
szHeaders - Headers to send to the client (ie. foo1: value1\r\n\r\n")
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER[%p]: Function Entry\r\n"
" Status: '%s'\r\n"
" Headers: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szStatus,
szHeaders ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// We need validate the fKeepConn status for the request now,
// since http.sys will generate the connection response
// header based on it.
//
// If we're going to support keep-alive, then the
// ISAPI must return either a content-length header,
// or use chunked transfer encoding. We'll check for
// that here.
//
if ( pIsapiContext->QueryClientKeepConn() )
{
if ( szHeaders != NULL &&
( stristr2( szHeaders, "content-length: " ) != NULL ||
stristr2( szHeaders, "transfer-encoding: chunked" ) != NULL ) )
{
pIsapiContext->SetKeepConn( TRUE );
}
}
//
// Since we automatically decided to keep the connection alive
// or not, we should not honor HSE_STATUS_SUCCESS_AND_KEEP_CONN.
// This maintains compatibility with previous IIS versions.
//
pIsapiContext->SetHonorAndKeepConn( FALSE );
//
// Note that NULL is valid for both szStatus and szHeaders,
// so there's no need to validate them.
//
hr = pIsapiCore->SendResponseHeaders(
!pIsapiContext->QueryKeepConn(),
szStatus,
szHeaders,
HSE_IO_SYNC
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
else
{
pIsapiContext->SetHeadersSent( TRUE );
}
IF_DEBUG( ISAPI_SSF_DETAILS )
{
IF_DEBUG( ISAPI_SUCCESS_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER[%p]: Succeeded\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
}
return hr;
}
HRESULT
SSFSendResponseHeaderEx(
ISAPI_CONTEXT * pIsapiContext,
HSE_SEND_HEADER_EX_INFO * pHeaderInfo
)
/*++
Routine Description:
Sends HTTP status and headers to the client, and offers
explicit control over keep-alive for this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pHeaderInfo - The response info to be passed to the client
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Function Entry\r\n"
" Status: '%s'\r\n"
" Headers: '%s'\r\n"
" KeepConn: %d\r\n",
pIsapiContext,
pHeaderInfo->pszStatus,
pHeaderInfo->pszHeader,
pHeaderInfo->fKeepConn ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( pHeaderInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Parameter validation failure\r\n"
" pHeaderInfo: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Set the keep connection flag. It can only be TRUE if the
// ISAPI and the client both want keep alive.
//
// Note that we are trusting the ISAPI to provide some kind
// of content length in the case where it's setting fKeepConn
// to TRUE. This is the same behavior as IIS 5 which, for
// performance reasons, doesn't try to parse the headers from
// the ISAPI.
//
if ( pHeaderInfo->fKeepConn &&
pIsapiContext->QueryClientKeepConn() )
{
pIsapiContext->SetKeepConn( TRUE );
}
hr = pIsapiCore->SendResponseHeaders(
!pIsapiContext->QueryKeepConn(),
const_cast<LPSTR>( pHeaderInfo->pszStatus ),
const_cast<LPSTR>( pHeaderInfo->pszHeader ),
HSE_IO_SYNC
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Failed.\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
else
{
pIsapiContext->SetHeadersSent( TRUE );
}
IF_DEBUG( ISAPI_SSF_DETAILS )
{
IF_DEBUG( ISAPI_SUCCESS_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_RESPONSE_HEADER_EX[%p]: Succeeded\r\n"
" <END>\r\n",
pIsapiContext ));
}
}
return hr;
}
HRESULT
SSFMapUrlToPath(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szBuffer,
LPDWORD pcbBuffer
)
/*++
Routine Description:
Maps a URL into a physical path
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szBuffer - On entry, contains the URL to map. On return,
contains the mapped physical path.
pcbBuffer - On entry, the size of szBuffer. On successful
return, the number of bytes copied to szUrl. On
failed return, the number of bytes needed for the
physical path.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH[%p]: Function Entry\r\n"
" URL: %s\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szBuffer ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( szBuffer == NULL ||
pcbBuffer == NULL ||
*pcbBuffer == 0 )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH[%p]: Parameter validation failure\r\n"
" Buffer: '%s'\r\n"
" Buffer Size Ptr: %p\r\n"
" Buffer Size: %d\r\n",
pIsapiContext,
pcbBuffer,
pcbBuffer ? *pcbBuffer : 0 ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->MapPath(
reinterpret_cast<BYTE*>( szBuffer ),
*pcbBuffer,
pcbBuffer,
FALSE
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
IF_DEBUG( ISAPI_SSF_DETAILS )
{
IF_DEBUG( ISAPI_SUCCESS_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH[%p]: Succeeded\r\n"
" Mapped URL: %s\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szBuffer ));
}
}
return hr;
}
HRESULT
SSFMapUrlToPathEx(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szUrl,
HSE_URL_MAPEX_INFO * pHseMapInfo,
LPDWORD pcbMappedPath
)
/*++
Routine Description:
Maps a URL to a physical path and returns some metadata
metrics for the URL to the caller.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szUrl - The URL to map
pHseMapInfo - Upon return, contains the mapped URL info
pcbMappedPath - If non-NULL, contains the buffer size needed
to store the mapped physical path.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
DWORD cbMapped;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Function Entry\r\n"
" URL='%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MA_URL_TO_PATH_EX[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Additional parameter validation
//
if ( szUrl == NULL ||
pHseMapInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Parameter validation failure\r\n"
" URL: '%s'\r\n"
" HSE_URL_MAPEX_INFO: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pHseMapInfo ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// The inline buffer within the HSE_URL_MAPEX_INFO structure
// is defined as being MAX_PATH size.
//
cbMapped = MAX_PATH;
pHseMapInfo->dwReserved1 = 0;
pHseMapInfo->dwReserved2 = 0;
hr = pIsapiCore->MapPathEx(
reinterpret_cast<BYTE*>( szUrl ),
(DWORD)strlen(szUrl) + 1,
reinterpret_cast<BYTE*>( pHseMapInfo->lpszPath ),
cbMapped,
pcbMappedPath ? pcbMappedPath : &cbMapped,
&pHseMapInfo->cchMatchingPath,
&pHseMapInfo->cchMatchingURL,
&pHseMapInfo->dwFlags,
FALSE
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_URL_TO_PATH_EX[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFMapUnicodeUrlToPath(
ISAPI_CONTEXT * pIsapiContext,
LPWSTR szBuffer,
LPDWORD pcbBuffer
)
/*++
Routine Description:
Maps a URL into a physical path
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szBuffer - On entry, contains the URL to map. On return,
contains the mapped physical path.
pcbBuffer - On entry, the size of szBuffer. On successful
return, the number of bytes copied to szUrl. On
failed return, the number of bytes needed for the
physical path.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Function Entry\r\n"
" URL='%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szBuffer ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MA_UNICODE_URL_TO_PATH[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( szBuffer == NULL ||
pcbBuffer == NULL ||
*pcbBuffer == 0 )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Parameter validation failure\r\n"
" Buffer: '%S'\r\n"
" Buffer Size Ptr: %p\r\n"
" Buffer Size: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szBuffer,
pcbBuffer,
pcbBuffer ? *pcbBuffer : 0 ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->MapPath(
reinterpret_cast<BYTE*>( szBuffer ),
*pcbBuffer,
pcbBuffer,
TRUE
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFMapUnicodeUrlToPathEx(
ISAPI_CONTEXT * pIsapiContext,
LPWSTR szUrl,
HSE_UNICODE_URL_MAPEX_INFO *pHseMapInfo,
LPDWORD pcbMappedPath
)
/*++
Routine Description:
Maps a URL to a physical path and returns some metadata
metrics for the URL to the caller.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szUrl - The URL to map
pHseMapInfo - Upon return, contains the mapped URL info
pcbMappedPath - If non-NULL, contains the buffer size needed
to store the mapped physical path.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
DWORD cbMapped;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Function Entry\r\n"
" URL='%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MA_UNICODE_URL_TO_PATH_EX[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Additional parameter validation
//
if ( szUrl == NULL ||
pHseMapInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Parameter validation failure\r\n"
" URL: '%s'\r\n"
" pHseMapInfo: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pHseMapInfo ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// The inline buffer within the HSE_URL_MAPEX_INFO structure
// is defined as being MAX_PATH size.
//
cbMapped = MAX_PATH * sizeof(WCHAR);
hr = pIsapiCore->MapPathEx(
reinterpret_cast<BYTE*>( szUrl ),
(DWORD)(wcslen(szUrl) + 1)*sizeof(WCHAR),
reinterpret_cast<BYTE*>( pHseMapInfo->lpszPath ),
cbMapped,
pcbMappedPath ? pcbMappedPath : &cbMapped,
&pHseMapInfo->cchMatchingPath,
&pHseMapInfo->cchMatchingURL,
&pHseMapInfo->dwFlags,
TRUE
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFGetImpersonationToken(
ISAPI_CONTEXT * pIsapiContext,
HANDLE * phToken
)
/*++
Routine Description:
Returns a (non-duplicated) copy of the token that the server
is using to impersonate the client for this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
phToken - Upon return, contains a copy of the token.
Return Value:
HRESULT
--*/
{
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_IMPERSONATION_TOKEN[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
//
// Validate parameters
//
if ( phToken == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_IMPERSONATION_TOKEN[%p]: Parameter validation failure\r\n"
" Token Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
*phToken = pIsapiContext->QueryToken();
return NO_ERROR;
}
HRESULT
SSFIsKeepConn(
ISAPI_CONTEXT * pIsapiContext,
BOOL * pfIsKeepAlive
)
/*++
Routine Description:
Returns information about whether the client wants us to keep
the connection open or not at completion of this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pfIsKeepAlive - Upon return, TRUE if IIS will be keeping the
connection alive, else FALSE.
Return Value:
HRESULT
--*/
{
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_KEEP_CONN[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
//
// Validate parameters
//
if ( pfIsKeepAlive == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_KEEP_CONN[%p]: Parameter validation failure\r\n"
" KeepAlive Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
*pfIsKeepAlive = pIsapiContext->QueryClientKeepConn();
return NO_ERROR;
}
HRESULT
SSFDoneWithSession(
ISAPI_CONTEXT * pIsapiContext,
DWORD * pHseResult
)
/*++
Routine Description:
Notifies the server that the calling ISAPI is done with the
ECB (and ISAPI_CONTEXT) for this request and that the server
can clean up.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pHseResult - A pointer to the HSE_STATUS code that the extension
wants to use.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_ASSERT( pIsapiContext->QueryIoState() == NoAsyncIoPending );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_DONE_WITH_SESSION[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
//
// If the caller wants to do STATUS_SUCCESS_AND_KEEP_CONN,
// then we need to do that now.
//
// Note that this overrides our own determination of whether
// the client can support keep-alive or not. We are trusting
// the caller to have returned the right headers to make this
// work with the client.
//
if ( pHseResult &&
*pHseResult == HSE_STATUS_SUCCESS_AND_KEEP_CONN )
{
if ( pIsapiContext->QueryClientKeepConn() )
{
pIsapiContext->SetKeepConn( TRUE );
pIsapiCore->SetConnectionClose( !pIsapiContext->QueryKeepConn() );
}
}
//
// We'll just release the reference on IsapiContext.
// Its destructor will do the rest.
//
pIsapiContext->DereferenceIsapiContext();
pIsapiContext = NULL;
return NO_ERROR;
}
HRESULT
SSFGetCertInfoEx(
ISAPI_CONTEXT * pIsapiContext,
CERT_CONTEXT_EX * pCertContext
)
/*++
Routine Description:
Returns certificate information about the client associated
with this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pCertContext - Upon return, contains info about the client cert.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CERT_INFO_EX[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CERT_INFO_EX[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( pCertContext == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CERT_INFO_EX[%p]: Parameter validation failure\r\n"
" CertContext Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetCertificateInfoEx(
pCertContext->cbAllocated,
&( pCertContext->CertContext.dwCertEncodingType ),
pCertContext->CertContext.pbCertEncoded,
&( pCertContext->CertContext.cbCertEncoded ),
&( pCertContext->dwCertificateFlags ) );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CERT_INFO_EX[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFIoCompletion(
ISAPI_CONTEXT * pIsapiContext,
PFN_HSE_IO_COMPLETION pCompletionRoutine,
LPVOID pHseIoContext
)
/*++
Routine Description:
Establishes the I/O completion routine and user-defined context
to be used for asynchronous operations associated with this
request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pCompletionRoutine - The function to call upon I/O completion
pHseIoContext - The user-defined context to be passed to the
completion routine.
Return Value:
HRESULT
--*/
{
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IO_COMPLETION[%p]: Function Entry\r\n"
" Completion Routine: %p\r\n"
" Context: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pCompletionRoutine,
pHseIoContext ));
}
//
// Validate parameters
//
if ( pCompletionRoutine == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IO_COMPLETION[%p]: Parameter validation failure\r\n"
" Completion Routine: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
pIsapiContext->SetPfnIoCompletion( pCompletionRoutine );
pIsapiContext->SetExtensionContext( pHseIoContext );
return NO_ERROR;
}
HRESULT
SSFAsyncReadClient(
ISAPI_CONTEXT * pIsapiContext,
LPVOID pBuffer,
LPDWORD pcbBuffer
)
/*++
Routine Description:
Queues an asynchronous read of data from the client.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pBuffer - Buffer to be filled with read data.
pcbBuffer - The size of pBuffer
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
DWORD cbBuffer;
HRESULT hr = NOERROR;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ASYNC_READ_CLIENT[%p]: Function Entry\r\n"
" Bytes to Read: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pcbBuffer ? *pcbBuffer : 0 ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( pIsapiContext->QueryPfnIoCompletion() == NULL ||
pBuffer == NULL ||
pcbBuffer == NULL ||
*pcbBuffer == 0 )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ASYNC_READ_CLIENT[%p]: Parameter validation failure\r\n"
" Completion Routine: %p\r\n"
" Buffer Ptr: %p\r\n"
" Buffer Size Ptr: %p\r\n"
" Buffer Size: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pIsapiContext->QueryPfnIoCompletion(),
pBuffer,
pcbBuffer,
pcbBuffer ? *pcbBuffer : 0 ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Do the async ReadClient call
//
if ( pIsapiContext->TryInitAsyncIo( AsyncReadPending ) == FALSE )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed\r\n"
" Another async operation is already pending\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Since we're never actually reading any data in the async
// case, we want to prevent pIsapiCore->ReadClient() from
// modifying the buffer size we report back to the caller,
// so we'll use a local for cbBuffer.
//
cbBuffer = *pcbBuffer;
//
// If this call will be going OOP, save a pointer to the
// read buffer so that the core can fill it when the
// operation completes.
//
if ( pIsapiContext->QueryIsOop() )
{
DBG_ASSERT( pIsapiContext->QueryAsyncIoBuffer() == NULL );
DBG_ASSERT( pIsapiContext->QueryLastAsyncIo() == 0 );
pIsapiContext->SetAsyncIoBuffer( pBuffer );
pIsapiContext->SetLastAsyncIo( cbBuffer );
}
hr = pIsapiCore->ReadClient(
reinterpret_cast<DWORD64>( pIsapiContext ),
pIsapiContext->QueryIsOop() ? NULL : reinterpret_cast<unsigned char*>( pBuffer ),
pIsapiContext->QueryIsOop() ? 0 : cbBuffer,
cbBuffer,
&cbBuffer,
HSE_IO_ASYNC
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ASYNC_READ_CLIENT[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
pIsapiContext->SetAsyncIoBuffer( NULL );
pIsapiContext->SetLastAsyncIo( 0 );
pIsapiContext->UninitAsyncIo();
}
return hr;
}
HRESULT
SSFTransmitFile(
ISAPI_CONTEXT * pIsapiContext,
HSE_TF_INFO * pTfInfo
)
/*++
Routine Description:
Transmits a file, a portion of a file, or some other data
(in the event on a NULL file handle) to the client.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pTfInfo - Describes the desired transmit file action.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
LARGE_INTEGER cbFileSize;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
STACK_STRA( strFilename,MAX_PATH );
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Function Entry\r\n"
" Completion Routine: %p\r\n"
" Context: %p\r\n"
" File Handle: %p\r\n"
" Status Code: '%s'\r\n"
" Bytes To Write: %d\r\n"
" Offset: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pTfInfo ? pTfInfo->pfnHseIO : 0,
pTfInfo ? pTfInfo->pContext : 0,
pTfInfo ? pTfInfo->hFile : 0,
pTfInfo ? pTfInfo->pszStatusCode : 0,
pTfInfo ? pTfInfo->BytesToWrite : 0,
pTfInfo ? pTfInfo->Offset : 0 ));
IF_DEBUG( ISAPI_DUMP_BUFFERS )
{
if ( pTfInfo )
{
STACK_STRA( strHead,MAX_PATH );
STACK_STRA( strTail,MAX_PATH );
DWORD dwBytesToDump;
dwBytesToDump = pTfInfo->HeadLength;
if ( dwBytesToDump > MAX_DEBUG_DUMP )
{
dwBytesToDump = MAX_DEBUG_DUMP;
}
if ( FAILED( strHead.CopyBinary( pTfInfo->pHead, dwBytesToDump ) ) )
{
strHead.Copy( "" );
}
dwBytesToDump = pTfInfo->TailLength;
if ( dwBytesToDump > MAX_DEBUG_DUMP )
{
dwBytesToDump = MAX_DEBUG_DUMP;
}
if ( FAILED( strTail.CopyBinary( pTfInfo->pTail, dwBytesToDump ) ) )
{
strTail.Copy( "" );
}
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Dump of up to %d bytes of head and tail data\r\n"
" Head Data:\r\n"
"%s"
" Tail Data:\r\n"
"%s"
" <END>\r\n",
pIsapiContext,
MAX_DEBUG_DUMP,
strHead.QueryStr(),
strTail.QueryStr() ));
}
}
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters - For TRANSMIT_FILE, this means:
//
// - We must have an ISAPI core interface to call through
// - We must have an HSE_TF_INFO structure
// - The HSE_IO_ASYNC flag must be set
// - If HeadLength is set, pHead cannot be NULL
// - If TailLength is set, pTail cannot be NULL
// - We must have either a completion routine already set
// in the ISAPI_CONTEXT, or the HSE_TF_INFO must provide
// one
// - There can be no other async operations in progress
//
if ( pTfInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
" Transmit File Info Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( ( pTfInfo->dwFlags & HSE_IO_ASYNC ) == 0 ||
pTfInfo->hFile == INVALID_HANDLE_VALUE ||
( pTfInfo->HeadLength != 0 && pTfInfo->pHead == NULL ) ||
( pTfInfo->TailLength != 0 && pTfInfo->pTail == NULL ) ||
( pIsapiContext->QueryPfnIoCompletion() == NULL &&
pTfInfo->pfnHseIO == NULL ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
" %s\r\n",
" File Handle: %p\r\n"
" Head: %p\r\n"
" Head Length: %d\r\n"
" Tail: %p\r\n"
" Tail Length: %d\r\n"
" Completion Routine: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pTfInfo->dwFlags & HSE_IO_ASYNC ? "Async flag set" : "Async flag not set",
pTfInfo->hFile,
pTfInfo->pHead,
pTfInfo->HeadLength,
pTfInfo->pTail,
pTfInfo->TailLength,
pTfInfo->pfnHseIO ? pTfInfo->pfnHseIO : pIsapiContext->QueryPfnIoCompletion() ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pIsapiContext->TryInitAsyncIo( AsyncWritePending ) == FALSE )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Failed\r\n"
" Another async operation is already pending.\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// We'll do some extra validation in the case where we've been
// provided a file handle.
//
// Specifically, we'll check to make sure that the offset and
// bytes-to-write are valid for the file.
//
// CODEWORK - Do we really need to do this, or can http.sys handle
// it? Also, does http.sys treat zero bytes to write
// the same as TransmitFile (ie. send the whole file?)
//
if ( pTfInfo->hFile != NULL )
{
if (!GetFileSizeEx(pTfInfo->hFile,
&cbFileSize))
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Done;
}
if ( pTfInfo->Offset > cbFileSize.QuadPart ||
(pTfInfo->Offset > 0 && pTfInfo->Offset == cbFileSize.QuadPart ) ||
pTfInfo->Offset + pTfInfo->BytesToWrite > cbFileSize.QuadPart )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Parameter validation failure\r\n"
" File Size: %d\r\n"
" Offset: %d\r\n"
" Bytes to Write: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
cbFileSize.QuadPart,
pTfInfo->Offset,
pTfInfo->BytesToWrite ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
}
else
{
//
// No file handle, so initialize the size to zero
//
cbFileSize.QuadPart = 0;
}
//
// If the HSE_TF_INFO includes I/O completion or context
// information, override the existing settings.
//
if ( pTfInfo->pfnHseIO )
{
pIsapiContext->SetPfnIoCompletion( pTfInfo->pfnHseIO );
}
if ( pTfInfo->pContext )
{
pIsapiContext->SetExtensionContext( pTfInfo->pContext );
}
//
// If the extension is setting HSE_IO_SEND_HEADERS, then we need
// to determine if it's sending some kind of content length. If
// it's not, then we need to set _fKeepConn to FALSE.
//
// CODEWORK
// Note that we're making a bold assumption here that if
// HSE_IO_SEND_HEADERS is set, then pHead points to a NULL
// terminated string.
//
if ( pIsapiContext->QueryClientKeepConn() &&
pTfInfo->pHead &&
( pTfInfo->dwFlags & HSE_IO_SEND_HEADERS ) &&
!( pTfInfo->dwFlags & HSE_IO_DISCONNECT_AFTER_SEND ) )
{
if ( stristr2( (LPSTR)pTfInfo->pHead, "content-length: " ) != NULL ||
stristr2( (LPSTR)pTfInfo->pHead, "transfer-encoding: chunked" ) != NULL )
{
pIsapiContext->SetKeepConn( TRUE );
}
}
if ( pIsapiContext->QueryKeepConn() == FALSE )
{
pTfInfo->dwFlags |= HSE_IO_DISCONNECT_AFTER_SEND;
}
else
{
//
// We need to clear the HSE_IO_DISCONNECT_AFTER_SEND flag
// in the case where QueryKeepConn is TRUE.
//
pTfInfo->dwFlags &= ~HSE_IO_DISCONNECT_AFTER_SEND;
}
//
// Save the BytesToWrite part as _cbLastAsyncIo, since the size of
// pHead and pTail confuses ISAPI's that examine the cbWritten
// value on completion.
//
ULARGE_INTEGER cbToWrite;
if ( pTfInfo->BytesToWrite )
{
cbToWrite.QuadPart = pTfInfo->BytesToWrite;
}
else
{
cbToWrite.QuadPart = cbFileSize.QuadPart - pTfInfo->Offset;
}
//
// Note that ISAPI doesn't support large integer values, so the
// best we can do here is to store the low bits.
//
pIsapiContext->SetLastAsyncIo( cbToWrite.LowPart );
hr = pIsapiCore->TransmitFile(
reinterpret_cast<DWORD64>( pIsapiContext ),
reinterpret_cast<DWORD_PTR>( pTfInfo->hFile ),
pTfInfo->Offset,
cbToWrite.QuadPart,
(pTfInfo->dwFlags & HSE_IO_SEND_HEADERS) ? const_cast<LPSTR>( pTfInfo->pszStatusCode ) : NULL,
reinterpret_cast<LPBYTE>( pTfInfo->pHead ),
pTfInfo->HeadLength,
reinterpret_cast<LPBYTE>( pTfInfo->pTail ),
pTfInfo->TailLength,
pTfInfo->dwFlags
);
Done:
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_TRANSMIT_FILE[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
pIsapiContext->SetLastAsyncIo( 0 );
pIsapiContext->UninitAsyncIo();
}
return hr;
}
HRESULT
SSFSendRedirect(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szUrl
)
/*++
Routine Description:
Sends a 302 redirect to the client associated with this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szUrl - The target URL for the redirection.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_REDIRECT[%p]: Function Entry\r\n"
" URL: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_REDIRECT[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( pIsapiContext == NULL ||
szUrl == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_REDIRECT[%p]: Parameter validation failure\r\n"
" szUrl: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pIsapiContext->QueryClientKeepConn() )
{
pIsapiContext->SetKeepConn( TRUE );
}
hr = pIsapiCore->SendRedirect(
szUrl,
!pIsapiContext->QueryKeepConn()
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_REDIRECT[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFIsConnected(
ISAPI_CONTEXT * pIsapiContext,
BOOL * pfIsConnected
)
/*++
Routine Description:
Returns the connection state (connected or not connected)
of the client associated with this request.
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pfIsConnected - TRUE upon return if the client is connected,
else FALSE.
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_CONNECTED[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_CONNECTED[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( pfIsConnected == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_CONNECTED[%p]: Parameter validation failure\r\n"
" IsConnected Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->TestConnection( pfIsConnected );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_CONNECTED[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFAppendLog(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szExtraParam
)
/*++
Routine Description:
Appends the string passed to the QueryString that will be logged
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
szExtraParam - The extra parameter to be logged
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_APPEND_LOG_PARAMETER[%p]: Function Entry\r\n"
" Extra Param: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szExtraParam ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_APPEND_LOG_PARAMETER[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate parameters
//
if ( szExtraParam == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_APPEND_LOG_PARAMETER[%p]: Parameter validation failure\r\n"
" Extra Param: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->AppendLog( szExtraParam, 0 );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_APPEND_LOG_PARAMETER[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFExecuteUrl(
ISAPI_CONTEXT * pIsapiContext,
VOID * pOrigExecUrlInfo,
BOOL fIsUnicode
)
/*++
Routine Description:
Execute a child request
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pOrigExecUrlInfo - Description of child request to execute
fIsUnicode - Are we passing unicode data?
Return Value:
HRESULT
--*/
{
EXEC_URL_USER_INFO UserName;
EXEC_URL_ENTITY_INFO Entity;
EXEC_URL_INFO UrlInfo;
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
HSE_EXEC_URL_ENTITY_INFO *pEntityInfo = NULL;
if ( fIsUnicode )
{
HSE_EXEC_UNICODE_URL_INFO *pInfo = (HSE_EXEC_UNICODE_URL_INFO *)pOrigExecUrlInfo;
HSE_EXEC_UNICODE_URL_USER_INFO *pUserInfo = NULL;
if ( pInfo )
{
pUserInfo = pInfo->pUserInfo;
pEntityInfo = pInfo->pEntity;
}
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Function Entry\r\n"
" URL: '%S'\r\n"
" Method: '%s'\r\n"
" Child Headers: '%s'\r\n"
" Flags: 0x%08x (%d)\r\n"
" Impersonation Token: %p\r\n"
" Custom User Name: '%S'\r\n"
" Custom Auth Type: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pInfo ? pInfo->pszUrl : NULL,
pInfo ? pInfo->pszMethod : NULL,
pInfo ? pInfo->pszChildHeaders : NULL,
pInfo ? pInfo->dwExecUrlFlags : 0,
pInfo ? pInfo->dwExecUrlFlags : 0,
pUserInfo ? pUserInfo->hImpersonationToken : NULL,
pUserInfo ? pUserInfo->pszCustomUserName : NULL,
pUserInfo ? pUserInfo->pszCustomAuthType : NULL ));
}
else
{
HSE_EXEC_URL_INFO *pInfo = (HSE_EXEC_URL_INFO *)pOrigExecUrlInfo;
HSE_EXEC_URL_USER_INFO *pUserInfo = NULL;
if ( pInfo )
{
pUserInfo = pInfo->pUserInfo;
pEntityInfo = pInfo->pEntity;
}
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Function Entry\r\n"
" URL: '%s'\r\n"
" Method: '%s'\r\n"
" Child Headers: '%s'\r\n"
" Flags: 0x%08x (%d)\r\n"
" Impersonation Token: %p\r\n"
" Custom User Name: '%s'\r\n"
" Custom Auth Type: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pInfo ? pInfo->pszUrl : NULL,
pInfo ? pInfo->pszMethod : NULL,
pInfo ? pInfo->pszChildHeaders : NULL,
pInfo ? pInfo->dwExecUrlFlags : 0,
pInfo ? pInfo->dwExecUrlFlags : 0,
pUserInfo ? pUserInfo->hImpersonationToken : NULL,
pUserInfo ? pUserInfo->pszCustomUserName : NULL,
pUserInfo ? pUserInfo->pszCustomAuthType : NULL ));
}
IF_DEBUG( ISAPI_DUMP_BUFFERS )
{
if ( pEntityInfo )
{
STACK_STRA( strBufferDump,512 );
DWORD dwBytesToDump = pEntityInfo->cbAvailable;
if ( dwBytesToDump > MAX_DEBUG_DUMP )
{
dwBytesToDump = MAX_DEBUG_DUMP;
}
if ( FAILED( strBufferDump.CopyBinary( pEntityInfo->lpbData, dwBytesToDump ) ) )
{
strBufferDump.Copy( "" );
}
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Dump of up to %d bytes of entity\r\n"
"%s"
" <END>\r\n\r\n",
pIsapiContext,
MAX_DEBUG_DUMP,
strBufferDump.QueryStr() ));
}
}
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pOrigExecUrlInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" ExecUrl Info: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// This is an async call, make sure a completion routine is set
//
if ( pIsapiContext->QueryPfnIoCompletion() == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Failed\r\n"
" No I/O completion has been set: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pIsapiContext->TryInitAsyncIo( AsyncExecPending ) == FALSE )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Failed\r\n"
" An async operation is already pending: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// If any of the optional parameters are not NULL, then ensure they are
// not empty. Also, copy parameters to the marshallable structure
//
// Note that any failures from here on down need to goto Done so
// that we properly uninitialize async IO.
//
if (fIsUnicode)
{
HSE_EXEC_UNICODE_URL_INFO *pExecUnicodeUrlInfo =
(HSE_EXEC_UNICODE_URL_INFO *)pOrigExecUrlInfo;
if ( pExecUnicodeUrlInfo->pszUrl != NULL )
{
if ( pExecUnicodeUrlInfo->pszUrl[ 0 ] == L'\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" URL is an empty string.\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
UrlInfo.fIsUrlUnicode = TRUE;
UrlInfo.pszUrl = (BYTE *)pExecUnicodeUrlInfo->pszUrl;
UrlInfo.cbUrl = (DWORD)(wcslen(pExecUnicodeUrlInfo->pszUrl) + 1)*sizeof(WCHAR);
}
else
{
UrlInfo.pszUrl = NULL;
UrlInfo.cbUrl = 0;
}
if ( pExecUnicodeUrlInfo->pszMethod != NULL )
{
if ( pExecUnicodeUrlInfo->pszMethod[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" Method is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
}
UrlInfo.pszMethod = pExecUnicodeUrlInfo->pszMethod;
if ( pExecUnicodeUrlInfo->pszChildHeaders != NULL )
{
if ( pExecUnicodeUrlInfo->pszChildHeaders[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" ChildHeaders is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
}
UrlInfo.pszChildHeaders = pExecUnicodeUrlInfo->pszChildHeaders;
if ( pExecUnicodeUrlInfo->pUserInfo != NULL )
{
if ( pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" Custom User Name: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
if ( pExecUnicodeUrlInfo->pUserInfo->pszCustomAuthType == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" Custom Auth Type: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
UserName.fIsUserNameUnicode = TRUE;
UserName.pszUserName = (BYTE *)pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName;
UserName.cbUserName = (DWORD)(wcslen(pExecUnicodeUrlInfo->pUserInfo->pszCustomUserName) + 1)*sizeof(WCHAR);
UserName.pszAuthType = pExecUnicodeUrlInfo->pUserInfo->pszCustomAuthType;
UserName.hImpersonationToken = (DWORD_PTR)pExecUnicodeUrlInfo->pUserInfo->hImpersonationToken;
UrlInfo.pUserInfo = &UserName;
}
else
{
UrlInfo.pUserInfo = NULL;
}
//
// If we are being told that there is available entity, ensure
// that the buffer is not NULL
//
if ( pExecUnicodeUrlInfo->pEntity != NULL )
{
if ( pExecUnicodeUrlInfo->pEntity->cbAvailable != 0 &&
pExecUnicodeUrlInfo->pEntity->lpbData == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_UNICODE_URL[%p]: Parameter validation failure\r\n"
" Available Entity bytes: %d\r\n"
" Available Entity Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pExecUnicodeUrlInfo->pEntity->cbAvailable,
pExecUnicodeUrlInfo->pEntity->lpbData ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
Entity.cbAvailable = pExecUnicodeUrlInfo->pEntity->cbAvailable;
Entity.lpbData = (BYTE *)pExecUnicodeUrlInfo->pEntity->lpbData;
}
else
{
//
// If no entity body was set for this child execute, then
// we should duplicate the original entity body. This means
// we will need to bring over the preloaded entity for the
// ISAPI which calls this routine.
//
Entity.cbAvailable = pIsapiContext->QueryECB()->cbAvailable;
Entity.lpbData = pIsapiContext->QueryECB()->lpbData;
}
UrlInfo.pEntity = &Entity;
UrlInfo.dwExecUrlFlags = pExecUnicodeUrlInfo->dwExecUrlFlags;
}
else
{
HSE_EXEC_URL_INFO *pExecAnsiUrlInfo =
(HSE_EXEC_URL_INFO *)pOrigExecUrlInfo;
if ( pExecAnsiUrlInfo->pszUrl != NULL )
{
if ( pExecAnsiUrlInfo->pszUrl[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" URL is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
UrlInfo.fIsUrlUnicode = FALSE;
UrlInfo.pszUrl = (BYTE *)pExecAnsiUrlInfo->pszUrl;
UrlInfo.cbUrl = (DWORD)strlen(pExecAnsiUrlInfo->pszUrl) + 1;
}
else
{
UrlInfo.pszUrl = NULL;
UrlInfo.cbUrl = 0;
}
if ( pExecAnsiUrlInfo->pszMethod != NULL )
{
if ( pExecAnsiUrlInfo->pszMethod[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" Method is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
}
UrlInfo.pszMethod = pExecAnsiUrlInfo->pszMethod;
if ( pExecAnsiUrlInfo->pszChildHeaders != NULL )
{
if ( pExecAnsiUrlInfo->pszChildHeaders[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" ChildHeaders is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
}
UrlInfo.pszChildHeaders = pExecAnsiUrlInfo->pszChildHeaders;
if ( pExecAnsiUrlInfo->pUserInfo != NULL )
{
if ( pExecAnsiUrlInfo->pUserInfo->pszCustomUserName == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" Custom User Name: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
if ( pExecAnsiUrlInfo->pUserInfo->pszCustomAuthType == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" Custom Auth Type: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
UserName.fIsUserNameUnicode = FALSE;
UserName.pszUserName = (BYTE *)pExecAnsiUrlInfo->pUserInfo->pszCustomUserName;
UserName.cbUserName = (DWORD)strlen(pExecAnsiUrlInfo->pUserInfo->pszCustomUserName) + 1;
UserName.pszAuthType = pExecAnsiUrlInfo->pUserInfo->pszCustomAuthType;
UserName.hImpersonationToken = (DWORD_PTR)pExecAnsiUrlInfo->pUserInfo->hImpersonationToken;
UrlInfo.pUserInfo = &UserName;
}
else
{
UrlInfo.pUserInfo = NULL;
}
//
// If we are being told that there is available entity, ensure
// that the buffer is not NULL
//
if ( pExecAnsiUrlInfo->pEntity != NULL )
{
if ( pExecAnsiUrlInfo->pEntity->cbAvailable != 0 &&
pExecAnsiUrlInfo->pEntity->lpbData == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Parameter validation failure\r\n"
" Available Entity Bytes: %d\r\n"
" Available Entity Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pExecAnsiUrlInfo->pEntity->cbAvailable,
pExecAnsiUrlInfo->pEntity->lpbData ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Done;
}
Entity.cbAvailable = pExecAnsiUrlInfo->pEntity->cbAvailable;
Entity.lpbData = (BYTE *)pExecAnsiUrlInfo->pEntity->lpbData;
}
else
{
//
// If no entity body was set for this child execute, then
// we should duplicate the original entity body. This means
// we will need to bring over the preloaded entity for the
// ISAPI which calls this routine.
//
Entity.cbAvailable = pIsapiContext->QueryECB()->cbAvailable;
Entity.lpbData = pIsapiContext->QueryECB()->lpbData;
}
UrlInfo.pEntity = &Entity;
UrlInfo.dwExecUrlFlags = pExecAnsiUrlInfo->dwExecUrlFlags;
}
//
// All the heavy lifting is in W3CORE.DLL
//
hr = pIsapiCore->ExecuteUrl(
reinterpret_cast<DWORD64>( pIsapiContext ),
&UrlInfo
);
Done:
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_EXEC_URL[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
pIsapiContext->UninitAsyncIo();
}
return hr;
}
HRESULT
SSFGetExecuteUrlStatus(
ISAPI_CONTEXT * pIsapiContext,
HSE_EXEC_URL_STATUS* pExecUrlStatus
)
/*++
Routine Description:
Get status of last child execute
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pExecUrlStatus - Filled with status
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_EXEC_URL_STATUS[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_EXEC_URL_STATUS[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pExecUrlStatus == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_EXEC_URL_STATUS[%p]: Parameter validation failure\r\n"
" EXEC_URL Status Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetExecuteUrlStatus(
&(pExecUrlStatus->uHttpStatusCode),
&(pExecUrlStatus->uHttpSubStatus),
&(pExecUrlStatus->dwWin32Error)
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_EXEC_URL_STATUS[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFSendCustomError(
ISAPI_CONTEXT * pIsapiContext,
HSE_CUSTOM_ERROR_INFO * pCustomErrorInfo
)
/*++
Routine Description:
Send custom error to client
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pCustomErrorInfo - Describes the custom error to send
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr = NOERROR;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Function Entry\r\n"
" Status: '%s'\r\n"
" SubError Code: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pCustomErrorInfo ? pCustomErrorInfo->pszStatus : NULL,
pCustomErrorInfo ? pCustomErrorInfo->uHttpSubError : 0 ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ( pCustomErrorInfo == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Parameter validation failure\r\n"
" Custom Error Info Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Ensure status is not empty
//
if ( pCustomErrorInfo->pszStatus != NULL )
{
if ( pCustomErrorInfo->pszStatus[ 0 ] == '\0' )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Parameter validation failure\r\n"
" Status is an empty string\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
}
//
// If this is an async call, then make sure a completion routine is set
//
if ( pCustomErrorInfo->fAsync )
{
if ( pIsapiContext->TryInitAsyncIo( AsyncExecPending ) == FALSE )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed\r\n"
" Another async operation is already pending\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
}
hr = pIsapiCore->SendCustomError(
pCustomErrorInfo->fAsync ? reinterpret_cast<DWORD64>( pIsapiContext ) : NULL,
pCustomErrorInfo->pszStatus,
pCustomErrorInfo->uHttpSubError );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_SEND_CUSTOM_ERROR[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
if ( pCustomErrorInfo->fAsync )
{
pIsapiContext->UninitAsyncIo();
}
return hr;
}
return hr;
}
HRESULT
SSFVectorSendDeprecated(
ISAPI_CONTEXT * pIsapiContext,
HSE_RESPONSE_VECTOR_DEPRECATED * pResponseVector
)
/*++
Routine Description:
The old deprecated vector-send
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pResponseVector - The vector to be sent
Return Value:
HRESULT
--*/
{
HSE_RESPONSE_VECTOR RealResponseVector;
STACK_BUFFER( buffResp, 512);
HRESULT hr;
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
if ( pResponseVector == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Parameter validation failure\r\n"
" Response Vector Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
RealResponseVector.dwFlags = pResponseVector->dwFlags;
RealResponseVector.pszStatus = pResponseVector->pszStatus;
RealResponseVector.pszHeaders = pResponseVector->pszHeaders;
RealResponseVector.nElementCount = pResponseVector->nElementCount;
if (!buffResp.Resize(pResponseVector->nElementCount * sizeof(HSE_VECTOR_ELEMENT)))
{
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
}
RealResponseVector.lpElementArray = (HSE_VECTOR_ELEMENT *)buffResp.QueryPtr();
for (DWORD i=0; i<pResponseVector->nElementCount; i++)
{
if (pResponseVector->lpElementArray[i].pBuffer != NULL)
{
RealResponseVector.lpElementArray[i].ElementType = HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER;
RealResponseVector.lpElementArray[i].pvContext = pResponseVector->lpElementArray[i].pBuffer;
RealResponseVector.lpElementArray[i].cbSize = pResponseVector->lpElementArray[i].cbSize;
}
else
{
RealResponseVector.lpElementArray[i].ElementType = HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE;
RealResponseVector.lpElementArray[i].pvContext = pResponseVector->lpElementArray[i].hFile;
RealResponseVector.lpElementArray[i].cbOffset = pResponseVector->lpElementArray[i].cbOffset;
RealResponseVector.lpElementArray[i].cbSize = pResponseVector->lpElementArray[i].cbSize;
}
}
hr = SSFVectorSend(pIsapiContext, &RealResponseVector);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND_DEPRECATED[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFVectorSend(
ISAPI_CONTEXT * pIsapiContext,
HSE_RESPONSE_VECTOR * pResponseVector
)
/*++
Routine Description:
Send an array of memory/file-handle/fragment-cache chunks
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pResponseVector - The vector to be sent
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
ULONGLONG cbTotalSend = 0;
STACK_BUFFER( buffResp, 512);
HRESULT hr = NOERROR;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Function Entry (%s)\r\n"
" Status: '%s'\r\n"
" Headers: '%s'\r\n"
" Element Count: %d\r\n"
" Flags: 0x%08x (%d)\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pResponseVector ? pResponseVector->dwFlags & HSE_IO_ASYNC ? "Asynchronous" : "Synchronous" : "",
pResponseVector ? pResponseVector->pszStatus : NULL,
pResponseVector ? pResponseVector->pszHeaders : NULL,
pResponseVector ? pResponseVector->nElementCount : 0,
pResponseVector ? pResponseVector->dwFlags : 0,
pResponseVector ? pResponseVector->dwFlags : 0 ));
IF_DEBUG( ISAPI_DUMP_BUFFERS )
{
if ( pResponseVector &&
pResponseVector->nElementCount )
{
STACK_STRA( strBufferDump,512 );
DWORD dwBytesToDump;
DWORD i;
for ( i = 0; i < pResponseVector->nElementCount; i++ )
{
if ( pResponseVector->lpElementArray[i].ElementType == HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER )
{
dwBytesToDump = pResponseVector->lpElementArray[i].cbSize;
if ( dwBytesToDump > MAX_DEBUG_DUMP )
{
dwBytesToDump = MAX_DEBUG_DUMP;
}
if ( FAILED( strBufferDump.CopyBinary( pResponseVector->lpElementArray[i].pvContext, dwBytesToDump ) ) )
{
strBufferDump.Copy( "" );
}
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Dump of up to %d bytes of element %d\r\n"
"%s"
" <END>\r\n\r\n",
pIsapiContext,
MAX_DEBUG_DUMP,
i,
strBufferDump.QueryStr() ));
}
else if ( pResponseVector->lpElementArray[i].ElementType == HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n",
" HSE_REQ_VECTOR_SEND[%p]: Element %d\r\n"
" File Handle: %p\r\n"
" Offset: %d\r\n"
" Bytes To Send: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pResponseVector->lpElementArray[i].pvContext,
pResponseVector->lpElementArray[i].cbOffset,
pResponseVector->lpElementArray[i].cbSize ));
}
}
}
}
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// verify the data passed in
//
if ( pResponseVector == NULL ||
( ( pResponseVector->dwFlags & HSE_IO_ASYNC ) != 0 &&
pIsapiContext->TryInitAsyncIo( AsyncVectorPending ) == FALSE ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Failed\r\n"
" Another async operation is already pending\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
if ((pResponseVector->dwFlags & HSE_IO_SYNC) &&
(pResponseVector->dwFlags & HSE_IO_ASYNC))
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" Both HSE_IO_SYNC and HSE_IO_ASYNC were specified\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
if (pResponseVector->dwFlags & HSE_IO_SEND_HEADERS)
{
if ((pResponseVector->pszStatus == NULL) ||
(pResponseVector->pszHeaders == NULL))
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" HSE_IO_SEND_HEADERS was specified, but some required info is missing\r\n"
" Status: '%s'\r\n"
" Headers: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pResponseVector->pszStatus,
pResponseVector->pszHeaders ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
}
else
{
if ((pResponseVector->pszStatus != NULL) ||
(pResponseVector->pszHeaders != NULL))
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" HSE_IO_SEND_HEADERS was not specified, yet status or header info was provided\r\n"
" Status: '%s'\r\n"
" Headers: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pResponseVector->pszStatus,
pResponseVector->pszHeaders ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
}
if (!buffResp.Resize(pResponseVector->nElementCount * sizeof(VECTOR_ELEMENT)))
{
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto Failed;
}
ZeroMemory(buffResp.QueryPtr(),
pResponseVector->nElementCount * sizeof(VECTOR_ELEMENT));
VECTOR_ELEMENT *pVectorElement = (VECTOR_ELEMENT *)buffResp.QueryPtr();
HSE_VECTOR_ELEMENT *pHseVectorElement;
for (DWORD i=0; i<pResponseVector->nElementCount; i++)
{
pHseVectorElement = &pResponseVector->lpElementArray[i];
if (pHseVectorElement->pvContext == NULL)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" Context: NULL on element %d in the array\r\n"
" <END>\r\n\r\n",
pIsapiContext,
i ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
switch (pHseVectorElement->ElementType)
{
case HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER:
if (pHseVectorElement->cbSize > MAXULONG)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" Invalid memory buffer size on element %d in the array\r\n"
" Size: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
i,
pHseVectorElement->cbSize ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
pVectorElement[i].pBuffer = (BYTE *)pHseVectorElement->pvContext;
cbTotalSend += ( pVectorElement[i].cbBufSize = (DWORD)pHseVectorElement->cbSize );
break;
case HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE:
if (pHseVectorElement->pvContext == INVALID_HANDLE_VALUE)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" Handle on file handle element %d in the array is invalid\r\n"
" File Handle: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
i,
pHseVectorElement->pvContext ));
}
hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
goto Failed;
}
//
// Treat 0 as "send the rest of the file" - same as TransmitFile
//
if (pHseVectorElement->cbSize == 0)
{
pHseVectorElement->cbSize = HTTP_BYTE_RANGE_TO_EOF;
}
pVectorElement[i].hFile = (DWORD_PTR)pHseVectorElement->pvContext;
pVectorElement[i].cbOffset = pHseVectorElement->cbOffset;
cbTotalSend += ( pVectorElement[i].cbFileSize = pHseVectorElement->cbSize );
break;
case HSE_VECTOR_ELEMENT_TYPE_FRAGMENT:
pVectorElement[i].pszFragmentName = (WCHAR *)pHseVectorElement->pvContext;
break;
default:
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Parameter validation failure\r\n"
" Unknown type on element %d in the array\r\n"
" Element Type: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
i,
pHseVectorElement->ElementType ));
}
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
goto Failed;
}
}
//
// Set up the total number of bytes we are trying to send so that ISAPIs
// are not confused
//
pIsapiContext->SetLastAsyncIo( (cbTotalSend > MAXULONG) ? MAXULONG : (DWORD)cbTotalSend );
//
// In general, VECTOR_SEND shouldn't touch the connection flags
// in the ISAPI_CONTEXT, since ISAPI tries to do the right thing
// automatically.
//
// There are couple of scenarios, though, where we might have a
// bit of connection management housekeeping to do.
//
// If the caller specified the HSE_IO_DISCONNECT_AFTER_SEND flag,
// then we need to force the connection closed.
//
// Otherwise, there are two scenarios where we may need to force
// the connection to stay open.
//
// First, if all of the below are true, we should set the
// connection to be open:
//
// - The client requested keep-alive
// - This call is sending headers (HSE_IO_SEND_HEADERS is set)
// - The disconnect flag has not been set
//
// Second, if all of the below are true, we should set the
// connection to be open.
//
// - The client requested keep-alive
// - The ISAPI has not already sent headers
// - The disconnect flag has not been set
// - This is the final send
//
// One final note: This logic does not account for the case where
// this call is sending headers, and the call fails for some reason.
// In the asynchronous case, this would be somewhat complicated to
// handle, since the completion routine would need to know both if
// the caller was sending headers, and also that the I/O failed.
// Presumably, if such a failure occurs, the most likely reason is
// that the client already disconnected, or it would otherwise be
// unlikely for the caller to do something to try and recover and
// redo this send in a way that would succeed, which makes all of this
// moot.
//
if ( pResponseVector->dwFlags & HSE_IO_DISCONNECT_AFTER_SEND )
{
pIsapiContext->SetKeepConn( FALSE );
}
else
{
if ( pIsapiContext->QueryClientKeepConn() )
{
if ( (pResponseVector->dwFlags & HSE_IO_SEND_HEADERS) ||
( pIsapiContext->QueryHeadersSent() == FALSE &&
(pResponseVector->dwFlags & HSE_IO_FINAL_SEND) ) )
{
pIsapiContext->SetKeepConn( TRUE );
}
}
}
hr = pIsapiCore->VectorSend(
pResponseVector->dwFlags & HSE_IO_ASYNC ? reinterpret_cast<DWORD64>( pIsapiContext ) : NULL,
!pIsapiContext->QueryKeepConn(),
pResponseVector->pszStatus,
pResponseVector->pszHeaders,
pVectorElement,
pResponseVector->nElementCount,
!!(pResponseVector->dwFlags & HSE_IO_FINAL_SEND),
!!(pResponseVector->dwFlags & HSE_IO_CACHE_RESPONSE)
);
if ( FAILED( hr ) )
{
goto Failed;
}
return hr;
Failed:
DBG_ASSERT( FAILED( hr ) );
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_VECTOR_SEND[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
if ( pResponseVector->dwFlags & HSE_IO_ASYNC )
{
pIsapiContext->SetLastAsyncIo( 0 );
pIsapiContext->UninitAsyncIo();
}
return hr;
}
HRESULT
SSFGetCustomErrorPage(
ISAPI_CONTEXT * pIsapiContext,
HSE_CUSTOM_ERROR_PAGE_INFO * pInfo
)
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Function Entry\r\n"
" Error: %d\r\n"
" SubError: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pInfo ? pInfo->dwError : 0,
pInfo ? pInfo->dwSubError : 0 ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Validate arguments
//
if ( pInfo == NULL ||
( pInfo->dwBufferSize != 0 && pInfo->pBuffer == NULL ) ||
pInfo->pdwBufferRequired == NULL ||
pInfo->pfIsFileError == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Parameter validation failure\r\n"
" Info Ptr: %p\r\n"
" Buffer Size: %d\r\n"
" Buffer Ptr: %p\r\n"
" Buffer Required Ptr: %p\r\n"
" IsFileError Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pInfo,
pInfo ? pInfo->dwBufferSize : 0,
pInfo ? pInfo->pBuffer : NULL,
pInfo ? pInfo->pdwBufferRequired : NULL,
pInfo ? pInfo->pfIsFileError : NULL ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetCustomError(
pInfo->dwError,
pInfo->dwSubError,
pInfo->dwBufferSize,
reinterpret_cast<BYTE*>( pInfo->pBuffer ),
pInfo->pdwBufferRequired,
pInfo->pfIsFileError,
pInfo->pfSendErrorBody
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CUSTOM_ERROR_PAGE[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFIsInProcess(
ISAPI_CONTEXT * pIsapiContext,
DWORD * pdwAppFlag
)
{
LPWSTR szClsid;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_IN_PROCESS[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
if ( pdwAppFlag == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_IS_IN_PROCESS[%p]: Parameter validation failure\r\n"
" AppFlag Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
szClsid = pIsapiContext->QueryClsid();
DBG_ASSERT( szClsid != NULL );
if ( wcslen( szClsid ) == 0 )
{
*pdwAppFlag = HSE_APP_FLAG_IN_PROCESS;
}
else if ( _wcsicmp( szClsid, W3_OOP_POOL_WAM_CLSID ) == NULL )
{
*pdwAppFlag = HSE_APP_FLAG_POOLED_OOP;
}
else
{
*pdwAppFlag = HSE_APP_FLAG_ISOLATED_OOP;
}
return NO_ERROR;
}
HRESULT
SSFGetSspiInfo(
ISAPI_CONTEXT * pIsapiContext,
CtxtHandle * pCtxtHandle,
CredHandle * pCredHandle
)
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_SSPI_INFO[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
//
// The CtxtHandle and CredHandle are only valid in their
// local process. There is no way to duplicate them into
// a dllhost. As a result, this function is inproc only.
//
if ( pIsapiContext->QueryIsOop() )
{
return HRESULT_FROM_WIN32( ERROR_INVALID_FUNCTION );
}
//
// Validate parameters
//
if ( pCtxtHandle == NULL || pCredHandle == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_SSPI_INFO[%p]: Parameter validation Failure\r\n"
" Context Handle Ptr: %p\r\n"
" Credential Handle Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pCtxtHandle,
pCredHandle ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetSspiInfo(
reinterpret_cast<BYTE*>( pCredHandle ),
sizeof( CredHandle ),
reinterpret_cast<BYTE*>( pCtxtHandle ),
sizeof( CtxtHandle )
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_SSPI_INFO[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFGetVirtualPathToken(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szUrl,
HANDLE * pToken,
BOOL fUnicode
)
{
IIsapiCore * pIsapiCore;
HRESULT hr = S_OK;
DWORD64 dwToken;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
if ( fUnicode )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN[%p]: Function Entry\r\n"
" URL: '%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
else
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_VIRTUAL_PATH_TOKEN[%p]: Function Entry\r\n"
" URL: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
}
//
// Validate parameters
//
if ( szUrl == NULL || pToken == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
if ( fUnicode )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN[%p]: Parameter validation failure\r\n"
" URL: '%S'\r\n"
" Token Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pToken ));
}
else
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_VIRTUAL_PATH_TOKEN[%p]: Parameter validation failure\r\n"
" URL: '%s'\r\n"
" Token Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pToken ));
}
}
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->QueryToken(
reinterpret_cast<BYTE*>( szUrl ),
(DWORD)( fUnicode ? (wcslen( (LPWSTR)szUrl ) + 1 ) * sizeof(WCHAR) : strlen( szUrl ) + 1 ),
TOKEN_VR_TOKEN,
&dwToken,
fUnicode
);
if (FAILED(hr))
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_%sVIRTUAL_PATH_TOKEN[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
fUnicode ? "UNICODE_" : "",
pIsapiContext,
hr ));
}
return hr;
}
*pToken = (HANDLE)dwToken;
return hr;
}
HRESULT
SSFGetAnonymousToken(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szUrl,
HANDLE * pToken,
BOOL fUnicode
)
{
IIsapiCore * pIsapiCore;
DWORD64 dwToken;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
if ( fUnicode )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN[%p]: Function Entry\r\n"
" URL: '%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
else
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_ANONYMOUS_TOKEN[%p]: Function Entry\r\n"
" URL: '%s\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl ));
}
}
//
// Validate parameters
//
if ( szUrl == NULL || pToken == NULL )
{
if ( fUnicode )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN[%p]: Parameter validation failure\r\n"
" URL: '%S'\r\n"
" Token Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pToken ));
}
}
else
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_ANONYMOUS_TOKEN[%p]: Parameter validation failure\r\n"
" URL: '%s'\r\n"
" Token Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szUrl,
pToken ));
}
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->QueryToken(
reinterpret_cast<BYTE*>( szUrl ),
(DWORD)( fUnicode ? (wcslen( (LPWSTR)szUrl ) + 1 ) * sizeof(WCHAR) : strlen( szUrl ) + 1 ),
TOKEN_ANONYMOUS_TOKEN,
&dwToken,
fUnicode
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_%sANONYMOUS_TOKEN[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
fUnicode ? "UNICODE_" : "",
pIsapiContext,
hr ));
}
return hr;
}
*pToken = (HANDLE)dwToken;
return hr;
}
HRESULT
SSFReportUnhealthy(
ISAPI_CONTEXT * pIsapiContext,
LPSTR szReason
)
{
IIsapiCore * pIsapiCore;
LPWSTR szImage;
STACK_STRU( strReason, 512 );
DWORD cbImage;
DWORD cbReason;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
DBG_REQUIRE( ( szImage = pIsapiContext->QueryGatewayImage() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REPORT_UNHEALTHY[%p]: Function Entry\r\n"
" Reason: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
szReason ));
}
cbImage = (DWORD)( wcslen( szImage ) + 1 ) * sizeof( WCHAR );
//
// If the ISAPI has given a reason, we need to send it
// as UNICODE.
//
if ( szReason == NULL )
{
cbReason = 0;
}
else
{
hr = strReason.CopyA( szReason );
if ( FAILED( hr ) )
{
return hr;
}
cbReason = ( strReason.QueryCCH() + 1 ) * sizeof( WCHAR );
}
hr = pIsapiCore->ReportAsUnhealthy(
reinterpret_cast<BYTE*>( szImage ),
cbImage,
cbReason ? reinterpret_cast<BYTE*>( strReason.QueryStr() ) : NULL,
cbReason
);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REPORT_UNHEALTHY[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFNormalizeUrl(
LPSTR pszURL
)
/*++
Routine Description:
Normalize URL
Arguments:
pszURL - On entry, contains not normalized URL. On return,
contains normalized URL.
Return Value:
HRESULT
--*/
{
HRESULT hr;
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_NORMALIZE_URL[]: Function Entry\r\n"
" URL: '%s'\r\n"
" <END>\r\n\r\n",
pszURL ));
}
//
// Validate parameters
//
if ( pszURL == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_NORMALIZE_URL[]: Parameter validation failure\r\n"
" URL: NULL\r\n"
" <END>\r\n\r\n" ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = NormalizeUrl( pszURL );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_NORMALIZE_URL[]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFAddFragmentToCache(
ISAPI_CONTEXT * pIsapiContext,
HSE_VECTOR_ELEMENT * pHseVectorElement,
WCHAR * pszFragmentName
)
/*++
Routine Description:
Add the given fragment to the fragment-cache
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pVectorElement - The fragment to be added
pszFragmentName - The name of the fragment
Return Value:
HRESULT
--*/
{
IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
HRESULT hr;
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Function Entry\r\n"
" Fragment Name: '%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pszFragmentName ));
}
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// verify the data passed in
//
if ( pHseVectorElement == NULL ||
pszFragmentName == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
" Vector Element Ptr: %p\r\n"
" Fragment Name: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pHseVectorElement,
pszFragmentName ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
VECTOR_ELEMENT VectorElement;
ZeroMemory(&VectorElement, sizeof VectorElement);
if (pHseVectorElement->pvContext == NULL)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
" Vector Element Context: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
switch (pHseVectorElement->ElementType)
{
case HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER:
if (pHseVectorElement->cbSize > MAXULONG)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
" Memory buffer size element invalid\r\n"
" Size: %d\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pHseVectorElement->cbSize ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
VectorElement.pBuffer = (BYTE *)pHseVectorElement->pvContext;
VectorElement.cbBufSize = (DWORD)pHseVectorElement->cbSize;
break;
case HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE:
if (pHseVectorElement->pvContext == INVALID_HANDLE_VALUE)
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
" Element file handle invalid\r\n"
" File Handle: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pHseVectorElement->pvContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// Treat 0 as "send the rest of the file" - same as TransmitFile/VectorSend
//
if (pHseVectorElement->cbSize == 0)
{
pHseVectorElement->cbSize = HTTP_BYTE_RANGE_TO_EOF;
}
VectorElement.hFile = (DWORD_PTR)pHseVectorElement->pvContext;
VectorElement.cbOffset = pHseVectorElement->cbOffset;
VectorElement.cbFileSize = pHseVectorElement->cbSize;
break;
case HSE_VECTOR_ELEMENT_TYPE_FRAGMENT:
default:
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Parameter validation failure\r\n"
" Unknown element type: %d\r\n"
" Fragment Name: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pHseVectorElement->ElementType ));
}
return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
}
hr = pIsapiCore->AddFragmentToCache(&VectorElement,
pszFragmentName);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_ADD_FRAGMENT_TO_CACHE[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFReadFragmentFromCache(
ISAPI_CONTEXT * pIsapiContext,
WCHAR * pszFragmentName,
BYTE * pvBuffer,
DWORD * pcbSize
)
/*++
Routine Description:
Read the given fragment from the fragment-cache
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pszFragmentName - The name of the fragment
pvBuffer - The buffer to read the fragment in
pcbSize - On entry, the size of the buffer and on exit, the number of bytes copied
Return Value:
HRESULT
--*/
{
IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
HRESULT hr;
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Function Entry\r\n"
" Fragment Name: '%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pszFragmentName ));
}
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// verify the data passed in
//
if ( pszFragmentName == NULL ||
pcbSize == NULL ||
(pvBuffer == NULL && *pcbSize != 0 ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Parameter validation failure\r\n"
" Fragment Name: '%s'\r\n"
" Size Ptr: %p\r\n"
" Size: %d\r\n"
" Buffer Ptr: %p\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pszFragmentName,
pcbSize,
pcbSize ? *pcbSize : 0,
pvBuffer ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->ReadFragmentFromCache(pszFragmentName,
pvBuffer,
*pcbSize,
pcbSize);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_READ_FRAGMENT_FROM_CACHE[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFRemoveFragmentFromCache(
ISAPI_CONTEXT * pIsapiContext,
WCHAR * pszFragmentName
)
/*++
Routine Description:
Remove the given fragment from the fragment-cache
Arguments:
pIsapiContext - The ISAPI_CONTEXT associated with this command.
pszFragmentName - The name of the fragment
Return Value:
HRESULT
--*/
{
IIsapiCore *pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
HRESULT hr;
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Function Entry\r\n"
" Fragment Name: '%S'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pszFragmentName ));
}
if ( pIsapiCore == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Failed to get interface to server core\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
//
// verify the data passed in
//
if ( pszFragmentName == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Parameter validation failure\r\n"
" Fragment Name: '%s'\r\n"
" <END>\r\n\r\n",
pIsapiContext,
pszFragmentName ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->RemoveFragmentFromCache(pszFragmentName);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_REMOVE_FRAGMENT_FROM_CACHE[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFGetMetadataProperty(
ISAPI_CONTEXT * pIsapiContext,
DWORD_PTR dwPropertyId,
BYTE * pbBuffer,
DWORD * pcbBuffer
)
/*++
Routine Description:
Retrieve a property from the UT_FILE metadata associated with the URL
of this request
Arguments:
pIsapiContext - ISAPI_CONTEXT
dwPropertyId - MD_* metabase property ID
pbBuffer - Points to buffer
pcbBuffer - On input size of buffer, on output size needed/used
Return Value:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
METADATA_RECORD * pRecord;
DBG_ASSERT( pIsapiContext != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_METADATA_PROPERTY[%p]: Function Entry\r\n"
" PropertyID: 0x%08x (%d)\r\n"
" <END>\r\n\r\n",
pIsapiContext,
dwPropertyId,
dwPropertyId ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
DBG_ASSERT( pIsapiCore != NULL );
if ( pcbBuffer == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_METADATA_PROPERTY[%p]: Parameter validation failure\r\n"
" Buffer Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetMetadataProperty( (DWORD) dwPropertyId,
pbBuffer,
*pcbBuffer,
pcbBuffer );
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_METADATA_PROPERTY[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
else
{
//
// OK. Before we return the METADATA_RECORD back to caller, set the
// pbMDData buffer pointer (since for OOP the pointer can only be
// calculated on this side
//
DBG_ASSERT( *pcbBuffer >= sizeof( METADATA_RECORD ) );
pRecord = (METADATA_RECORD*) pbBuffer;
pRecord->pbMDData = (BYTE*) (pRecord + 1);
}
return hr;
}
HRESULT
SSFGetCacheInvalidationCallback(
ISAPI_CONTEXT * pIsapiContext,
PFN_HSE_CACHE_INVALIDATION_CALLBACK * pfnCallback
)
/*++
Routine description:
Get the callback function to use to flush a response from the http.sys cache
Arguments:
pIsapiContext - The ISAPI_CONTEXT corresponding to the request
pfnCallback - On successful return, the address of the callback function
Return:
HRESULT
--*/
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
DBG_ASSERT( pIsapiCore != NULL );
if ( pfnCallback == NULL )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Parameter validation failure\r\n"
" Callback Ptr: NULL\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
hr = pIsapiCore->GetCacheInvalidationCallback((DWORD64 *)pfnCallback);
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
HRESULT
SSFCloseConnection(
ISAPI_CONTEXT * pIsapiContext
)
{
IIsapiCore * pIsapiCore;
HRESULT hr;
DBG_ASSERT( pIsapiContext );
DBG_ASSERT( pIsapiContext->CheckSignature() );
DBG_REQUIRE( ( pIsapiCore = pIsapiContext->QueryIsapiCoreInterface() ) != NULL );
IF_DEBUG( ISAPI_SSF_DETAILS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_CLOSE_CONNECTION[%p]: Function Entry\r\n"
" <END>\r\n\r\n",
pIsapiContext ));
}
hr = pIsapiCore->CloseConnection();
if ( FAILED( hr ) )
{
IF_DEBUG( ISAPI_ERROR_RETURNS )
{
DBGPRINTF(( DBG_CONTEXT,
"\r\n"
" HSE_REQ_CLOSE_CONNECTION[%p]: Failed\r\n"
" Error: 0x%08x\r\n"
" <END>\r\n\r\n",
pIsapiContext,
hr ));
}
return hr;
}
return hr;
}
// stristr (stolen from fts.c, wickn)
//
// case-insensitive version of strstr.
// stristr returns a pointer to the first occurrence of
// pszSubString in pszString. The search does not include
// terminating nul characters.
//
// BUGBUG: is this DBCS-safe?
const char*
stristr2(
const char* pszString,
const char* pszSubString
)
{
const char *cp1 = (const char*) pszString, *cp2, *cp1a;
char first;
// get the first char in string to find
first = pszSubString[0];
// first char often won't be alpha
if (isalpha(first))
{
first = (char) tolower(first);
for ( ; *cp1 != '\0'; cp1++)
{
if (tolower(*cp1) == first)
{
for (cp1a = &cp1[1], cp2 = (const char*) &pszSubString[1];
;
cp1a++, cp2++)
{
if (*cp2 == '\0')
return cp1;
if (tolower(*cp1a) != tolower(*cp2))
break;
}
}
}
}
else
{
for ( ; *cp1 != '\0' ; cp1++)
{
if (*cp1 == first)
{
for (cp1a = &cp1[1], cp2 = (const char*) &pszSubString[1];
;
cp1a++, cp2++)
{
if (*cp2 == '\0')
return cp1;
if (tolower(*cp1a) != tolower(*cp2))
break;
}
}
}
}
return NULL;
}