// ScriptPlugin.cpp : Implementation of cScriptPlugin #include "stdafx.h" #include "PlainText.h" #include "ScriptPlugin.h" #include "../Inject/Inject.h" #include "ScriptView.h" ///////////////////////////////////////////////////////////////////////////// // cScriptPlugin void cScriptPlugin::getCLSID( BSTR *pbstrCLSID ) { MSXML::IXMLDOMAttributePtr pAttr = m_pPlugin->selectSingleNode( _T( "/plugin/@clsid" ) ); _ASSERTE( pAttr.GetInterfacePtr() != NULL ); *pbstrCLSID = OLE2BSTR( pAttr->value.bstrVal ); } void cScriptPlugin::getLanguage( BSTR *pbstrLanguage ) { MSXML::IXMLDOMAttributePtr pAttr = m_pPlugin->selectSingleNode( _T( "/plugin/@language" ) ); if( pAttr.GetInterfacePtr() == NULL ) *pbstrLanguage = T2BSTR( _T( "VBScript" ) ); else *pbstrLanguage = OLE2BSTR( pAttr->value.bstrVal ); } HRESULT cScriptPlugin::LoadScript(BSTR strFilename) { USES_CONVERSION; HRESULT hRes = ::CoCreateInstance( __uuidof( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER, __uuidof( MSXML::IXMLDOMDocument ), reinterpret_cast< void ** >( &m_pPlugin ) ); if( FAILED( hRes ) ) return hRes; bool bLoad = !!m_pPlugin->load( strFilename ); if( !bLoad ) { // The document failed to load, get the error info for posterity MSXML::IXMLDOMParseErrorPtr pErr = m_pPlugin->parseError; long nCode = pErr->errorCode; long nFilePos = pErr->filepos; long nLine = pErr->line; long nLinePos = pErr->linepos; _bstr_t strReason = pErr->reason; _bstr_t strText = pErr->srcText; TCHAR szError[ 1024 ]; ::_stprintf( szError, _T( "0x%08X (%i, %i): %s" ), nCode, nLine, nLinePos, OLE2T( strReason ) ); ::MessageBox( NULL, szError, _T( "XML Parse Error" ), MB_ICONERROR | MB_OK ); // Give the user a chance to break and look at this lovely info _ASSERTE( FALSE ); return E_FAIL; } // Looking good return S_OK; } STDMETHODIMP cScriptPlugin::CreateInstance(IDecalEnum *pInitData, REFIID iid, LPVOID *pObject) { CComVariant vFile; HRESULT hRes = pInitData->get_Property( _bstr_t( "File" ), &vFile ); if( FAILED( hRes ) ) return hRes; if( vFile.vt != VT_BSTR ) return E_FAIL; m_strFilename = vFile.bstrVal; return static_cast< IDecalSurrogate * >( this )->QueryInterface( iid, pObject ); } STDMETHODIMP cScriptPlugin::Initialize( IPluginSite2 *pSite ) { USES_CONVERSION; m_pSite = pSite; // First, map the map and load the script file CComPtr< IDecal > pDecal; m_pSite->get_Decal( &pDecal ); CComBSTR strTruePath; HRESULT hRes = pDecal->MapPath( m_strFilename, &strTruePath ); if( FAILED( hRes ) ) return hRes; hRes = LoadScript( strTruePath ); if( FAILED( hRes ) ) return hRes; // Set up the scripting environment, the default scripting language // is VBScript CComBSTR strScript; getLanguage( &strScript ); hRes = createScriptEngine( strScript ); _ASSERTE( SUCCEEDED( hRes ) ); // Load the script text CComPtr< IActiveScriptParse > pParse; m_pScript->QueryInterface( &pParse ); pParse->InitNew(); addNamedItem( _bstr_t( _T( "Site" ) ), static_cast< IDispatch * >( this ) ); MSXML::IXMLDOMElementPtr pScript = m_pPlugin->selectSingleNode( _T( "/plugin/script" ) ); // Load the main script block if( pScript.GetInterfacePtr() != NULL ) { EXCEPINFO ei; HRESULT hRes = pParse->ParseScriptText( pScript->text, NULL, NULL, NULL, 0, 0, SCRIPTITEM_ISVISIBLE, NULL, &ei ); _ASSERTE( SUCCEEDED( hRes ) ); } else { ::MessageBox(NULL, "Couldn't load the main script block", "cScriptPlugin::Initialize", MB_OK); } // Walk through the intrinsic object MSXML::IXMLDOMNodeListPtr pNetworks = m_pPlugin->selectNodes( _T( "/plugin/decal" ) ); for( MSXML::IXMLDOMElementPtr pNetwork = pNetworks->nextNode(); pNetwork.GetInterfacePtr() != NULL; pNetwork = pNetworks->nextNode() ) { CComPtr< IDispatch > pObject; HRESULT hRes = pDecal->get_Object( pNetwork->getAttribute( _T( "path" ) ).bstrVal, IID_IDispatch, reinterpret_cast< void ** >( &pObject ) ); if( FAILED( hRes ) ) { ::MessageBox(NULL, "SCRIPT ERROR: Couldn't load decal object", OLE2A(pNetwork->getAttribute(_T("path")).bstrVal), MB_OK); continue; } // Add the item addNamedItem( pNetwork->getAttribute( _T( "name" ) ).bstrVal, pObject ); } // Walk through the instance objects MSXML::IXMLDOMNodeListPtr pObjects = m_pPlugin->selectNodes( _T( "/plugin/object" ) ); for( MSXML::IXMLDOMElementPtr pObject = pObjects->nextNode(); pObject.GetInterfacePtr() != NULL; pObject = pObjects->nextNode() ) { _variant_t vProgid = pObject->getAttribute( _T( "progid" ) ); if( vProgid.vt == VT_NULL ) { _ASSERT( FALSE ); continue; } CComPtr< IDispatch > pInstance; CLSID clsid; HRESULT hRes = ::CLSIDFromProgID( vProgid.bstrVal, &clsid ); if( FAILED( hRes ) ) { _ASSERT( FALSE ); continue; } hRes = ::CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, reinterpret_cast< void ** >( &pInstance ) ); if( FAILED( hRes ) ) { _ASSERT( FALSE ); continue; } // Add the item addNamedItem( pObject->getAttribute( _T( "name" ) ).bstrVal, pInstance ); } // Start up the plugin m_pScript->SetScriptState(SCRIPTSTATE_CONNECTED); Fire_Initialize(); return S_OK; } STDMETHODIMP cScriptPlugin::Terminate() { // Shut down the plugin Fire_Terminate(); m_pScript->SetScriptState( SCRIPTSTATE_DISCONNECTED ); m_pScript->Close(); m_pSite.Release(); m_pPlugin.Release(); return S_OK; } STDMETHODIMP cScriptPlugin::CreateObject( BSTR strProgID, LPDISPATCH *pDisp ) { if( pDisp == NULL ) { _ASSERT( FALSE ); return E_POINTER; } HRESULT hRes; CLSID clsid; if( strProgID[ 0 ] == OLESTR( '{' ) ) hRes = ::CLSIDFromString( strProgID, &clsid ); else hRes = ::CLSIDFromProgID( strProgID, &clsid ); if( FAILED( hRes ) ) return hRes; return ::CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, reinterpret_cast< void ** >( pDisp ) ); } STDMETHODIMP cScriptPlugin::WriteToChatWindow(BSTR szText, long lColor) { getPluginSite()->WriteToChatWindow(szText, lColor); return S_OK; } STDMETHODIMP cScriptPlugin::MessageBox(BSTR Title, BSTR Text) { USES_CONVERSION; ::MessageBox(NULL, OLE2A(Text), OLE2A(Title), MB_OK); return S_OK; } IPluginSite * cScriptPlugin::getPluginSite() { CComPtr< IDecal > pDecal; m_pSite->get_Decal ( &pDecal ); CComPtr< IInjectService > pInject; CComPtr< IPluginSite > pSite; HRESULT hRes = pDecal->get_Object ( _bstr_t ( _T( "services\\DecalPlugins.InjectService" ) ), __uuidof ( IInjectService ), reinterpret_cast< LPVOID * > ( &pInject ) ); pInject->get_Site(&pSite); return pSite; } STDMETHODIMP cScriptPlugin::LoadView(BSTR Text, IView **pView) { getPluginSite()->LoadView(Text, pView); return S_OK; } void cScriptPlugin::removeView( CScriptView *pView ) { for( cViewList::iterator i = m_views.begin(); i != m_views.end(); ++ i ) { if( *i == pView ) { m_views.erase( i ); return; } } // The view was not found in the list _ASSERTE( FALSE ); } void cScriptPlugin::postRemoveView( CScriptView *pView ) { m_destroy.push_back( pView ); } STDMETHODIMP cScriptPlugin::CreateView(BSTR strTemplateName, LPDISPATCH *ppNewView) { USES_CONVERSION; TCHAR szQuery[ 255 ]; ::_stprintf( szQuery, _T( "/plugin/view[@name='%s']" ), OLE2T( strTemplateName ) ); MSXML::IXMLDOMElementPtr pView = m_pPlugin->selectSingleNode( szQuery ); if( pView.GetInterfacePtr() == NULL ) return E_INVALIDARG; CComObject< CScriptView > *pNewView; CComObject< CScriptView >::CreateInstance( &pNewView ); CComPtr< IDispatch > pDispPlugin; m_pScript->GetScriptDispatch( NULL, &pDispPlugin ); CComBSTR strLanguage; getLanguage( &strLanguage ); pNewView->loadView( this, pView, ppNewView ); return S_OK; }