cvs: php-src /sapi/activescript README classfactory.cpp php5activescript.c php5as_classfactory.h php5as_scriptengine.h scriptengine.cpp
| From: | Wez Furlong | Date: | Tue, 04 May 2004 14:54:01 +0000 |
| Subject: | cvs: php-src /sapi/activescript README classfactory.cpp php5activescript.c php5as_classfactory.h php5as_scriptengine.h scriptengine.cpp | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-27250@lists.php.net to get a copy of this message | ||
wez Tue May 4 10:54:01 2004 EDT
Modified files:
/php-src/sapi/activescript README classfactory.cpp
php5activescript.c php5as_classfactory.h
php5as_scriptengine.h scriptengine.cpp
Log:
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.
http://cvs.php.net/diff.php/php-src/sapi/activescript/README?r1=1.2&r2=1.3&ty=u Index: php-src/sapi/activescript/README diff -u php-src/sapi/activescript/README:1.2 php-src/sapi/activescript/README:1.3 --- php-src/sapi/activescript/README:1.2 Sat Jan 17 08:00:01 2004 +++ php-src/sapi/activescript/README Tue May 4 10:54:01 2004 @@ -26,7 +26,7 @@ o. Client-side script in Internet Explorer - <script language="ActivePHP"> + <script language="ActivePHP5"> $window->alert("Hello"); </script> @@ -35,22 +35,22 @@ 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" http://cvs.php.net/diff.php/php-src/sapi/activescript/classfactory.cpp?r1=1.8&r2=1.9&ty=u Index: php-src/sapi/activescript/classfactory.cpp diff -u php-src/sapi/activescript/classfactory.cpp:1.8 php-src/sapi/activescript/classfactory.cpp:1.9 --- php-src/sapi/activescript/classfactory.cpp:1.8 Sat Jan 17 08:00:01 2004 +++ php-src/sapi/activescript/classfactory.cpp Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: classfactory.cpp,v 1.8 2004/01/17 13:00:01 sniper Exp $ */ +/* $Id: classfactory.cpp,v 1.9 2004/05/04 14:54:01 wez Exp $ */ /* IClassFactory Implementation, and DllXXX function implementation */ @@ -145,10 +145,10 @@ { 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 } }; http://cvs.php.net/diff.php/php-src/sapi/activescript/php5activescript.c?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5activescript.c diff -u php-src/sapi/activescript/php5activescript.c:1.1 php-src/sapi/activescript/php5activescript.c:1.2 --- php-src/sapi/activescript/php5activescript.c:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5activescript.c Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5activescript.c,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5activescript.c,v 1.2 2004/05/04 14:54:01 wez Exp $ */ #include "php.h" #include "php_main.h" @@ -127,7 +127,7 @@ 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 @@ 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; } http://cvs.php.net/diff.php/php-src/sapi/activescript/php5as_classfactory.h?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5as_classfactory.h diff -u php-src/sapi/activescript/php5as_classfactory.h:1.1 php-src/sapi/activescript/php5as_classfactory.h:1.2 --- php-src/sapi/activescript/php5as_classfactory.h:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5as_classfactory.h Tue May 4 10:54:01 2004 @@ -15,15 +15,22 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5as_classfactory.h,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5as_classfactory.h,v 1.2 2004/05/04 14:54:01 wez Exp $ */ /* IClassFactory Implementation */ #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 http://cvs.php.net/diff.php/php-src/sapi/activescript/php5as_scriptengine.h?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5as_scriptengine.h diff -u php-src/sapi/activescript/php5as_scriptengine.h:1.1 php-src/sapi/activescript/php5as_scriptengine.h:1.2 --- php-src/sapi/activescript/php5as_scriptengine.h:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5as_scriptengine.h Tue May 4 10:54:01 2004 @@ -15,9 +15,10 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5as_scriptengine.h,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5as_scriptengine.h,v 1.2 2004/05/04 14:54:01 wez Exp $ */ #include <activscp.h> +#include <objsafe.h> #include "zend.h" #include <setjmp.h> @@ -106,6 +107,9 @@ public IActiveScript, public IActiveScriptParse, public IActiveScriptParseProcedure +#if ACTIVEPHP_OBJECT_SAFETY + , public IObjectSafety +#endif { public: volatile LONG m_refcount; @@ -227,6 +231,20 @@ /* [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(); http://cvs.php.net/diff.php/php-src/sapi/activescript/scriptengine.cpp?r1=1.11&r2=1.12&ty=u Index: php-src/sapi/activescript/scriptengine.cpp diff -u php-src/sapi/activescript/scriptengine.cpp:1.11 php-src/sapi/activescript/scriptengine.cpp:1.12 --- php-src/sapi/activescript/scriptengine.cpp:1.11 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/scriptengine.cpp Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: scriptengine.cpp,v 1.11 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: scriptengine.cpp,v 1.12 2004/05/04 14:54:01 wez Exp $ */ /* Implementation Notes: * @@ -50,6 +50,9 @@ #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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ } 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 @@ 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; - while(!terminated) { - DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); + 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"); + } - 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); + while(!terminated) { + DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); - } 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); - } + 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); + + } 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 @@ * * 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 @@ 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 @@ 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 @@ /* 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 @@ *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::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 @@ * 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 @@ 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, ...) {
http://cvs.php.net/diff.php/php-src/sapi/activescript/README?r1=1.2&r2=1.3&ty=u Index: php-src/sapi/activescript/README diff -u php-src/sapi/activescript/README:1.2 php-src/sapi/activescript/README:1.3 --- php-src/sapi/activescript/README:1.2 Sat Jan 17 08:00:01 2004 +++ php-src/sapi/activescript/README Tue May 4 10:54:01 2004 @@ -26,7 +26,7 @@ o. Client-side script in Internet Explorer - <script language="ActivePHP"> + <script language="ActivePHP5"> $window->alert("Hello"); </script> @@ -35,22 +35,22 @@ 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" http://cvs.php.net/diff.php/php-src/sapi/activescript/classfactory.cpp?r1=1.8&r2=1.9&ty=u Index: php-src/sapi/activescript/classfactory.cpp diff -u php-src/sapi/activescript/classfactory.cpp:1.8 php-src/sapi/activescript/classfactory.cpp:1.9 --- php-src/sapi/activescript/classfactory.cpp:1.8 Sat Jan 17 08:00:01 2004 +++ php-src/sapi/activescript/classfactory.cpp Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: classfactory.cpp,v 1.8 2004/01/17 13:00:01 sniper Exp $ */ +/* $Id: classfactory.cpp,v 1.9 2004/05/04 14:54:01 wez Exp $ */ /* IClassFactory Implementation, and DllXXX function implementation */ @@ -145,10 +145,10 @@ { 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 } }; http://cvs.php.net/diff.php/php-src/sapi/activescript/php5activescript.c?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5activescript.c diff -u php-src/sapi/activescript/php5activescript.c:1.1 php-src/sapi/activescript/php5activescript.c:1.2 --- php-src/sapi/activescript/php5activescript.c:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5activescript.c Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5activescript.c,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5activescript.c,v 1.2 2004/05/04 14:54:01 wez Exp $ */ #include "php.h" #include "php_main.h" @@ -127,7 +127,7 @@ 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 @@ 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; } http://cvs.php.net/diff.php/php-src/sapi/activescript/php5as_classfactory.h?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5as_classfactory.h diff -u php-src/sapi/activescript/php5as_classfactory.h:1.1 php-src/sapi/activescript/php5as_classfactory.h:1.2 --- php-src/sapi/activescript/php5as_classfactory.h:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5as_classfactory.h Tue May 4 10:54:01 2004 @@ -15,15 +15,22 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5as_classfactory.h,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5as_classfactory.h,v 1.2 2004/05/04 14:54:01 wez Exp $ */ /* IClassFactory Implementation */ #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 http://cvs.php.net/diff.php/php-src/sapi/activescript/php5as_scriptengine.h?r1=1.1&r2=1.2&ty=u Index: php-src/sapi/activescript/php5as_scriptengine.h diff -u php-src/sapi/activescript/php5as_scriptengine.h:1.1 php-src/sapi/activescript/php5as_scriptengine.h:1.2 --- php-src/sapi/activescript/php5as_scriptengine.h:1.1 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/php5as_scriptengine.h Tue May 4 10:54:01 2004 @@ -15,9 +15,10 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: php5as_scriptengine.h,v 1.1 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: php5as_scriptengine.h,v 1.2 2004/05/04 14:54:01 wez Exp $ */ #include <activscp.h> +#include <objsafe.h> #include "zend.h" #include <setjmp.h> @@ -106,6 +107,9 @@ public IActiveScript, public IActiveScriptParse, public IActiveScriptParseProcedure +#if ACTIVEPHP_OBJECT_SAFETY + , public IObjectSafety +#endif { public: volatile LONG m_refcount; @@ -227,6 +231,20 @@ /* [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(); http://cvs.php.net/diff.php/php-src/sapi/activescript/scriptengine.cpp?r1=1.11&r2=1.12&ty=u Index: php-src/sapi/activescript/scriptengine.cpp diff -u php-src/sapi/activescript/scriptengine.cpp:1.11 php-src/sapi/activescript/scriptengine.cpp:1.12 --- php-src/sapi/activescript/scriptengine.cpp:1.11 Sat Jan 17 08:00:02 2004 +++ php-src/sapi/activescript/scriptengine.cpp Tue May 4 10:54:01 2004 @@ -15,7 +15,7 @@ | Authors: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: scriptengine.cpp,v 1.11 2004/01/17 13:00:02 sniper Exp $ */ +/* $Id: scriptengine.cpp,v 1.12 2004/05/04 14:54:01 wez Exp $ */ /* Implementation Notes: * @@ -50,6 +50,9 @@ #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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ } 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 @@ 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; - while(!terminated) { - DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); + 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"); + } - 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); + while(!terminated) { + DWORD result = MsgWaitForMultipleObjects(0, NULL, FALSE, 4000, QS_ALLINPUT); - } 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); - } + 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); + + } 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 @@ * * 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 @@ 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 @@ 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 @@ /* 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 @@ *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::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 @@ * 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 @@ 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, ...) {