windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/w3isapi/w3isapi.cxx
2020-09-26 16:20:57 +08:00

1310 lines
30 KiB
C++

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Module Name :
w3isapi.cxx
Abstract:
IIS Plus ISAPI Handler
Author:
Wade Hilmo (WadeH) 03-Feb-2000
Project:
w3isapi.dll
--*/
/************************************************************
* Include Headers
************************************************************/
#include "precomp.hxx"
#include "isapi_context.hxx"
#include "server_support.hxx"
/************************************************************
* Globals
************************************************************/
CHAR g_szClsid[SIZE_CLSID_STRING];
CHAR g_szIsapiHandlerInstance[SIZE_CLSID_STRING];
DWORD g_dwPidW3Core;
/************************************************************
* Declarations
************************************************************/
BOOL
WINAPI
GetServerVariable(
HCONN hConn,
LPSTR lpszVariableName,
LPVOID lpvBuffer,
LPDWORD lpdwSize
);
BOOL
WINAPI
WriteClient(
HCONN ConnID,
LPVOID Buffer,
LPDWORD lpdwBytes,
DWORD dwReserved
);
BOOL
WINAPI
ReadClient(
HCONN ConnID,
LPVOID lpvBuffer,
LPDWORD lpdwSize
);
BOOL
WINAPI
ServerSupportFunction(
HCONN hConn,
DWORD dwHSERequest,
LPVOID lpvBuffer,
LPDWORD lpdwSize,
LPDWORD lpdwDataType
);
HRESULT
ProcessIsapiRequest(
IIsapiCore * pIsapiCore,
ISAPI_CORE_DATA * pCoreData,
DWORD * pHseResult
);
HRESULT
ProcessIsapiCompletion(
VOID * pContext,
DWORD cbCompletion,
DWORD dwCompletionStatus
);
HRESULT
InitModule(
LPCSTR szClsid,
LPCSTR szIsapiHandlerInstance,
DWORD dwPidW3Core
);
VOID
TerminateModule( VOID );
// BUGBUG
#undef INET_INFO_KEY
#undef INET_INFO_PARAMETERS_KEY
//
// Configuration parameters registry key.
//
#define INET_INFO_KEY \
"System\\CurrentControlSet\\Services\\w3svc"
#define INET_INFO_PARAMETERS_KEY \
INET_INFO_KEY "\\Parameters"
const CHAR g_pszWpRegLocation[] =
INET_INFO_PARAMETERS_KEY "\\w3isapi";
DECLARE_DEBUG_PRINTS_OBJECT();
DECLARE_DEBUG_VARIABLE();
DECLARE_PLATFORM_TYPE();
/************************************************************
* Type Definitions
************************************************************/
HRESULT
InitModule(
LPCSTR szClsid,
LPCSTR szIsapiHandlerInstance,
DWORD dwPidW3Core
)
/*++
Routine Description:
Initializes the w3isapi module
Arguments:
szClsid - In the OOP case, this is the CLSID of
the application being hosted. This
value may be NULL (ie. in the case of
inproc ISAPI).
szIsapiHandlerInstance - The instance ID of the ISAPI handler
that's initializing this module.
dwPidW3Core - The PID of the process containing the
core server that's responsible for this
module
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
CREATE_DEBUG_PRINT_OBJECT("w3isapi");
if (!VALID_DEBUG_PRINT_OBJECT())
{
return E_FAIL;
}
LOAD_DEBUG_FLAGS_FROM_REG_STR( g_pszWpRegLocation, DEBUG_ERROR );
INITIALIZE_PLATFORM_TYPE();
DBGPRINTF((
DBG_CONTEXT,
"Initializing w3isapi.dll - CLSID: %s, "
"ISAPI Handler: %s, W3Core PID %d.\r\n",
szClsid ? szClsid : "NULL",
szIsapiHandlerInstance,
dwPidW3Core
));
//
// If g_pDllManager is not NULL at this point, then
// this module is being intialized multiple times. This
// is an unexpected state.
//
if ( g_pDllManager != NULL )
{
DBGPRINTF((
DBG_CONTEXT,
"Warning - w3isapi.dll previously initalized.\r\n"
"Previous CLSID: %s, Previous ISAPI Handler: %s, "
"Previous W3Core PID: %d.\r\n",
g_szClsid,
g_szIsapiHandlerInstance,
g_dwPidW3Core
));
DBG_ASSERT( FALSE && "w3isapi.dll previously initialized." );
}
g_pDllManager = new ISAPI_DLL_MANAGER();
if( g_pDllManager == NULL )
{
hr = E_OUTOFMEMORY;
}
hr = ISAPI_CONTEXT::Initialize();
if ( FAILED( hr ) )
{
delete g_pDllManager;
g_pDllManager = NULL;
}
hr = ISAPI_DLL::Initialize();
if ( FAILED( hr ) )
{
delete g_pDllManager;
g_pDllManager = NULL;
ISAPI_CONTEXT::Terminate();
}
//
// If we've successfully initialized, then store
// the information from the caller so that we can
// debug double initializations.
//
if ( SUCCEEDED( hr ) )
{
if ( szClsid )
{
strncpy(
g_szClsid,
szClsid,
SIZE_CLSID_STRING
);
g_szClsid[SIZE_CLSID_STRING - 1] = '\0';
}
else
{
strcpy( g_szClsid, "NULL" );
}
strncpy(
g_szIsapiHandlerInstance,
szIsapiHandlerInstance,
SIZE_CLSID_STRING
);
g_szIsapiHandlerInstance[SIZE_CLSID_STRING - 1] = '\0';
g_dwPidW3Core = dwPidW3Core;
}
return hr;
}
VOID
TerminateModule( VOID )
/*++
Routine Description:
Terminates the w3isapi module
Arguments:
None
Return Value:
None
--*/
{
ISAPI_CONTEXT::Terminate();
DBG_ASSERT( g_pDllManager );
if( g_pDllManager )
{
delete g_pDllManager;
g_pDllManager = NULL;
}
ISAPI_DLL::Terminate();
DELETE_DEBUG_PRINT_OBJECT();
}
HRESULT
ProcessIsapiRequest(
IIsapiCore * pIsapiCore,
ISAPI_CORE_DATA * pCoreData,
DWORD * pHseResult
)
/*++
Routine Description:
Processes an ISAPI request
Arguments:
pIsapiCore - The interface that provides connectivity to the core server
pCoreData - The core data that describes the request
pHseResult - Upon return, contains the return code from
the extension's HttpExtensionProc
Return Value:
HRESULT
--*/
{
ISAPI_DLL * pIsapiDll = NULL;
DWORD dwIsapiReturn = HSE_STATUS_ERROR;
ISAPI_CONTEXT * pIsapiContext = NULL;
PFN_HTTPEXTENSIONPROC pfnHttpExtensionProc;
EXTENSION_CONTROL_BLOCK * pEcb = NULL;
HRESULT hr = NO_ERROR;
ISAPI_CORE_DATA * pTempCoreData = NULL;
DBG_ASSERT( g_pDllManager );
//
// This function is only called by w3core.dll
//
DBG_ASSERT( pIsapiCore );
DBG_ASSERT( pCoreData );
DBG_ASSERT( pHseResult );
//
// If this request is running OOP, then make a local copy
// and fix up the core data internal pointers.
//
if ( pCoreData->fIsOop )
{
pTempCoreData = (ISAPI_CORE_DATA*) LocalAlloc( LPTR, pCoreData->cbSize );
if ( !pTempCoreData )
{
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto Failed;
}
memcpy( pTempCoreData, pCoreData, pCoreData->cbSize );
//
// All the extra data begins right at the end of pCoreData, start
// pointing there
//
pTempCoreData->szGatewayImage = (LPWSTR)(pTempCoreData + 1);
pTempCoreData->szApplMdPathW = (LPWSTR)((LPSTR)pTempCoreData->szGatewayImage + pTempCoreData->cbGatewayImage);
pTempCoreData->szPathTranslatedW = (LPWSTR)((LPSTR)pTempCoreData->szApplMdPathW + pTempCoreData->cbApplMdPathW);
pTempCoreData->szPhysicalPath = (LPSTR)pTempCoreData->szPathTranslatedW + pTempCoreData->cbPathTranslatedW;
pTempCoreData->szPathInfo = pTempCoreData->szPhysicalPath + pTempCoreData->cbPhysicalPath;
pTempCoreData->szMethod = pTempCoreData->szPathInfo + pTempCoreData->cbPathInfo;
pTempCoreData->szQueryString = pTempCoreData->szMethod + pTempCoreData->cbMethod;
pTempCoreData->szPathTranslated = pTempCoreData->szQueryString + pTempCoreData->cbQueryString;
pTempCoreData->szContentType = pTempCoreData->szPathTranslated + pTempCoreData->cbPathTranslated;
pTempCoreData->szConnection = pTempCoreData->szContentType + pTempCoreData->cbContentType;
pTempCoreData->szUserAgent = pTempCoreData->szConnection + pTempCoreData->cbConnection;
pTempCoreData->szCookie = pTempCoreData->szUserAgent + pTempCoreData->cbUserAgent;
pTempCoreData->szApplMdPath = pTempCoreData->szCookie + pTempCoreData->cbCookie;
if ( pTempCoreData->cbAvailableEntity )
{
pTempCoreData->pAvailableEntity = pTempCoreData->szApplMdPath + pTempCoreData->cbApplMdPath;
}
else
{
pTempCoreData->pAvailableEntity = NULL;
}
//
// We'll set pCoreData to point to our temp one. This
// doesn't leak because the ISAPI_CONTEXT destructor is smart
// enough to know it needs to be deleted in the OOP case.
//
pCoreData = pTempCoreData;
}
//
// Get the entry point for the ISAPI
//
hr = g_pDllManager->GetIsapi(
pCoreData->szGatewayImage,
&pIsapiDll,
pCoreData->hToken,
pCoreData->pSid
);
if ( FAILED( hr ) )
{
goto Failed;
}
//
// Construct the ISAPI_CONTEXT for this request. Once it's
// allocated, it owns the lifetime of the ISAPI_REQUEST. When
// the ISAPI_CONTEXT is deallocated, it may release the final
// reference.
//
pIsapiContext = new ISAPI_CONTEXT( pIsapiCore, pCoreData, pIsapiDll );
if ( pIsapiContext == NULL )
{
hr = HRESULT_FROM_WIN32( GetLastError () );
goto Failed;
}
//
// Set the ECB
//
pEcb = pIsapiContext->QueryECB();
//
// Set the ECB function pointers
//
pEcb->GetServerVariable = GetServerVariable;
pEcb->WriteClient = WriteClient;
pEcb->ReadClient = ReadClient;
pEcb->ServerSupportFunction = ServerSupportFunction;
//
// Get the extension's entry point
//
pfnHttpExtensionProc = pIsapiDll->QueryHttpExtensionProc();
//
// If we are running OOP, set the COM state so that the
// extension can CoInitialize/CoUninitialize.
//
if ( pIsapiContext->QueryIsOop() )
{
hr = pIsapiContext->SetComStateForOop();
DBG_ASSERT( SUCCEEDED( hr ) );
}
//
// Impersonate the authenticated user and call it
//
if ( !SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Failed;
}
pIsapiContext->ReferenceIsapiContext();
dwIsapiReturn = pfnHttpExtensionProc( pEcb );
DBG_REQUIRE( RevertToSelf() );
if ( pIsapiContext->QueryIsOop() )
{
pIsapiContext->RestoreComStateForOop();
}
pIsapiContext->DereferenceIsapiContext();
switch ( dwIsapiReturn )
{
case HSE_STATUS_PENDING:
//
// Don't dereference the ISAPI_CONTEXT. This
// will guarantee that it lives on beyond the
// return from this function.
//
break;
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
//
// Special case of success. The extension wants
// to keep the connection open, even though we may
// not have detected proper response headers.
//
// After setting the disconnect mode, fall through.
//
if ( pIsapiContext->QueryClientKeepConn() )
{
pIsapiContext->SetKeepConn( TRUE );
pIsapiCore->SetConnectionClose( FALSE );
}
case HSE_STATUS_ERROR:
case HSE_STATUS_SUCCESS:
default:
pIsapiContext->DereferenceIsapiContext();
break;
}
*pHseResult = dwIsapiReturn;
pIsapiDll->DereferenceIsapiDll();
pIsapiDll = NULL;
return NO_ERROR;
Failed:
DBG_ASSERT( FAILED( hr ) );
if ( pIsapiContext )
{
pIsapiContext->DereferenceIsapiContext();
pIsapiContext = NULL;
}
else
{
//
// In OOP case, we're depending on the ISAPI_CONTEXT destructor
// to free the copy of the core data and close the impersonation
// token. If we weren't able to allocate one, we'll have to
// do it here.
//
if ( pCoreData->fIsOop )
{
CloseHandle( pCoreData->hToken );
if ( pTempCoreData )
{
LocalFree( pTempCoreData );
pTempCoreData = NULL;
}
}
}
if ( pIsapiDll )
{
pIsapiDll->DereferenceIsapiDll();
pIsapiDll = NULL;
}
return hr;
}
HRESULT
ProcessIsapiCompletion(
DWORD64 IsaContext,
DWORD cbCompletion,
DWORD dwCompletionStatus
)
/*++
Routine Description:
Processes an I/O completion for an ISAPI extension
Arguments:
IsaContext - The ISAPI_CONTEXT for this completion
cbCompletion - The byte count associated with the completion
dwCompletionStatus - The result code associated with the completion
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
ASYNC_PENDING IoType;
PFN_HSE_IO_COMPLETION pfnCompletion;
DWORD cbLastIo;
HRESULT hr = NO_ERROR;
DBG_REQUIRE( pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( IsaContext ) );
pIsapiContext->ReferenceIsapiContext();
//
// Magical hand waving:
//
// If this is a completion for a write, then we need to
// restore the original buffer size. This is necessary
// to keep from confusing ISAPI extensions that examine
// the cbCompletion value in the case where a filter
// changed the size of the buffer before the actual
// IO occured.
//
// If this is a completion for an EXEC_URL, then we need
// to set the dwCompletionStatus to ERROR_SUCCESS. The
// caller of the EXEC_URL should use GET_EXECUTE_URL_STATUS
// to see the result of the child URL.
//
cbLastIo = pIsapiContext->QueryLastAsyncIo();
pIsapiContext->SetLastAsyncIo( 0 );
IoType = pIsapiContext->UninitAsyncIo();
if ( IoType == AsyncWritePending )
{
cbCompletion = cbLastIo;
}
else if ( IoType == AsyncExecPending )
{
dwCompletionStatus = ERROR_SUCCESS;
}
//
// If the completion context indicates a completion routine,
// then call it.
//
pfnCompletion = pIsapiContext->QueryPfnIoCompletion();
if ( pfnCompletion )
{
//
// First, impersonate the client
//
if ( SetThreadToken( NULL, pIsapiContext->QueryToken() ) )
{
pfnCompletion(
pIsapiContext->QueryECB(),
pIsapiContext->QueryExtensionContext(),
cbCompletion,
dwCompletionStatus
);
DBG_REQUIRE( RevertToSelf() );
}
else
{
hr = HRESULT_FROM_WIN32( GetLastError() );
}
}
pIsapiContext->DereferenceIsapiContext();
return hr;
}
BOOL
WINAPI
GetServerVariable(
HCONN hConn,
LPSTR lpszVariableName,
LPVOID lpvBuffer,
LPDWORD lpdwSize
)
/*++
Routine Description:
Retrieves a server variable
Arguments:
hConn - The ConnID associated with the request. This
value is opaque to the ISAPI that calls into
this function, but it can be cast to the
ISAPI_CONTEXT associated with the request.
lpszVariableName - The name of the variable to retrieve
lpvBuffer - Upon return, contains the value of the variable
lpdwSize - On entry, contains the size of lpvBuffer, upon
return, contains the number of bytes actually
needed to contain the value.
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
IIsapiCore * pIsapiCore;
HANDLE hCurrentUser;
HRESULT hr;
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
//
// Parameter validation
//
if ( pIsapiContext == NULL ||
lpszVariableName == NULL ||
lpdwSize == NULL ||
( *lpdwSize != 0 && lpvBuffer == NULL ) )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// If we are running OOP, then try and get the data
// locally from the process.
//
if ( pIsapiContext->QueryIsOop() )
{
SERVER_VARIABLE_INDEX Index;
Index = LookupServerVariableIndex( lpszVariableName );
if ( Index != ServerVariableExternal )
{
return pIsapiContext->GetOopServerVariableByIndex(
Index,
lpvBuffer,
lpdwSize
);
}
}
//
// Call it
//
pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
hr = pIsapiCore->GetServerVariable(
lpszVariableName,
*lpdwSize ? (BYTE*)lpvBuffer : NULL,
*lpdwSize,
lpdwSize
);
pIsapiContext->IsapiUndoRevertHack( &hCurrentUser);
if ( FAILED( hr ) )
{
SetLastError( WIN32_FROM_HRESULT( hr ) );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
WriteClient(
HCONN ConnID,
LPVOID Buffer,
LPDWORD lpdwBytes,
DWORD dwReserved
)
/*++
Routine Description:
Writes data to the client
Arguments:
hConn - The ConnID associated with the request. This
value is opaque to the ISAPI that calls into
this function, but it can be cast to the
ISAPI_CONTEXT associated with the request.
Buffer - The data to write
lpdwBytes - On entry, the number of bytes to write. Upon
return, the number of bytes written (or so the
docs say)
dwReserved - Flags (ie. HSE_IO_SYNC, etc.)
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
IIsapiCore * pIsapiCore;
HANDLE hCurrentUser;
BOOL fResult;
HRESULT hr;
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
//
// Parameter validation
//
if ( pIsapiContext == NULL ||
lpdwBytes == NULL ||
( *lpdwBytes != 0 && Buffer == NULL ) )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// If the user is sending zero bytes, return TRUE here. Yeah, this
// will be kind of a bogus thing to do because if the call is async,
// we will return successful with no completion ever occuring.
//
// IIS has done this for as long as sync WriteClient has existed, and
// we'd risk breaking legacy code if we change it now.
//
if ( *lpdwBytes == 0 )
{
return TRUE;
}
//
// BUGBUG - Need to map the documented HSE_IO flags to reasonable
// UL equivalents and provide a mechanism to pass them.
//
if ( dwReserved & HSE_IO_ASYNC )
{
//
// Do an asynchronous write
//
// Check to make sure that we have a completion
// function.
//
if ( pIsapiContext->QueryPfnIoCompletion() == NULL ||
pIsapiContext->TryInitAsyncIo( AsyncWritePending ) == FALSE )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
//
// Some extensions depend on the number of bytes reported in the
// completion to confirm success. In the case where a send raw
// data filter is installed (or if we are using SSL), it's possible
// that the number of bytes in the completion is not what the
// caller expects.
//
// We need to save away the number of bytes that they are sending
// to protect them from themselves.
//
pIsapiContext->SetLastAsyncIo( *lpdwBytes );
pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
hr = pIsapiCore->WriteClient(
reinterpret_cast<DWORD64>( pIsapiContext ),
reinterpret_cast<LPBYTE>( Buffer ),
*lpdwBytes,
HSE_IO_ASYNC
);
pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
if ( FAILED( hr ) )
{
pIsapiContext->SetLastAsyncIo( 0 );
pIsapiContext->UninitAsyncIo();
}
}
else
{
//
// Do a synchronous write
//
pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
hr = pIsapiCore->WriteClient(
NULL,
reinterpret_cast<LPBYTE>( Buffer ),
*lpdwBytes,
HSE_IO_SYNC
);
pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
}
if ( FAILED( hr ) )
{
SetLastError( WIN32_FROM_HRESULT( hr ) );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
ReadClient(
HCONN ConnID,
LPVOID lpvBuffer,
LPDWORD lpdwSize
)
/*++
Routine Description:
Reads data from the client
Arguments:
hConn - The ConnID associated with the request. This
value is opaque to the ISAPI that calls into
this function, but it can be cast to the
ISAPI_CONTEXT associated with the request.
lpvBuffer - Upon return, contains the data read
lpdwsize - On entry, the size of lpvBuffer. Upon
return, the number of bytes read.
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
IIsapiCore * pIsapiCore;
HANDLE hCurrentUser;
HRESULT hr;
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( ConnID );
//
// Parameter validation
//
if ( pIsapiContext == NULL ||
lpdwSize == NULL ||
( *lpdwSize != 0 && lpvBuffer == NULL ) )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
pIsapiCore = pIsapiContext->QueryIsapiCoreInterface();
if ( pIsapiCore == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
hr = pIsapiCore->ReadClient(
NULL,
reinterpret_cast<unsigned char *>( lpvBuffer ),
*lpdwSize,
*lpdwSize,
lpdwSize,
HSE_IO_SYNC
);
pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
if ( FAILED( hr ) )
{
SetLastError( WIN32_FROM_HRESULT( hr ) );
return FALSE;
}
return TRUE;
}
BOOL
WINAPI
ServerSupportFunction(
HCONN hConn,
DWORD dwHSERequest,
LPVOID lpvBuffer,
LPDWORD lpdwSize,
LPDWORD lpdwDataType
)
/*++
Routine Description:
Dispatches a ServerSupportFunction command to the appropriate
server support function.
Arguments:
hConn - The ConnID associated with the request. This
value is opaque to the ISAPI that calls into
this function, but it can be cast to the
ISAPI_CONTEXT associated with the request.
dwHSERequest - The server support command
lpvBuffer - Command-specific data
lpdwSize - Command-specific data
lpdwDataType - Command-specific data
Return Value:
HRESULT
--*/
{
ISAPI_CONTEXT * pIsapiContext;
HANDLE hCurrentUser;
HRESULT hr = NO_ERROR;
pIsapiContext = reinterpret_cast<ISAPI_CONTEXT*>( hConn );
//
// Parameter validation
//
if ( pIsapiContext == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
pIsapiContext->ReferenceIsapiContext();
pIsapiContext->IsapiDoRevertHack( &hCurrentUser );
//
// Handle the specified command
//
switch ( dwHSERequest )
{
case HSE_REQ_SEND_RESPONSE_HEADER:
hr = SSFSendResponseHeader(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer ),
reinterpret_cast<LPSTR>( lpdwDataType )
);
break;
case HSE_REQ_SEND_RESPONSE_HEADER_EX:
hr = SSFSendResponseHeaderEx(
pIsapiContext,
reinterpret_cast<HSE_SEND_HEADER_EX_INFO*>( lpvBuffer )
);
break;
case HSE_REQ_MAP_URL_TO_PATH:
hr = SSFMapUrlToPath(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer ),
lpdwSize
);
break;
case HSE_REQ_MAP_URL_TO_PATH_EX:
hr = SSFMapUrlToPathEx(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer ),
reinterpret_cast<HSE_URL_MAPEX_INFO*>( lpdwDataType ),
lpdwSize
);
break;
case HSE_REQ_MAP_UNICODE_URL_TO_PATH:
hr = SSFMapUnicodeUrlToPath(
pIsapiContext,
reinterpret_cast<LPWSTR>( lpvBuffer ),
lpdwSize
);
break;
case HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX:
hr = SSFMapUnicodeUrlToPathEx(
pIsapiContext,
reinterpret_cast<LPWSTR>( lpvBuffer ),
reinterpret_cast<HSE_UNICODE_URL_MAPEX_INFO*>( lpdwDataType ),
lpdwSize
);
break;
case HSE_REQ_GET_IMPERSONATION_TOKEN:
hr = SSFGetImpersonationToken(
pIsapiContext,
reinterpret_cast<HANDLE*>( lpvBuffer )
);
break;
case HSE_REQ_IS_KEEP_CONN:
hr = SSFIsKeepConn(
pIsapiContext,
reinterpret_cast<BOOL*>( lpvBuffer )
);
break;
case HSE_REQ_DONE_WITH_SESSION:
hr = SSFDoneWithSession(
pIsapiContext,
reinterpret_cast<DWORD*>( lpvBuffer )
);
break;
case HSE_REQ_GET_CERT_INFO_EX:
hr = SSFGetCertInfoEx(
pIsapiContext,
reinterpret_cast<CERT_CONTEXT_EX*>( lpvBuffer )
);
break;
case HSE_REQ_IO_COMPLETION:
hr = SSFIoCompletion(
pIsapiContext,
reinterpret_cast<PFN_HSE_IO_COMPLETION>( lpvBuffer ),
reinterpret_cast<VOID*>( lpdwDataType )
);
break;
case HSE_REQ_ASYNC_READ_CLIENT:
hr = SSFAsyncReadClient(
pIsapiContext,
lpvBuffer,
lpdwSize
);
break;
case HSE_REQ_TRANSMIT_FILE:
hr = SSFTransmitFile(
pIsapiContext,
reinterpret_cast<HSE_TF_INFO*>( lpvBuffer )
);
break;
case HSE_REQ_SEND_URL:
case HSE_REQ_SEND_URL_REDIRECT_RESP:
hr = SSFSendRedirect(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer )
);
break;
case HSE_REQ_IS_CONNECTED:
hr = SSFIsConnected(
pIsapiContext,
reinterpret_cast<BOOL*>( lpvBuffer )
);
break;
case HSE_APPEND_LOG_PARAMETER:
hr = SSFAppendLog(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer )
);
break;
case HSE_REQ_EXEC_URL:
hr = SSFExecuteUrl(
pIsapiContext,
reinterpret_cast<HSE_EXEC_URL_INFO*>( lpvBuffer )
);
break;
case HSE_REQ_GET_EXEC_URL_STATUS:
hr = SSFGetExecuteUrlStatus(
pIsapiContext,
reinterpret_cast<HSE_EXEC_URL_STATUS*>( lpvBuffer )
);
break;
case HSE_REQ_SEND_CUSTOM_ERROR:
hr = SSFSendCustomError(
pIsapiContext,
reinterpret_cast<HSE_CUSTOM_ERROR_INFO*>( lpvBuffer )
);
break;
case HSE_REQ_VECTOR_SEND:
hr = SSFVectorSend(
pIsapiContext,
reinterpret_cast<HSE_RESPONSE_VECTOR*>( lpvBuffer )
);
break;
case HSE_REQ_GET_CUSTOM_ERROR_PAGE:
hr = SSFGetCustomErrorPage(
pIsapiContext,
reinterpret_cast<HSE_CUSTOM_ERROR_PAGE_INFO*>( lpvBuffer )
);
break;
case HSE_REQ_IS_IN_PROCESS:
hr = SSFIsInProcess(
pIsapiContext,
reinterpret_cast<DWORD*>( lpvBuffer )
);
break;
case HSE_REQ_GET_SSPI_INFO:
hr = SSFGetSspiInfo(
pIsapiContext,
reinterpret_cast<CtxtHandle*>( lpvBuffer ),
reinterpret_cast<CredHandle*>( lpdwDataType )
);
break;
case HSE_REQ_GET_VIRTUAL_PATH_TOKEN:
hr = SSFGetVirtualPathToken(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer ),
reinterpret_cast<HANDLE*>( lpdwSize ),
FALSE
);
break;
case HSE_REQ_GET_UNICODE_VIRTUAL_PATH_TOKEN:
hr = SSFGetVirtualPathToken(
pIsapiContext,
reinterpret_cast<LPSTR>( lpvBuffer ),
reinterpret_cast<HANDLE*>( lpdwSize ),
TRUE
);
break;
default:
hr = HRESULT_FROM_WIN32( ERROR_CALL_NOT_IMPLEMENTED );
}
pIsapiContext->IsapiUndoRevertHack( &hCurrentUser );
pIsapiContext->DereferenceIsapiContext();
pIsapiContext = NULL;
if ( FAILED( hr ) )
{
SetLastError( WIN32_FROM_HRESULT( hr ) );
return FALSE;
}
return TRUE;
}