wez Thu Aug 14 12:49:56 2003 EDT Added files: /php-src/ext/com_dotnet README com_com.c com_dotnet.c com_extension.c com_handlers.c com_misc.c com_olechar.c com_typeinfo.c com_variant.c php_com_dotnet.h php_com_dotnet_internal.h /php-src/ext/com_dotnet/tests variants.phpt
Modified files: /php-src/main config.w32.h internal_functions_win32.c Log: Add new COM (and .Net) extension for php5. Not yet complete, but should work for most people.
Index: php-src/main/config.w32.h diff -u php-src/main/config.w32.h:1.75 php-src/main/config.w32.h:1.76 --- php-src/main/config.w32.h:1.75 Fri Jun 27 12:43:05 2003 +++ php-src/main/config.w32.h Thu Aug 14 12:49:56 2003 @@ -2,7 +2,7 @@ Build Configuration for Win32. This has only been tested with MS VisualC++ 6 (and later). - $Id: config.w32.h,v 1.75 2003/06/27 16:43:05 sebastian Exp $ + $Id: config.w32.h,v 1.76 2003/08/14 16:49:56 wez Exp $ */ /* Default PHP / PEAR directories */ @@ -46,6 +46,10 @@ /* #define HAVE_MBSTR_KR 0 */ /* #define HAVE_MBSTR_RU 0 */ /* #define HAVE_MBSTR_TW 0 */ + +/* If you have the .Net SDK in your include path, define this + * to compile .Net support into your COM extension. */ +#define HAVE_MSCOREE_H 0 /* Enable / Disable ODBC extension (default: enabled) */ #define HAVE_UODBC 1 Index: php-src/main/internal_functions_win32.c diff -u php-src/main/internal_functions_win32.c:1.78 php-src/main/internal_functions_win32.c:1.79 --- php-src/main/internal_functions_win32.c:1.78 Fri Jun 27 10:32:59 2003 +++ php-src/main/internal_functions_win32.c Thu Aug 14 12:49:56 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: internal_functions_win32.c,v 1.78 2003/06/27 14:32:59 edink Exp $ */ +/* $Id: internal_functions_win32.c,v 1.79 2003/08/14 16:49:56 wez Exp $ */ /* {{{ includes */ @@ -97,6 +97,7 @@ #ifdef HAVE_SQLITE #include "ext/sqlite/php_sqlite.h" #endif +#include "ext/com_dotnet/php_com_dotnet.h" /* }}} */ /* {{{ php_builtin_extensions[] @@ -109,6 +110,7 @@ #if HAVE_CALENDAR ,phpext_calendar_ptr #endif + ,phpext_com_dotnet_ptr #if HAVE_CTYPE ,phpext_ctype_ptr #endif @@ -135,14 +137,14 @@ #endif #if HAVE_LIBXML #if HAVE_DOM - ,phpext_dom_ptr + phpext_dom_ptr #endif #if HAVE_SIMPLEXML - ,phpext_simplexml_ptr + phpext_simplexml_ptr #endif #endif #if HAVE_XML - ,phpext_xml_ptr + phpext_xml_ptr #endif #if HAVE_XML && HAVE_WDDX ,phpext_wddx_ptr Index: php-src/ext/com_dotnet/com_com.c +++ php-src/ext/com_dotnet/com_com.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_com.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" #include "Zend/zend_default_classes.h" /* {{{ com_create_instance - ctor for COM class */ PHP_FUNCTION(com_create_instance) { zval *object = getThis(); zval *server_params = NULL; php_com_dotnet_object *obj; char *module_name, *typelib_name = NULL, *server_name = NULL; char *user_name = NULL, *domain_name = NULL, *password = NULL; long module_name_len, typelib_name_len, server_name_len, user_name_len, domain_name_len, password_len; OLECHAR *moniker; CLSID clsid; CLSCTX ctx = CLSCTX_SERVER; HRESULT res = E_FAIL; int mode = COMG(autoreg_case_sensitive) ? CONST_CS : 0; ITypeLib *TL = NULL; obj = CDNO_FETCH(object); if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s|s!ls", &module_name, &module_name_len, &server_name, &server_name_len, &obj->code_page, &typelib_name, &typelib_name_len) && FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "sa|ls", &module_name, &module_name_len, &server_params, &obj->code_page, &typelib_name, &typelib_name_len)) { php_com_throw_exception("Could not create COM object - invalid arguments!" TSRMLS_CC); ZVAL_NULL(object); return; } if (server_name) { ctx = CLSCTX_REMOTE_SERVER; } else if (server_params) { zval **tmp; /* decode the data from the array */ if (SUCCESS == zend_hash_find(HASH_OF(server_params), "Server", sizeof("Server"), (void**)&tmp)) { convert_to_string_ex(tmp); server_name = Z_STRVAL_PP(tmp); server_name_len = Z_STRLEN_PP(tmp); ctx = CLSCTX_REMOTE_SERVER; } if (SUCCESS == zend_hash_find(HASH_OF(server_params), "Username", sizeof("Username"), (void**)&tmp)) { convert_to_string_ex(tmp); user_name = Z_STRVAL_PP(tmp); user_name_len = Z_STRLEN_PP(tmp); } if (SUCCESS == zend_hash_find(HASH_OF(server_params), "Password", sizeof("Password"), (void**)&tmp)) { convert_to_string_ex(tmp); password = Z_STRVAL_PP(tmp); password_len = Z_STRLEN_PP(tmp); } if (SUCCESS == zend_hash_find(HASH_OF(server_params), "Domain", sizeof("Domain"), (void**)&tmp)) { convert_to_string_ex(tmp); domain_name = Z_STRVAL_PP(tmp); domain_name_len = Z_STRLEN_PP(tmp); } if (SUCCESS == zend_hash_find(HASH_OF(server_params), "Flags", sizeof("Flags"), (void**)&tmp)) { convert_to_long_ex(tmp); ctx = (CLSCTX)Z_LVAL_PP(tmp); } } if (server_name && !COMG(allow_dcom)) { php_com_throw_exception("DCOM has been disabled by your administrator [com.allow_dcom=0]" TSRMLS_CC); return; } moniker = php_com_string_to_olestring(module_name, module_name_len, obj->code_page TSRMLS_CC); if (FAILED(CLSIDFromString(moniker, &clsid))) { /* try to use it as a moniker */ IBindCtx *pBindCtx = NULL; IMoniker *pMoniker = NULL; ULONG ulEaten; if (server_name == NULL) { res = MK_E_SYNTAX; } else if (SUCCEEDED(res = CreateBindCtx(0, &pBindCtx)) && SUCCEEDED(res = MkParseDisplayName(pBindCtx, moniker, &ulEaten, &pMoniker))) { res = IMoniker_BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID*)&V_DISPATCH(&obj->v)); if (SUCCEEDED(res)) { V_VT(&obj->v) = VT_DISPATCH; } IMoniker_Release(pMoniker); } if (pBindCtx) { IBindCtx_Release(pBindCtx); } } else if (server_name) { COSERVERINFO info; MULTI_QI qi; COAUTHIDENTITY authid; COAUTHINFO authinfo = { RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, &authid, EOAC_NONE }; info.dwReserved1 = 0; info.dwReserved2 = 0; info.pwszName = php_com_string_to_olestring(server_name, server_name_len, obj->code_page TSRMLS_CC); if (user_name) { authid.User = php_com_string_to_olestring(user_name, -1, obj->code_page TSRMLS_CC); authid.UserLength = user_name_len; if (password) { authid.Password = (OLECHAR*)password; authid.PasswordLength = password_len; } else { authid.Password = (OLECHAR*)""; authid.PasswordLength = 0; } if (domain_name) { authid.Domain = (OLECHAR*)domain_name; authid.DomainLength = domain_name_len; } else { authid.Domain = (OLECHAR*)""; authid.DomainLength = 0; } authid.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; info.pAuthInfo = &authinfo; } else { info.pAuthInfo = NULL; } qi.pIID = &IID_IDispatch; qi.pItf = NULL; qi.hr = S_OK; res = CoCreateInstanceEx(&clsid, NULL, ctx, &info, 1, &qi); efree(info.pwszName); if (SUCCEEDED(res)) { res = qi.hr; V_DISPATCH(&obj->v) = (IDispatch*)qi.pItf; V_VT(&obj->v) = VT_DISPATCH; } } else { res = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&V_DISPATCH(&obj->v)); if (SUCCEEDED(res)) { V_VT(&obj->v) = VT_DISPATCH; } } efree(moniker); if (FAILED(res)) { char *werr, *msg; werr = php_win_err(res); spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr); LocalFree(werr); php_com_throw_exception(msg TSRMLS_CC); efree(msg); ZVAL_NULL(object); return; } /* we got the object and it lives ! */ /* see if it has TypeInfo available */ if (FAILED(IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo)) && typelib_name) { /* load up the library from the named file */ int cached; TL = php_com_load_typelib_via_cache(typelib_name, mode, obj->code_page, &cached TSRMLS_CC); if (TL) { if (COMG(autoreg_on) && !cached) { php_com_import_typelib(TL, mode, obj->code_page TSRMLS_CC); } /* cross your fingers... there is no guarantee that this ITypeInfo * instance has any relation to this IDispatch instance... */ ITypeLib_GetTypeInfo(TL, 0, &obj->typeinfo); ITypeLib_Release(TL); } } else if (obj->typeinfo && COMG(autoreg_on)) { int idx; if (SUCCEEDED(ITypeInfo_GetContainingTypeLib(obj->typeinfo, &TL, &idx))) { /* check if the library is already in the cache by getting its name */ BSTR name; if (SUCCEEDED(ITypeLib_GetDocumentation(TL, -1, &name, NULL, NULL, NULL))) { typelib_name = php_com_olestring_to_string(name, &typelib_name_len, obj->code_page TSRMLS_CC); if (SUCCESS == zend_ts_hash_add(&php_com_typelibraries, typelib_name, typelib_name_len+1, (void*)&TL, sizeof(ITypeLib*), NULL)) { php_com_import_typelib(TL, mode, obj->code_page TSRMLS_CC); /* add a reference for the hash */ ITypeLib_AddRef(TL); } } else { /* try it anyway */ php_com_import_typelib(TL, mode, obj->code_page TSRMLS_CC); } ITypeLib_Release(TL); } } } /* }}} */ /* Performs an Invoke on the given com object. * returns a failure code and creates an exception if there was an error */ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC) { HRESULT hr; unsigned int arg_err; EXCEPINFO e; if (obj->typeinfo) { hr = ITypeInfo_Invoke(obj->typeinfo, V_DISPATCH(&obj->v), id_member, flags, disp_params, v, &e, &arg_err); if (FAILED(hr) && (hr != DISP_E_EXCEPTION)) { hr = IDispatch_Invoke(V_DISPATCH(&obj->v), id_member, &IID_NULL, LOCALE_SYSTEM_DEFAULT, flags, disp_params, v, &e, &arg_err); if (SUCCEEDED(hr)) { /* fall back on using IDispatch directly */ ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } } } else { hr = IDispatch_Invoke(V_DISPATCH(&obj->v), id_member, &IID_NULL, LOCALE_SYSTEM_DEFAULT, flags, disp_params, v, &e, &arg_err); } if (FAILED(hr)) { char *source = NULL, *desc = NULL, *msg = NULL; int source_len, desc_len; switch (hr) { case DISP_E_EXCEPTION: if (e.bstrSource) { source = php_com_olestring_to_string(e.bstrSource, &source_len, obj->code_page TSRMLS_CC); SysFreeString(e.bstrSource); } if (e.bstrDescription) { desc = php_com_olestring_to_string(e.bstrDescription, &desc_len, obj->code_page TSRMLS_CC); SysFreeString(e.bstrDescription); } if (PG(html_errors)) { spprintf(&msg, 0, "<b>Source:</b> %s<br/><b>Description:</b> %s", source ? source : "Unknown", desc ? desc : "Unknown"); } else { spprintf(&msg, 0, "Source: %s\nDescription: %s", source ? source : "Unknown", desc ? desc : "Unknown"); } if (desc) { efree(desc); } if (source) { efree(source); } if (e.bstrHelpFile) { SysFreeString(e.bstrHelpFile); } break; case DISP_E_PARAMNOTFOUND: case DISP_E_TYPEMISMATCH: desc = php_win_err(hr); spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc); LocalFree(desc); break; default: desc = php_win_err(hr); spprintf(&msg, 0, "Error %s", desc); LocalFree(desc); break; } if (msg) { php_com_throw_exception(msg TSRMLS_CC); efree(msg); } } return hr; } /* map an ID to a name */ HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name, int namelen, DISPID *dispid TSRMLS_DC) { OLECHAR *olename; HRESULT hr; olename = php_com_string_to_olestring(name, namelen, obj->code_page TSRMLS_CC); if (obj->typeinfo) { hr = ITypeInfo_GetIDsOfNames(obj->typeinfo, &olename, 1, dispid); if (FAILED(hr)) { hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, dispid); if (SUCCEEDED(hr)) { /* fall back on IDispatch direct */ ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } } } else { hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, dispid); } efree(olename); return hr; } /* the core of COM */ int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC) { DISPID altdispid; DISPPARAMS disp_params; HRESULT hr; VARIANT *vargs = NULL; int i; if (nargs) { vargs = (VARIANT*)emalloc(sizeof(VARIANT) * nargs); } /* Invoke'd args are in reverse order */ for (i = 0; i < nargs; i++) { php_com_variant_from_zval(&vargs[i], args[nargs - i - 1], obj->code_page TSRMLS_CC); } disp_params.cArgs = nargs; disp_params.cNamedArgs = 0; disp_params.rgvarg = vargs; disp_params.rgdispidNamedArgs = NULL; if (flags & DISPATCH_PROPERTYPUT) { altdispid = DISPID_PROPERTYPUT; disp_params.rgdispidNamedArgs = &altdispid; disp_params.cNamedArgs = 1; } /* this will create an exception if needed */ hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v TSRMLS_CC); /* release variants */ if (vargs) { for (i = 0; i < nargs; i++) { VariantClear(&vargs[i]); } efree(vargs); } return SUCCEEDED(hr) ? SUCCESS : FAILURE; } int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC) { DISPID dispid; HRESULT hr; char *winerr = NULL; char *msg = NULL; hr = php_com_get_id_of_name(obj, name, namelen, &dispid TSRMLS_CC); if (FAILED(hr)) { winerr = php_win_err(hr); spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr); LocalFree(winerr); php_com_throw_exception(msg TSRMLS_CC); efree(msg); return FAILURE; } return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args TSRMLS_CC); } Index: php-src/ext/com_dotnet/com_dotnet.c +++ php-src/ext/com_dotnet/com_dotnet.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_dotnet.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_MSCOREE_H # include "php_ini.h" # include "ext/standard/info.h" # include "php_com_dotnet.h" # include "php_com_dotnet_internal.h" # include "Zend/zend_default_classes.h" # include <mscoree.h> struct dotnet_runtime_stuff { ICorRuntimeHost *dotnet_host; IDispatch *dotnet_domain; DISPID create_instance; }; /* Since there is no official public mscorlib.h header file, and since * generating your own version from the binary .tlb file results in a 3MB * header file (!), we opt for the Dispatch-able approach. This is slightly * slower for creating new objects, but not too bad */ static int dotnet_init(TSRMLS_D) { HRESULT hr; struct dotnet_runtime_stuff *stuff; IUnknown *unk = NULL; OLECHAR *olename; stuff = emalloc(sizeof(*stuff)); memset(stuff, 0, sizeof(*stuff)); if (SUCCEEDED(CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL, &IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host))) { /* fire up the host and get the domain object */ if (SUCCEEDED(ICorRuntimeHost_Start(stuff->dotnet_host)) && SUCCEEDED(ICorRuntimeHost_GetDefaultDomain(stuff->dotnet_host, &unk)) && SUCCEEDED(IUnknown_QueryInterface(unk, &IID_IDispatch, (LPVOID*)&stuff->dotnet_domain))) { /* locate the create-instance member */ olename = php_com_string_to_olestring("CreateInstance", sizeof("CreateInstance")-1, CP_ACP TSRMLS_CC); hr = IDispatch_GetIDsOfNames(stuff->dotnet_domain, &IID_NULL, &olename, 1, LOCALE_SYSTEM_DEFAULT, &stuff->create_instance); efree(olename); if (SUCCEEDED(hr)) { COMG(dotnet_runtime_stuff) = stuff; } } if (unk) { IUnknown_Release(unk); } } if (COMG(dotnet_runtime_stuff) == NULL) { /* clean up */ if (stuff->dotnet_domain) { IDispatch_Release(stuff->dotnet_domain); } if (stuff->dotnet_host) { ICorRuntimeHost_Stop(stuff->dotnet_host); ICorRuntimeHost_Release(stuff->dotnet_host); } efree(stuff); return FAILURE; } return SUCCESS; } /* {{{ com_dotnet_create_instance - ctor for DOTNET class */ PHP_FUNCTION(com_dotnet_create_instance) { zval *object = getThis(); php_com_dotnet_object *obj; char *assembly_name, *datatype_name; long assembly_name_len, datatype_name_len; struct dotnet_runtime_stuff *stuff; IObjectHandle *handle; DISPPARAMS params; VARIANT vargs[2]; VARIANT retval; HRESULT hr; int ret = FAILURE; if (COMG(dotnet_runtime_stuff) == NULL) { if (FAILURE == dotnet_init(TSRMLS_C)) { com_throw_exception("Failed to initialize .Net runtime" TSRMLS_CC); ZVAL_NULL(object); return; } } stuff = (struct dotnet_runtime_stuff*)COMG(dotnet_runtime_stuff); obj = CDNO_FETCH(object); if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &assembly_name, &assembly_name_len, &datatype_name, &datatype_name_len, &obj->code_page)) { com_throw_exception("Could not create .Net object - invalid arguments!" TSRMLS_CC); ZVAL_NULL(object); return; } params.cArgs = 2; params.cNamedArgs = 0; params.rgdispidNamedArgs = NULL; params.rgvarg = vargs; VariantInit(&vargs[0]); VariantInit(&vargs[1]); VariantInit(&retval); V_VT(&vargs[0]) = VT_BSTR; V_BSTR(&vargs[0]) = php_com_string_to_olestring(datatype_name, datatype_name_len, obj->code_page TSRMLS_CC); V_VT(&vargs[1]) = VT_BSTR; V_BSTR(&vargs[1]) = php_com_string_to_olestring(assembly_name, assembly_name_len, obj->code_page TSRMLS_CC); hr = IDispatch_Invoke(stuff->dotnet_domain, stuff->create_instance, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, &retval, NULL, NULL); if (SUCCEEDED(hr)) { /* retval should now be an IUnknown/IDispatch representation of an IObjectHandle interface */ if ((V_VT(&retval) == VT_UNKNOWN || V_VT(&retval) == VT_DISPATCH) && SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(&retval), &IID_IObjectHandle, &handle))) { VARIANT unwrapped; if (SUCCEEDED(IObjectHandle_Unwrap(handle, &unwrapped))) { /* unwrapped is now the dispatch pointer we want */ V_DISPATCH(&obj->v) = V_DISPATCH(&unwrapped); V_VT(&obj->v) = VT_DISPATCH; /* get its type-info */ IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); ret = SUCCESS; } IObjectHandle_Release(handle); } VariantClear(&retval); } VariantClear(&vargs[0]); VariantClear(&vargs[1]); if (ret == FAILURE) { com_throw_exception("Failed to instantiate .Net object" TSRMLS_CC); ZVAL_NULL(object); return; } } /* }}} */ void php_com_dotnet_rshutdown(TSRMLS_D) { struct dotnet_runtime_stuff *stuff = COMG(dotnet_runtime_stuff); IDispatch_Release(stuff->dotnet_domain); ICorRuntimeHost_Stop(stuff->dotnet_host); ICorRuntimeHost_Release(stuff->dotnet_host); efree(stuff); COMG(dotnet_runtime_stuff) = NULL; } #endif /* HAVE_MSCOREE_H */ Index: php-src/ext/com_dotnet/com_extension.c +++ php-src/ext/com_dotnet/com_extension.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_extension.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" #include "Zend/zend_default_classes.h" ZEND_DECLARE_MODULE_GLOBALS(com_dotnet) TsHashTable php_com_typelibraries; zend_class_entry *php_com_variant_class_entry; function_entry com_dotnet_functions[] = { PHP_FE(variant_set, NULL) PHP_FE(variant_add, NULL) PHP_FE(variant_cat, NULL) PHP_FE(variant_sub, NULL) PHP_FE(variant_mul, NULL) PHP_FE(variant_and, NULL) PHP_FE(variant_div, NULL) PHP_FE(variant_eqv, NULL) PHP_FE(variant_idiv, NULL) PHP_FE(variant_imp, NULL) PHP_FE(variant_mod, NULL) PHP_FE(variant_or, NULL) PHP_FE(variant_pow, NULL) PHP_FE(variant_xor, NULL) PHP_FE(variant_abs, NULL) PHP_FE(variant_fix, NULL) PHP_FE(variant_int, NULL) PHP_FE(variant_neg, NULL) PHP_FE(variant_not, NULL) PHP_FE(variant_round, NULL) PHP_FE(variant_cmp, NULL) PHP_FE(variant_date_to_timestamp, NULL) PHP_FE(variant_date_from_timestamp, NULL) PHP_FE(variant_get_type, NULL) PHP_FE(variant_set_type, NULL) PHP_FE(variant_cast, NULL) { NULL, NULL, NULL } }; /* {{{ com_dotnet_module_entry */ zend_module_entry com_dotnet_module_entry = { STANDARD_MODULE_HEADER, "com_dotnet", com_dotnet_functions, PHP_MINIT(com_dotnet), PHP_MSHUTDOWN(com_dotnet), PHP_RINIT(com_dotnet), PHP_RSHUTDOWN(com_dotnet), PHP_MINFO(com_dotnet), "0.1", STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_COM_DOTNET ZEND_GET_MODULE(com_dotnet) #endif /* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("com.allow_dcom", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals) STD_PHP_INI_ENTRY("com.autoregister_verbose", "0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals) STD_PHP_INI_ENTRY("com.autoregister_typelib", "0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals) STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "0", PHP_INI_ALL, OnUpdateBool, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals) PHP_INI_END() /* }}} */ /* {{{ php_com_dotnet_init_globals */ static void php_com_dotnet_init_globals(zend_com_dotnet_globals *com_dotnet_globals) { memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals)); } /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(com_dotnet) { zend_class_entry ce; ZEND_INIT_MODULE_GLOBALS(com_dotnet, php_com_dotnet_init_globals, NULL); REGISTER_INI_ENTRIES(); INIT_CLASS_ENTRY(ce, "variant", NULL); ce.create_object = php_com_object_new; php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC); INIT_CLASS_ENTRY(ce, "com", NULL); ce.create_object = php_com_object_new; zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC); zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 0); #if HAVE_MSCOREE_H INIT_CLASS_ENTRY(ce, "dotnet", NULL); ce.create_object = php_com_object_new; zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC); #endif #define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT) COM_CONST(CLSCTX_INPROC_SERVER); COM_CONST(CLSCTX_INPROC_HANDLER); COM_CONST(CLSCTX_LOCAL_SERVER); COM_CONST(CLSCTX_REMOTE_SERVER); COM_CONST(CLSCTX_SERVER); COM_CONST(CLSCTX_ALL); COM_CONST(DISPATCH_METHOD); COM_CONST(DISPATCH_PROPERTYGET); COM_CONST(DISPATCH_PROPERTYPUT); COM_CONST(VT_NULL); COM_CONST(VT_EMPTY); COM_CONST(VT_UI1); COM_CONST(VT_I1); COM_CONST(VT_UI2); COM_CONST(VT_I2); COM_CONST(VT_UI4); COM_CONST(VT_I4); COM_CONST(VT_R4); COM_CONST(VT_R8); COM_CONST(VT_BOOL); COM_CONST(VT_ERROR); COM_CONST(VT_CY); COM_CONST(VT_DATE); COM_CONST(VT_BSTR); COM_CONST(VT_DECIMAL); COM_CONST(VT_UNKNOWN); COM_CONST(VT_DISPATCH); COM_CONST(VT_VARIANT); COM_CONST(VT_INT); COM_CONST(VT_UINT); COM_CONST(VT_ARRAY); COM_CONST(VT_BYREF); COM_CONST(CP_ACP); COM_CONST(CP_MACCP); COM_CONST(CP_OEMCP); COM_CONST(CP_UTF7); COM_CONST(CP_UTF8); COM_CONST(CP_SYMBOL); COM_CONST(CP_THREAD_ACP); COM_CONST(VARCMP_LT); COM_CONST(VARCMP_EQ); COM_CONST(VARCMP_GT); COM_CONST(VARCMP_NULL); return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(com_dotnet) { UNREGISTER_INI_ENTRIES(); zend_ts_hash_destroy(&php_com_typelibraries); return SUCCESS; } /* }}} */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(com_dotnet) { return SUCCESS; } /* }}} */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(com_dotnet) { #if HAVE_MSCOREE_H if (COMG(dotnet_runtime_stuff)) { php_com_dotnet_rshutdown(TSRMLS_C); } #endif return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(com_dotnet) { php_info_print_table_start(); php_info_print_table_header(2, "COM support", "enabled"); php_info_print_table_header(2, "DCOM support", COMG(allow_dcom) ? "enabled" : "disabled"); #if HAVE_MSCOREE_H php_info_print_table_header(2, ".Net support", "enabled"); #else php_info_print_table_header(2, ".Net support", "not present in this build"); #endif php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ Index: php-src/ext/com_dotnet/com_handlers.c +++ php-src/ext/com_dotnet/com_handlers.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_handlers.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" #include "Zend/zend_default_classes.h" static zval *com_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) { zval *return_value; php_com_dotnet_object *obj; VARIANT v; MAKE_STD_ZVAL(return_value); ZVAL_NULL(return_value); obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { VariantInit(&v); convert_to_string_ex(&member); if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); VariantClear(&v); } } else { if (!silent) { php_com_throw_exception("this variant has no properties" TSRMLS_CC); } } return return_value; } static void com_property_write(zval *object, zval *member, zval *value TSRMLS_DC) { php_com_dotnet_object *obj; VARIANT v; obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { VariantInit(&v); convert_to_string_ex(&member); if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), DISPATCH_PROPERTYPUT, &v, 1, &value TSRMLS_CC)) { VariantClear(&v); } } else { php_com_throw_exception("this variant has no properties" TSRMLS_CC); } } static HRESULT com_get_default_binding(php_com_dotnet_object *obj TSRMLS_DC) { VARDESC *vardesc; int i; if (!obj->typeinfo) { return FAILURE; } for (i = 0; !obj->have_default_bind; i++) { if (FAILED(ITypeInfo_GetVarDesc(obj->typeinfo, i, &vardesc))) { return FAILURE; } if (vardesc->wVarFlags & VARFLAG_FDEFAULTBIND) { obj->default_bind = (DISPID)vardesc->memid; obj->have_default_bind = 1; } ITypeInfo_ReleaseVarDesc(obj->typeinfo, vardesc); } return obj->have_default_bind ? SUCCESS : FAILURE; } static zval *com_read_dimension(zval *object, zval *offset TSRMLS_DC) { zval *return_value; php_com_dotnet_object *obj; VARIANT v; MAKE_STD_ZVAL(return_value); ZVAL_NULL(return_value); obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { php_com_throw_exception("this COM object has no default property" TSRMLS_CC); return return_value; } VariantInit(&v); if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, &offset TSRMLS_CC)) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); VariantClear(&v); } } else if (V_ISARRAY(&obj->v)) { SAFEARRAY *sa = V_ARRAY(&obj->v); UINT dims; VARTYPE vt; LONG bound_low = 0, bound_high = 0; LONG indices[1]; dims = SafeArrayGetDim(sa); if (dims != 1) { php_com_throw_exception("can only handle single dimension arrays" TSRMLS_CC); return return_value; } if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) { vt = V_VT(&obj->v) & ~VT_ARRAY; } SafeArrayGetUBound(sa, 1, &bound_high); SafeArrayGetLBound(sa, 1, &bound_low); convert_to_long(offset); /* check bounds */ if (Z_LVAL_P(offset) < bound_low || Z_LVAL_P(offset) > bound_high) { php_com_throw_exception("index out of bounds" TSRMLS_CC); return return_value; } indices[0] = Z_LVAL_P(offset); VariantInit(&v); V_VT(&v) = vt; /* store the value into "lVal" member of the variant. * This works because it is a union; since we know the variant * type, we end up with a working variant */ SafeArrayGetElement(sa, indices, &v.lVal); /* now we can set the return value from that element */ php_com_wrap_variant(return_value, &v, obj->code_page TSRMLS_CC); VariantClear(&v); } else { php_com_throw_exception("this variant is not an array type" TSRMLS_CC); } return return_value; } static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) { php_com_dotnet_object *obj; zval *args[2]; VARIANT v; obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { php_com_throw_exception("this COM object has no default property" TSRMLS_CC); return; } args[0] = offset; args[1] = value; VariantInit(&v); if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind, DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args TSRMLS_CC)) { VariantClear(&v); } } else { /* TODO: check for safearray */ php_com_throw_exception("this variant is not an array type" TSRMLS_CC); } } static zval **com_property_get_ptr(zval *object, zval *member TSRMLS_DC) { zval **prop_ptr; prop_ptr = emalloc(sizeof(zval **)); *prop_ptr = com_property_read(object, member, 0 TSRMLS_CC); return prop_ptr; } static void com_object_set(zval **property, zval *value TSRMLS_DC) { /* Not yet implemented in the engine */ } static zval *com_object_get(zval *property TSRMLS_DC) { /* Not yet implemented in the engine */ return NULL; } static int com_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC) { DISPID dispid; php_com_dotnet_object *obj; obj = CDNO_FETCH(object); if (V_VT(&obj->v) == VT_DISPATCH) { convert_to_string_ex(&member); if (SUCCEEDED(php_com_get_id_of_name(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), &dispid TSRMLS_CC))) { /* TODO: distinguish between property and method! */ return 1; } } else { /* TODO: check for safearray */ } return 0; } static void com_property_delete(zval *object, zval *member TSRMLS_DC) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object"); } static void com_dimension_delete(zval *object, zval *offset TSRMLS_DC) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object"); } static HashTable *com_properties_get(zval *object TSRMLS_DC) { /* TODO: use type-info to get all the names and values ? * DANGER: if we do that, there is a strong possibility for * infinite recursion when the hash is displayed via var_dump(). * Perhaps it is best to leave it un-implemented. */ return NULL; } static union _zend_function *com_method_get(zval *object, char *name, int len TSRMLS_DC) { zend_internal_function *f; php_com_dotnet_object *obj; /* TODO: cache this */ obj = CDNO_FETCH(object); if (V_VT(&obj->v) != VT_DISPATCH) { return NULL; } f = emalloc(sizeof(zend_internal_function)); f->type = ZEND_OVERLOADED_FUNCTION; f->num_args = 0; f->arg_info = NULL; f->scope = obj->ce; f->fn_flags = 0; f->function_name = estrndup(name, len); if (obj->typeinfo) { /* look for byref params */ ITypeComp *comp; ITypeInfo *TI = NULL; DESCKIND kind; BINDPTR bindptr; OLECHAR *olename; ULONG lhash; int i; if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) { olename = php_com_string_to_olestring(name, len, obj->code_page TSRMLS_CC); lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename); if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) { switch (kind) { case DESCKIND_FUNCDESC: f->arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info)); for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) { f->arg_info[i].allow_null = 1; if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) { f->arg_info[i].pass_by_reference = 1; } } f->num_args = bindptr.lpfuncdesc->cParams; ITypeInfo_ReleaseFuncDesc(TI, bindptr.lpfuncdesc); break; /* these should not happen, but *might* happen if the user * screws up; lets avoid a leak in that case */ case DESCKIND_VARDESC: ITypeInfo_ReleaseVarDesc(TI, bindptr.lpvardesc); break; case DESCKIND_TYPECOMP: ITypeComp_Release(bindptr.lptcomp); break; } ITypeInfo_Release(TI); } ITypeComp_Release(comp); efree(olename); } } return (union _zend_function*)f; } static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) { zval **args = NULL; php_com_dotnet_object *obj; int nargs; VARIANT v; int ret = FAILURE; obj = CDNO_FETCH(getThis()); if (V_VT(&obj->v) != VT_DISPATCH) { //php_com_throw_exception("call to member function of non-object"); return FAILURE; } nargs = ZEND_NUM_ARGS(); if (nargs) { args = (zval **)emalloc(sizeof(zval *) * nargs); zend_get_parameters_array(ht, nargs, args); } VariantInit(&v); if (SUCCESS == php_com_do_invoke(obj, method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); ret = SUCCESS; VariantClear(&v); } if (args) { efree(args); } return ret; } static union _zend_function *com_constructor_get(zval *object TSRMLS_DC) { php_com_dotnet_object *obj; zend_internal_function *f; obj = CDNO_FETCH(object); /* TODO: this leaks */ f = emalloc(sizeof(zend_internal_function)); f->type = ZEND_INTERNAL_FUNCTION; f->function_name = obj->ce->name; f->scope = obj->ce; f->arg_info = NULL; f->num_args = 0; f->fn_flags = 0; #if HAVE_MSCOREE_H if (f->function_name[0] == 'd') { /* 'd'otnet */ f->handler = ZEND_FN(com_dotnet_create_instance); } else #endif if (f->function_name[0] == 'c') { /* 'c'om */ f->handler = ZEND_FN(com_create_instance); } else { /* 'v'ariant */ f->handler = ZEND_FN(com_variant_create_instance); } return (union _zend_function*)f; } static zend_class_entry *com_class_entry_get(zval *object TSRMLS_DC) { php_com_dotnet_object *obj; obj = CDNO_FETCH(object); return obj->ce; } static int com_class_name_get(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) { php_com_dotnet_object *obj; obj = CDNO_FETCH(object); *class_name = estrndup(obj->ce->name, obj->ce->name_length); *class_name_len = obj->ce->name_length; return 0; } /* This compares two variants for equality */ static int com_objects_compare(zval *object1, zval *object2 TSRMLS_DC) { php_com_dotnet_object *obja, *objb; int ret; /* strange header bug problem here... the headers define the proto without the * flags parameter. However, the MSDN docs state that there is a flags parameter, * and my VC6 won't link unless the code uses the version with 4 parameters. * So, we have this declaration here to fix it */ STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags); obja = CDNO_FETCH(object1); objb = CDNO_FETCH(object2); switch (VarCmp(&obja->v, &objb->v, LOCALE_SYSTEM_DEFAULT, 0)) { case VARCMP_LT: ret = -1; break; case VARCMP_GT: ret = 1; break; case VARCMP_EQ: ret = 0; break; default: /* either or both operands are NULL... * not 100% sure how to handle this */ ret = -2; } return ret; } static void com_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) { php_com_dotnet_object *obj; VARIANT v; VARTYPE vt = VT_EMPTY; if (should_free) { zval_dtor(writeobj); } ZVAL_NULL(writeobj); obj = CDNO_FETCH(readobj); VariantInit(&v); if (V_VT(&obj->v) == VT_DISPATCH) { if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) { return; } if (FAILURE == php_com_do_invoke_by_id(obj, obj->default_bind, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) { return; } } else { VariantCopy(&v, &obj->v); } switch(type) { case IS_LONG: vt = VT_INT; break; case IS_DOUBLE: vt = VT_R8; break; case IS_BOOL: vt = VT_BOOL; break; case IS_STRING: vt = VT_BSTR; break; } if (vt != VT_EMPTY) { VariantChangeType(&v, &v, 0, vt); } php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC); VariantClear(&v); } zend_object_handlers php_com_object_handlers = { ZEND_OBJECTS_STORE_HANDLERS, com_property_read, com_property_write, com_read_dimension, com_write_dimension, com_property_get_ptr, com_property_get_ptr, com_object_get, com_object_set, com_property_exists, com_property_delete, com_dimension_delete, com_properties_get, com_method_get, com_call_method, com_constructor_get, com_class_entry_get, com_class_name_get, com_objects_compare, com_object_cast }; void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) { php_com_dotnet_object *obj = (php_com_dotnet_object*)object; if (obj->typeinfo) { ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } VariantClear(&obj->v); efree(obj); } void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC) { php_com_dotnet_object *cloneobj, *origobject; origobject = (php_com_dotnet_object*)object; cloneobj = (php_com_dotnet_object*)emalloc(sizeof(php_com_dotnet_object)); memcpy(cloneobj, origobject, sizeof(*cloneobj)); /* VariantCopy will perform VariantClear; we don't want to clobber * the IDispatch that we memcpy'd, so we init a new variant in the * clone structure */ VariantInit(&cloneobj->v); /* We use the Indirection-following version of the API since we * want to clone as much as possible */ VariantCopyInd(&cloneobj->v, &origobject->v); if (cloneobj->typeinfo) { ITypeInfo_AddRef(cloneobj->typeinfo); } *clone_ptr = cloneobj; } zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC) { php_com_dotnet_object *obj; zend_object_value retval; obj = emalloc(sizeof(*obj)); memset(obj, 0, sizeof(*obj)); VariantInit(&obj->v); obj->code_page = CP_ACP; obj->ce = ce; retval.handle = zend_objects_store_put(obj, php_com_object_dtor, php_com_object_clone TSRMLS_CC); retval.handlers = &php_com_object_handlers; return retval; } Index: php-src/ext/com_dotnet/com_misc.c +++ php-src/ext/com_dotnet/com_misc.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_misc.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" #include "Zend/zend_default_classes.h" zval *php_com_throw_exception(char *message TSRMLS_DC) { zval *e, *tmp; ALLOC_ZVAL(e); Z_TYPE_P(e) = IS_OBJECT; object_init_ex(e, zend_exception_get_default()); e->refcount = 1; e->is_ref = 1; MAKE_STD_ZVAL(tmp); ZVAL_STRING(tmp, message, 1); zend_hash_update(Z_OBJPROP_P(e), "message", sizeof("message"), (void**)&tmp, sizeof(zval*), NULL); MAKE_STD_ZVAL(tmp); ZVAL_STRING(tmp, zend_get_executed_filename(TSRMLS_C), 1); zend_hash_update(Z_OBJPROP_P(e), "file", sizeof("file"), (void**)&tmp, sizeof(zval*), NULL); MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, zend_get_executed_lineno(TSRMLS_C)); zend_hash_update(Z_OBJPROP_P(e), "line", sizeof("line"), (void**)&tmp, sizeof(zval*), NULL); EG(exception) = e; return e; } PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp, int codepage TSRMLS_DC) { php_com_dotnet_object *obj; obj = emalloc(sizeof(*obj)); memset(obj, 0, sizeof(*obj)); obj->code_page = codepage; obj->ce = php_com_variant_class_entry; VariantInit(&obj->v); V_VT(&obj->v) = VT_DISPATCH; V_DISPATCH(&obj->v) = disp; IDispatch_AddRef(V_DISPATCH(&obj->v)); IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); Z_TYPE_P(z) = IS_OBJECT; z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor, php_com_object_clone TSRMLS_CC); z->value.obj.handlers = &php_com_object_handlers; } PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC) { php_com_dotnet_object *obj; obj = emalloc(sizeof(*obj)); memset(obj, 0, sizeof(*obj)); obj->code_page = codepage; obj->ce = php_com_variant_class_entry; VariantInit(&obj->v); VariantCopy(&obj->v, v); if (V_VT(&obj->v) == VT_DISPATCH) { IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo); } Z_TYPE_P(z) = IS_OBJECT; z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor, php_com_object_clone TSRMLS_CC); z->value.obj.handlers = &php_com_object_handlers; } Index: php-src/ext/com_dotnet/com_olechar.c +++ php-src/ext/com_dotnet/com_olechar.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | | Harald Radi <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_olechar.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" PHPAPI OLECHAR *php_com_string_to_olestring(char *string, uint string_len, int codepage TSRMLS_DC) { OLECHAR *olestring = NULL; DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS; BOOL ok; if (string_len == -1) { /* determine required length for the buffer (includes NUL terminator) */ string_len = MultiByteToWideChar(codepage, flags, string, -1, NULL, 0); } else { /* allow room for NUL terminator */ string_len++; } if (strlen > 0) { olestring = (OLECHAR*)emalloc(sizeof(OLECHAR) * string_len); ok = MultiByteToWideChar(codepage, flags, string, string_len, olestring, string_len); } else { ok = FALSE; olestring = (OLECHAR*)emalloc(sizeof(OLECHAR)); *olestring = 0; } if (!ok) { char *msg = php_win_err(GetLastError()); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not convert string to unicode: `%s'", msg); LocalFree(msg); } return olestring; } PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring, uint *string_len, int codepage TSRMLS_DC) { char *string; uint length = 0; BOOL ok; LONG err; length = WideCharToMultiByte(codepage, 0, olestring, -1, NULL, 0, NULL, NULL); if (length) { string = (char*)emalloc(sizeof(char) * length); length = WideCharToMultiByte(codepage, 0, olestring, -1, string, length, NULL, NULL); ok = length > 0; } else { err = GetLastError(); string = (char*)emalloc(sizeof(char)); *string = '\0'; ok = FALSE; length = 0; } if (!ok) { char *msg = php_win_err(err); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not convert string from unicode: `%s'", msg); LocalFree(msg); } if (string_len) { *string_len = length-1; } return string; } Index: php-src/ext/com_dotnet/com_typeinfo.c +++ php-src/ext/com_dotnet/com_typeinfo.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | | Harald Radi <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_typeinfo.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" /* The search string can be either: * a) a file name * b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0" * c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library" */ PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode, int codepage TSRMLS_DC) { ITypeLib *TL = NULL; char *strtok_buf, *major, *minor; CLSID clsid; OLECHAR *p; HRESULT hr; search_string = php_strtok_r(search_string, ",", &strtok_buf); if (search_string == NULL) { return NULL; } major = php_strtok_r(NULL, ",", &strtok_buf); minor = php_strtok_r(NULL, ",", &strtok_buf); p = php_com_string_to_olestring(search_string, strlen(search_string), codepage TSRMLS_CC); if (SUCCEEDED(CLSIDFromString(p, &clsid))) { WORD major_i = 1, minor_i = 0; /* pick up the major/minor numbers; if none specified, default to 1,0 */ if (major && minor) { major_i = (WORD)atoi(major); minor_i = (WORD)atoi(minor); } /* Load the TypeLib by GUID */ hr = LoadRegTypeLib((REFGUID)&clsid, major_i, minor_i, LANG_NEUTRAL, &TL); /* if that failed, assumed that the GUID is actually a CLSID and * attemp to get the library via an instance of that class */ if (FAILED(hr) && (major == NULL || minor == NULL)) { IDispatch *disp = NULL; ITypeInfo *info = NULL; int idx; if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&disp)) && SUCCEEDED(hr = IDispatch_GetTypeInfo(disp, 0, LANG_NEUTRAL, &info))) { hr = ITypeInfo_GetContainingTypeLib(info, &TL, &idx); } if (info) { ITypeInfo_Release(info); } if (disp) { IDispatch_Release(disp); } } } else { /* Try to load it from a file; if it fails, do a really painful search of * the registry */ if (FAILED(LoadTypeLib(p, &TL))) { HKEY hkey, hsubkey; DWORD SubKeys, MaxSubKeyLength; char *keyname; unsigned int i, j; DWORD VersionCount; char version[20]; char *libname; DWORD libnamelen; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_READ, &hkey) && ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys, &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL)) { MaxSubKeyLength++; /* make room for NUL */ keyname = emalloc(MaxSubKeyLength); libname = emalloc(strlen(search_string) + 1); for (i = 0; i < SubKeys && TL == NULL; i++) { if (ERROR_SUCCESS == RegEnumKey(hkey, i, keyname, MaxSubKeyLength) && ERROR_SUCCESS == RegOpenKeyEx(hkey, keyname, 0, KEY_READ, &hsubkey)) { if (ERROR_SUCCESS == RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { for (j = 0; j < VersionCount; j++) { if (ERROR_SUCCESS != RegEnumKey(hsubkey, j, version, sizeof(version))) { continue; } /* get the default value for this key and compare */ libnamelen = strlen(search_string)+1; if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) { if (0 == ((mode & CONST_CS) ? strcmp(libname, search_string) : stricmp(libname, search_string))) { char *str = NULL; int major, minor; /* fetch the GUID and add the version numbers */ if (2 != sscanf(version, "%d.%d", &major, &minor)) { major = 1; minor = 0; } spprintf(&str, 0, "%s,%d,%d", keyname, major, minor); /* recurse */ TL = php_com_load_typelib(str, mode, codepage TSRMLS_CC); efree(str); break; } } } } RegCloseKey(hsubkey); } } RegCloseKey(hkey); efree(keyname); efree(libname); } } } efree(p); return TL; } /* Given a type-library, merge it into the current engine state */ PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC) { int i, j, interfaces; TYPEKIND pTKind; ITypeInfo *TypeInfo; VARDESC *pVarDesc; UINT NameCount; BSTR bstr_ids; zend_constant c; zval exists, results, value; char *const_name; if (TL == NULL) { return FAILURE; } interfaces = ITypeLib_GetTypeInfoCount(TL); for (i = 0; i < interfaces; i++) { ITypeLib_GetTypeInfoType(TL, i, &pTKind); if (pTKind == TKIND_ENUM) { ITypeLib_GetTypeInfo(TL, i, &TypeInfo); for (j = 0; ; j++) { if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) { break; } ITypeInfo_GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount); if (NameCount != 1) { ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } const_name = php_com_olestring_to_string(bstr_ids, &c.name_len, codepage TSRMLS_CC); c.name = zend_strndup(const_name, c.name_len); efree(const_name); c.name_len++; /* include NUL */ SysFreeString(bstr_ids); /* sanity check for the case where the constant is already defined */ if (zend_get_constant(c.name, c.name_len - 1, &exists TSRMLS_CC)) { if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, &exists TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name); } free(c.name); ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } /* register the constant */ php_com_zval_from_variant(&value, pVarDesc->lpvarValue, codepage TSRMLS_CC); if (Z_TYPE(value) == IS_LONG) { c.flags = mode; c.value.type = IS_LONG; c.value.value.lval = Z_LVAL(value); c.module_number = 0; zend_register_constant(&c TSRMLS_CC); } ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); } ITypeInfo_Release(TypeInfo); } } return SUCCESS; } /* Type-library stuff */ void php_com_typelibrary_dtor(void *pDest) { ITypeLib *Lib = *(ITypeLib**)pDest; ITypeLib_Release(Lib); } PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string, int mode, int codepage, int *cached TSRMLS_DC) { ITypeLib **TL; char *name_dup; int l; l = strlen(search_string); if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1, (void**)&TL) == SUCCESS) { *cached = 1; /* add a reference for the caller */ ITypeLib_AddRef(*TL); return *TL; } *cached = 0; name_dup = estrndup(search_string, l); *TL = php_com_load_typelib(name_dup, mode, codepage TSRMLS_CC); efree(name_dup); if (*TL) { if (SUCCESS == zend_ts_hash_update(&php_com_typelibraries, search_string, l+1, (void*)*TL, sizeof(ITypeLib*), NULL)) { /* add a reference for the hash table */ ITypeLib_AddRef(*TL); } } return *TL; } Index: php-src/ext/com_dotnet/com_variant.c +++ php-src/ext/com_dotnet/com_variant.c /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: com_variant.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_com_dotnet.h" #include "php_com_dotnet_internal.h" PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC) { OLECHAR *olestring; php_com_dotnet_object *obj; switch (Z_TYPE_P(z)) { case IS_NULL: V_VT(v) = VT_NULL; break; case IS_BOOL: V_VT(v) = VT_BOOL; V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE; break; case IS_OBJECT: if (php_com_is_valid_object(z TSRMLS_CC)) { obj = CDNO_FETCH(z); if (V_VT(&obj->v) == VT_DISPATCH) { /* pass the underlying object */ V_VT(v) = VT_DISPATCH; if (V_DISPATCH(&obj->v)) { IDispatch_AddRef(V_DISPATCH(&obj->v)); } V_DISPATCH(v) = V_DISPATCH(&obj->v); } else { /* pass the variant by reference */ V_VT(v) = VT_VARIANT | VT_BYREF; V_VARIANTREF(v) = &obj->v; } } else { /* TODO: export the object using our COM wrapper */ V_VT(v) = VT_NULL; } break; case IS_ARRAY: V_VT(v) = VT_NULL; /* TODO: map as safe array ? */ break; case IS_LONG: V_VT(v) = VT_I4; V_I4(v) = Z_LVAL_P(z); break; case IS_DOUBLE: V_VT(v) = VT_R8; V_R8(v) = Z_DVAL_P(z); break; case IS_STRING: V_VT(v) = VT_BSTR; olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage TSRMLS_CC); V_BSTR(v) = SysAllocStringByteLen((char*)olestring, Z_STRLEN_P(z) * sizeof(OLECHAR)); efree(olestring); break; case IS_RESOURCE: case IS_CONSTANT: case IS_CONSTANT_ARRAY: default: V_VT(v) = VT_NULL; break; } } PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC) { OLECHAR *olestring = NULL; int ret = SUCCESS; SYSTEMTIME systime; struct tm tmv; php_com_dotnet_object *obj; switch (V_VT(v)) { case VT_EMPTY: case VT_NULL: case VT_VOID: ZVAL_NULL(z); break; case VT_UI1: ZVAL_LONG(z, (long)V_UI1(v)); break; case VT_I1: ZVAL_LONG(z, (long)V_I1(v)); break; case VT_UI2: ZVAL_LONG(z, (long)V_UI2(v)); break; case VT_I2: ZVAL_LONG(z, (long)V_I2(v)); break; case VT_UI4: /* TODO: promote to double if large? */ ZVAL_LONG(z, (long)V_UI4(v)); break; case VT_I4: ZVAL_LONG(z, (long)V_I4(v)); break; case VT_INT: ZVAL_LONG(z, V_INT(v)); break; case VT_UINT: /* TODO: promote to double if large? */ ZVAL_LONG(z, (long)V_UINT(v)); break; case VT_R4: ZVAL_DOUBLE(z, (double)V_R4(v)); break; case VT_R8: ZVAL_DOUBLE(z, V_R8(v)); break; case VT_BOOL: ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0); break; case VT_BSTR: olestring = V_BSTR(v); if (olestring) { Z_TYPE_P(z) = IS_STRING; Z_STRVAL_P(z) = php_com_olestring_to_string(olestring, &Z_STRLEN_P(z), codepage TSRMLS_CC); olestring = NULL; } break; case VT_UNKNOWN: if (V_UNKNOWN(v) != NULL) { IDispatch *disp; if (SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, &disp))) { php_com_wrap_dispatch(z, disp, codepage TSRMLS_CC); IDispatch_Release(disp); } else { ret = FAILURE; } } break; case VT_DISPATCH: if (V_DISPATCH(v) != NULL) { php_com_wrap_dispatch(z, V_DISPATCH(v), codepage TSRMLS_CC); } break; case VT_VARIANT: default: php_com_wrap_variant(z, v, codepage TSRMLS_CC); } if (olestring) { efree(olestring); } if (ret == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->zval: conversion from 0x%x ret=%d", V_VT(v), ret); } return ret; } /* {{{ com_variant_create_instance - ctor for new VARIANT() */ PHP_FUNCTION(com_variant_create_instance) { VARTYPE vt = VT_EMPTY; long codepage = CP_ACP; zval *object = getThis(); php_com_dotnet_object *obj; zval *zvalue = NULL; HRESULT res; if (ZEND_NUM_ARGS() == 0) { /* just leave things as-is - an empty variant */ return; } obj = CDNO_FETCH(object); if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!|ll", &zvalue, &vt, &codepage)) { php_com_throw_exception("Invalid arguments" TSRMLS_CC); return; } if (ZEND_NUM_ARGS() == 3) { obj->code_page = codepage; } php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC); if (ZEND_NUM_ARGS() >= 2) { res = VariantChangeType(&obj->v, &obj->v, 0, vt); if (FAILED(res)) { char *werr, *msg; werr = php_win_err(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); LocalFree(werr); php_com_throw_exception(msg TSRMLS_CC); efree(msg); } } if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) { ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } } /* }}} */ /* {{{ proto void variant_set(object variant, mixed value) Assigns a new value for a variant object (like "set" in VB) */ PHP_FUNCTION(variant_set) { zval *zobj, *zvalue = NULL; php_com_dotnet_object *obj; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz!", &zobj, php_com_variant_class_entry, &zvalue)) { return; } obj = CDNO_FETCH(zobj); /* dtor the old value */ if (obj->typeinfo) { ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } VariantClear(&obj->v); php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC); } /* }}} */ enum variant_binary_opcode { VOP_ADD, VOP_CAT, VOP_SUB, VOP_MUL, VOP_AND, VOP_DIV, VOP_EQV, VOP_IDIV, VOP_IMP, VOP_MOD, VOP_OR, VOP_POW, VOP_XOR }; enum variant_unary_opcode { VOP_ABS, VOP_FIX, VOP_INT, VOP_NEG, VOP_NOT }; static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { VARIANT vres; VARIANT left_val, right_val; VARIANT *vleft = NULL, *vright = NULL; zval *zleft = NULL, *zright = NULL; php_com_dotnet_object *obj; HRESULT result; int codepage = CP_ACP; VariantInit(&left_val); VariantInit(&right_val); VariantInit(&vres); if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zleft, php_com_variant_class_entry, &zright, php_com_variant_class_entry)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; obj = CDNO_FETCH(zright); vright = &obj->v; } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "Oz!", &zleft, php_com_variant_class_entry, &zright)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; vright = &right_val; php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC); } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z!O", &zleft, &zright, php_com_variant_class_entry)) { obj = CDNO_FETCH(zright); vright = &obj->v; vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z!", &zleft, &zright)) { vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); vright = &right_val; php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC); } else { return; } switch (op) { case VOP_ADD: result = VarAdd(vleft, vright, &vres); break; case VOP_CAT: result = VarCat(vleft, vright, &vres); break; case VOP_SUB: result = VarSub(vleft, vright, &vres); break; case VOP_MUL: result = VarMul(vleft, vright, &vres); break; case VOP_AND: result = VarAnd(vleft, vright, &vres); break; case VOP_DIV: result = VarDiv(vleft, vright, &vres); break; case VOP_EQV: result = VarEqv(vleft, vright, &vres); break; case VOP_IDIV: result = VarIdiv(vleft, vright, &vres); break; case VOP_IMP: result = VarImp(vleft, vright, &vres); break; case VOP_MOD: result = VarMod(vleft, vright, &vres); break; case VOP_OR: result = VarOr(vleft, vright, &vres); break; case VOP_POW: result = VarPow(vleft, vright, &vres); break; case VOP_XOR: result = VarXor(vleft, vright, &vres); break; } if (SUCCEEDED(result)) { php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC); } VariantClear(&vres); VariantClear(&left_val); VariantClear(&right_val); } /* }}} */ /* {{{ proto mixed variant_add(mixed left, mixed right) "Adds" two variant values together and returns the result */ PHP_FUNCTION(variant_add) { variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_cat(mixed left, mixed right) concatenates two variant values together and returns the result */ PHP_FUNCTION(variant_cat) { variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_sub(mixed left, mixed right) subjects the value of the right variant from the left variant value and returns the result */ PHP_FUNCTION(variant_sub) { variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_mul(mixed left, mixed right) multiplies the values of the two variants and returns the result */ PHP_FUNCTION(variant_mul) { variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_and(mixed left, mixed right) performs a bitwise AND operation between two variants and returns the result */ PHP_FUNCTION(variant_and) { variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_div(mixed left, mixed right) Returns the result from dividing two variants */ PHP_FUNCTION(variant_div) { variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_eqv(mixed left, mixed right) Performs a bitwise equivalence on two variants */ PHP_FUNCTION(variant_eqv) { variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_idiv(mixed left, mixed right) Converts variants to operands and then returns the result from dividing them */ PHP_FUNCTION(variant_idiv) { variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_imp(mixed left, mixed right) Performs a bitwise implication on two variants */ PHP_FUNCTION(variant_imp) { variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_mod(mixed left, mixed right) Divides two variants and returns only the remainder */ PHP_FUNCTION(variant_mod) { variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_or(mixed left, mixed right) Performs a logical disjunction on two variants */ PHP_FUNCTION(variant_or) { variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_pow(mixed left, mixed right) Returns the result of performing the power function with two variants */ PHP_FUNCTION(variant_pow) { variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_xor(mixed left, mixed right) Performs a logical exclusion on two variants */ PHP_FUNCTION(variant_xor) { variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { VARIANT vres; VARIANT left_val; VARIANT *vleft = NULL; zval *zleft = NULL; php_com_dotnet_object *obj; HRESULT result; int codepage = CP_ACP; VariantInit(&left_val); VariantInit(&vres); if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &zleft, php_com_variant_class_entry)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!", &zleft)) { vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); } else { return; } switch (op) { case VOP_ABS: result = VarAbs(vleft, &vres); break; case VOP_FIX: result = VarFix(vleft, &vres); break; case VOP_INT: result = VarInt(vleft, &vres); break; case VOP_NEG: result = VarNeg(vleft, &vres); break; case VOP_NOT: result = VarNot(vleft, &vres); break; } if (SUCCEEDED(result)) { php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC); } VariantClear(&vres); VariantClear(&left_val); } /* }}} */ /* {{{ proto mixed variant_abs(mixed left) Returns the absolute value of a variant */ PHP_FUNCTION(variant_abs) { variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_fix(mixed left) Returns the ? of a variant */ PHP_FUNCTION(variant_fix) { variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_int(mixed left) Returns the integer portion of a variant */ PHP_FUNCTION(variant_int) { variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_neg(mixed left) Performs logical negation on a variant */ PHP_FUNCTION(variant_neg) { variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_not(mixed left) Performs bitwise not negation on a variant */ PHP_FUNCTION(variant_not) { variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto mixed variant_round(mixed left, int decimals) Rounds a variant to the specified number of decimal places */ PHP_FUNCTION(variant_round) { VARIANT vres; VARIANT left_val; VARIANT *vleft = NULL; zval *zleft = NULL; php_com_dotnet_object *obj; HRESULT result; int codepage = CP_ACP; long decimals = 0; VariantInit(&left_val); VariantInit(&vres); if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zleft, php_com_variant_class_entry, &decimals)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!l", &zleft, &decimals)) { vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); } else { return; } if (SUCCEEDED(VarRound(vleft, decimals, &vres))) { php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC); } VariantClear(&vres); VariantClear(&left_val); } /* }}} */ /* {{{ proto int variant_cmp(mixed left, mixed right [, int lcid [, int flags]]) Compares two variants */ PHP_FUNCTION(variant_cmp) { VARIANT left_val, right_val; VARIANT *vleft = NULL, *vright = NULL; zval *zleft = NULL, *zright = NULL; php_com_dotnet_object *obj; HRESULT result; int codepage = CP_ACP; long lcid = LOCALE_SYSTEM_DEFAULT; long flags = 0; /* it is safe to ignore the warning for this line; see the comments in com_handlers.c */ STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags); VariantInit(&left_val); VariantInit(&right_val); if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OO|ll", &zleft, php_com_variant_class_entry, &zright, php_com_variant_class_entry, &lcid, &flags)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; obj = CDNO_FETCH(zright); vright = &obj->v; } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "Oz!|ll", &zleft, php_com_variant_class_entry, &zright, &lcid, &flags)) { obj = CDNO_FETCH(zleft); vleft = &obj->v; vright = &right_val; php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC); } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z!O|ll", &zleft, &zright, php_com_variant_class_entry, &lcid, &flags)) { obj = CDNO_FETCH(zright); vright = &obj->v; vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z!|ll", &zleft, &zright, &lcid, &flags)) { vleft = &left_val; php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC); vright = &right_val; php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC); } else { return; } ZVAL_LONG(return_value, VarCmp(vleft, vright, lcid, flags)); VariantClear(&left_val); VariantClear(&right_val); } /* }}} */ /* {{{ proto int variant_date_to_timestamp(object variant) Converts a variant date/time value to unix timestamp */ PHP_FUNCTION(variant_date_to_timestamp) { VARIANT vres; zval *zleft = NULL; php_com_dotnet_object *obj; VariantInit(&vres); if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zleft, php_com_variant_class_entry)) { return; } obj = CDNO_FETCH(zleft); if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) { SYSTEMTIME systime; struct tm tmv; VariantTimeToSystemTime(V_DATE(&vres), &systime); memset(&tmv, 0, sizeof(tmv)); tmv.tm_year = systime.wYear - 1900; tmv.tm_mon = systime.wMonth - 1; tmv.tm_mday = systime.wDay; tmv.tm_hour = systime.wHour; tmv.tm_min = systime.wMinute; tmv.tm_sec = systime.wSecond; tmv.tm_isdst = -1; tzset(); RETVAL_LONG(mktime(&tmv)); } VariantClear(&vres); } /* }}} */ /* {{{ proto object variant_date_from_timestamp(int timestamp) Returns a variant date representation of a unix timestamp */ PHP_FUNCTION(variant_date_from_timestamp) { int timestamp; SYSTEMTIME systime; struct tm *tmv; VARIANT res; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", ×tamp)) { return; } VariantInit(&res); tmv = gmtime(×tamp); memset(&systime, 0, sizeof(systime)); systime.wDay = tmv->tm_mday; systime.wHour = tmv->tm_hour; systime.wMinute = tmv->tm_min; systime.wMonth = tmv->tm_mon + 1; systime.wSecond = tmv->tm_sec; systime.wYear = tmv->tm_year + 1900; V_VT(&res) = VT_DATE; SystemTimeToVariantTime(&systime, &V_DATE(&res)); php_com_wrap_variant(return_value, &res, CP_ACP TSRMLS_CC); VariantClear(&res); } /* }}} */ /* {{{ proto int variant_get_type(object variant) Returns the VT_XXX type code for a variant */ PHP_FUNCTION(variant_get_type) { zval *zobj; php_com_dotnet_object *obj; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &zobj, php_com_variant_class_entry)) { return; } obj = CDNO_FETCH(zobj); RETURN_LONG(V_VT(&obj->v)); } /* }}} */ /* {{{ proto void variant_set_type(object variant, int type) Convert a variant into another type. Variant is modified "in-place" */ PHP_FUNCTION(variant_set_type) { zval *zobj; php_com_dotnet_object *obj; VARTYPE vt; HRESULT res; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zobj, php_com_variant_class_entry, &vt)) { return; } obj = CDNO_FETCH(zobj); res = VariantChangeType(&obj->v, &obj->v, 0, vt); if (SUCCEEDED(res)) { if (vt != VT_DISPATCH && obj->typeinfo) { ITypeInfo_Release(obj->typeinfo); obj->typeinfo = NULL; } } else { char *werr, *msg; werr = php_win_err(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); LocalFree(werr); php_com_throw_exception(msg TSRMLS_CC); efree(msg); } } /* }}} */ /* {{{ proto object variant_cast(object variant, int type) Convert a variant into a new variant object of another type */ PHP_FUNCTION(variant_cast) { zval *zobj; php_com_dotnet_object *obj; VARTYPE vt; VARIANT vres; HRESULT res; if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zobj, php_com_variant_class_entry, &vt)) { return; } obj = CDNO_FETCH(zobj); VariantInit(&vres); res = VariantChangeType(&vres, &obj->v, 0, vt); if (SUCCEEDED(res)) { php_com_wrap_variant(return_value, &vres, obj->code_page TSRMLS_CC); } else { char *werr, *msg; werr = php_win_err(res); spprintf(&msg, 0, "Variant type conversion failed: %s", werr); LocalFree(werr); php_com_throw_exception(msg TSRMLS_CC); efree(msg); } VariantClear(&vres); } /* }}} */ /* {{{ proto mixed variant_index_get(object variant, mixed index1 [, mixed index2 [, ...]]) Get the value of a multi dimensional array property */ PHP_FUNCTION(variant_index_get) { zval *zobj; php_com_dotnet_object *obj; VARIANT vres; HRESULT res; if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "O", &zobj, php_com_variant_class_entry)) { return; } obj = CDNO_FETCH(zobj); /* TODO: finish... */ } /* }}} */ Index: php-src/ext/com_dotnet/php_com_dotnet.h +++ php-src/ext/com_dotnet/php_com_dotnet.h /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: php_com_dotnet.h,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifndef PHP_COM_DOTNET_H #define PHP_COM_DOTNET_H extern zend_module_entry com_dotnet_module_entry; #define phpext_com_dotnet_ptr &com_dotnet_module_entry #ifdef PHP_WIN32 # define PHP_COM_DOTNET_API __declspec(dllexport) #else # define PHP_COM_DOTNET_API #endif #ifdef ZTS #include "TSRM.h" #endif PHP_MINIT_FUNCTION(com_dotnet); PHP_MSHUTDOWN_FUNCTION(com_dotnet); PHP_RINIT_FUNCTION(com_dotnet); PHP_RSHUTDOWN_FUNCTION(com_dotnet); PHP_MINFO_FUNCTION(com_dotnet); PHP_FUNCTION(confirm_com_dotnet_compiled); ZEND_BEGIN_MODULE_GLOBALS(com_dotnet) zend_bool allow_dcom; zend_bool autoreg_verbose; zend_bool autoreg_on; zend_bool autoreg_case_sensitive; void *dotnet_runtime_stuff; /* opaque to avoid cluttering up other modules */ ZEND_END_MODULE_GLOBALS(com_dotnet) #ifdef ZTS # define COMG(v) TSRMG(com_dotnet_globals_id, zend_com_dotnet_globals *, v) #else # define COMG(v) (com_dotnet_globals.v) #endif extern ZEND_DECLARE_MODULE_GLOBALS(com_dotnet); #endif /* PHP_COM_DOTNET_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h +++ php-src/ext/com_dotnet/php_com_dotnet_internal.h /* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [EMAIL PROTECTED] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ /* $Id: php_com_dotnet_internal.h,v 1.1 2003/08/14 16:49:55 wez Exp $ */ #ifndef PHP_COM_DOTNET_INTERNAL_H #define PHP_COM_DOTNET_INTERNAL_H #define _WIN32_DCOM #define COBJMACROS #include <ocidl.h> #include "oleauto.h" #include "win32/winutil.h" /* brain-death in winutil.h defines the macro to hide the useful function... */ #undef php_win_err typedef struct _php_com_dotnet_object { VARIANT v; ITypeInfo *typeinfo; int code_page; unsigned int have_default_bind:1; zend_class_entry *ce; DISPID default_bind; /* default property for array accesses */ } php_com_dotnet_object; static inline int php_com_is_valid_object(zval *zv TSRMLS_DC) { zend_class_entry *ce = Z_OBJCE_P(zv); return strcmp("com", ce->name) == 0 || strcmp("dotnet", ce->name) == 0 || strcmp("variant", ce->name) == 0; } #define CDNO_FETCH(zv) (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC) #define CDNO_FETCH_VERIFY(obj, zv) do { \ if (!php_com_is_valid_object(zv TSRMLS_CC)) { \ php_com_throw_exception("expected a variant object" TSRMLS_CC); \ return; \ } \ obj = (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC); \ } while(0) /* com_extension.c */ TsHashTable php_com_typelibraries; zend_class_entry *php_com_variant_class_entry; /* com_handlers.c */ zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC); void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC); void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC); zend_object_handlers php_com_object_handlers; /* com_olechar.c */ PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring, uint *string_len, int codepage TSRMLS_DC); PHPAPI OLECHAR *php_com_string_to_olestring(char *string, uint string_len, int codepage TSRMLS_DC); /* com_com.c */ PHP_FUNCTION(com_create_instance); HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member, WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC); HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name, int namelen, DISPID *dispid TSRMLS_DC); int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC); int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC); /* com_variant.c */ PHP_FUNCTION(com_variant_create_instance); PHP_FUNCTION(variant_set); PHP_FUNCTION(variant_add); PHP_FUNCTION(variant_cat); PHP_FUNCTION(variant_sub); PHP_FUNCTION(variant_mul); PHP_FUNCTION(variant_and); PHP_FUNCTION(variant_div); PHP_FUNCTION(variant_eqv); PHP_FUNCTION(variant_idiv); PHP_FUNCTION(variant_imp); PHP_FUNCTION(variant_mod); PHP_FUNCTION(variant_or); PHP_FUNCTION(variant_pow); PHP_FUNCTION(variant_xor); PHP_FUNCTION(variant_abs); PHP_FUNCTION(variant_fix); PHP_FUNCTION(variant_int); PHP_FUNCTION(variant_neg); PHP_FUNCTION(variant_not); PHP_FUNCTION(variant_round); PHP_FUNCTION(variant_cmp); PHP_FUNCTION(variant_date_to_timestamp); PHP_FUNCTION(variant_date_from_timestamp); PHP_FUNCTION(variant_get_type); PHP_FUNCTION(variant_set_type); PHP_FUNCTION(variant_cast); PHPAPI void php_com_variant_from_zval_with_type(VARIANT *v, zval *z, VARTYPE type, int codepage TSRMLS_DC); PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC); PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC); /* com_dotnet.c */ PHP_FUNCTION(com_dotnet_create_instance); void php_com_dotnet_rshutdown(TSRMLS_D); /* com_misc.c */ zval *php_com_throw_exception(char *message TSRMLS_DC); PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp, int codepage TSRMLS_DC); PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC); /* com_typeinfo.c */ PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string, int mode, int codepage, int *cached TSRMLS_DC); PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode, int codepage TSRMLS_DC); PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC); void php_com_typelibrary_dtor(void *pDest); #endif Index: php-src/ext/com_dotnet/tests/variants.phpt +++ php-src/ext/com_dotnet/tests/variants.phpt --TEST-- COM: General variant tests --SKIPIF-- <?php # vim:ft=php if (!extension_loaded("com_dotnet")) print "skip"; ?> --FILE-- <?php // $Id: variants.phpt,v 1.1 2003/08/14 16:49:56 wez Exp $ error_reporting(E_ALL); $v = new VARIANT(); if (VT_EMPTY != variant_get_type($v)) { echo "VT_EMPTY: bork\n"; } $values = array(VT_I4 => 42, VT_R8 => 3.5, VT_BSTR => "hello", VT_BOOL => false); $binary_ops = array('add', 'cat', 'sub', 'mul', 'and', 'div', 'eqv', 'idiv', 'imp', 'mod', 'or', 'pow', 'xor'); foreach ($values as $t => $val) { $v = new VARIANT($val); if ($t != variant_get_type($v)) { printf("Bork: [%d] %d: %s\n", $t, variant_get_type($v), (string)$v); } $results = array(); foreach ($values as $op2) { echo "--\n"; foreach ($binary_ops as $op) { echo "$op: " . call_user_func('variant_' . $op, $v, $op2) . "\n"; } } } $a = new VARIANT('10.0', VT_DECIMAL); var_dump($a); echo "OK!"; ?> --EXPECT-- -- add: 84 cat: 4242 sub: 0 mul: 1764 and: 42 div: 1 eqv: -1 idiv: 1 imp: -1 mod: 0 or: 42 pow: 1.50130937545297E+68 xor: 0 -- add: 45.5 cat: 423.5 sub: 38.5 mul: 147 and: 0 div: 12 eqv: -47 idiv: 10 imp: -43 mod: 2 or: 46 pow: 480145.116863642 xor: 46 -- add: cat: 42hello sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: 42 cat: 42False sub: 42 mul: 0 and: 0 div: eqv: -43 idiv: imp: -43 mod: or: 42 pow: 1 xor: 42 -- add: 45.5 cat: 3.542 sub: -38.5 mul: 147 and: 0 div: 8.33333333333333E-02 eqv: -47 idiv: 0 imp: -5 mod: 4 or: 46 pow: 7.09345573078604E+22 xor: 46 -- add: 7 cat: 3.53.5 sub: 0 mul: 12.25 and: 4 div: 1 eqv: -1 idiv: 1 imp: -1 mod: 0 or: 4 pow: 80.2117802289664 xor: 0 -- add: cat: 3.5hello sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: 3.5 cat: 3.5False sub: 3.5 mul: 0 and: 0 div: eqv: -5 idiv: imp: -5 mod: or: 4 pow: 1 xor: 4 -- add: cat: hello42 sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: cat: hello3.5 sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: hellohello cat: hellohello sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: cat: helloFalse sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: 42 cat: False42 sub: -42 mul: 0 and: 0 div: 0 eqv: -43 idiv: 0 imp: -1 mod: 0 or: 42 pow: 0 xor: 42 -- add: 3.5 cat: False3.5 sub: -3.5 mul: 0 and: 0 div: 0 eqv: -5 idiv: 0 imp: -1 mod: 0 or: 4 pow: 0 xor: 4 -- add: cat: Falsehello sub: mul: and: div: eqv: idiv: imp: mod: or: pow: xor: -- add: 0 cat: FalseFalse sub: 0 mul: 0 and: 0 div: eqv: -1 idiv: imp: -1 mod: or: 0 pow: 1 xor: 0 OK!
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php