⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scriptengine.cpp

📁 php-4.4.7学习linux时下载的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*   +----------------------------------------------------------------------+   | PHP Version 4                                                        |   +----------------------------------------------------------------------+   | Copyright (c) 1997-2006 The PHP Group                                |   +----------------------------------------------------------------------+   | This source file is subject to version 3.01 of the PHP license,      |   | that is bundled with this package in the file LICENSE, and is        |   | available through the world-wide-web at the following url:           |   | http://www.php.net/license/3_01.txt                                  |   | If you did not receive a copy of the PHP license and are unable to   |   | obtain it through the world-wide-web, please send a note to          |   | license@php.net so we can mail you a copy immediately.               |   +----------------------------------------------------------------------+   | Authors: Wez Furlong <wez@thebrainroom.com>                          |   +----------------------------------------------------------------------+ *//* $Id: scriptengine.cpp,v 1.4.16.1 2006/01/01 13:47:01 sniper Exp $ *//* Implementation Notes: * * PHP stores scripting engine state in thread-local storage. That means * that we need to create a dedicated thread per-engine so that a host can * use more than one engine object per thread. * * There are some interesting synchronization issues: Anything to do with * running script in the PHP/Zend engine must take place on the engine * thread.  Likewise, calling back to the host must take place on the base * thread - the thread that set the script site. * */#define _WIN32_DCOM#include "php.h"extern "C" {#include "php_main.h"#include "SAPI.h"#include "zend.h"#include "zend_execute.h"#include "zend_compile.h"#include "php_globals.h"#include "php_variables.h"#include "php_ini.h"#include "php4activescript.h"#include "ext/com/com.h"#include "ext/com/php_COM.h"#include "ext/com/conversion.h"}#include "php_ticks.h"#include "php4as_scriptengine.h"#include "php4as_classfactory.h"#include <objbase.h>/* {{{ trace */static inline void trace(char *fmt, ...){	va_list ap;	char buf[4096];	sprintf(buf, "T=%08x ", tsrm_thread_id());	OutputDebugString(buf);		va_start(ap, fmt);	vsnprintf(buf, sizeof(buf), fmt, ap);	OutputDebugString(buf);		va_end(ap);}/* }}} *//* {{{ scriptstate_to_string */static const char *scriptstate_to_string(SCRIPTSTATE ss){	switch(ss) {		case SCRIPTSTATE_UNINITIALIZED: return "SCRIPTSTATE_UNINITIALIZED";		case SCRIPTSTATE_INITIALIZED: return "SCRIPTSTATE_INITIALIZED";		case SCRIPTSTATE_STARTED: return "SCRIPTSTATE_STARTED";		case SCRIPTSTATE_CONNECTED: return "SCRIPTSTATE_CONNECTED";		case SCRIPTSTATE_DISCONNECTED: return "SCRIPTSTATE_DISCONNECTED";		case SCRIPTSTATE_CLOSED: return "SCRIPTSTATE_CLOSED";		default:			return "unknown";	}}/* }}} *//* {{{ TWideString *//* This class helps manipulate strings from OLE. * It does not use emalloc, so it is better suited for passing pointers * between threads. */class TWideString {	public:		LPOLESTR m_ole;		char *m_ansi;		int m_ansi_strlen;		TWideString(LPOLESTR olestr) {			m_ole = olestr;			m_ansi = NULL;		}		TWideString(LPCOLESTR olestr) {			m_ole = (LPOLESTR)olestr;			m_ansi = NULL;		}		~TWideString() {			if (m_ansi) {				CoTaskMemFree(m_ansi);			}			m_ansi = NULL;		}		char *safe_ansi_string() {			char *ret = ansi_string();			if (ret == NULL)				return "<NULL>";			return ret;		}		int ansi_len(void) {			/* force conversion if it has not already occurred */			if (m_ansi == NULL)				ansi_string();			return m_ansi_strlen;		}		static BSTR bstr_from_ansi(char *ansi) {			OLECHAR *ole = NULL;			BSTR bstr = NULL;			int req = MultiByteToWideChar(CP_ACP, 0, ansi, -1, NULL, 0);			if (req) {				ole = (OLECHAR*)CoTaskMemAlloc((req + 1) * sizeof(OLECHAR));				if (ole) {					req = MultiByteToWideChar(CP_ACP, 0, ansi, -1, ole, req);					req--;					ole[req] = 0;					bstr = SysAllocString(ole);					CoTaskMemFree(ole);				}			}			return bstr;		}		char *ansi_string(void)		{			if (m_ansi)				return m_ansi;			if (m_ole == NULL)				return NULL;			int bufrequired = WideCharToMultiByte(CP_ACP, 0, m_ole, -1, NULL, 0, NULL, NULL);			if (bufrequired) {				m_ansi = (char*)CoTaskMemAlloc(bufrequired + 1);				if (m_ansi) {					m_ansi_strlen = WideCharToMultiByte(CP_ACP, 0, m_ole, -1, m_ansi, bufrequired + 1, NULL, NULL);					if (m_ansi_strlen) {						m_ansi_strlen--;						m_ansi[m_ansi_strlen] = 0;					} else {						trace("conversion failed with return code %08x\n", GetLastError());						}				}			}			return m_ansi;		}};/* }}} *//* {{{ code fragment structures */enum fragtype {	FRAG_MAIN,	FRAG_SCRIPTLET,	FRAG_PROCEDURE};typedef struct {	enum fragtype fragtype;	zend_op_array *opcodes;	char *code;	int persistent;	/* should be retained for Clone */	int executed;	/* for "main" */	char *functionname;	unsigned int codelen;	unsigned int starting_line;	TPHPScriptingEngine *engine;	void *ptr;} code_frag;#define FRAG_CREATE_FUNC	(char*)-1static code_frag *compile_code_fragment(		enum fragtype fragtype,		char *functionname,		LPCOLESTR code,		ULONG starting_line,		EXCEPINFO *excepinfo,		TPHPScriptingEngine *engine		TSRMLS_DC);static int execute_code_fragment(code_frag *frag,		VARIANT *varResult,		EXCEPINFO *excepinfo		TSRMLS_DC);static void free_code_fragment(code_frag *frag);static code_frag *clone_code_fragment(code_frag *frag, TPHPScriptingEngine *engine TSRMLS_DC);/* }}} *//* Magic for handling threading correctly */static inline HRESULT SEND_THREAD_MESSAGE(TPHPScriptingEngine *engine, LONG msg, WPARAM wparam, LPARAM lparam TSRMLS_DC){	if (engine->m_enginethread == 0)		return E_UNEXPECTED;	if (tsrm_thread_id() == (engine)->m_enginethread) 		return (engine)->engine_thread_handler((msg), (wparam), (lparam), NULL TSRMLS_CC);	return (engine)->SendThreadMessage((msg), (wparam), (lparam));}/* These functions do some magic so that interfaces can be * used across threads without worrying about marshalling * or not marshalling, as appropriate. * Win95 without DCOM 1.1, and NT SP 2 or lower do not have * the GIT; so we emulate the GIT using other means. * If you trace problems back to this code, installing the relevant * SP should solve them. * */static inline HRESULT GIT_get(DWORD cookie, REFIID riid, void **obj){	IGlobalInterfaceTable *git;	HRESULT ret;		if (SUCCEEDED(CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL,					CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable,					(void**)&git))) {				ret = git->GetInterfaceFromGlobal(cookie, riid, obj);		git->Release();		return ret;	}	return CoGetInterfaceAndReleaseStream((LPSTREAM)cookie, riid, obj);}static inline HRESULT GIT_put(IUnknown *unk, REFIID riid, DWORD *cookie){	IGlobalInterfaceTable *git;	HRESULT ret;		if (SUCCEEDED(CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL,					CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable,					(void**)&git))) {				ret = git->RegisterInterfaceInGlobal(unk, riid, cookie);		git->Release();		return ret;	}	return CoMarshalInterThreadInterfaceInStream(riid, unk, (LPSTREAM*)cookie);}static inline HRESULT GIT_revoke(DWORD cookie, IUnknown *unk){	IGlobalInterfaceTable *git;	HRESULT ret;		if (SUCCEEDED(CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL,					CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable,					(void**)&git))) {				ret = git->RevokeInterfaceFromGlobal(cookie);		git->Release();	}	/* Kill remote clients */	return CoDisconnectObject(unk, 0);}/* {{{ A generic stupid IDispatch implementation */class IDispatchImpl:	public IDispatch{protected:	volatile LONG m_refcount;public:	/* IUnknown */	STDMETHODIMP QueryInterface(REFIID iid, void **ppvObject) {		*ppvObject = NULL;		if (IsEqualGUID(IID_IDispatch, iid)) {			*ppvObject = (IDispatch*)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("%08x: IDispatchImpl: release ref count is now %d\n", this, ret);		if (ret == 0)			delete this;		return ret;	}	/* IDispatch */	STDMETHODIMP GetTypeInfoCount(unsigned int *  pctinfo) {		*pctinfo = 0;		trace("%08x: IDispatchImpl: GetTypeInfoCount\n", this);		return S_OK;	}	STDMETHODIMP GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo **ppTInfo) {		trace("%08x: IDispatchImpl: GetTypeInfo\n", this);		return DISP_E_BADINDEX;	}	STDMETHODIMP GetIDsOfNames( REFIID  riid, OLECHAR **rgszNames, unsigned int cNames, LCID lcid, DISPID *rgDispId)	{		unsigned int i;		trace("%08x: IDispatchImpl: GetIDsOfNames: \n", this);		for (i = 0; i < cNames; i++) {			TWideString name(rgszNames[i]);			trace("      %s\n", name.ansi_string());		}		trace("----\n");		return DISP_E_UNKNOWNNAME;	}	STDMETHODIMP Invoke( DISPID  dispIdMember, REFIID  riid, LCID  lcid, WORD  wFlags,		DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult, EXCEPINFO FAR*  pExcepInfo,		unsigned int FAR*  puArgErr)	{		trace("%08x: IDispatchImpl: Invoke dispid %08x\n", this, dispIdMember);		return S_OK;	}	IDispatchImpl() {		m_refcount = 1;	}	virtual ~IDispatchImpl() {	}};/* }}} *//* {{{ This object represents the PHP engine to the scripting host. * Although the docs say it's implementation is optional, I found that * the Windows Script host would crash if we did not provide it. */class ScriptDispatch:	public IDispatchImpl{public:	ScriptDispatch() {		m_refcount = 1;	}};/* }}} *//* {{{ This object is used in conjunction with IActiveScriptParseProcedure to * allow scriptlets to be bound to events.  IE uses this for declaring * event handlers such as onclick="...". * The compiled code is stored in this object; IE will call * IDispatch::Invoke when the element is clicked. * */class ScriptProcedureDispatch:	public IDispatchImpl{public:	code_frag 		*m_frag;	DWORD			m_procflags;	TPHPScriptingEngine *m_engine;	DWORD			m_gitcookie;	STDMETHODIMP Invoke( DISPID  dispIdMember, REFIID  riid, LCID  lcid, WORD  wFlags,		DISPPARAMS FAR*  pDispParams, VARIANT FAR*  pVarResult, EXCEPINFO FAR*  pExcepInfo,		unsigned int FAR*  puArgErr)	{		TSRMLS_FETCH();		if (m_frag) {			trace("%08x: Procedure Dispatch: Invoke dispid %08x\n", this, dispIdMember);			SEND_THREAD_MESSAGE(m_engine, PHPSE_EXEC_PROC, 0, (LPARAM)this TSRMLS_CC);		}		return S_OK;	}	ScriptProcedureDispatch() {		m_refcount = 1;		GIT_put((IDispatch*)this, IID_IDispatch, &m_gitcookie);	}};/* }}} *//* {{{ code fragment management */static code_frag *compile_code_fragment(		enum fragtype fragtype,		char *functionname,		LPCOLESTR code,		ULONG starting_line,		EXCEPINFO *excepinfo,		TPHPScriptingEngine *engine		TSRMLS_DC){	zval pv;	int code_offs = 0;	char namebuf[256];		code_frag *frag = (code_frag*)CoTaskMemAlloc(sizeof(code_frag));	memset(frag, 0, sizeof(code_frag));	frag->engine = engine;		/* handle the function name */	if (functionname) {		int namelen;		if (functionname == FRAG_CREATE_FUNC) {			ULONG n = ++engine->m_lambda_count;			sprintf(namebuf, "__frag_%08x_%u", engine, n);			functionname = namebuf;			}		namelen = strlen(functionname);		code_offs = namelen + sizeof("function (){");		frag->functionname = (char*)CoTaskMemAlloc((namelen + 1) * sizeof(char));		memcpy(frag->functionname, functionname, namelen+1);	}	frag->functionname = functionname;	trace("%08x: COMPILED FRAG\n", frag);		frag->codelen = WideCharToMultiByte(CP_ACP, 0, code, -1, NULL, 0, NULL, NULL);	frag->code = (char*)CoTaskMemAlloc(sizeof(char) * (frag->codelen + code_offs + 1));	if (functionname) {		sprintf(frag->code, "function %s(){ ", functionname);	}		frag->codelen = WideCharToMultiByte(CP_ACP, 0, code, -1, frag->code + code_offs, frag->codelen, NULL, NULL) - 1;		if (functionname) {		frag->codelen += code_offs + 1;		frag->code[frag->codelen-1] = '}';		frag->code[frag->codelen] = 0;	}trace("code to compile is:\ncode_offs=%d  func=%s\n%s\n", code_offs, functionname, frag->code);			frag->fragtype = fragtype;	frag->starting_line = starting_line;		pv.type = IS_STRING;	pv.value.str.val = frag->code;	pv.value.str.len = frag->codelen;	frag->opcodes = compile_string(&pv, "fragment" TSRMLS_CC);	if (frag->opcodes == NULL) {		free_code_fragment(frag);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -