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.

243 lines
6.3 KiB

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 4.0 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997, 1998, 1999, 2000 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. | Author: Sam Ruby <rubys@us.ibm.com> |
  16. +----------------------------------------------------------------------+
  17. */
  18. /*
  19. * This module implements support for Microsoft .Net components.
  20. */
  21. #ifdef PHP_WIN32
  22. #include <iostream.h>
  23. #include <math.h>
  24. #include <comdef.h>
  25. extern "C" {
  26. #include "php.h"
  27. #include "php_ini.h"
  28. pval php_COM_get_property_handler(zend_property_reference *property_reference);
  29. int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
  30. char *php_COM_error_message(HRESULT hr);
  31. void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
  32. int php_COM_get_le_idispatch();
  33. }
  34. #include <stdio.h>
  35. #include "Mscoree.h"
  36. #include "mscorlib.h"
  37. using namespace mscorlib;
  38. static ICorRuntimeHost *pHost;
  39. static mscorlib::_AppDomain *pDomain;
  40. static zend_class_entry dotnet_class_entry;
  41. static OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen)
  42. {
  43. OLECHAR *unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR)*(strlen+1));
  44. OLECHAR *unicode_ptr = unicode_str;
  45. while (*C_str) {
  46. *unicode_ptr++ = (unsigned short) *C_str++;
  47. }
  48. *unicode_ptr = 0;
  49. return unicode_str;
  50. }
  51. HRESULT dotnet_init() {
  52. HRESULT hr;
  53. hr = CoCreateInstance(CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
  54. IID_ICorRuntimeHost, (void **)&pHost);
  55. if (FAILED(hr)) return hr;
  56. hr = pHost->Start();
  57. if (FAILED(hr)) return hr;
  58. IUnknown *uDomain;
  59. hr = pHost->GetDefaultDomain(&uDomain);
  60. if (FAILED(hr)) return hr;
  61. hr = uDomain->QueryInterface(__uuidof(_AppDomain), (void**) &pDomain);
  62. if (FAILED(hr)) return -1;
  63. uDomain->Release();
  64. return ERROR_SUCCESS;
  65. }
  66. HRESULT dotnet_create(OLECHAR *assembly, OLECHAR *datatype, struct IDispatch **object) {
  67. HRESULT hr;
  68. _ObjectHandle *pHandle;
  69. hr = pDomain->CreateInstance(_bstr_t(assembly), _bstr_t(datatype), &pHandle);
  70. if (FAILED(hr)) return hr;
  71. if (!pHandle) return hr;
  72. _variant_t unwrapped;
  73. hr = pHandle->Unwrap(&unwrapped);
  74. pHandle->Release();
  75. if (FAILED(hr)) return hr;
  76. *object = unwrapped.pdispVal;
  77. return ERROR_SUCCESS;
  78. }
  79. void dotnet_term() {
  80. if (pHost) pHost->Stop();
  81. if (pHost) pHost->Release();
  82. if (pDomain) pDomain->Release();
  83. pHost = 0;
  84. pDomain = 0;
  85. }
  86. /* {{{ proto int dotnet_load(string module_name)
  87. Loads a DOTNET module */
  88. PHP_FUNCTION(DOTNET_load)
  89. {
  90. HRESULT hr;
  91. pval *assembly_name, *datatype_name;
  92. OLECHAR *assembly, *datatype;
  93. IDispatch FAR *i_dispatch = NULL;
  94. if (ZEND_NUM_ARGS() != 2) WRONG_PARAM_COUNT;
  95. getParameters(ht, 2, &assembly_name, &datatype_name);
  96. convert_to_string(assembly_name);
  97. assembly = php_char_to_OLECHAR(assembly_name->value.str.val, assembly_name->value.str.len);
  98. convert_to_string(datatype_name);
  99. datatype = php_char_to_OLECHAR(datatype_name->value.str.val, datatype_name->value.str.len);
  100. /* obtain IDispatch */
  101. hr=dotnet_create(assembly, datatype, &i_dispatch);
  102. efree(assembly);
  103. efree(datatype);
  104. if (FAILED(hr)) {
  105. char *error_message;
  106. error_message = php_COM_error_message(hr);
  107. php_error(E_WARNING,"Error obtaining .Net class for %s in assembly %s: %s",datatype_name->value.str.val,assembly_name->value.str.val,error_message);
  108. LocalFree(error_message);
  109. RETURN_FALSE;
  110. }
  111. if (!i_dispatch) {
  112. php_error(E_WARNING,"Unable to locate %s in assembly %s",datatype_name->value.str.val,assembly_name->value.str.val);
  113. RETURN_FALSE;
  114. }
  115. RETURN_LONG(zend_list_insert(i_dispatch,php_COM_get_le_idispatch()));
  116. }
  117. /* }}} */
  118. void php_DOTNET_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
  119. {
  120. pval *object = property_reference->object;
  121. zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
  122. if (zend_llist_count(property_reference->elements_list)==1
  123. && !strcmp(function_name->element.value.str.val, "dotnet")) { /* constructor */
  124. pval *object_handle;
  125. PHP_FN(DOTNET_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  126. if (!zend_is_true(return_value)) {
  127. var_reset(object);
  128. return;
  129. }
  130. ALLOC_ZVAL(object_handle);
  131. *object_handle = *return_value;
  132. pval_copy_constructor(object_handle);
  133. INIT_PZVAL(object_handle);
  134. zend_hash_index_update(object->value.obj.properties, 0, &object_handle, sizeof(pval *), NULL);
  135. pval_destructor(&function_name->element);
  136. } else {
  137. php_COM_call_function_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_reference);
  138. }
  139. }
  140. void php_register_DOTNET_class()
  141. {
  142. INIT_OVERLOADED_CLASS_ENTRY(dotnet_class_entry, "DOTNET", NULL,
  143. php_DOTNET_call_function_handler,
  144. php_COM_get_property_handler,
  145. php_COM_set_property_handler);
  146. zend_register_internal_class(&dotnet_class_entry);
  147. }
  148. function_entry DOTNET_functions[] = {
  149. {NULL, NULL, NULL}
  150. };
  151. static PHP_MINFO_FUNCTION(DOTNET)
  152. {
  153. DISPLAY_INI_ENTRIES();
  154. }
  155. PHP_INI_BEGIN()
  156. PHP_INI_END()
  157. PHP_MINIT_FUNCTION(DOTNET)
  158. {
  159. HRESULT hr;
  160. CoInitialize(0);
  161. hr = dotnet_init();
  162. if (FAILED(hr)) return hr;
  163. php_register_DOTNET_class();
  164. REGISTER_INI_ENTRIES();
  165. return SUCCESS;
  166. }
  167. PHP_MSHUTDOWN_FUNCTION(DOTNET)
  168. {
  169. dotnet_term();
  170. CoUninitialize();
  171. UNREGISTER_INI_ENTRIES();
  172. return SUCCESS;
  173. }
  174. zend_module_entry dotnet_module_entry = {
  175. "dotnet", DOTNET_functions, PHP_MINIT(DOTNET), PHP_MSHUTDOWN(DOTNET), NULL, NULL, PHP_MINFO(DOTNET), STANDARD_MODULE_PROPERTIES
  176. };
  177. extern "C" {
  178. ZEND_GET_MODULE(dotnet)
  179. }
  180. void php_register_DOTNET_class();
  181. #endif