You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

361 lines
8.9 KiB

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 4 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2002 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.02 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available at through the world-wide-web at |
  10. | http://www.php.net/license/2_02.txt. |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Wez Furlong <wez@thebrainroom.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /* $Id$ */
  19. /* IClassFactory Implementation, and DllXXX function implementation */
  20. #define INITGUID
  21. #define DEBUG_CLASS_FACTORY 0
  22. #include <windows.h>
  23. #include <initguid.h>
  24. extern "C" {
  25. HINSTANCE module_handle;
  26. }
  27. #include <comcat.h>
  28. #include "TSRM.h"
  29. #include "php4as_classfactory.h"
  30. #include "php4as_scriptengine.h"
  31. volatile LONG TPHPClassFactory::factory_count = 0;
  32. volatile LONG TPHPClassFactory::object_count = 0;
  33. /* {{{ Class Factory Implementation */
  34. TPHPClassFactory::TPHPClassFactory()
  35. {
  36. m_refcount = 1;
  37. InterlockedIncrement(const_cast<long*> (&factory_count));
  38. }
  39. TPHPClassFactory::~TPHPClassFactory()
  40. {
  41. InterlockedDecrement(const_cast<long*> (&factory_count));
  42. }
  43. void TPHPClassFactory::AddToObjectCount(void)
  44. {
  45. InterlockedIncrement(const_cast<long*> (&object_count));
  46. }
  47. void TPHPClassFactory::RemoveFromObjectCount(void)
  48. {
  49. InterlockedDecrement(const_cast<long*> (&object_count));
  50. }
  51. STDMETHODIMP_(DWORD) TPHPClassFactory::AddRef(void)
  52. {
  53. return InterlockedIncrement(const_cast<long*> (&m_refcount));
  54. }
  55. STDMETHODIMP_(DWORD) TPHPClassFactory::Release(void)
  56. {
  57. DWORD ret = InterlockedDecrement(const_cast<long*> (&m_refcount));
  58. if (ret == 0)
  59. delete this;
  60. return ret;
  61. }
  62. STDMETHODIMP TPHPClassFactory::QueryInterface(REFIID iid, void **ppvObject)
  63. {
  64. *ppvObject = NULL;
  65. if (IsEqualGUID(IID_IClassFactory, iid)) {
  66. *ppvObject = (IClassFactory*)this;
  67. } else if (IsEqualGUID(IID_IUnknown, iid)) {
  68. *ppvObject = this;
  69. }
  70. if (*ppvObject) {
  71. AddRef();
  72. return S_OK;
  73. }
  74. return E_NOINTERFACE;
  75. }
  76. STDMETHODIMP TPHPClassFactory::LockServer(BOOL fLock)
  77. {
  78. return E_NOTIMPL;
  79. }
  80. STDMETHODIMP TPHPClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppvObject)
  81. {
  82. TPHPScriptingEngine *engine = new TPHPScriptingEngine;
  83. HRESULT ret = engine->QueryInterface(iid, ppvObject);
  84. engine->Release();
  85. return ret;
  86. }
  87. int TPHPClassFactory::CanUnload(void)
  88. {
  89. return (object_count + factory_count) == 0 ? 1 : 0;
  90. }
  91. /* }}} */
  92. /* {{{ Registration structures */
  93. struct reg_entry {
  94. HKEY root_key;
  95. char *sub_key;
  96. char *value_name;
  97. char *data;
  98. };
  99. struct reg_class {
  100. /* REFIID here causes compilation errors */
  101. const GUID *class_id;
  102. char *class_name;
  103. char *threading;
  104. const struct reg_entry *reg;
  105. const GUID **cats;
  106. };
  107. #define MAX_REG_SUBST 8
  108. struct reg_subst {
  109. int count;
  110. char *names[MAX_REG_SUBST];
  111. char *values[MAX_REG_SUBST];
  112. };
  113. /* }}} */
  114. /* {{{ Registration information */
  115. /* This registers the sapi as a scripting engine that can be instantiated using it's progid */
  116. static const struct reg_entry engine_entries[] = {
  117. { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]", NULL, "[CLASSNAME]" },
  118. { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\InprocServer32", NULL, "[MODULENAME]" },
  119. { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\InprocServer32", "ThreadingModel", "[THREADING]" },
  120. { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\OLEScript", NULL, NULL },
  121. { HKEY_CLASSES_ROOT, "CLSID\\[CLSID]\\ProgID", NULL, "ActivePHP" },
  122. { HKEY_CLASSES_ROOT, "ActivePHP", NULL, "ActivePHP" },
  123. { HKEY_CLASSES_ROOT, "ActivePHP\\CLSID", NULL, "[CLSID]"},
  124. { HKEY_CLASSES_ROOT, "ActivePHP\\OLEScript", NULL, NULL},
  125. { 0, NULL, NULL, NULL }
  126. };
  127. static const GUID *script_engine_categories[] = {
  128. &CATID_ActiveScript,
  129. &CATID_ActiveScriptParse,
  130. NULL
  131. };
  132. static const struct reg_class classes_to_register[] = {
  133. { &CLSID_PHPActiveScriptEngine, "PHP Active Script Engine", "Both", engine_entries, script_engine_categories },
  134. { NULL, NULL, NULL, 0, NULL }
  135. };
  136. /* }}} */
  137. /* {{{ Registration code */
  138. static void substitute(struct reg_subst *subst, char *srcstring, char *deststring)
  139. {
  140. int i;
  141. char *srcpos = srcstring;
  142. char *destpos = deststring;
  143. while(1) {
  144. char *repstart = strchr(srcpos, '[');
  145. if (repstart == NULL) {
  146. strcpy(destpos, srcpos);
  147. break;
  148. }
  149. /* copy everything up until that character to the dest */
  150. strncpy(destpos, srcpos, repstart - srcpos);
  151. destpos += repstart - srcpos;
  152. *destpos = 0;
  153. /* search for replacement strings in the table */
  154. for (i = 0; i < subst->count; i++) {
  155. int len = strlen(subst->names[i]);
  156. if (strncmp(subst->names[i], repstart + 1, len) == 0) {
  157. /* append the replacement value to the buffer */
  158. strcpy(destpos, subst->values[i]);
  159. destpos += strlen(subst->values[i]);
  160. srcpos = repstart + len + 2;
  161. break;
  162. }
  163. }
  164. }
  165. #if DEBUG_CLASS_FACTORY
  166. MessageBox(0, deststring, srcstring, MB_ICONHAND);
  167. #endif
  168. }
  169. static int reg_string(BOOL do_reg, struct reg_subst *subst, const struct reg_entry *entry)
  170. {
  171. char subbuf[MAX_PATH], valuebuf[MAX_PATH], databuf[MAX_PATH];
  172. char *sub = NULL, *value = NULL, *data = NULL;
  173. LRESULT res;
  174. HKEY hkey;
  175. DWORD disp;
  176. if (entry->sub_key) {
  177. substitute(subst, entry->sub_key, subbuf);
  178. sub = subbuf;
  179. }
  180. if (entry->value_name) {
  181. substitute(subst, entry->value_name, valuebuf);
  182. value = valuebuf;
  183. }
  184. if (entry->data) {
  185. substitute(subst, entry->data, databuf);
  186. data = databuf;
  187. }
  188. if (do_reg) {
  189. res = RegCreateKeyEx(entry->root_key, sub, 0, NULL, REG_OPTION_NON_VOLATILE,
  190. KEY_WRITE, NULL, &hkey, &disp);
  191. if (res == NOERROR) {
  192. if (data)
  193. res = RegSetValueEx(hkey, value, 0, REG_SZ, (LPBYTE)data, strlen(data) + 1);
  194. RegCloseKey(hkey);
  195. }
  196. } else {
  197. res = RegDeleteKey(entry->root_key, sub);
  198. }
  199. return res == NOERROR ? 1 : 0;
  200. }
  201. static int perform_registration(BOOL do_reg)
  202. {
  203. char module_name[MAX_PATH];
  204. char classid[40];
  205. int ret = 0;
  206. int i, j;
  207. struct reg_subst subst = {0};
  208. LPOLESTR classidw;
  209. ICatRegister *catreg = NULL;
  210. CATID cats[8];
  211. int ncats;
  212. CoInitialize(NULL);
  213. CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (LPVOID*)&catreg);
  214. GetModuleFileName(module_handle, module_name, sizeof(module_name));
  215. subst.names[0] = "CLSID";
  216. subst.values[0] = classid;
  217. subst.names[1] = "MODULENAME";
  218. subst.values[1] = module_name;
  219. subst.names[2] = "CLASSNAME";
  220. subst.names[3] = "THREADING";
  221. subst.count = 4;
  222. for (i = 0; classes_to_register[i].class_id; i++) {
  223. StringFromCLSID(*classes_to_register[i].class_id, &classidw);
  224. WideCharToMultiByte(CP_ACP, 0, classidw, -1, classid, sizeof(classid), NULL, NULL);
  225. classid[39] = 0;
  226. CoTaskMemFree(classidw);
  227. subst.values[2] = classes_to_register[i].class_name;
  228. subst.values[3] = classes_to_register[i].threading;
  229. if (catreg && classes_to_register[i].cats) {
  230. ncats = 0;
  231. while(classes_to_register[i].cats[ncats]) {
  232. CopyMemory(&cats[ncats], classes_to_register[i].cats[ncats], sizeof(CATID));
  233. ncats++;
  234. }
  235. }
  236. if (do_reg) {
  237. for (j = 0; classes_to_register[i].reg[j].root_key; j++) {
  238. if (!reg_string(do_reg, &subst, &classes_to_register[i].reg[j])) {
  239. ret = 0;
  240. break;
  241. }
  242. }
  243. if (catreg && ncats) {
  244. catreg->RegisterClassImplCategories(*classes_to_register[i].class_id, ncats, cats);
  245. }
  246. } else {
  247. if (catreg && ncats) {
  248. catreg->UnRegisterClassImplCategories(*classes_to_register[i].class_id, ncats, cats);
  249. }
  250. /* do it in reverse order, so count the number of entries first */
  251. for (j = 0; classes_to_register[i].reg[j].root_key; j++)
  252. ;
  253. while(j-- > 0) {
  254. if (!reg_string(do_reg, &subst, &classes_to_register[i].reg[j])) {
  255. ret = 0;
  256. break;
  257. }
  258. }
  259. }
  260. }
  261. if (catreg)
  262. catreg->Release();
  263. CoUninitialize();
  264. return ret;
  265. }
  266. /* }}} */
  267. /* {{{ Standard COM server DllXXX entry points */
  268. STDAPI DllCanUnloadNow(void)
  269. {
  270. if (TPHPClassFactory::CanUnload())
  271. return S_OK;
  272. return S_FALSE;
  273. }
  274. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  275. {
  276. HRESULT ret = E_FAIL;
  277. if (IsEqualCLSID(CLSID_PHPActiveScriptEngine, rclsid)) {
  278. TPHPClassFactory *factory = new TPHPClassFactory();
  279. if (factory) {
  280. ret = factory->QueryInterface(riid, ppv);
  281. factory->Release();
  282. }
  283. }
  284. return ret;
  285. }
  286. STDAPI DllRegisterServer(void)
  287. {
  288. return perform_registration(TRUE) ? S_OK : S_FALSE;
  289. }
  290. STDAPI DllUnregisterServer(void)
  291. {
  292. return perform_registration(FALSE) ? S_OK : S_FALSE;
  293. }
  294. /* }}} */