diff options
| author | Wez Furlong <wez@php.net> | 2002-05-20 01:35:29 +0000 | 
|---|---|---|
| committer | Wez Furlong <wez@php.net> | 2002-05-20 01:35:29 +0000 | 
| commit | e754361405395908abd687b1403215da2bd98b92 (patch) | |
| tree | e695f256b31e3a721667dba65199d34869455948 /sapi/activescript/classfactory.cpp | |
| parent | 50f7427e69741acf9094a0f63c35503bfa4afca6 (diff) | |
| download | php-git-e754361405395908abd687b1403215da2bd98b92.tar.gz | |
Implement ActiveScript interfaces.
This allows use of PHP in:
  Client-side script in Internet Explorer
  Windows Scripting Host
  ASP and ASP.NET pages
It's mostly working... give it a go.
You will need to regsvr32 the php4activescript.dll manually.
Diffstat (limited to 'sapi/activescript/classfactory.cpp')
| -rw-r--r-- | sapi/activescript/classfactory.cpp | 361 | 
1 files changed, 361 insertions, 0 deletions
diff --git a/sapi/activescript/classfactory.cpp b/sapi/activescript/classfactory.cpp new file mode 100644 index 0000000000..3d4f256db6 --- /dev/null +++ b/sapi/activescript/classfactory.cpp @@ -0,0 +1,361 @@ +/* +   +----------------------------------------------------------------------+ +   | PHP Version 4                                                        | +   +----------------------------------------------------------------------+ +   | Copyright (c) 1997-2002 The PHP Group                                | +   +----------------------------------------------------------------------+ +   | This source file is subject to version 2.02 of the PHP license,      | +   | that is bundled with this package in the file LICENSE, and is        | +   | available at through the world-wide-web at                           | +   | http://www.php.net/license/2_02.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$ */ + +/* IClassFactory Implementation, and DllXXX function implementation */ + +#define INITGUID +#define DEBUG_CLASS_FACTORY 0 + +#include <windows.h> +#include <initguid.h> + +extern "C" { +HINSTANCE module_handle; +} + +#include <comcat.h> +#include "TSRM.h" +#include "php4as_classfactory.h" +#include "php4as_scriptengine.h" + +volatile LONG TPHPClassFactory::factory_count = 0; +volatile LONG TPHPClassFactory::object_count = 0; + +/* {{{ Class Factory Implementation */ +TPHPClassFactory::TPHPClassFactory() +{ +	m_refcount = 1; +	InterlockedIncrement(&factory_count); +} + +TPHPClassFactory::~TPHPClassFactory() +{ +	InterlockedDecrement(&factory_count); +} + +void TPHPClassFactory::AddToObjectCount(void) +{ +	InterlockedIncrement(&object_count); +} + +void TPHPClassFactory::RemoveFromObjectCount(void) +{ +	InterlockedDecrement(&object_count); +} + +STDMETHODIMP_(DWORD) TPHPClassFactory::AddRef(void) +{ +	return InterlockedIncrement(&m_refcount); +} + +STDMETHODIMP_(DWORD) TPHPClassFactory::Release(void) +{ +	DWORD ret = InterlockedDecrement(&m_refcount); +	if (ret == 0) +		delete this; +	return ret; +} + +STDMETHODIMP TPHPClassFactory::QueryInterface(REFIID iid, void **ppvObject) +{ +	*ppvObject = NULL; +	 +	if (IsEqualGUID(IID_IClassFactory, iid)) { +		*ppvObject = (IClassFactory*)this; +	} else if (IsEqualGUID(IID_IUnknown, iid)) { +		*ppvObject = this;	 +	} +	if (*ppvObject) { +		AddRef(); +		return S_OK; +	} +	 +	return E_NOINTERFACE; +} + +STDMETHODIMP TPHPClassFactory::LockServer(BOOL fLock) +{ +	return E_NOTIMPL; +} + +STDMETHODIMP TPHPClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppvObject) +{ +	TPHPScriptingEngine *engine = new TPHPScriptingEngine; + +	HRESULT ret = engine->QueryInterface(iid, ppvObject); + +	engine->Release(); +	 +	return ret; +} + +int TPHPClassFactory::CanUnload(void) +{ +	return (object_count + factory_count) == 0 ? 1 : 0; +} + +/* }}} */ + +/* {{{ Registration structures */ +struct reg_entry { +	HKEY root_key; +	char *sub_key; +	char *value_name; +	char *data; +}; + +struct reg_class { +	/* REFIID here causes compilation errors */ +	const GUID *class_id; +	char *class_name; +	char *threading; +	const struct reg_entry *reg; +	const GUID **cats; +}; + +#define MAX_REG_SUBST	8 +struct reg_subst { +	int count; +	char *names[MAX_REG_SUBST]; +	char *values[MAX_REG_SUBST]; +}; +/* }}} */ + +/* {{{ Registration information */ +/* This registers the sapi as a scripting engine that can be instantiated using it's progid */ +static const struct reg_entry engine_entries[] = { +	{ HKEY_CLASSES_ROOT,	"CLSID\\[CLSID]",	 				NULL,				"[CLASSNAME]" }, +	{ 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}, +	 +	{ 0, NULL, NULL, NULL } +}; + +static const GUID *script_engine_categories[] = { +	&CATID_ActiveScript, +	&CATID_ActiveScriptParse, +	NULL +}; + +static const struct reg_class classes_to_register[] = { +	{ &CLSID_PHPActiveScriptEngine, "PHP Active Script Engine", "Both", engine_entries, script_engine_categories }, +	{ NULL, NULL, NULL, 0, NULL } +}; +/* }}} */ + +/* {{{ Registration code */ +static void substitute(struct reg_subst *subst, char *srcstring, char *deststring) +{ +	int i; +	char *srcpos = srcstring; +	char *destpos = deststring; +	 +	while(1) { +		char *repstart = strchr(srcpos, '['); + +		if (repstart == NULL) { +			strcpy(destpos, srcpos); +			break; +		} + +		/* copy everything up until that character to the dest */ +		strncpy(destpos, srcpos, repstart - srcpos); +		destpos += repstart - srcpos; +		*destpos = 0; + +		/* search for replacement strings in the table */ +		for (i = 0; i < subst->count; i++) { +			int len = strlen(subst->names[i]); +			if (strncmp(subst->names[i], repstart + 1, len) == 0) { +				/* append the replacement value to the buffer */ +				strcpy(destpos, subst->values[i]); +				destpos += strlen(subst->values[i]); +				srcpos = repstart + len + 2; + +				break; +			} +		} +	} +#if DEBUG_CLASS_FACTORY +	MessageBox(0, deststring, srcstring, MB_ICONHAND); +#endif +} + +static int reg_string(BOOL do_reg, struct reg_subst *subst, const struct reg_entry *entry) +{ +	char subbuf[MAX_PATH], valuebuf[MAX_PATH], databuf[MAX_PATH]; +	char *sub = NULL, *value = NULL, *data = NULL; +	LRESULT res; +	HKEY hkey; +	DWORD disp; +	 +	if (entry->sub_key) { +		substitute(subst, entry->sub_key, subbuf); +		sub = subbuf; +	} + +	if (entry->value_name) { +		substitute(subst, entry->value_name, valuebuf); +		value = valuebuf; +	} + +	if (entry->data) { +		substitute(subst, entry->data, databuf); +		data = databuf; +	} + +	if (do_reg) { +		res = RegCreateKeyEx(entry->root_key, sub, 0, NULL, REG_OPTION_NON_VOLATILE, +				KEY_WRITE, NULL, &hkey, &disp); +		if (res == NOERROR) { +			if (data) +				res = RegSetValueEx(hkey, value, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1); +			RegCloseKey(hkey); +		} +	} else { +		res = RegDeleteKey(entry->root_key, sub); +	} +	return res == NOERROR ? 1 : 0; +} + +static int perform_registration(BOOL do_reg) +{ +	char module_name[MAX_PATH]; +	char classid[40]; +	int ret = 0; +	int i, j; +	struct reg_subst subst = {0}; +	LPOLESTR classidw; +	ICatRegister *catreg = NULL; +	CATID cats[8]; +	int ncats; + +	CoInitialize(NULL); +	CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID*)&catreg); + +	GetModuleFileName(module_handle, module_name, sizeof(module_name)); +		 +	subst.names[0] = "CLSID"; +	subst.values[0] = classid; + +	subst.names[1] = "MODULENAME"; +	subst.values[1] = module_name; + +	subst.names[2] = "CLASSNAME"; +	subst.names[3] = "THREADING"; + +	subst.count = 4; + +	for (i = 0; classes_to_register[i].class_id; i++) { +		StringFromCLSID(*classes_to_register[i].class_id, &classidw); +		WideCharToMultiByte(CP_ACP, 0, classidw, -1, classid, sizeof(classid), NULL, NULL); +		classid[39] = 0; +		CoTaskMemFree(classidw); + +		subst.values[2] = classes_to_register[i].class_name; +		subst.values[3] = classes_to_register[i].threading; + +		if (catreg && classes_to_register[i].cats) { +			ncats = 0; +			while(classes_to_register[i].cats[ncats]) { +				CopyMemory(&cats[ncats], classes_to_register[i].cats[ncats], sizeof(CATID)); +				ncats++; +			} +		} +		 +		if (do_reg) { +			for (j = 0; classes_to_register[i].reg[j].root_key; j++) { +				if (!reg_string(do_reg, &subst, &classes_to_register[i].reg[j])) { +					ret = 0; +					break; +				} +			} +			 +			if (catreg && ncats) { +				catreg->RegisterClassImplCategories(*classes_to_register[i].class_id, ncats, cats); +			} +			 +		} else { + +			if (catreg && ncats) { +				catreg->UnRegisterClassImplCategories(*classes_to_register[i].class_id, ncats, cats); +			} + +			/* do it in reverse order, so count the number of entries first */ +			for (j = 0; classes_to_register[i].reg[j].root_key; j++) +				; +			while(j-- > 0) { +				if (!reg_string(do_reg, &subst, &classes_to_register[i].reg[j])) { +					ret = 0; +					break; +				} +			} +		} +	} + +	if (catreg) +		catreg->Release(); +	CoUninitialize(); +	 +	return ret; +} +/* }}} */ + +/* {{{ Standard COM server DllXXX entry points */ + +STDAPI DllCanUnloadNow(void) +{ +	if (TPHPClassFactory::CanUnload()) +		return S_OK; +	return S_FALSE; +} + +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ +	HRESULT ret = E_FAIL; + +	if (IsEqualCLSID(CLSID_PHPActiveScriptEngine, rclsid)) { +		TPHPClassFactory *factory = new TPHPClassFactory(); + +		if (factory) { +			ret = factory->QueryInterface(riid, ppv); +			factory->Release(); +		} +	} +	return ret; +} + + + +STDAPI DllRegisterServer(void) +{ +	return perform_registration(TRUE) ? S_OK : S_FALSE; +} + +STDAPI DllUnregisterServer(void) +{ +	return perform_registration(FALSE) ? S_OK : S_FALSE; +} + +/* }}} */  | 
