summaryrefslogtreecommitdiff
path: root/sapi/activescript/classfactory.cpp
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2002-05-20 01:35:29 +0000
committerWez Furlong <wez@php.net>2002-05-20 01:35:29 +0000
commite754361405395908abd687b1403215da2bd98b92 (patch)
treee695f256b31e3a721667dba65199d34869455948 /sapi/activescript/classfactory.cpp
parent50f7427e69741acf9094a0f63c35503bfa4afca6 (diff)
downloadphp-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.cpp361
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;
+}
+
+/* }}} */