mirror of https://github.com/lianthony/NT4.0
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.
471 lines
12 KiB
471 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ssibgi.cxx
|
|
|
|
Abstract:
|
|
|
|
Code to do #EXECing of ISAPI apps
|
|
|
|
Author:
|
|
|
|
Bilal Alam (t-bilala) 20-June-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ssinc.hxx"
|
|
#include "ssicgi.hxx"
|
|
#include "ssibgi.hxx"
|
|
|
|
// Globals
|
|
|
|
BOOL fExtInitialized = FALSE;
|
|
BOOL fCacheExtensions = TRUE;
|
|
|
|
// Prototypes
|
|
|
|
extern "C" {
|
|
dllexp
|
|
BOOL
|
|
SEGetEntryPoint(
|
|
const char * pszDLL,
|
|
HANDLE hImpersonation,
|
|
PFN_HTTPEXTENSIONPROC * ppfnSEProc,
|
|
HMODULE * phMod
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIServerSupportFunction(
|
|
HCONN hConn,
|
|
DWORD dwRequest,
|
|
LPVOID lpvBuffer,
|
|
LPDWORD lpdwSize,
|
|
LPDWORD lpdwDataType
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIGetServerVariable(
|
|
HCONN hConn,
|
|
LPSTR lpszVariableName,
|
|
LPVOID lpvBuffer,
|
|
LPDWORD lpdwSize
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIWriteClient(
|
|
HCONN hConn,
|
|
LPVOID Buffer,
|
|
LPDWORD lpdwBytes,
|
|
DWORD dwReserved
|
|
);
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIReadClient(
|
|
HCONN hConn,
|
|
LPVOID Buffer,
|
|
LPDWORD lpdwBytes
|
|
);
|
|
|
|
class BGI_INFO
|
|
{
|
|
public:
|
|
EXTENSION_CONTROL_BLOCK _ECB;
|
|
|
|
SSI_REQUEST * _pRequest;
|
|
DWORD _cRef;
|
|
HMODULE _hMod;
|
|
HANDLE _hPendingEvent;
|
|
|
|
// this variable should be "managed" internally
|
|
|
|
STR _strQuery;
|
|
STR _strPathInfo;
|
|
STR _strPathTranslated;
|
|
};
|
|
|
|
DWORD
|
|
InitializeBGI( VOID )
|
|
/*
|
|
Return Value:
|
|
|
|
0 on success, win32 error on failure
|
|
|
|
--*/
|
|
{
|
|
HKEY hkeyParam;
|
|
|
|
//
|
|
// Check to see if we should cache extensions
|
|
//
|
|
|
|
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
W3_PARAMETERS_KEY,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyParam ) == NO_ERROR )
|
|
{
|
|
fCacheExtensions = !!ReadRegistryDword( hkeyParam,
|
|
W3_CACHE_EXTENSIONS,
|
|
TRUE );
|
|
RegCloseKey( hkeyParam );
|
|
}
|
|
|
|
fExtInitialized = TRUE;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
BOOL
|
|
ProcessBGI(
|
|
IN SSI_REQUEST * pRequest,
|
|
IN STR * pstrDLL,
|
|
IN STR * pstrQueryString,
|
|
IN STR * pstrPathInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Synchronously executes ISAPI application.
|
|
|
|
Arguments:
|
|
|
|
pRequest - SSI_REQUEST utility structure
|
|
pstrDLL - ISAPI DLL to load
|
|
pstrQueryString - QueryString of #EXEC statement (or .STM query string)
|
|
pstrPathInfo - PathInfo of #EXEC statement (or .STM path info)
|
|
|
|
Return Value:
|
|
|
|
TRUE on success, FALSE on failure
|
|
|
|
--*/
|
|
{
|
|
BGI_INFO BGIInfo;
|
|
int iRet;
|
|
PFN_HTTPEXTENSIONPROC pfnSEProc;
|
|
BOOL bBGIRet = FALSE;
|
|
|
|
// Fill in some CGI variables before called ISA
|
|
|
|
if ( !BGIInfo._strQuery.Copy( pstrQueryString->QueryStr() ) ||
|
|
!BGIInfo._strPathInfo.Copy( pstrPathInfo->QueryStr() ) ||
|
|
!pRequest->LookupVirtualRoot( pstrPathInfo->QueryStr(),
|
|
&BGIInfo._strPathTranslated,
|
|
0 ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Create copy of ECB for ISA, instead of changing pointers, so that
|
|
// at anypoint, original ISAPI functionality is SSINC.DLL can be utilized
|
|
// without needing to continually revert back to original ECB.
|
|
|
|
memcpy( &(BGIInfo._ECB), pRequest->GetECB(), sizeof( BGIInfo._ECB ) );
|
|
BGIInfo._pRequest = pRequest;
|
|
BGIInfo._cRef = 2;
|
|
BGIInfo._hPendingEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
if ( BGIInfo._hPendingEvent == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
BGIInfo._ECB.ServerSupportFunction = SSIServerSupportFunction;
|
|
BGIInfo._ECB.GetServerVariable = SSIGetServerVariable;
|
|
BGIInfo._ECB.WriteClient = SSIWriteClient;
|
|
BGIInfo._ECB.ReadClient = SSIReadClient;
|
|
BGIInfo._ECB.ConnID = (HCONN) &BGIInfo;
|
|
BGIInfo._ECB.lpszQueryString = BGIInfo._strQuery.QueryStr();
|
|
BGIInfo._ECB.lpszPathInfo = BGIInfo._strPathInfo.QueryStr();
|
|
BGIInfo._ECB.lpszPathTranslated = BGIInfo._strPathTranslated.QueryStr();
|
|
|
|
// W3SVC entry point, loads the ISAPI DLL and caches extension
|
|
|
|
if ( !SEGetEntryPoint( pstrDLL->QueryStr(),
|
|
pRequest->GetUser(),
|
|
&pfnSEProc,
|
|
&(BGIInfo._hMod) ) )
|
|
{
|
|
LPCTSTR apszParms[ 2 ];
|
|
CHAR pszNumBuf[ SSI_MAX_NUMBER_STRING ];
|
|
_ultoa( GetLastError(), pszNumBuf, 10 );
|
|
apszParms[ 0 ] = pstrDLL->QueryStr();
|
|
apszParms[ 1 ] = pszNumBuf;
|
|
|
|
pRequest->SSISendError( SSINCMSG_CANT_LOAD_ISA_DLL,
|
|
apszParms );
|
|
|
|
TCP_REQUIRE( CloseHandle( BGIInfo._hPendingEvent ) );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Try not to let crappy ISA kill SSINC.DLL
|
|
|
|
__try
|
|
{
|
|
iRet = pfnSEProc( &(BGIInfo._ECB) );
|
|
}
|
|
__except ( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
iRet = HSE_STATUS_ERROR;
|
|
}
|
|
|
|
switch ( iRet )
|
|
{
|
|
case HSE_STATUS_PENDING:
|
|
|
|
// Need to run ISA synchronously. If it returns pending, we need
|
|
// to wait (indefinitely) for it to finish before we can move
|
|
// on to next SSI directive.
|
|
|
|
bBGIRet = TRUE;
|
|
if ( !InterlockedDecrement( (LONG*) &BGIInfo._cRef ) )
|
|
{
|
|
// Already received a ServerSupportFunction( HSE_REQ_DONE.. )
|
|
break;
|
|
}
|
|
// Wait for ISAPI app to ServerSupportFunction( HSE_REQ_DONE...)
|
|
WaitForSingleObject( BGIInfo._hPendingEvent, INFINITE );
|
|
break;
|
|
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
|
|
case HSE_STATUS_SUCCESS:
|
|
bBGIRet = TRUE;
|
|
break;
|
|
case HSE_STATUS_ERROR:
|
|
bBGIRet = FALSE;
|
|
break;
|
|
default:
|
|
bBGIRet = FALSE;
|
|
break;
|
|
}
|
|
if ( !fCacheExtensions )
|
|
{
|
|
PFN_TERMINATEEXTENSION pfnTerminate;
|
|
|
|
pfnTerminate = (PFN_TERMINATEEXTENSION) GetProcAddress(
|
|
BGIInfo._hMod,
|
|
SE_TERM_ENTRY );
|
|
|
|
if ( pfnTerminate )
|
|
{
|
|
pfnTerminate( HSE_TERM_MUST_UNLOAD );
|
|
}
|
|
|
|
TCP_REQUIRE( FreeLibrary( BGIInfo._hMod ) );
|
|
}
|
|
|
|
TCP_REQUIRE( CloseHandle( BGIInfo._hPendingEvent ) );
|
|
return bBGIRet;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIServerSupportFunction(
|
|
HCONN hConn,
|
|
DWORD dwHSERequest,
|
|
LPVOID pData,
|
|
LPDWORD lpdwSize,
|
|
LPDWORD lpdwDataType
|
|
)
|
|
{
|
|
BGI_INFO * pBGIInfo;
|
|
EXTENSION_CONTROL_BLOCK * pSSIECB;
|
|
SSI_REQUEST * pRequest;
|
|
BOOL fSuccess = TRUE;
|
|
|
|
pBGIInfo = (BGI_INFO*) hConn;
|
|
pRequest = pBGIInfo->_pRequest;
|
|
pSSIECB = pRequest->GetECB();
|
|
|
|
switch ( dwHSERequest )
|
|
{
|
|
case HSE_REQ_SEND_URL_REDIRECT_RESP:
|
|
{
|
|
// Redirect tried, don't do it, just send a message
|
|
|
|
LPCTSTR apszParms[ 1 ];
|
|
apszParms[ 0 ] = (CHAR*) pData;
|
|
|
|
pRequest->SSISendError( SSINCMSG_CGI_REDIRECT_RESPONSE,
|
|
apszParms );
|
|
break;
|
|
}
|
|
case HSE_REQ_SEND_URL:
|
|
case HSE_REQ_SEND_URL_EX:
|
|
|
|
// SendURL tries, don't do it, just send a message
|
|
|
|
LPCTSTR apszParms[ 1 ];
|
|
apszParms[ 0 ] = (CHAR*) pData;
|
|
|
|
pRequest->SSISendError( SSINCMSG_ISA_TRIED_SEND_URL,
|
|
apszParms );
|
|
break;
|
|
case HSE_REQ_DONE_WITH_SESSION:
|
|
|
|
// If main thread is waiting for ISA to finished, signal this
|
|
|
|
if ( !InterlockedDecrement( (LONG*) &(pBGIInfo->_cRef) ) )
|
|
{
|
|
SetEvent( pBGIInfo->_hPendingEvent );
|
|
}
|
|
break;
|
|
case HSE_REQ_SEND_RESPONSE_HEADER:
|
|
if ( lpdwDataType != NULL )
|
|
{
|
|
DWORD cbSent;
|
|
BYTE * pbTextToSend;
|
|
|
|
// only send the message to the client
|
|
// but don't send any header info contained in message
|
|
|
|
pbTextToSend = ScanForTerminator( (TCHAR*) lpdwDataType );
|
|
pbTextToSend = ( pbTextToSend == NULL ) ? (BYTE*)lpdwDataType
|
|
: pbTextToSend;
|
|
fSuccess = pRequest->WriteToClient( pbTextToSend,
|
|
strlen( (CHAR*) pbTextToSend ),
|
|
&cbSent );
|
|
}
|
|
break;
|
|
case HSE_REQ_TRANSMIT_FILE:
|
|
pRequest->SSISendError( SSINCMSG_SSF_NOT_SUPPORTED, NULL );
|
|
fSuccess = FALSE;
|
|
break;
|
|
case HSE_REQ_IO_COMPLETION:
|
|
pRequest->SSISendError( SSINCMSG_SSF_NOT_SUPPORTED, NULL );
|
|
fSuccess = FALSE;
|
|
break;
|
|
default:
|
|
fSuccess = pSSIECB->ServerSupportFunction( pSSIECB->ConnID,
|
|
dwHSERequest,
|
|
pData,
|
|
lpdwSize,
|
|
lpdwDataType );
|
|
}
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIGetServerVariable(
|
|
HCONN hConn,
|
|
LPSTR lpszVariableName,
|
|
LPVOID lpvBuffer,
|
|
LPDWORD lpdwSize
|
|
)
|
|
{
|
|
BGI_INFO * pBGIInfo;
|
|
EXTENSION_CONTROL_BLOCK * pSSIECB;
|
|
DWORD cbBytes;
|
|
|
|
pBGIInfo = (BGI_INFO*)hConn;
|
|
pSSIECB = pBGIInfo->_pRequest->GetECB();
|
|
|
|
// intercept GetServerVariable() for certain variables and return the
|
|
// appropriate string, otherwise, let ISAPI GetServerVariable()
|
|
// retrieve it.
|
|
|
|
if ( !strcmp( lpszVariableName, "QUERY_STRING" ) )
|
|
{
|
|
cbBytes = pBGIInfo->_strQuery.QueryCB() + sizeof( CHAR );
|
|
if ( *lpdwSize < cbBytes )
|
|
{
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
*lpdwSize = cbBytes;
|
|
return FALSE;
|
|
}
|
|
memcpy( lpvBuffer, pBGIInfo->_strQuery.QueryStr(), cbBytes );
|
|
return TRUE;
|
|
}
|
|
else if ( !strcmp( lpszVariableName, "PATH_INFO" ) )
|
|
{
|
|
cbBytes = pBGIInfo->_strPathInfo.QueryCB() + sizeof( CHAR );
|
|
if ( *lpdwSize < cbBytes )
|
|
{
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
*lpdwSize = cbBytes;
|
|
return FALSE;
|
|
}
|
|
memcpy( lpvBuffer, pBGIInfo->_strPathInfo.QueryStr(), cbBytes );
|
|
return TRUE;
|
|
}
|
|
else if ( !strcmp( lpszVariableName, "PATH_TRANSLATED" ) )
|
|
{
|
|
cbBytes = pBGIInfo->_strPathTranslated.QueryCB() + sizeof( CHAR );
|
|
if ( *lpdwSize < cbBytes )
|
|
{
|
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
|
*lpdwSize = cbBytes;
|
|
return FALSE;
|
|
}
|
|
memcpy( lpvBuffer, pBGIInfo->_strPathTranslated.QueryStr(), cbBytes );
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return pSSIECB->GetServerVariable( pSSIECB->ConnID,
|
|
lpszVariableName,
|
|
lpvBuffer,
|
|
lpdwSize );
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIWriteClient(
|
|
HCONN hConn,
|
|
LPVOID Buffer,
|
|
LPDWORD lpdwBytes,
|
|
DWORD dwReserved
|
|
)
|
|
{
|
|
if ( dwReserved == HSE_IO_ASYNC )
|
|
{
|
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
EXTENSION_CONTROL_BLOCK * pSSIECB;
|
|
pSSIECB = ((BGI_INFO*)hConn)->_pRequest->GetECB();
|
|
|
|
return pSSIECB->WriteClient( pSSIECB->ConnID,
|
|
Buffer,
|
|
lpdwBytes,
|
|
dwReserved );
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SSIReadClient(
|
|
HCONN hConn,
|
|
LPVOID Buffer,
|
|
LPDWORD lpdwBytes
|
|
)
|
|
{
|
|
EXTENSION_CONTROL_BLOCK * pSSIECB;
|
|
EXTENSION_CONTROL_BLOCK * pBGIECB;
|
|
|
|
pBGIECB = &(((BGI_INFO*)hConn)->_ECB);
|
|
pSSIECB = ((BGI_INFO*)hConn)->_pRequest->GetECB();
|
|
|
|
if ( pSSIECB->ReadClient( pSSIECB->ConnID,
|
|
Buffer,
|
|
lpdwBytes ) )
|
|
{
|
|
pBGIECB->cbTotalBytes -= *lpdwBytes;
|
|
pBGIECB->cbAvailable -= *lpdwBytes;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|