2003-08-14 16:49:56 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-07 21:00:07 +00:00
| PHP Version 5 |
2003-08-14 16:49:56 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-01-08 08:18:22 +00:00
| Copyright ( c ) 1997 - 2004 The PHP Group |
2003-08-14 16:49:56 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| 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 |
| license @ php . net so we can mail you a copy immediately . |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Author : Wez Furlong < wez @ thebrainroom . com > |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/* $Id$ */
# 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"
2004-02-12 10:43:27 +00:00
# include "Zend/zend_exceptions.h"
2003-08-14 16:49:56 +00:00
2004-03-22 22:47:05 +00:00
static zval * com_property_read ( zval * object , zval * member , int type TSRMLS_DC )
2003-08-14 16:49:56 +00:00
{
zval * return_value ;
php_com_dotnet_object * obj ;
VARIANT v ;
2004-04-28 08:23:22 +00:00
HRESULT res ;
2003-08-14 16:49:56 +00:00
MAKE_STD_ZVAL ( return_value ) ;
ZVAL_NULL ( return_value ) ;
2004-01-13 16:02:56 +00:00
return_value - > refcount = 0 ;
return_value - > is_ref = 0 ;
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( object ) ;
if ( V_VT ( & obj - > v ) = = VT_DISPATCH ) {
VariantInit ( & v ) ;
convert_to_string_ex ( & member ) ;
2004-04-28 08:23:22 +00:00
res = php_com_do_invoke ( obj , Z_STRVAL_P ( member ) , Z_STRLEN_P ( member ) ,
DISPATCH_PROPERTYGET , & v , 0 , NULL TSRMLS_CC ) ;
if ( res = = SUCCESS ) {
2003-08-14 16:49:56 +00:00
php_com_zval_from_variant ( return_value , & v , obj - > code_page TSRMLS_CC ) ;
VariantClear ( & v ) ;
2004-04-28 08:23:22 +00:00
} else if ( res = = DISP_E_BADPARAMCOUNT ) {
php_com_saproxy_create ( object , return_value , member TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
} else {
2004-03-22 22:47:05 +00:00
php_com_throw_exception ( E_INVALIDARG , " this variant has no properties " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
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 {
2004-01-07 21:00:07 +00:00
php_com_throw_exception ( E_INVALIDARG , " this variant has no properties " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
}
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 ;
}
2004-02-08 17:25:54 +00:00
static zval * com_read_dimension ( zval * object , zval * offset , int type TSRMLS_DC )
2003-08-14 16:49:56 +00:00
{
zval * return_value ;
php_com_dotnet_object * obj ;
VARIANT v ;
MAKE_STD_ZVAL ( return_value ) ;
ZVAL_NULL ( return_value ) ;
2004-01-13 16:02:56 +00:00
return_value - > refcount = 0 ;
return_value - > is_ref = 0 ;
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( object ) ;
if ( V_VT ( & obj - > v ) = = VT_DISPATCH ) {
if ( ! obj - > have_default_bind & & ! com_get_default_binding ( obj TSRMLS_CC ) ) {
2004-01-07 21:00:07 +00:00
php_com_throw_exception ( E_INVALIDARG , " this COM object has no default property " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
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 ) ) {
convert_to_long ( offset ) ;
2004-01-07 21:00:07 +00:00
if ( SafeArrayGetDim ( V_ARRAY ( & obj - > v ) ) = = 1 ) {
if ( php_com_safearray_get_elem ( & obj - > v , & v , Z_LVAL_P ( offset ) TSRMLS_CC ) ) {
php_com_wrap_variant ( return_value , & v , obj - > code_page TSRMLS_CC ) ;
VariantClear ( & v ) ;
}
} else {
2004-04-28 08:23:22 +00:00
php_com_saproxy_create ( object , return_value , offset TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
} else {
2004-01-07 21:00:07 +00:00
php_com_throw_exception ( E_INVALIDARG , " this variant is not an array type " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
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 ;
2004-05-03 20:10:58 +00:00
HRESULT res ;
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( object ) ;
if ( V_VT ( & obj - > v ) = = VT_DISPATCH ) {
if ( ! obj - > have_default_bind & & ! com_get_default_binding ( obj TSRMLS_CC ) ) {
2004-01-07 21:00:07 +00:00
php_com_throw_exception ( E_INVALIDARG , " this COM object has no default property " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
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 ) ;
}
2004-05-03 20:10:58 +00:00
} else if ( V_ISARRAY ( & obj - > v ) ) {
LONG indices = 0 ;
VARTYPE vt ;
if ( SafeArrayGetDim ( V_ARRAY ( & obj - > v ) ) = = 1 ) {
if ( FAILED ( SafeArrayGetVartype ( V_ARRAY ( & obj - > v ) , & vt ) ) | | vt = = VT_EMPTY ) {
vt = V_VT ( & obj - > v ) & ~ VT_ARRAY ;
}
convert_to_long ( offset ) ;
indices = Z_LVAL_P ( offset ) ;
VariantInit ( & v ) ;
php_com_variant_from_zval ( & v , value , obj - > code_page TSRMLS_CC ) ;
if ( V_VT ( & v ) ! = vt ) {
VariantChangeType ( & v , & v , 0 , vt ) ;
}
if ( vt = = VT_VARIANT ) {
res = SafeArrayPutElement ( V_ARRAY ( & obj - > v ) , & indices , & v ) ;
} else {
res = SafeArrayPutElement ( V_ARRAY ( & obj - > v ) , & indices , & v . lVal ) ;
}
VariantClear ( & v ) ;
if ( FAILED ( res ) ) {
php_com_throw_exception ( res , NULL TSRMLS_CC ) ;
}
} else {
php_com_throw_exception ( DISP_E_BADINDEX , " this variant has multiple dimensions; you can't set a new value without specifying *all* dimensions " TSRMLS_CC ) ;
}
2003-08-14 16:49:56 +00:00
} else {
2004-01-07 21:00:07 +00:00
php_com_throw_exception ( E_INVALIDARG , " this variant is not an array type " TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
}
}
2004-05-03 18:19:07 +00:00
#if 0
2003-08-14 16:49:56 +00:00
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 ;
}
2004-05-03 18:19:07 +00:00
# endif
2003-08-14 16:49:56 +00:00
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 ;
}
2003-11-27 17:58:58 +00:00
static int com_dimension_exists ( zval * object , zval * member , int check_empty TSRMLS_DC )
{
php_error_docref ( NULL TSRMLS_CC , E_WARNING , " Operation not yet supported on a COM object " ) ;
return 0 ;
}
2003-08-14 16:49:56 +00:00
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 ;
}
2004-01-13 13:38:11 +00:00
static void function_dtor ( void * pDest )
{
zend_internal_function * f = ( zend_internal_function * ) pDest ;
efree ( f - > function_name ) ;
if ( f - > arg_info ) {
efree ( f - > arg_info ) ;
}
}
2004-07-27 22:17:00 +00:00
static PHP_FUNCTION ( com_method_handler )
{
Z_OBJ_HANDLER_P ( getThis ( ) , call_method ) (
( ( zend_internal_function * ) EG ( function_state_ptr ) - > function ) - > function_name ,
INTERNAL_FUNCTION_PARAM_PASSTHRU ) ;
}
2004-11-20 11:40:49 +00:00
static union _zend_function * com_method_get ( zval * * object_ptr , char * name , int len TSRMLS_DC )
2003-08-14 16:49:56 +00:00
{
2004-01-13 13:38:11 +00:00
zend_internal_function f , * fptr = NULL ;
2003-08-14 16:49:56 +00:00
php_com_dotnet_object * obj ;
2004-01-13 13:38:11 +00:00
union _zend_function * func ;
2004-07-27 22:17:00 +00:00
DISPID dummy ;
2004-11-20 11:40:49 +00:00
zval * object = * object_ptr ;
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( object ) ;
if ( V_VT ( & obj - > v ) ! = VT_DISPATCH ) {
return NULL ;
}
2004-07-27 22:17:00 +00:00
if ( FAILED ( php_com_get_id_of_name ( obj , name , len , & dummy TSRMLS_CC ) ) ) {
return NULL ;
}
2004-01-13 13:38:11 +00:00
/* check cache */
if ( obj - > method_cache = = NULL | | FAILURE = = zend_hash_find ( obj - > method_cache , name , len , ( void * * ) & fptr ) ) {
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 ) ;
2004-07-27 22:17:00 +00:00
f . handler = PHP_FN ( com_method_handler ) ;
2004-01-13 13:38:11 +00:00
2004-07-27 01:59:44 +00:00
fptr = & f ;
2004-07-29 14:06:24 +00:00
2004-01-13 13:38:11 +00:00
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 ;
}
2003-08-14 16:49:56 +00:00
}
2004-01-13 13:38:11 +00:00
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 ;
2004-07-27 01:59:44 +00:00
case DESCKIND_NONE :
break ;
2004-01-13 13:38:11 +00:00
}
if ( TI ) {
ITypeInfo_Release ( TI ) ;
}
2003-10-13 01:29:39 +00:00
}
2004-01-13 13:38:11 +00:00
ITypeComp_Release ( comp ) ;
efree ( olename ) ;
2003-08-14 16:49:56 +00:00
}
}
2004-01-13 13:38:11 +00:00
2004-07-27 01:59:44 +00:00
if ( fptr ) {
/* save this method in the cache */
if ( ! obj - > method_cache ) {
ALLOC_HASHTABLE ( obj - > method_cache ) ;
zend_hash_init ( obj - > method_cache , 2 , NULL , function_dtor , 0 ) ;
}
2004-01-13 13:38:11 +00:00
2004-07-27 01:59:44 +00:00
zend_hash_update ( obj - > method_cache , name , len , & f , sizeof ( f ) , ( void * * ) & fptr ) ;
}
2003-08-14 16:49:56 +00:00
}
2004-07-27 01:59:44 +00:00
if ( fptr ) {
/* duplicate this into a new chunk of emalloc'd memory,
* since the engine will efree it */
func = emalloc ( sizeof ( * fptr ) ) ;
memcpy ( func , fptr , sizeof ( * fptr ) ) ;
return func ;
}
2004-01-13 13:38:11 +00:00
2004-07-27 01:59:44 +00:00
return NULL ;
2003-08-14 16:49:56 +00:00
}
static int com_call_method ( char * method , INTERNAL_FUNCTION_PARAMETERS )
{
2004-01-13 00:40:14 +00:00
zval * * * args = NULL ;
2003-08-14 16:49:56 +00:00
php_com_dotnet_object * obj ;
int nargs ;
VARIANT v ;
int ret = FAILURE ;
2004-01-13 13:38:11 +00:00
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( getThis ( ) ) ;
if ( V_VT ( & obj - > v ) ! = VT_DISPATCH ) {
return FAILURE ;
}
nargs = ZEND_NUM_ARGS ( ) ;
if ( nargs ) {
2004-01-13 00:40:14 +00:00
args = ( zval * * * ) safe_emalloc ( sizeof ( zval * ) , nargs , 0 ) ;
zend_get_parameters_array_ex ( nargs , args ) ;
2003-08-14 16:49:56 +00:00
}
VariantInit ( & v ) ;
2004-01-13 00:40:14 +00:00
if ( SUCCESS = = php_com_do_invoke_byref ( obj , method , - 1 , DISPATCH_METHOD | DISPATCH_PROPERTYGET , & v , nargs , args TSRMLS_CC ) ) {
2003-08-14 16:49:56 +00:00
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 ;
2004-01-13 13:38:11 +00:00
static zend_internal_function c , d , v ;
2003-08-14 16:49:56 +00:00
obj = CDNO_FETCH ( object ) ;
2004-01-13 13:38:11 +00:00
# define POPULATE_CTOR(f, fn) \
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 ; \
f . handler = ZEND_FN ( fn ) ; \
return ( union _zend_function * ) & f ;
switch ( obj - > ce - > name [ 0 ] ) {
2004-01-13 16:05:38 +00:00
# if HAVE_MSCOREE_H
2004-01-13 13:38:11 +00:00
case ' d ' :
POPULATE_CTOR ( d , com_dotnet_create_instance ) ;
2004-01-13 16:05:38 +00:00
# endif
2004-01-13 13:38:11 +00:00
case ' c ' :
2004-02-12 12:11:21 +00:00
POPULATE_CTOR ( c , com_create_instance ) ;
2004-01-13 13:38:11 +00:00
case ' v ' :
2004-02-12 12:11:21 +00:00
POPULATE_CTOR ( v , com_variant_create_instance ) ;
2004-01-13 13:38:11 +00:00
default :
return NULL ;
2003-08-14 16:49:56 +00:00
}
}
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 ;
}
2003-10-07 15:47:25 +00:00
static int com_object_cast ( zval * readobj , zval * writeobj , int type , int should_free TSRMLS_DC )
2003-08-14 16:49:56 +00:00
{
php_com_dotnet_object * obj ;
VARIANT v ;
VARTYPE vt = VT_EMPTY ;
2004-07-29 14:06:24 +00:00
2003-08-14 16:49:56 +00:00
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 ) ) {
2003-10-07 15:47:25 +00:00
return FAILURE ;
2003-08-14 16:49:56 +00:00
}
if ( FAILURE = = php_com_do_invoke_by_id ( obj , obj - > default_bind ,
DISPATCH_METHOD | DISPATCH_PROPERTYGET , & v , 0 , NULL TSRMLS_CC ) ) {
2003-10-07 15:47:25 +00:00
return FAILURE ;
2003-08-14 16:49:56 +00:00
}
} 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 ;
2004-07-29 14:06:24 +00:00
default :
;
2003-08-14 16:49:56 +00:00
}
2004-07-29 14:06:24 +00:00
if ( vt ! = VT_EMPTY & & vt ! = V_VT ( & v ) ) {
2003-08-14 16:49:56 +00:00
VariantChangeType ( & v , & v , 0 , vt ) ;
}
php_com_zval_from_variant ( writeobj , & v , obj - > code_page TSRMLS_CC ) ;
VariantClear ( & v ) ;
2003-10-07 15:47:25 +00:00
return SUCCESS ;
2003-08-14 16:49:56 +00:00
}
2004-05-04 15:03:48 +00:00
static int com_object_count ( zval * object , long * count TSRMLS_DC )
{
php_com_dotnet_object * obj ;
LONG ubound = 0 , lbound = 0 ;
obj = CDNO_FETCH ( object ) ;
if ( ! V_ISARRAY ( & obj - > v ) ) {
return FAILURE ;
}
SafeArrayGetLBound ( V_ARRAY ( & obj - > v ) , 1 , & lbound ) ;
SafeArrayGetUBound ( V_ARRAY ( & obj - > v ) , 1 , & ubound ) ;
* count = ubound - lbound + 1 ;
return SUCCESS ;
}
2003-08-14 16:49:56 +00:00
zend_object_handlers php_com_object_handlers = {
ZEND_OBJECTS_STORE_HANDLERS ,
com_property_read ,
com_property_write ,
com_read_dimension ,
com_write_dimension ,
2003-10-05 08:08:49 +00:00
NULL ,
2004-05-03 18:19:07 +00:00
NULL , //com_object_get,
NULL , //com_object_set,
2003-08-14 16:49:56 +00:00
com_property_exists ,
com_property_delete ,
2003-11-27 17:58:58 +00:00
com_dimension_exists ,
2003-08-14 16:49:56 +00:00
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 ,
2004-05-04 15:03:48 +00:00
com_object_cast ,
com_object_count
2003-08-14 16:49:56 +00:00
} ;
2004-01-07 21:00:07 +00:00
void php_com_object_enable_event_sink ( php_com_dotnet_object * obj , int enable TSRMLS_DC )
{
if ( obj - > sink_dispatch ) {
IConnectionPointContainer * cont ;
IConnectionPoint * point ;
if ( SUCCEEDED ( IDispatch_QueryInterface ( V_DISPATCH ( & obj - > v ) ,
& IID_IConnectionPointContainer , ( void * * ) & cont ) ) ) {
if ( SUCCEEDED ( IConnectionPointContainer_FindConnectionPoint ( cont ,
& obj - > sink_id , & point ) ) ) {
if ( enable ) {
IConnectionPoint_Advise ( point , ( IUnknown * ) obj - > sink_dispatch , & obj - > sink_cookie ) ;
} else {
IConnectionPoint_Unadvise ( point , obj - > sink_cookie ) ;
}
IConnectionPoint_Release ( point ) ;
}
IConnectionPointContainer_Release ( cont ) ;
}
}
}
2004-02-04 11:14:47 +00:00
void php_com_object_free_storage ( void * object TSRMLS_DC )
2003-08-14 16:49:56 +00:00
{
php_com_dotnet_object * obj = ( php_com_dotnet_object * ) object ;
2004-05-03 18:19:07 +00:00
2003-08-14 16:49:56 +00:00
if ( obj - > typeinfo ) {
ITypeInfo_Release ( obj - > typeinfo ) ;
obj - > typeinfo = NULL ;
}
2004-01-07 21:00:07 +00:00
if ( obj - > sink_dispatch ) {
php_com_object_enable_event_sink ( obj , FALSE TSRMLS_CC ) ;
IDispatch_Release ( obj - > sink_dispatch ) ;
obj - > sink_dispatch = NULL ;
}
2003-08-14 16:49:56 +00:00
2004-01-07 21:00:07 +00:00
VariantClear ( & obj - > v ) ;
2004-01-13 13:38:11 +00:00
if ( obj - > method_cache ) {
FREE_HASHTABLE ( obj - > method_cache ) ;
}
if ( obj - > id_of_name_cache ) {
FREE_HASHTABLE ( obj - > id_of_name_cache ) ;
}
2003-08-14 16:49:56 +00:00
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 ;
2004-02-04 11:14:47 +00:00
retval . handle = zend_objects_store_put ( obj , NULL , php_com_object_free_storage , php_com_object_clone TSRMLS_CC ) ;
2003-08-14 16:49:56 +00:00
retval . handlers = & php_com_object_handlers ;
return retval ;
}