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.

362 lines
9.0 KiB

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