summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2004-05-04 14:54:01 +0000
committerWez Furlong <wez@php.net>2004-05-04 14:54:01 +0000
commitc921ceb49c5df9b3ae71d9ef451093e1abbc1720 (patch)
treef0b6c8bae667fc39506b7c0fa867df06e549275a
parentd6838a86f355f82dfde3c12253617924d7421896 (diff)
downloadphp-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/README10
-rw-r--r--sapi/activescript/classfactory.cpp8
-rw-r--r--sapi/activescript/php5activescript.c4
-rw-r--r--sapi/activescript/php5as_classfactory.h7
-rw-r--r--sapi/activescript/php5as_scriptengine.h18
-rw-r--r--sapi/activescript/scriptengine.cpp228
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, ...)
{