Annotation of embedaddon/php/ext/com_dotnet/com_dotnet.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 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_01.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: Wez Furlong <wez@thebrainroom.com> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: com_dotnet.c 321634 2012-01-01 13:15:04Z felipe $ */
! 20:
! 21: #ifdef HAVE_CONFIG_H
! 22: #include "config.h"
! 23: #endif
! 24:
! 25: #include "php.h"
! 26:
! 27: #if HAVE_MSCOREE_H
! 28: # include "php_ini.h"
! 29: # include "ext/standard/info.h"
! 30: # include "php_com_dotnet.h"
! 31: # include "php_com_dotnet_internal.h"
! 32: # include "Zend/zend_exceptions.h"
! 33: # include <mscoree.h>
! 34:
! 35: /* Since there is no official public mscorlib.h header file, and since
! 36: * generating your own version from the elusive binary .tlb file takes a lot of
! 37: * hacking and results in a 3MB header file (!), we opt for this slightly
! 38: * voodoo approach. The following is just enough definition to be able to
! 39: * reach the _AppDomain::CreateInstance method that we need to use to be able
! 40: * to fire up .Net objects. We used to use IDispatch for this, but it would
! 41: * not always work.
! 42: *
! 43: * The following info was obtained using OleView to export the IDL from
! 44: * mscorlib.tlb. Note that OleView is unable to generate C headers for this
! 45: * particular tlb... hence this mess.
! 46: */
! 47:
! 48: const GUID IID_mscorlib_System_AppDomain = {
! 49: 0x05F696DC, 0x2B29, 0x3663, {0xAD, 0x8B, 0xC4, 0x38, 0x9C, 0xF2, 0xA7, 0x13 }};
! 50:
! 51: typedef struct _Imscorlib_System_AppDomain IAppDomain;
! 52:
! 53: struct _Imscorlib_System_AppDomainVtbl {
! 54: BEGIN_INTERFACE
! 55:
! 56: HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
! 57: IAppDomain * This,
! 58: /* [in] */ REFIID riid,
! 59: /* [iid_is][out] */ void **ppvObject);
! 60:
! 61: ULONG ( STDMETHODCALLTYPE *AddRef )(
! 62: IAppDomain * This);
! 63:
! 64: ULONG ( STDMETHODCALLTYPE *Release )(
! 65: IAppDomain * This);
! 66:
! 67: /* this is padding to get CreateInstance into the correct position */
! 68: #define DUMMY_METHOD(x) HRESULT ( STDMETHODCALLTYPE *dummy_##x )(IAppDomain *This)
! 69:
! 70: DUMMY_METHOD(GetTypeInfoCount);
! 71: DUMMY_METHOD(GetTypeInfo);
! 72: DUMMY_METHOD(GetIDsOfNames);
! 73: DUMMY_METHOD(Invoke);
! 74: DUMMY_METHOD(ToString);
! 75: DUMMY_METHOD(Equals);
! 76: DUMMY_METHOD(GetHashCode);
! 77: DUMMY_METHOD(GetType);
! 78: DUMMY_METHOD(InitializeLifetimeService);
! 79: DUMMY_METHOD(GetLifetimeService);
! 80: DUMMY_METHOD(Evidence);
! 81: DUMMY_METHOD(add_DomainUnload);
! 82: DUMMY_METHOD(remove_DomainUnload);
! 83: DUMMY_METHOD(add_AssemblyLoad);
! 84: DUMMY_METHOD(remove_AssemblyLoad);
! 85: DUMMY_METHOD(add_ProcessExit);
! 86: DUMMY_METHOD(remove_ProcessExit);
! 87: DUMMY_METHOD(add_TypeResolve);
! 88: DUMMY_METHOD(remove_TypeResolve);
! 89: DUMMY_METHOD(add_ResourceResolve);
! 90: DUMMY_METHOD(remove_ResourceResolve);
! 91: DUMMY_METHOD(add_AssemblyResolve);
! 92: DUMMY_METHOD(remove_AssemblyResolve);
! 93: DUMMY_METHOD(add_UnhandledException);
! 94: DUMMY_METHOD(remove_UnhandledException);
! 95: DUMMY_METHOD(DefineDynamicAssembly);
! 96: DUMMY_METHOD(DefineDynamicAssembly_2);
! 97: DUMMY_METHOD(DefineDynamicAssembly_3);
! 98: DUMMY_METHOD(DefineDynamicAssembly_4);
! 99: DUMMY_METHOD(DefineDynamicAssembly_5);
! 100: DUMMY_METHOD(DefineDynamicAssembly_6);
! 101: DUMMY_METHOD(DefineDynamicAssembly_7);
! 102: DUMMY_METHOD(DefineDynamicAssembly_8);
! 103: DUMMY_METHOD(DefineDynamicAssembly_9);
! 104:
! 105: HRESULT ( STDMETHODCALLTYPE *CreateInstance )(IAppDomain * This, BSTR AssemblyName, BSTR typeName, IUnknown **pRetVal);
! 106: HRESULT ( STDMETHODCALLTYPE *CreateInstanceFrom )(IAppDomain * This, BSTR AssemblyFile, BSTR typeName, IUnknown **pRetVal);
! 107:
! 108: /* more methods live here */
! 109:
! 110: END_INTERFACE
! 111: };
! 112:
! 113: struct _Imscorlib_System_AppDomain {
! 114: struct _Imscorlib_System_AppDomainVtbl *lpVtbl;
! 115: };
! 116:
! 117:
! 118: struct dotnet_runtime_stuff {
! 119: ICorRuntimeHost *dotnet_host;
! 120: IAppDomain *dotnet_domain;
! 121: DISPID create_instance;
! 122: };
! 123:
! 124: static HRESULT dotnet_init(char **p_where TSRMLS_DC)
! 125: {
! 126: HRESULT hr;
! 127: struct dotnet_runtime_stuff *stuff;
! 128: IUnknown *unk = NULL;
! 129: char *where = "";
! 130:
! 131: stuff = malloc(sizeof(*stuff));
! 132: if (!stuff) {
! 133: return S_FALSE;
! 134: }
! 135: memset(stuff, 0, sizeof(*stuff));
! 136:
! 137: where = "CoCreateInstance";
! 138: hr = CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
! 139: &IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host);
! 140:
! 141: if (FAILED(hr))
! 142: goto out;
! 143:
! 144: /* fire up the host and get the domain object */
! 145: where = "ICorRuntimeHost_Start\n";
! 146: hr = ICorRuntimeHost_Start(stuff->dotnet_host);
! 147: if (FAILED(hr))
! 148: goto out;
! 149:
! 150: where = "ICorRuntimeHost_GetDefaultDomain";
! 151: hr = ICorRuntimeHost_GetDefaultDomain(stuff->dotnet_host, &unk);
! 152: if (FAILED(hr))
! 153: goto out;
! 154:
! 155: where = "QI: System._AppDomain";
! 156: hr = IUnknown_QueryInterface(unk, &IID_mscorlib_System_AppDomain, (LPVOID*)&stuff->dotnet_domain);
! 157: if (FAILED(hr))
! 158: goto out;
! 159:
! 160: COMG(dotnet_runtime_stuff) = stuff;
! 161:
! 162: out:
! 163: if (unk) {
! 164: IUnknown_Release(unk);
! 165: }
! 166: if (COMG(dotnet_runtime_stuff) == NULL) {
! 167: /* clean up */
! 168: if (stuff->dotnet_domain) {
! 169: IUnknown_Release(stuff->dotnet_domain);
! 170: }
! 171: if (stuff->dotnet_host) {
! 172: ICorRuntimeHost_Stop(stuff->dotnet_host);
! 173: ICorRuntimeHost_Release(stuff->dotnet_host);
! 174: }
! 175: free(stuff);
! 176:
! 177: *p_where = where;
! 178:
! 179: return hr;
! 180: }
! 181:
! 182: return S_OK;
! 183: }
! 184:
! 185: /* {{{ com_dotnet_create_instance - ctor for DOTNET class */
! 186: PHP_FUNCTION(com_dotnet_create_instance)
! 187: {
! 188: zval *object = getThis();
! 189: php_com_dotnet_object *obj;
! 190: char *assembly_name, *datatype_name;
! 191: int assembly_name_len, datatype_name_len;
! 192: struct dotnet_runtime_stuff *stuff;
! 193: OLECHAR *oleassembly, *oletype;
! 194: BSTR oleassembly_sys, oletype_sys;
! 195: HRESULT hr;
! 196: int ret = FAILURE;
! 197: char *where = "";
! 198: IUnknown *unk = NULL;
! 199:
! 200: php_com_initialize(TSRMLS_C);
! 201: if (COMG(dotnet_runtime_stuff) == NULL) {
! 202: hr = dotnet_init(&where TSRMLS_CC);
! 203: if (FAILED(hr)) {
! 204: char buf[1024];
! 205: char *err = php_win_err(hr);
! 206: snprintf(buf, sizeof(buf), "Failed to init .Net runtime [%s] %s", where, err);
! 207: if (err)
! 208: LocalFree(err);
! 209: php_com_throw_exception(hr, buf TSRMLS_CC);
! 210: ZVAL_NULL(object);
! 211: return;
! 212: }
! 213: }
! 214:
! 215: stuff = (struct dotnet_runtime_stuff*)COMG(dotnet_runtime_stuff);
! 216:
! 217: obj = CDNO_FETCH(object);
! 218:
! 219: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l",
! 220: &assembly_name, &assembly_name_len,
! 221: &datatype_name, &datatype_name_len,
! 222: &obj->code_page)) {
! 223: php_com_throw_exception(E_INVALIDARG, "Could not create .Net object - invalid arguments!" TSRMLS_CC);
! 224: ZVAL_NULL(object);
! 225: return;
! 226: }
! 227:
! 228: oletype = php_com_string_to_olestring(datatype_name, datatype_name_len, obj->code_page TSRMLS_CC);
! 229: oleassembly = php_com_string_to_olestring(assembly_name, assembly_name_len, obj->code_page TSRMLS_CC);
! 230: oletype_sys = SysAllocString(oletype);
! 231: oleassembly_sys = SysAllocString(oleassembly);
! 232: where = "CreateInstance";
! 233: hr = stuff->dotnet_domain->lpVtbl->CreateInstance(stuff->dotnet_domain, oleassembly_sys, oletype_sys, &unk);
! 234: efree(oletype);
! 235: efree(oleassembly);
! 236: SysFreeString(oletype_sys);
! 237: SysFreeString(oleassembly_sys);
! 238:
! 239: if (SUCCEEDED(hr)) {
! 240: VARIANT unwrapped;
! 241: IObjectHandle *handle = NULL;
! 242:
! 243: where = "QI: IObjectHandle";
! 244: hr = IUnknown_QueryInterface(unk, &IID_IObjectHandle, &handle);
! 245:
! 246: if (SUCCEEDED(hr)) {
! 247: where = "IObjectHandle_Unwrap";
! 248: hr = IObjectHandle_Unwrap(handle, &unwrapped);
! 249: if (SUCCEEDED(hr)) {
! 250:
! 251: if (V_VT(&unwrapped) == VT_UNKNOWN) {
! 252: where = "Unwrapped, QI for IDispatch";
! 253: hr = IUnknown_QueryInterface(V_UNKNOWN(&unwrapped), &IID_IDispatch, &V_DISPATCH(&obj->v));
! 254:
! 255: if (SUCCEEDED(hr)) {
! 256: V_VT(&obj->v) = VT_DISPATCH;
! 257:
! 258: /* get its type-info */
! 259: IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
! 260: ret = SUCCESS;
! 261: }
! 262: } else if (V_VT(&unwrapped) == VT_DISPATCH) {
! 263: /* unwrapped is now the dispatch pointer we want */
! 264: V_DISPATCH(&obj->v) = V_DISPATCH(&unwrapped);
! 265: V_VT(&obj->v) = VT_DISPATCH;
! 266:
! 267: /* get its type-info */
! 268: IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
! 269:
! 270: ret = SUCCESS;
! 271: } else {
! 272: /* shouldn't happen, but let's be ready for it */
! 273: VariantClear(&unwrapped);
! 274: hr = E_INVALIDARG;
! 275: }
! 276: }
! 277: IObjectHandle_Release(handle);
! 278: }
! 279: IUnknown_Release(unk);
! 280: }
! 281:
! 282: if (ret == FAILURE) {
! 283: char buf[1024];
! 284: char *err = php_win_err(hr);
! 285: snprintf(buf, sizeof(buf), "Failed to instantiate .Net object [%s] [0x%08x] %s", where, hr, err);
! 286: if (err && err[0]) {
! 287: LocalFree(err);
! 288: }
! 289: php_com_throw_exception(hr, buf TSRMLS_CC);
! 290: ZVAL_NULL(object);
! 291: return;
! 292: }
! 293: }
! 294: /* }}} */
! 295:
! 296: void php_com_dotnet_mshutdown(TSRMLS_D)
! 297: {
! 298: struct dotnet_runtime_stuff *stuff = COMG(dotnet_runtime_stuff);
! 299:
! 300: if (stuff->dotnet_domain) {
! 301: IDispatch_Release(stuff->dotnet_domain);
! 302: }
! 303: if (stuff->dotnet_host) {
! 304: ICorRuntimeHost_Stop(stuff->dotnet_host);
! 305: ICorRuntimeHost_Release(stuff->dotnet_host);
! 306: stuff->dotnet_host = NULL;
! 307: }
! 308: free(stuff);
! 309: COMG(dotnet_runtime_stuff) = NULL;
! 310: }
! 311:
! 312: void php_com_dotnet_rshutdown(TSRMLS_D)
! 313: {
! 314: struct dotnet_runtime_stuff *stuff = COMG(dotnet_runtime_stuff);
! 315:
! 316: if (stuff->dotnet_domain) {
! 317: IDispatch_Release(stuff->dotnet_domain);
! 318: stuff->dotnet_domain = NULL;
! 319: }
! 320: }
! 321:
! 322: #endif /* HAVE_MSCOREE_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>