diff options
author | Wez Furlong <wez@php.net> | 2004-05-04 14:54:01 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2004-05-04 14:54:01 +0000 |
commit | c921ceb49c5df9b3ae71d9ef451093e1abbc1720 (patch) | |
tree | f0b6c8bae667fc39506b7c0fa867df06e549275a | |
parent | d6838a86f355f82dfde3c12253617924d7421896 (diff) | |
download | php-git-c921ceb49c5df9b3ae71d9ef451093e1abbc1720.tar.gz |
Improve stability.
Give it a new CLSID and change the engine name to ActivePHP5.
Globals registered by the scripting host are now auto-globals and don't
need to be declared global when accessed from within functions.
-rw-r--r-- | sapi/activescript/README | 10 | ||||
-rw-r--r-- | sapi/activescript/classfactory.cpp | 8 | ||||
-rw-r--r-- | sapi/activescript/php5activescript.c | 4 | ||||
-rw-r--r-- | sapi/activescript/php5as_classfactory.h | 7 | ||||
-rw-r--r-- | sapi/activescript/php5as_scriptengine.h | 18 | ||||
-rw-r--r-- | sapi/activescript/scriptengine.cpp | 228 |
6 files changed, 212 insertions, 63 deletions
diff --git a/sapi/activescript/README b/sapi/activescript/README index 70f49821d8..39066f5783 100644 --- a/sapi/activescript/README +++ b/sapi/activescript/README @@ -26,7 +26,7 @@ Usage. o. Client-side script in Internet Explorer - <script language="ActivePHP"> + <script language="ActivePHP5"> $window->alert("Hello"); </script> @@ -35,22 +35,22 @@ o. Windows Script Host Create a .wsf file like this: <job id="test"> - <script language="ActivePHP"> + <script language="ActivePHP5"> $WScript->Echo("Hello"); </script> </script> o. ASP and ASP.NET - <%@language=ActivePHP %> + <%@language=ActivePHP5 %> <% $Response->Write("Hello"); %> o. Windows Script Components / Behaviours - Use language="ActivePHP" on your <script> tags + Use language="ActivePHP5" on your <script> tags o. MS Scriptlet control - Set the language property to "ActivePHP" + Set the language property to "ActivePHP5" diff --git a/sapi/activescript/classfactory.cpp b/sapi/activescript/classfactory.cpp index ecdd6f63a3..698a052cd2 100644 --- a/sapi/activescript/classfactory.cpp +++ b/sapi/activescript/classfactory.cpp @@ -145,10 +145,10 @@ static const struct reg_entry engine_entries[] = { { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\InprocServer32", NULL, "[MODULENAME]" }, { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\InprocServer32", "ThreadingModel", "[THREADING]" }, { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\OLEScript", NULL, NULL }, - { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\ProgID", NULL, "ActivePHP" }, - { HKEY_CLASSES_ROOT, "ActivePHP", NULL, "ActivePHP" }, - { HKEY_CLASSES_ROOT, "ActivePHP\\CLSID", NULL, "[CLSID]"}, - { HKEY_CLASSES_ROOT, "ActivePHP\\OLEScript", NULL, NULL}, + { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\ProgID", NULL, "ActivePHP5" }, + { HKEY_CLASSES_ROOT, "ActivePHP5", NULL, "ActivePHP5" }, + { HKEY_CLASSES_ROOT, "ActivePHP5\\CLSID", NULL, "[CLSID]"}, + { HKEY_CLASSES_ROOT, "ActivePHP5\\OLEScript", NULL, NULL}, { 0, NULL, NULL, NULL } }; diff --git a/sapi/activescript/php5activescript.c b/sapi/activescript/php5activescript.c index 6aa4b41495..93222fdbf8 100644 --- a/sapi/activescript/php5activescript.c +++ b/sapi/activescript/php5activescript.c @@ -127,7 +127,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: module_handle = hinstDLL; - tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "C:\\TSRM.log"); + tsrm_startup(128, 32, TSRM_ERROR_LEVEL_CORE, "C:\\TSRM.log"); sapi_startup(&activescript_sapi_module); if (activescript_sapi_module.startup) { @@ -137,12 +137,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: + //OutputDebugString("THREAD_DETACH\n"); ts_free_thread(); break; case DLL_PROCESS_DETACH: if (activescript_sapi_module.shutdown) { activescript_sapi_module.shutdown(&sapi_module); } + //OutputDebugString("PROCESS_DETACH\n"); tsrm_shutdown(); break; } diff --git a/sapi/activescript/php5as_classfactory.h b/sapi/activescript/php5as_classfactory.h index 2f1695fa0c..61823fb689 100644 --- a/sapi/activescript/php5as_classfactory.h +++ b/sapi/activescript/php5as_classfactory.h @@ -21,9 +21,16 @@ #include <unknwn.h> +// {CF108A38-59A9-468a-AF45-1368D7855DAE} +DEFINE_GUID(CLSID_PHPActiveScriptEngine, +0xcf108a38, 0x59a9, 0x468a, 0xaf, 0x45, 0x13, 0x68, 0xd7, 0x85, 0x5d, 0xae); + +#if 0 +/* this was for PHP 4 */ // {A0AD8E7A-95EC-4819-986F-78D93895F2AE} DEFINE_GUID(CLSID_PHPActiveScriptEngine, 0xa0ad8e7a, 0x95ec, 0x4819, 0x98, 0x6f, 0x78, 0xd9, 0x38, 0x95, 0xf2, 0xae); +#endif class TPHPClassFactory: public IClassFactory diff --git a/sapi/activescript/php5as_scriptengine.h b/sapi/activescript/php5as_scriptengine.h index fd5fd522a8..6e9a06ff46 100644 --- a/sapi/activescript/php5as_scriptengine.h +++ b/sapi/activescript/php5as_scriptengine.h @@ -18,6 +18,7 @@ /* $Id$ */ #include <activscp.h> +#include <objsafe.h> #include "zend.h" #include <setjmp.h> @@ -106,6 +107,9 @@ class TPHPScriptingEngine: public IActiveScript, public IActiveScriptParse, public IActiveScriptParseProcedure +#if ACTIVEPHP_OBJECT_SAFETY + , public IObjectSafety +#endif { public: volatile LONG m_refcount; @@ -227,6 +231,20 @@ public: /* IActiveScriptParseProcedure */ /* [in] */ ULONG ulStartingLineNumber, /* [in] */ DWORD dwFlags, /* [out] */ IDispatch **ppdisp); + +#if ACTIVEPHP_OBJECT_SAFETY +public: /* IObjectSafety */ + STDMETHODIMP GetInterfaceSafetyOptions( + /* [in] */ REFIID riid, // Interface that we want options for + /* [out] */ DWORD *pdwSupportedOptions, // Options meaningful on this interface + /* [out] */ DWORD *pdwEnabledOptions); // current option values on this interface + + STDMETHODIMP SetInterfaceSafetyOptions( + /* [in] */ REFIID riid, // Interface to set options for + /* [in] */ DWORD dwOptionSetMask, // Options to change + /* [in] */ DWORD dwEnabledOptions); // New option values +#endif + public: TPHPScriptingEngine(); ~TPHPScriptingEngine(); diff --git a/sapi/activescript/scriptengine.cpp b/sapi/activescript/scriptengine.cpp index 7853af1637..9906ca1490 100644 --- a/sapi/activescript/scriptengine.cpp +++ b/sapi/activescript/scriptengine.cpp @@ -50,6 +50,9 @@ extern "C" { #include "php5as_scriptengine.h" #include "php5as_classfactory.h" #include <objbase.h> +#undef php_win_err + +#define ACTIVEPHP_THREADING_MODE COINIT_MULTITHREADED /* {{{ trace */ static inline void trace(char *fmt, ...) @@ -651,7 +654,6 @@ TPHPScriptingEngine::TPHPScriptingEngine() TPHPClassFactory::AddToObjectCount(); m_engine_thread_handle = CreateThread(NULL, 0, begin_engine_thread, this, 0, &m_enginethread); - CloseHandle(m_engine_thread_handle); } void activescript_run_ticks(int count) @@ -733,10 +735,14 @@ HRESULT TPHPScriptingEngine::SendThreadMessage(LONG msg, WPARAM wparam, LPARAM l TPHPScriptingEngine::~TPHPScriptingEngine() { trace("\n\n *** Engine Destructor Called\n\n"); - if (m_scriptstate != SCRIPTSTATE_UNINITIALIZED && m_scriptstate != SCRIPTSTATE_CLOSED && m_enginethread) - Close(); + if (m_scriptstate != SCRIPTSTATE_UNINITIALIZED && m_scriptstate != SCRIPTSTATE_CLOSED && m_enginethread) { + Close(); + } + PostThreadMessage(m_enginethread, WM_QUIT, 0, 0); + WaitForSingleObject(m_engine_thread_handle, INFINITE); + CloseHandle(m_engine_thread_handle); TPHPClassFactory::RemoveFromObjectCount(); tsrm_mutex_free(m_mutex); @@ -851,6 +857,8 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR /* Prepare PHP/ZE for use */ trace("%08x: m_frags : INIT NEW\n", this); + +#if 0 zend_hash_init(&m_frags, 0, NULL, frag_dtor, TRUE); SG(options) |= SAPI_OPTION_NO_CHDIR; @@ -865,8 +873,9 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR php_request_startup(TSRMLS_C); PG(during_request_startup) = 0; - trace("\n\n *** ticks func at %08x %08x ***\n\n\n", activescript_run_ticks, &activescript_run_ticks); +// trace("\n\n *** ticks func at %08x %08x ***\n\n\n", activescript_run_ticks, &activescript_run_ticks); // php_add_tick_function(activescript_run_ticks); +#endif } break; @@ -881,8 +890,10 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR m_pass_eng->Release(); m_pass_eng = NULL; } +#if 0 zend_hash_destroy(&m_frags); php_request_shutdown(NULL); +#endif break; } @@ -998,7 +1009,7 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR { struct php_active_script_get_dispatch_info *info = (struct php_active_script_get_dispatch_info *)lParam; IDispatch *disp = NULL; - + if (info->pstrItemName != NULL) { zval **tmp; /* use this rather than php_OLECHAR_to_char because we want to avoid emalloc here */ @@ -1025,8 +1036,10 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR if (disp) { ret = GIT_put(disp, IID_IDispatch, &info->dispatch); disp->Release(); + trace("GET_DISPATCH: we put it in the GIT\n"); } else { ret = S_FALSE; + trace("GET_DISPATCH: FAILED to put it in the GIT\n"); } } break; @@ -1039,10 +1052,22 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR struct php_active_script_add_named_item_info *info = (struct php_active_script_add_named_item_info *)lParam; TWideString name(info->pstrName); - IDispatch *disp; - - if (SUCCEEDED(GIT_get(info->marshal, IID_IDispatch, (void**)&disp))) + IDispatch *disp = NULL; + HRESULT res; + + trace("ADD_NAMED_ITEM\n"); + +#if ACTIVEPHP_THREADING_MODE == COINIT_MULTITHREADED + res = info->punk->QueryInterface(IID_IDispatch, (void**)&disp); +#else + res = GIT_get(info->marshal, IID_IDispatch, (void**)&disp); +#endif + if (SUCCEEDED(res) && disp) { add_to_global_namespace(disp, info->dwFlags, name.ansi_string() TSRMLS_CC); + disp->Release(); + } else { + trace("Ouch: failed to get IDispatch for %s from GIT '%s'\n", name.ansi_string(), php_win_err(res)); + } } break; @@ -1178,7 +1203,7 @@ HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPAR } break; default: - trace("unhandled message type %08x\n", msg); + trace("XXXXX: unhandled message type %08x\n", msg); if (handled) *handled = 0; } @@ -1195,55 +1220,86 @@ void TPHPScriptingEngine::engine_thread_func(void) trace("%08x: engine thread started up!\n", this); - CoInitializeEx(0, COINIT_MULTITHREADED); + CoInitializeEx(0, ACTIVEPHP_THREADING_MODE); - m_tsrm_hack = tsrm_ls; + zend_first_try { + m_tsrm_hack = tsrm_ls; + + SG(options) |= SAPI_OPTION_NO_CHDIR; + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + + SG(server_context) = this; + /* override the default PHP error callback */ + zend_error_cb = activescript_error_handler; + + zend_alter_ini_entry("register_argc_argv", 19, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry("implicit_flush", 15, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); + + if (SUCCESS == php_request_startup(TSRMLS_C)) { + PG(during_request_startup) = 0; + if (FAILURE == zend_hash_init(&m_frags, 0, NULL, frag_dtor, 1)) { + trace("failed to init frags hash\n"); + } - while(!terminated) { - DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); + while(!terminated) { + DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); - switch(result) { - case WAIT_OBJECT_0: - while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + switch(result) { + case WAIT_OBJECT_0: + while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - if (msg.message == WM_QUIT) { - terminated = 1; - } else if (msg.hwnd) { - TranslateMessage(&msg); - DispatchMessage(&msg); + if (msg.message == WM_QUIT) { + terminated = 1; + } else if (msg.hwnd) { + TranslateMessage(&msg); + DispatchMessage(&msg); - } else { - handled = 1; - m_sync_thread_ret = engine_thread_handler(msg.message, msg.wParam, msg.lParam, &handled TSRMLS_CC); - if (handled) - SetEvent(m_sync_thread_msg); - } + } else { + handled = 1; + m_sync_thread_ret = engine_thread_handler(msg.message, msg.wParam, msg.lParam, &handled TSRMLS_CC); + if (handled) + SetEvent(m_sync_thread_msg); + } + } + break; + case WAIT_TIMEOUT: + trace("thread wait timed out\n"); + break; + default: + trace("some strange value\n"); } - break; - case WAIT_TIMEOUT: - trace("thread wait timed out\n"); - break; - default: - trace("some strange value\n"); - } - } - + } + #if 0 - while(GetMessage(&msg, NULL, 0, 0)) { + while(GetMessage(&msg, NULL, 0, 0)) { - if (msg.message == WM_QUIT) - break; - - handled = 1; - m_sync_thread_ret = engine_thread_handler(msg.message, msg.wParam, msg.lParam, &handled TSRMLS_CC); - if (handled) - SetEvent(m_sync_thread_msg); - } - trace("%08x: engine thread exiting!!!!!\n", this); + if (msg.message == WM_QUIT) + break; + + handled = 1; + m_sync_thread_ret = engine_thread_handler(msg.message, msg.wParam, msg.lParam, &handled TSRMLS_CC); + if (handled) + SetEvent(m_sync_thread_msg); + } #endif - m_enginethread = 0; + trace("%08x: engine thread exiting!!!!!\n", this); + zend_hash_destroy(&m_frags); + trace("calling request shutdown\n"); + php_request_shutdown(NULL); + } else { + trace("request startup failed\n"); + } + + } zend_catch { + trace("ouch: bailed out\n"); + } zend_end_try(); + + m_enginethread = 0; CoUninitialize(); } @@ -1255,6 +1311,16 @@ void TPHPScriptingEngine::engine_thread_func(void) * * TODO: evaluate if it is appropriate to register as an auto_global * */ + +static inline void make_auto_global(char *name, zval *val TSRMLS_DC) +{ + int namelen = strlen(name); + + zend_register_auto_global(name, namelen, NULL TSRMLS_CC); + zend_auto_global_disable_jit(name, namelen TSRMLS_CC); + ZEND_SET_SYMBOL(&EG(symbol_table), name, val); +} + void TPHPScriptingEngine::add_to_global_namespace(IDispatch *disp, DWORD flags, char *name TSRMLS_DC) { zval *val; @@ -1271,6 +1337,7 @@ void TPHPScriptingEngine::add_to_global_namespace(IDispatch *disp, DWORD flags, trace("Add %s to global namespace\n", name); + MAKE_STD_ZVAL(val); php_com_wrap_dispatch(val, disp, CP_ACP TSRMLS_CC); if (val == NULL) { @@ -1278,7 +1345,7 @@ trace("Add %s to global namespace\n", name); return; } - ZEND_SET_SYMBOL(&EG(symbol_table), name, val); + make_auto_global(name, val TSRMLS_CC); if ((flags & SCRIPTITEM_GLOBALMEMBERS) == 0) { disp->Release(); @@ -1329,10 +1396,12 @@ trace("Add %s to global namespace\n", name); /* add to namespace */ zval *subval; + + MAKE_STD_ZVAL(subval); php_com_wrap_dispatch(subval, sub, CP_ACP TSRMLS_CC); if (subval) { - ZEND_SET_SYMBOL(&EG(symbol_table), name, subval); + make_auto_global(name, subval TSRMLS_CC); } efree(name); @@ -1377,6 +1446,10 @@ STDMETHODIMP TPHPScriptingEngine::QueryInterface(REFIID iid, void **ppvObject) *ppvObject = (IActiveScriptParse*)this; } else if (IsEqualGUID(IID_IActiveScriptParseProcedure, iid)) { *ppvObject = (IActiveScriptParseProcedure*)this; +#if ACTIVEPHP_OBJECT_SAFETY + } else if (IsEqualGUID(IID_IObjectSafety, iid)) { + *ppvObject = (IObjectSafety*)this; +#endif } else if (IsEqualGUID(IID_IUnknown, iid)) { *ppvObject = this; } else { @@ -1486,16 +1559,38 @@ STDMETHODIMP TPHPScriptingEngine::Close(void) STDMETHODIMP TPHPScriptingEngine::AddNamedItem(LPCOLESTR pstrName, DWORD dwFlags) { struct php_active_script_add_named_item_info info; + HRESULT res; 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))) { + res = m_pass->GetItemInfo(pstrName, SCRIPTINFO_IUNKNOWN, &info.punk, NULL); + + if (SUCCEEDED(res)) { +#if ACTIVEPHP_THREADING_MODE == COINIT_MULTITHREADED + /* strangely, the GIT doesn't want to give the engine thread the interface + * in this threading mode */ SEND_THREAD_MESSAGE(this, PHPSE_ADD_NAMED_ITEM, 0, (LPARAM)&info TSRMLS_CC); +#else + IDispatch *disp; + res = info.punk->QueryInterface(IID_IDispatch, (void**)&disp); + + if (SUCCEEDED(res) && disp) { + if (SUCCEEDED(GIT_put(disp, IID_IDispatch, &info.marshal))) { + trace("put disp=%p into git with marshal ID of %x\n", disp, info.marshal); + SEND_THREAD_MESSAGE(this, PHPSE_ADD_NAMED_ITEM, 0, (LPARAM)&info TSRMLS_CC); + GIT_revoke(info.marshal, disp); + } + disp->Release(); + } else { + trace("failed to get IDispatch from punk %s", php_win_err(res)); + } + info.punk->Release(); +#endif + } else { + trace("failed to get named item, %s", php_win_err(res)); } - info.punk->Release(); return S_OK; } @@ -1545,7 +1640,9 @@ STDMETHODIMP TPHPScriptingEngine::GetScriptDispatch( * 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. */ + * method is only called in the base thread. + * This appears to only happen when we set the threading to + * apartment. */ if (tsrm_thread_id() != m_enginethread) { tsrm_ls = m_tsrm_hack; @@ -1748,6 +1845,31 @@ STDMETHODIMP TPHPScriptingEngine::ParseProcedureText( return ret; } +#if ACTIVEPHP_OBJECT_SAFETY +STDMETHODIMP TPHPScriptingEngine::GetInterfaceSafetyOptions( + /* [in] */ REFIID riid, // Interface that we want options for + /* [out] */ DWORD *pdwSupportedOptions, // Options meaningful on this interface + /* [out] */ DWORD *pdwEnabledOptions) // current option values on this interface +{ + /* PHP isn't really safe for untrusted anything */ + *pdwSupportedOptions = 0; + *pdwEnabledOptions = 0; + return S_OK; +} + +STDMETHODIMP TPHPScriptingEngine::SetInterfaceSafetyOptions( + /* [in] */ REFIID riid, // Interface to set options for + /* [in] */ DWORD dwOptionSetMask, // Options to change + /* [in] */ DWORD dwEnabledOptions) // New option values +{ + /* PHP isn't really safe for untrusted anything */ + if (dwEnabledOptions == 0) { + return S_OK; + } + return E_FAIL; +} +#endif + extern "C" void activescript_error_func(int type, const char *error_msg, ...) { |