windows-nt/Source/XPSP1/NT/inetsrv/iis/staxinc/esh.cpp
2020-09-26 16:20:57 +08:00

400 lines
8.6 KiB
C++

// esh.cpp: implementation of the CEventScriptHandler class.
//
//////////////////////////////////////////////////////////////////////
//#include "stdafx.h"
#include <esh.h>
#include <scripto.h>
#include <pbag.h>
#include <stags.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CEventScriptHandler::CEventScriptHandler()
{
m_cNamedProps = 0;
m_pScripto = NULL;
m_pBag = new CPropBag;
VariantInit(&m_varErrorResponse);
VariantInit(&m_varScriptResponse);
}
CEventScriptHandler::~CEventScriptHandler()
{
if( m_pBag != NULL )
m_pBag->Release();
if( m_pScripto != NULL )
m_pScripto->Release();
}
STDMETHODIMP CEventScriptHandler::SetScript(BSTR bstrFileName)
{
HRESULT hr = NOERROR;
HANDLE hFile = INVALID_HANDLE_VALUE;
CStreamFile* pstmFile = NULL;
if( bstrFileName == NULL )
return E_POINTER;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
hFile = CreateFileW(bstrFileName,GENERIC_READ,FILE_SHARE_READ,NULL,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if( hFile == INVALID_HANDLE_VALUE )
{
hr = HRGetLastError();
goto exit;
}
pstmFile = new CStreamFile(hFile,TRUE);
if( pstmFile == NULL )
{
CloseHandle(hFile);
hr = E_OUTOFMEMORY;
goto exit;
}
hr = SetScript((IStream*)pstmFile);
exit:
if( pstmFile != NULL )
pstmFile->Release();
return hr;
}
STDMETHODIMP CEventScriptHandler::SetScript(IStream * pstmScript)
{
HRESULT hr = NOERROR;
VARIANT var;
IUnknown* pUnk = NULL;
if( pstmScript == NULL )
return E_POINTER;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
hr = pstmScript->QueryInterface(IID_IUnknown,(void**)&pUnk);
if(FAILED(hr))
goto exit;
// put the script stream into the bag
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = (IUnknown*)pUnk;
hr = m_pBag->Write(wszScriptTextProp, &var);
VariantClear(&var);
exit:
return hr;
}
STDMETHODIMP CEventScriptHandler::AddGlobalVariable(BSTR bstrName, VARIANT varVariable)
{
HRESULT hr = NOERROR;
WCHAR wszBagProp[64] = {0};
VARIANT var;
if( bstrName == NULL )
return E_POINTER;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
VariantInit(&var);
m_cNamedProps++;
// add the name
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = SysAllocString(bstrName);
wsprintfW(wszBagProp, L"%ls%ld", wszNamedPropIDPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &var);
VariantClear(&var);
if(FAILED(hr))
goto exit;
// add the value
wsprintfW(wszBagProp, L"%ls%ld", wszNamedUnkPtrPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &varVariable);
if(FAILED(hr))
goto exit;
// not a NamedSource (for connection points)
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = VARIANT_FALSE;
wsprintfW(wszBagProp, L"%ls%ld", wszNamedSourcesPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &var);
if(FAILED(hr))
goto exit;
exit:
return hr;
}
STDMETHODIMP CEventScriptHandler::AddConnectionPoint(BSTR bstrName, IConnectionPointContainer * pContainer)
{
HRESULT hr = NOERROR;
WCHAR wszBagProp[64] = {0};
VARIANT var;
if( bstrName == NULL || pContainer == NULL )
return E_POINTER;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
VariantInit(&var);
m_cNamedProps++;
// add the name
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = SysAllocString(bstrName);
wsprintfW(wszBagProp, L"%ls%ld", wszNamedPropIDPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &var);
VariantClear(&var);
if(FAILED(hr))
goto exit;
// add the value as IUnknown*
V_VT(&var) = VT_UNKNOWN;
hr = pContainer->QueryInterface(IID_IUnknown, (void**)&V_UNKNOWN(&var));
if(FAILED(hr))
goto exit;
wsprintfW(wszBagProp, L"%ls%ld", wszNamedUnkPtrPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &var);
VariantClear(&var);
if(FAILED(hr))
goto exit;
// the object is a NamedSource, so we will connect to
// script functions that look like <Object>_xxx
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = VARIANT_TRUE;
wsprintfW(wszBagProp, L"%ls%ld", wszNamedSourcesPrefix, m_cNamedProps);
hr = m_pBag->Write(wszBagProp, &var);
if(FAILED(hr))
goto exit;
exit:
return hr;
}
STDMETHODIMP CEventScriptHandler::ASPSyntax(BOOL fIsASPSyntax)
{
HRESULT hr = NOERROR;
VARIANT var;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = fIsASPSyntax ? VARIANT_TRUE : VARIANT_FALSE ;
hr = m_pBag->Write(wszASPSyntaxProp, &var);
return hr;
}
STDMETHODIMP CEventScriptHandler::AllowCreateObject(BOOL fCreateObjectAllowed)
{
HRESULT hr = NOERROR;
VARIANT var;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
V_VT(&var) = VT_BOOL;
V_BOOL(&var) = fCreateObjectAllowed ? VARIANT_TRUE : VARIANT_FALSE ;
hr = m_pBag->Write(wszEnableCreateObjects, &var);
return hr;
}
STDMETHODIMP CEventScriptHandler::MaxExecutionTime(DWORD dwMaxExecutionTime)
{
HRESULT hr = NOERROR;
VARIANT var;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
V_VT(&var) = VT_UI4;
V_UI4(&var) = dwMaxExecutionTime;
hr = m_pBag->Write(wszMaxExecutionTimeProp, &var);
return hr;
}
STDMETHODIMP CEventScriptHandler::StartScript()
{
HRESULT hr = NOERROR;
VARIANT var;
if( m_pBag == NULL )
return E_OUTOFMEMORY;
if( m_pScripto != NULL )
return RestartScript();
// write the number of named props to pBag
V_VT(&var) = VT_UI4;
V_UI4(&var) = m_cNamedProps;
hr = m_pBag->Write(wszNumNamedPropsProp, &var);
if(FAILED(hr))
goto exit;
// create the scripto object
hr = CoCreateInstance(CLSID_Scripto, NULL, CLSCTX_INPROC_SERVER, IID_IScripto, (void**)&m_pScripto);
if(FAILED(hr))
goto exit;
// init the script
hr = m_pScripto->InitScript(m_pBag);
if( FAILED(hr) )
{
VariantClear(&m_varErrorResponse);
m_pBag->Read(wszErrorResponse, &m_varErrorResponse, NULL);
}
else
{
VariantClear(&m_varScriptResponse);
m_pBag->Read(wszScriptResponse, &m_varScriptResponse, NULL);
}
exit:
return hr;
}
STDMETHODIMP CEventScriptHandler::RestartScript()
{
HRESULT hr = NOERROR;
if( m_pScripto == NULL )
return E_OUTOFMEMORY;
if( !m_fScriptStopped )
StopScript();
hr = m_pScripto->ReInitScript(NULL);
return hr;
}
STDMETHODIMP CEventScriptHandler::StopScript()
{
HRESULT hr = NOERROR;
if( m_pScripto == NULL )
return E_OUTOFMEMORY;
hr = m_pScripto->DeActivateScript(FALSE);
m_fScriptStopped = TRUE;
return hr;
}
STDMETHODIMP CEventScriptHandler::ExecuteConnectionPoint(IConnectionPoint* pConnectionPoint, DISPID dispid)
{
HRESULT hr = NOERROR;
IEnumConnections* pConnections = NULL;
CONNECTDATA ConnectData = {0};
LPDISPATCH pConnection = NULL;
DWORD cConnections = 0;
DISPPARAMS NoArgs = {NULL, NULL, 0, 0};
bool fGotOne = false;
if( pConnectionPoint == NULL )
return E_POINTER;
if( m_pScripto == NULL )
return E_OUTOFMEMORY;
// find out if the script has any connections for this event
hr = pConnectionPoint->EnumConnections(&pConnections);
if(hr == S_FALSE)
{
// No connection points.
hr = DISP_E_UNKNOWNNAME;
goto exit;
}
else if( FAILED(hr) )
goto exit;
hr = pConnections->Reset();
if( FAILED(hr) )
goto exit;
// loop through each connection and execute its associated code
do
{
hr = pConnections->Next(1, &ConnectData, &cConnections);
if(SUCCEEDED(hr))
{
if(cConnections)
{
hr = ConnectData.pUnk->QueryInterface(IID_IDispatch, (void**)&pConnection);
if(SUCCEEDED(hr))
{
// try to invoke - this may fail non-fatally
hr = pConnection->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &NoArgs, NULL, NULL, NULL);
if(hr != DISP_E_UNKNOWNNAME)
{
// we at least got one connection point
fGotOne = true;
if( FAILED(hr) )
{
// event execution failed
VariantClear(&m_varErrorResponse);
m_pBag->Read(wszErrorResponse, &m_varErrorResponse, NULL);
m_pScripto->Abort();
}
else
{
VariantClear(&m_varScriptResponse);
m_pBag->Read(wszScriptResponse, &m_varScriptResponse, NULL);
m_pScripto->Complete();
}
}
pConnection->Release();
pConnection = NULL;
}
ConnectData.pUnk->Release();
ConnectData.pUnk = NULL;
}
else
{
// means we are done - no more connections
// if we got at least one to work then we consider it
// a success
hr = fGotOne ? S_OK : DISP_E_UNKNOWNNAME;
}
}
}
while(SUCCEEDED(hr) && cConnections);
// tell scripto whether we are happy campers or not
if(SUCCEEDED(hr))
{
m_pScripto->Complete();
}
else
{
m_pScripto->Abort();
}
// must leave scripto in the deactived state so that it can be
// called again on another thread
m_pScripto->DeActivateScript(false);
exit:
if( pConnections )
pConnections->Release();
return hr;
}