📄 scriptengine.cpp
字号:
} if (pass == NULL) { trace("Closing down site; we should have no references to objects from the host\n" " m_pass=%08x\n m_pass_eng=%08x\n What about named items??\n", m_pass, m_pass_eng); } m_pass = pass; if (m_pass) { m_pass->AddRef(); DWORD cookie; if (SUCCEEDED(GIT_put(m_pass, IID_IActiveScriptSite, &cookie))) SEND_THREAD_MESSAGE(this, PHPSE_SET_SITE, 0, cookie TSRMLS_CC); if (m_scriptstate == SCRIPTSTATE_UNINITIALIZED) SEND_THREAD_MESSAGE(this, PHPSE_STATE_CHANGE, 0, SCRIPTSTATE_INITIALIZED TSRMLS_CC); } tsrm_mutex_unlock(m_mutex); return S_OK;}STDMETHODIMP TPHPScriptingEngine::GetScriptSite(REFIID riid, void **ppvObject){ HRESULT ret = S_FALSE; trace("%08x: GetScriptSite()\n", this); tsrm_mutex_lock(m_mutex); if (m_pass) ret = m_pass->QueryInterface(riid, ppvObject); tsrm_mutex_unlock(m_mutex); return ret;}STDMETHODIMP TPHPScriptingEngine::SetScriptState(SCRIPTSTATE ss){ TSRMLS_FETCH(); trace("%08x: SetScriptState(%s)\n", this, scriptstate_to_string(ss)); return SEND_THREAD_MESSAGE(this, PHPSE_STATE_CHANGE, 0, ss TSRMLS_CC);}STDMETHODIMP TPHPScriptingEngine::GetScriptState(SCRIPTSTATE *pssState){ trace("%08x: GetScriptState(current=%s)\n", this, scriptstate_to_string(m_scriptstate)); tsrm_mutex_lock(m_mutex); *pssState = m_scriptstate; tsrm_mutex_unlock(m_mutex); return S_OK;}STDMETHODIMP TPHPScriptingEngine::Close(void){ TSRMLS_FETCH(); if (m_pass) { m_pass->Release(); m_pass = NULL; } SEND_THREAD_MESSAGE(this, PHPSE_CLOSE, 0, 0 TSRMLS_CC); return S_OK;}/* Add an item to global namespace. * This is called in the context of the base thread (or perhaps some other thread). * We want to be able to work with the object in the engine thread, so we marshal * it into a stream and let the engine thread deal with it. * This works quite nicely when PHP scripts call into the object; threading is * handled correctly. */STDMETHODIMP TPHPScriptingEngine::AddNamedItem(LPCOLESTR pstrName, DWORD dwFlags){ struct php_active_script_add_named_item_info info; TSRMLS_FETCH(); info.pstrName = pstrName; info.dwFlags = dwFlags; m_pass->GetItemInfo(pstrName, SCRIPTINFO_IUNKNOWN, &info.punk, NULL); if (SUCCEEDED(GIT_put(info.punk, IID_IDispatch, &info.marshal))) { SEND_THREAD_MESSAGE(this, PHPSE_ADD_NAMED_ITEM, 0, (LPARAM)&info TSRMLS_CC); } info.punk->Release(); return S_OK;}/* Bind to a type library */STDMETHODIMP TPHPScriptingEngine::AddTypeLib( /* [in] */ REFGUID rguidTypeLib, /* [in] */ DWORD dwMajor, /* [in] */ DWORD dwMinor, /* [in] */ DWORD dwFlags){ struct php_active_script_add_tlb_info info; TSRMLS_FETCH(); info.rguidTypeLib = &rguidTypeLib; info.dwMajor = dwMajor; info.dwMinor = dwMinor; info.dwFlags = dwFlags; SEND_THREAD_MESSAGE(this, PHPSE_ADD_TYPELIB, 0, (LPARAM)&info TSRMLS_CC); return S_OK;}/* Returns an object representing the PHP Scripting Engine. * Optionally, a client can request a particular item directly. * For the moment, we only do the bare minimum amount of work * for the engine to work correctly; we can flesh out this part * a little later. */STDMETHODIMP TPHPScriptingEngine::GetScriptDispatch( /* [in] */ LPCOLESTR pstrItemName, /* [out] */ IDispatch **ppdisp){ TSRMLS_FETCH(); *ppdisp = NULL; struct php_active_script_get_dispatch_info info; info.pstrItemName = pstrItemName; info.dispatch = NULL; /* This hack is required because the host is likely to query us * for a dispatch if we use any of it's objects from PHP script. * Since the engine thread will be waiting for the return from * a COM call, we need to deliberately poke a hole in thread * safety so that it is possible to read the symbol table from * outside the engine thread and give it a valid return value. * This is "safe" only in this instance, since we are not modifying * the engine state by looking up the dispatch (I hope). * The scripting engine rules pretty much guarantee that this * method is only called in the base thread. */ if (tsrm_thread_id() != m_enginethread) { tsrm_ls = m_tsrm_hack; trace("HEY: hacking thread safety!\n"); } if (S_OK == engine_thread_handler(PHPSE_GET_DISPATCH, 0, (LPARAM)&info, NULL TSRMLS_CC)) { GIT_get(info.dispatch, IID_IDispatch, (void**)ppdisp); } if (*ppdisp) { return S_OK; } return S_FALSE;}STDMETHODIMP TPHPScriptingEngine::GetCurrentScriptThreadID( /* [out] */ SCRIPTTHREADID *pstidThread){// tsrm_mutex_lock(m_mutex); trace("%08x: GetCurrentScriptThreadID()\n", this); *pstidThread = m_enginethread;// tsrm_mutex_unlock(m_mutex); return S_OK;}STDMETHODIMP TPHPScriptingEngine::GetScriptThreadID( /* [in] */ DWORD dwWin32ThreadId, /* [out] */ SCRIPTTHREADID *pstidThread){// tsrm_mutex_lock(m_mutex); trace("%08x: GetScriptThreadID()\n", this); *pstidThread = dwWin32ThreadId;// tsrm_mutex_unlock(m_mutex); return S_OK;}STDMETHODIMP TPHPScriptingEngine::GetScriptThreadState( /* [in] */ SCRIPTTHREADID stidThread, /* [out] */ SCRIPTTHREADSTATE *pstsState){// tsrm_mutex_lock(m_mutex); trace("%08x: GetScriptThreadState()\n", this); *pstsState = SCRIPTTHREADSTATE_NOTINSCRIPT; switch(stidThread) { case SCRIPTTHREADID_BASE: stidThread = m_basethread; break; case SCRIPTTHREADID_CURRENT: stidThread = m_enginethread; break; }; if (stidThread == m_basethread) { *pstsState = SCRIPTTHREADSTATE_NOTINSCRIPT; } else if (stidThread == m_enginethread) { *pstsState = SCRIPTTHREADSTATE_NOTINSCRIPT; }// tsrm_mutex_unlock(m_mutex); return S_OK;}STDMETHODIMP TPHPScriptingEngine::InterruptScriptThread( /* [in] */ SCRIPTTHREADID stidThread, /* [in] */ const EXCEPINFO *pexcepinfo, /* [in] */ DWORD dwFlags){ /* do not serialize this method, or call into the script site */ trace("%08x: InterruptScriptThread()\n", this); return S_OK;}/* Clone is essential when running under Windows Script Host. * It creates an engine to parse the code. Once it is parsed, * the host clones other engines from the original and runs those. * It is intended to be a fast method of running the same script * multiple times in multiple threads. */STDMETHODIMP TPHPScriptingEngine::Clone( /* [out] */ IActiveScript **ppscript){ TPHPScriptingEngine *cloned = new TPHPScriptingEngine; TSRMLS_FETCH(); trace("%08x: Clone()\n", this); if (ppscript) *ppscript = NULL; if (cloned) { cloned->InitNew(); SEND_THREAD_MESSAGE(cloned, PHPSE_CLONE, 0, (LPARAM)this TSRMLS_CC); trace("%08x: Cloned OK, returning cloned object ptr %08x\n", this, cloned); *ppscript = (IActiveScript*)cloned; return S_OK; } return E_FAIL;}STDMETHODIMP TPHPScriptingEngine::InitNew( void){ TSRMLS_FETCH(); SEND_THREAD_MESSAGE(this, PHPSE_INIT_NEW, 0, 0 TSRMLS_CC); return S_OK;}STDMETHODIMP TPHPScriptingEngine::AddScriptlet( /* [in] */ LPCOLESTR pstrDefaultName, /* [in] */ LPCOLESTR pstrCode, /* [in] */ LPCOLESTR pstrItemName, /* [in] */ LPCOLESTR pstrSubItemName, /* [in] */ LPCOLESTR pstrEventName, /* [in] */ LPCOLESTR pstrDelimiter, /* [in] */ DWORD dwSourceContextCookie, /* [in] */ ULONG ulStartingLineNumber, /* [in] */ DWORD dwFlags, /* [out] */ BSTR *pbstrName, /* [out] */ EXCEPINFO *pexcepinfo){ struct php_active_script_add_scriptlet_info info; TSRMLS_FETCH(); info.pstrDefaultName = pstrDefaultName; info.pstrCode = pstrCode; info.pstrItemName = pstrItemName; info.pstrSubItemName = pstrSubItemName; info.pstrEventName = pstrEventName; info.pstrDelimiter = pstrDelimiter; info.dwSourceContextCookie = dwSourceContextCookie; info.ulStartingLineNumber = ulStartingLineNumber; info.dwFlags = dwFlags; info.pbstrName = pbstrName; info.pexcepinfo = pexcepinfo; return SEND_THREAD_MESSAGE(this, PHPSE_ADD_SCRIPTLET, 0, (LPARAM)&info TSRMLS_CC);}STDMETHODIMP TPHPScriptingEngine::ParseScriptText( /* [in] */ LPCOLESTR pstrCode, /* [in] */ LPCOLESTR pstrItemName, /* [in] */ IUnknown *punkContext, /* [in] */ LPCOLESTR pstrDelimiter, /* [in] */ DWORD dwSourceContextCookie, /* [in] */ ULONG ulStartingLineNumber, /* [in] */ DWORD dwFlags, /* [out] */ VARIANT *pvarResult, /* [out] */ EXCEPINFO *pexcepinfo){ struct php_active_script_parse_info info; TSRMLS_FETCH(); info.pstrCode = pstrCode; info.pstrItemName = pstrItemName; info.punkContext = punkContext; info.pstrDelimiter = pstrDelimiter; info.dwSourceContextCookie = dwSourceContextCookie; info.ulStartingLineNumber = ulStartingLineNumber; info.dwFlags = dwFlags; info.pvarResult = pvarResult; info.pexcepinfo = pexcepinfo; return SEND_THREAD_MESSAGE(this, PHPSE_PARSE_SCRIPT, 0, (LPARAM)&info TSRMLS_CC);}STDMETHODIMP TPHPScriptingEngine::ParseProcedureText( /* [in] */ LPCOLESTR pstrCode, /* [in] */ LPCOLESTR pstrFormalParams, /* [in] */ LPCOLESTR pstrProcedureName, /* [in] */ LPCOLESTR pstrItemName, /* [in] */ IUnknown *punkContext, /* [in] */ LPCOLESTR pstrDelimiter, /* [in] */ DWORD dwSourceContextCookie, /* [in] */ ULONG ulStartingLineNumber, /* [in] */ DWORD dwFlags, /* [out] */ IDispatch **ppdisp){ struct php_active_script_parse_proc_info info; HRESULT ret; TSRMLS_FETCH(); info.pstrCode = pstrCode; info.pstrFormalParams = pstrFormalParams; info.pstrProcedureName = pstrProcedureName; info.pstrItemName = pstrItemName; info.punkContext = punkContext; info.pstrDelimiter = pstrDelimiter; info.dwSourceContextCookie = dwSourceContextCookie; info.ulStartingLineNumber = ulStartingLineNumber; info.dwFlags = dwFlags; ret = SEND_THREAD_MESSAGE(this, PHPSE_PARSE_PROC, 0, (LPARAM)&info TSRMLS_CC); if (ret == S_OK) ret = GIT_get(info.dispcookie, IID_IDispatch, (void**)ppdisp); trace("ParseProc: ret=%08x disp=%08x\n", ret, *ppdisp); return ret;}extern "C" void activescript_error_func(int type, const char *error_msg, ...){ TSRMLS_FETCH(); TPHPScriptingEngine *engine = (TPHPScriptingEngine*)SG(server_context); }class TActiveScriptError: public IActiveScriptError{protected: volatile LONG m_refcount;public: /* IUnknown */ STDMETHODIMP QueryInterface(REFIID iid, void **ppvObject) { *ppvObject = NULL; if (IsEqualGUID(IID_IActiveScriptError, iid)) { *ppvObject = (IActiveScriptError*)this; } else if (IsEqualGUID(IID_IUnknown, iid)) { *ppvObject = this; } if (*ppvObject) { AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(DWORD) AddRef(void) { return InterlockedIncrement(const_cast<long*> (&m_refcount)); } STDMETHODIMP_(DWORD) Release(void) { DWORD ret = InterlockedDecrement(const_cast<long*> (&m_refcount)); trace("Release: errobj refcount=%d\n", ret); if (ret == 0) delete this; return ret; } HRESULT STDMETHODCALLTYPE GetExceptionInfo( /* [out] */ EXCEPINFO *pexcepinfo) { memset(pexcepinfo, 0, sizeof(EXCEPINFO)); pexcepinfo->bstrDescription = SysAllocString(m_message); pexcepinfo->bstrSource = SysAllocString(m_filename); pexcepinfo->wCode = 1000; return S_OK; } HRESULT STDMETHODCALLTYPE GetSourcePosition( /* [out] */ DWORD *pdwSourceContext, /* [out] */ ULONG *pulLineNumber, /* [out] */ LONG *plCharacterPosition) { *pdwSourceContext = 0; *pulLineNumber = m_lineno; *plCharacterPosition = 0; return S_OK; } HRESULT STDMETHODCALLTYPE GetSourceLineText( /* [out] */ BSTR *pbstrSourceLine) { *pbstrSourceLine = NULL; return E_FAIL; } BSTR m_filename, m_message; UINT m_lineno; TActiveScriptError(const char *filename, const uint lineno, const char *message) { m_refcount = 0; /* start with zero refcount because this object is passed * directly to the script site; it will call addref */ m_filename = TWideString::bstr_from_ansi((char*)filename); m_message = TWideString::bstr_from_ansi((char*)message); m_lineno = lineno; } ~TActiveScriptError() { trace("%08x: cleaning up error object\n", this); SysFreeString(m_filename); SysFreeString(m_message); }};extern "C"void activescript_error_handler(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args){ TSRMLS_FETCH(); char *buf; int buflen; TPHPScriptingEngine *engine = (TPHPScriptingEngine*)SG(server_context); buflen = vspprintf(&buf, PG(log_errors_max_len), format, args); trace("%08x: Error: %s\n", engine, buf); /* if it's a fatal error, report it using IActiveScriptError. */ switch(type) { case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: case E_PARSE: /* trigger an error in the host */ TActiveScriptError *eobj = new TActiveScriptError(error_filename, error_lineno, buf); trace("raising error object!\n"); if (engine->m_pass_eng) engine->m_pass_eng->OnScriptError(eobj); /* now throw the exception to abort execution */ if (engine->m_err_trap) longjmp(*engine->m_err_trap, 1); break; } efree(buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -