/
MadDAD
/
alterplast
Обзор
Документация
Войти
/
MadDAD
/
alterplast
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
openconf_src/Scripting.cpp
568 строк
16 KB
trdm
24 мар 2017, 13:27
24 мар 2017, 13:27
886e846
Код
Авторство
О чём код?
// Scripting.cpp: implementation of the CScripting class. #include "stdafx.h" #include "configsvcimpl.h" #include "Scripting.h" #include "Scriptmaneger.h" #include "initguid.h" #include "iconfig.h" #include "OCView.h" #include "IdleHandler.h" #include "ItemScript.h" #include "iselfscript.h" #include "tlibversion.h" CScripting* CScripting::m_pActiveScript=NULL; CMapStringToString CScripting::m_mapEngineNames; CScripting::CScripting() { m_dwRef=1; m_pEngine=NULL; m_pDebugDocumentHelper=NULL; m_EnterCount=0; m_DelayUnReload=0; m_pViewItem=NULL; m_pSelf=new CISelfScript; m_pSelf->m_pScript=this; } CScripting::~CScripting() { if(m_pEngine!=NULL) { m_pEngine->SetScriptState(SCRIPTSTATE_CLOSED); m_pEngine=NULL; } if(m_pDebugDocumentHelper) { m_pDebugDocumentHelper->Detach(); m_pDebugDocumentHelper->Release(); m_pDebugDocumentHelper=NULL; } m_pSelf->Release(); } STDMETHODIMP CScripting::OnStateChange(SCRIPTSTATE ssScriptState) { return S_OK; } static void ScriptIdleProc() { CPtrArray& DelayUnReloadScripts=CScriptManager::GetScriptManager()->m_Delayed; long count=DelayUnReloadScripts.GetSize(); for(int i=0;i<count;i++) { CScripting* pScript=(CScripting*)DelayUnReloadScripts[i]; if(pScript) { if(pScript->m_DelayUnReload==1) { pScript->Unload(); pScript->Release(); } else if(pScript->m_DelayUnReload==2) pScript->ReloadScript(); } } DelayUnReloadScripts.RemoveAll(); CIdleHandler::RemoveIdleHandler(ScriptIdleProc); } STDMETHODIMP CScripting::OnLeaveScript(void) { m_pActiveScript=NULL; if(!--m_EnterCount) { if(m_DelayUnReload) CIdleHandler::SetIdleHandler(ScriptIdleProc); } return S_OK; } int CScripting::ReportError(IActiveScriptError *pse,bool bDebug) { EXCEPINFO ei; BSTR bstrLine = NULL; HRESULT hr; DWORD ctx; ULONG lineNum; LONG posNum; hr=pse->GetSourceLineText(&bstrLine); pse->GetSourcePosition(&ctx,&lineNum,&posNum); CString line(bstrLine); ::SysFreeString(bstrLine); pse->GetExceptionInfo(&ei); CString source(ei.bstrSource); CString descr(ei.bstrDescription); CString msg; msg.Format("������ ���������� �������.\n" "������: %s\n" "����: %s\n" "������: %i\n" "�������: %i\n" "���: %i\n" "��������: %s\n" "��������: %s", m_ScriptName,m_FileName,lineNum,posNum,ei.wCode,source,descr); if(!line.IsEmpty()) msg=msg+"\n�������� ���: "+line; UINT mbType=MB_OK; if(bDebug) { msg+="\n��������� �������� ��������?"; mbType=MB_YESNO; } return AfxMessageBox(msg,mbType); } STDMETHODIMP CScripting::OnScriptError(IActiveScriptError *pse) { ReportError(pse); return S_OK; } bool CScripting::LoadScript(const CString file) { CString FileText; // Open file try{ CFile f(file,CFile::modeRead|CFile::shareDenyWrite); int len=f.GetLength(); f.Read(FileText.GetBufferSetLength(len),len); FileText.ReleaseBuffer(); }catch(CFileException* pEx) { char buf[1024]; pEx->GetErrorMessage(buf,1024); pEx->Delete(); DoMsgLine("������ �������� �������\r\n%s\r\n%s (%i)",mmRedErr,file,buf,pEx->m_lOsError); return false; } m_FileName=file; // Find Name of Scripting Engine LPCTSTR pStartText=FileText; ExtractEngineAndName(pStartText,m_EngineName,m_ScriptName); if(m_EngineName.IsEmpty()) { DoMsgLine("������ %s\r\n�� ������� �������� ��� ����������� ������.",mmRedErr,m_FileName); return false; } if(m_ScriptName.IsEmpty()) { DoMsgLine("������ %s\r\n�� ������� �������� ��� �������",mmRedErr,m_FileName); return false; } // Create Engine if(!CreateScript(pStartText)) return false; return true; } bool CScripting::Unload() { if(m_pEngine!=NULL) { try{ if(m_EnterCount) { m_pEngine->SetScriptState(SCRIPTSTATE_DISCONNECTED); m_DelayUnReload=1; return false; } m_pEngine->SetScriptState(SCRIPTSTATE_CLOSED); m_pEngine=NULL; } catch(_com_error err) { DoMsgLine(err.ErrorMessage()); } catch(...) { DoMsgLine("Error Unload Script"); } } return true; } STDMETHODIMP CScripting::GetItemInfo(LPCOLESTR pstrName,DWORD dwReturnMask, IUnknown** ppunkItemOut,ITypeInfo** pptinfoOut) { return CScriptManager::GetScriptManager()->GetItemInfo(this,pstrName,dwReturnMask, ppunkItemOut,pptinfoOut); } /* STDMETHODIMP CScripting::GetDocVersionString(BSTR *pbstrVersion) { return E_NOTIMPL; // UNDONE: Implement this method } STDMETHODIMP CScripting::OnScriptTerminate (const VARIANT *pvarResult,const EXCEPINFO *pexcepinfo) { return S_OK; } STDMETHODIMP CScripting::OnStateChange(SCRIPTSTATE ssScriptState) { // Don't care about notification return S_OK; } STDMETHODIMP CScripting::OnEnterScript(void) { return S_OK; } STDMETHODIMP CScripting::OnLeaveScript(void) { return S_OK; } */ bool CScripting::CreateScript(LPCTSTR text) { //tracing purposes only HRESULT hr = S_OK; //Now we need to set up for Smart Debugging. First, we need a Process Debug //Manager. bool IsDebugInit=false; CScriptManager* pSM=CScriptManager::GetScriptManager(); if(pSM->m_pProcDebugManager) { //Create a new DebugDocumentHelper to use with the script added by the //simple host. if(m_pDebugDocumentHelper) { m_pDebugDocumentHelper->Detach(); m_pDebugDocumentHelper->Release(); m_pDebugDocumentHelper=NULL; } hr=pSM->m_pProcDebugManager->CreateDebugDocumentHelper(NULL, &m_pDebugDocumentHelper); if(hr==S_OK) { //Initialize the DebugDocumentHelper so it's ready to handle the script. hr=m_pDebugDocumentHelper->Init(pSM->m_pDebugApplication, _bstr_t(m_ScriptName),_bstr_t(m_FileName),TEXT_DOC_ATTR_READONLY); if(hr==S_OK) { //Attach our DebugDocumentHelper to the debugger application. The NULL //parameter indicates that the DebugDocumentHelper should be at the root //of the debug tree. IsDebugInit=(m_pDebugDocumentHelper->Attach(NULL)==S_OK); } } } if(!IsDebugInit) { if(m_pDebugDocumentHelper) { m_pDebugDocumentHelper->Detach(); m_pDebugDocumentHelper->Release(); m_pDebugDocumentHelper=NULL; } } try{ hr=m_pEngine.CreateInstance(m_EngineName,NULL,CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER); if(hr) { DoMsgLine("������ %s\r\n�� ������� ������� ��������� ����������� ������ %s\r\n%s", mmRedErr,m_FileName,m_EngineName,GetErrorDescription(hr)); return false; } // Script Engine must support IActiveScriptParse for us to use it IActiveScriptParsePtr pParse=m_pEngine; if(pParse==NULL) { DoMsgLine("������ %s\r\n������ ������� %s �� ������������ �������� ������.",mmRedErr,m_FileName,m_EngineName); return false; } bool IsInit=true; hr=pParse->InitNew(); if(hr) IsInit=false; if(IsInit) { hr=m_pEngine->SetScriptSite(this); if(hr) IsInit=false; } //_bstr_t bstrName=m_ScriptName; //hr=m_pEngine->AddNamedItem(bstrName,SCRIPTITEM_ISVISIBLE|SCRIPTITEM_CODEONLY|SCRIPTITEM_GLOBALMEMBERS); if(IsInit) { hr=m_pEngine->AddTypeLib(LIBID_OpenConf,TLIB_MAJOR,TLIB_MINOR,0); if(hr) IsInit=false; } if(IsInit) { _bstr_t bstrSrc=text; hr=pParse->ParseScriptText(bstrSrc,NULL,NULL,NULL,0,0,SCRIPTTEXT_ISVISIBLE,NULL,NULL); if(hr) IsInit=false; } if(!IsInit) { DoMsgLine("������ %s\r\n�� ������� ���������������� ������ �������.",mmRedErr,m_FileName); return false; } }catch(_com_error err) { MessageBox(NULL,err.ErrorMessage(),"OpenConf",MB_ICONERROR); return false; } return true; } bool CScripting::ExtractEngineAndName(LPCTSTR& text,CString& EngineName,CString& ScriptName) { LPCTSTR pStartText=text; LPCTSTR pEngPos=strstr(pStartText,"$ENGINE"); if(pEngPos==text) { pEngPos=strstr(text,"\r"); EngineName=CString(text+8,pEngPos-text-8); text=pEngPos+2; } if(EngineName.IsEmpty()) { int lastdec=m_FileName.ReverseFind('.'); if(lastdec!=-1) { CString ext=m_FileName.Mid(lastdec); ext.MakeLower(); if(!m_mapEngineNames.Lookup(ext,m_EngineName)) { HKEY hKey; if(RegOpenKeyEx(HKEY_CLASSES_ROOT,ext,0,KEY_READ,&hKey)==ERROR_SUCCESS) { char type[MAX_PATH]; DWORD size=MAX_PATH; if(RegQueryValueEx(hKey,NULL,0,NULL,(BYTE*)type,&size)==ERROR_SUCCESS) { strcat(type,"\\ScriptEngine"); HKEY hSubKey; if(RegOpenKeyEx(HKEY_CLASSES_ROOT,type,0,KEY_READ,&hSubKey)==ERROR_SUCCESS) { size=MAX_PATH; if(RegQueryValueEx(hSubKey,NULL,0,NULL,(BYTE*)type,&size)==ERROR_SUCCESS) EngineName=type; RegCloseKey(hSubKey); } } RegCloseKey(hKey); } if(!EngineName.IsEmpty()) m_mapEngineNames[ext]=EngineName; } else EngineName=m_mapEngineNames[ext]; } if(EngineName.IsEmpty()) { DoMsgLine("������ %s\r\n�� ������� �������� ��� ����������� ������.",mmRedErr,m_FileName); return false; } } // Find Script Name LPCTSTR pNameScript=strstr(text,"$NAME"); if(pNameScript==text) { pNameScript=strstr(text,"\r"); ScriptName=CString(text+6,pNameScript-text-6); text=pNameScript+2; } else { LPCTSTR pDecPos=NULL; int lastdec=m_FileName.ReverseFind('.'); if(lastdec!=-1) pDecPos=LPCTSTR(m_FileName)+lastdec-1; if(!pDecPos) pDecPos=(LPCTSTR)m_FileName+m_FileName.GetLength()-1; while(*pDecPos!='\\') ScriptName.Insert(0,*pDecPos--); } return true; } LPCTSTR CScripting::GetCurrentState() { static const char* states[]={ "�� ���������������", "��������", "��������", "����������", "������", "���������������" }; SCRIPTSTATE st; m_pEngine->GetScriptState(&st); return states[st]; } bool CScripting::ReloadScript() { if(m_EnterCount) { m_DelayUnReload=2; CScriptManager::GetScriptManager()->AddDelayed(this); return false; } DoStsLine("�������� ������� %s ...",m_FileName); CString FileText; // Open file try{ CFile f(m_FileName,CFile::modeRead); int len=f.GetLength(); f.Read(FileText.GetBufferSetLength(len),len); FileText.ReleaseBuffer(); }catch(CFileException* pEx) { char buf[1024]; pEx->GetErrorMessage(buf,1024); pEx->Delete(); DoMsgLine("������ �������� �����\r\n%s\r\n%s (%i)",mmRedErr,m_FileName,buf,pEx->m_lOsError); return false; } Unload(); // ��������� ������� ������ m_pSelf->ResetAdded(); CString name,engine; LPCTSTR pRead=FileText; ExtractEngineAndName(pRead,engine,name); // ��� ������������ ��� ������� � ������ �� ���������� bool ret=CreateScript(pRead); if(ret) CScriptManager::GetScriptManager()->ConnectScript(this); DoStsLine(""); m_DelayUnReload=0; if(m_pViewItem) m_pViewItem->FillMacros(); return ret; } /****************************************************************************** * GetDocumentContextFromPosition -- Used by the language engine to delegate * IDebugCodeContext::GetSourceContext and get the IDebugDocumentContext * associated with a position. * Parameters: dwSourceContext -- Host defined cookie which was passed to * IActiveScriptParse::ParseScriptText or * IActiveScriptParse::AddScriptlet when the * text the engine is interested in was added. * uCharacterOffset -- Offset from the beginning of the script * block * uNumChars -- Length of the script block * ppsc -- Address of the IDebugDocumentContext reference to be * returned by this method * Returns: S_OK * E_INVALIDARG * E_POINTER * E_FALI ******************************************************************************/ STDMETHODIMP CScripting::GetDocumentContextFromPosition( DWORD dwSourceContext, ULONG uCharacterOffset, ULONG uNumChars, IDebugDocumentContext **ppsc) { HRESULT hr = E_FAIL; //Use the IDebugDocumentHelper for this CScripting to delegate this //call if(m_pDebugDocumentHelper) { ULONG ulStartPos; //Find out where this source context starts. hr = m_pDebugDocumentHelper->GetScriptBlockInfo(dwSourceContext,NULL, &ulStartPos,NULL); //If that succeeded, then create an IDebugDocumentContext if(SUCCEEDED(hr)) { hr=m_pDebugDocumentHelper->CreateDebugDocumentContext( ulStartPos+uCharacterOffset,uNumChars,ppsc); } } return hr; } /****************************************************************************** * GetApplication -- Returns the debug application object associated with this * script site. Provides a means for a smart host to define what application * object each script belongs to. Script engines should attempt to call this * method to get their containing application and resort to * IProcessDebugManager::GetDefaultApplication if this fails. * * Parameters: ppda -- Address of the IDebugApplication pointer which this * method should fill. * Returns: S_OK * E_POINTER * E_FAIL ******************************************************************************/ STDMETHODIMP CScripting::GetApplication(IDebugApplication **ppda) { HRESULT hr=E_FAIL; //if we were successful in creating an IDebugApplication in Initialize, //then return it here. if(CScriptManager::GetScriptManager()->m_pDebugApplication) { hr=CScriptManager::GetScriptManager()->m_pDebugApplication->QueryInterface( IID_IDebugApplication,(void**)ppda); } return hr; } /****************************************************************************** * GetRootApplicationNode -- Gets the application node under which script * documents should be added. This method can return NULL if script documents * should be top-level. * Parameters: ppdanRoot -- Address of the IDebugApplicationNode pointer which * this method should fill * Returns: S_OK * E_POINTER * E_FAIL ******************************************************************************/ STDMETHODIMP CScripting::GetRootApplicationNode( IDebugApplicationNode **ppdanRoot) { HRESULT hr=E_FAIL; //If we were successful in creating an IDebugApplication in Initialize, //then call GetRootNode on it here. if(m_pDebugDocumentHelper) { hr=m_pDebugDocumentHelper->GetDebugApplicationNode(ppdanRoot); //hr=m_pDebugApplication->GetRootNode(ppdanRoot); } return hr; } /****************************************************************************** * OnScriptErrorDebug -- Allows a smart host to control the handling of runtime * errors. * Parameters: pErrorDebug -- the runtime error that occurred * pfEnterDebugger -- whether to pass the error to the debugger to * do JIT debugging * pfCallOnScriptErrorWhenContinuing -- whether to call * IActiveScriptSite::OnScriptError() when the * user decides to continue without debugging. * Returns: S_OK * E_POINTER * E_FAIL ******************************************************************************/ STDMETHODIMP CScripting::OnScriptErrorDebug( IActiveScriptErrorDebug *pErrorDebug, BOOL *pfEnterDebugger, BOOL *pfCallOnScriptErrorWhenContinuing) { *pfCallOnScriptErrorWhenContinuing = true; *pfEnterDebugger = true; IActiveScriptError* pError=NULL; HRESULT hr=pErrorDebug->QueryInterface(IID_IActiveScriptError,(void**)&pError); if(hr==S_OK && pError) { *pfEnterDebugger=ReportError(pError,true)==IDYES; pError->Release(); } return S_OK; }