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.

237 lines
6.2 KiB

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP version 4.0 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2001 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. | Harald Radi <h.radi@nme.at> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /*
  20. * This module implements support for Microsoft .Net components.
  21. */
  22. /*
  23. * 28.1.2001
  24. * use external unicode conversion functions
  25. *
  26. * harald radi <h.radi@nme.at>
  27. */
  28. #ifdef PHP_WIN32
  29. #include <iostream.h>
  30. #include <math.h>
  31. #include <comdef.h>
  32. extern "C" { /* this should be included in the includes itself !! */
  33. #include "php.h"
  34. #include "ext/standard/info.h"
  35. }
  36. #include "../com/conversion.h"
  37. #include "../com/php_COM.h"
  38. #include "Mscoree.h"
  39. #include "mscorlib.h"
  40. using namespace mscorlib;
  41. static ICorRuntimeHost *pHost;
  42. static mscorlib::_AppDomain *pDomain;
  43. static zend_class_entry dotnet_class_entry;
  44. static int codepage;
  45. HRESULT dotnet_init() {
  46. HRESULT hr;
  47. hr = CoCreateInstance(CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
  48. IID_ICorRuntimeHost, (void **)&pHost);
  49. if (FAILED(hr)) return hr;
  50. hr = pHost->Start();
  51. if (FAILED(hr)) return hr;
  52. IUnknown *uDomain;
  53. hr = pHost->GetDefaultDomain(&uDomain);
  54. if (FAILED(hr)) return hr;
  55. hr = uDomain->QueryInterface(__uuidof(_AppDomain), (void**) &pDomain);
  56. if (FAILED(hr)) return -1;
  57. uDomain->Release();
  58. return ERROR_SUCCESS;
  59. }
  60. HRESULT dotnet_create(OLECHAR *assembly, OLECHAR *datatype, comval *obj) {
  61. HRESULT hr;
  62. _ObjectHandle *pHandle;
  63. hr = pDomain->CreateInstance(_bstr_t(assembly), _bstr_t(datatype), &pHandle);
  64. if (FAILED(hr)) return hr;
  65. if (!pHandle) return hr;
  66. _variant_t unwrapped;
  67. hr = pHandle->Unwrap(&unwrapped);
  68. pHandle->Release();
  69. if (FAILED(hr)) return hr;
  70. php_COM_set(obj, unwrapped.pdispVal, TRUE);
  71. return ERROR_SUCCESS;
  72. }
  73. void dotnet_term() {
  74. if (pHost) pHost->Stop();
  75. if (pHost) pHost->Release();
  76. if (pDomain) pDomain->Release();
  77. pHost = 0;
  78. pDomain = 0;
  79. }
  80. /* {{{ proto int dotnet_load(string assembly_name [, string datatype_name, int codepage])
  81. Loads a DOTNET module */
  82. PHP_FUNCTION(dotnet_load)
  83. {
  84. HRESULT hr;
  85. pval *assembly_name, *datatype_name, *code_page;
  86. OLECHAR *assembly, *datatype;
  87. comval *obj;
  88. switch(ZEND_NUM_ARGS())
  89. {
  90. case 2:
  91. getParameters(ht, 2, &assembly_name, &datatype_name);
  92. codepage = CP_ACP;
  93. break;
  94. case 3:
  95. getParameters(ht, 3, &assembly_name, &datatype_name, &code_page);
  96. convert_to_long(code_page);
  97. codepage = Z_LVAL_P(code_page);
  98. break;
  99. default:
  100. WRONG_PARAM_COUNT;
  101. break;
  102. }
  103. convert_to_string(assembly_name);
  104. assembly = php_char_to_OLECHAR(Z_STRVAL_P(assembly_name), Z_STRLEN_P(assembly_name), codepage);
  105. convert_to_string(datatype_name);
  106. datatype = php_char_to_OLECHAR(Z_STRVAL_P(datatype_name), Z_STRLEN_P(datatype_name), codepage);
  107. ALLOC_COM(obj);
  108. /* obtain IDispatch */
  109. hr = dotnet_create(assembly, datatype, obj);
  110. efree(assembly);
  111. efree(datatype);
  112. if (FAILED(hr)) {
  113. char *error_message;
  114. error_message = php_COM_error_message(hr);
  115. 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);
  116. LocalFree(error_message);
  117. efree(obj);
  118. RETURN_FALSE;
  119. }
  120. if (C_DISPATCH(obj) == NULL) {
  121. php_error(E_WARNING,"Unable to locate %s in assembly %s",datatype_name->value.str.val,assembly_name->value.str.val);
  122. efree(obj);
  123. RETURN_FALSE;
  124. }
  125. RETURN_LONG(zend_list_insert(obj, IS_COM));
  126. }
  127. /* }}} */
  128. void php_DOTNET_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
  129. {
  130. pval *object = property_reference->object;
  131. zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
  132. if (zend_llist_count(property_reference->elements_list)==1
  133. && !strcmp(Z_STRVAL(function_name->element), "dotnet")) { /* constructor */
  134. pval *object_handle;
  135. PHP_FN(dotnet_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  136. if (!zend_is_true(return_value)) {
  137. var_reset(object);
  138. return;
  139. }
  140. ALLOC_ZVAL(object_handle);
  141. *object_handle = *return_value;
  142. pval_copy_constructor(object_handle);
  143. INIT_PZVAL(object_handle);
  144. zend_hash_index_update(object->value.obj.properties, 0, &object_handle, sizeof(pval *), NULL);
  145. pval_destructor(&function_name->element);
  146. } else {
  147. php_COM_call_function_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, property_reference);
  148. }
  149. }
  150. void php_register_DOTNET_class()
  151. {
  152. INIT_OVERLOADED_CLASS_ENTRY(dotnet_class_entry, "DOTNET", NULL,
  153. php_DOTNET_call_function_handler,
  154. php_COM_get_property_handler,
  155. php_COM_set_property_handler);
  156. zend_register_internal_class(&dotnet_class_entry);
  157. }
  158. function_entry DOTNET_functions[] = {
  159. {NULL, NULL, NULL}
  160. };
  161. static PHP_MINFO_FUNCTION(DOTNET)
  162. {
  163. php_info_print_table_start();
  164. php_info_print_table_row(2, ".NET support", "enabled");
  165. php_info_print_table_end();
  166. }
  167. PHP_MINIT_FUNCTION(DOTNET)
  168. {
  169. HRESULT hr;
  170. CoInitialize(0);
  171. hr = dotnet_init();
  172. if (FAILED(hr)) return hr;
  173. php_register_DOTNET_class();
  174. return SUCCESS;
  175. }
  176. PHP_MSHUTDOWN_FUNCTION(DOTNET)
  177. {
  178. dotnet_term();
  179. CoUninitialize();
  180. return SUCCESS;
  181. }
  182. zend_module_entry dotnet_module_entry = {
  183. "dotnet", DOTNET_functions, PHP_MINIT(DOTNET), PHP_MSHUTDOWN(DOTNET), NULL, NULL, PHP_MINFO(DOTNET), STANDARD_MODULE_PROPERTIES
  184. };
  185. BEGIN_EXTERN_C()
  186. ZEND_GET_MODULE(dotnet)
  187. END_EXTERN_C()
  188. #endif