root/ext/com_dotnet/com_handlers.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. com_property_read
  2. com_property_write
  3. com_read_dimension
  4. com_write_dimension
  5. com_object_set
  6. com_object_get
  7. com_property_exists
  8. com_dimension_exists
  9. com_property_delete
  10. com_dimension_delete
  11. com_properties_get
  12. function_dtor
  13. PHP_FUNCTION
  14. com_method_get
  15. com_call_method
  16. com_constructor_get
  17. com_class_name_get
  18. com_objects_compare
  19. com_object_cast
  20. com_object_count
  21. php_com_object_enable_event_sink
  22. php_com_object_free_storage
  23. php_com_object_clone
  24. php_com_object_new

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: Wez Furlong  <wez@thebrainroom.com>                          |
  16    +----------------------------------------------------------------------+
  17  */
  18 
  19 /* $Id$ */
  20 
  21 #ifdef HAVE_CONFIG_H
  22 #include "config.h"
  23 #endif
  24 
  25 #include "php.h"
  26 #include "php_ini.h"
  27 #include "ext/standard/info.h"
  28 #include "php_com_dotnet.h"
  29 #include "php_com_dotnet_internal.h"
  30 #include "Zend/zend_exceptions.h"
  31 
  32 static zval *com_property_read(zval *object, zval *member, int type, void **cahce_slot, zval *rv)
  33 {
  34         php_com_dotnet_object *obj;
  35         VARIANT v;
  36         HRESULT res;
  37 
  38         ZVAL_NULL(rv);
  39 
  40         obj = CDNO_FETCH(object);
  41 
  42         if (V_VT(&obj->v) == VT_DISPATCH) {
  43                 VariantInit(&v);
  44 
  45                 convert_to_string_ex(member);
  46 
  47                 res = php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
  48                                 DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL, 1);
  49 
  50                 if (res == SUCCESS) {
  51                         php_com_zval_from_variant(rv, &v, obj->code_page);
  52                         VariantClear(&v);
  53                 } else if (res == DISP_E_BADPARAMCOUNT) {
  54                         php_com_saproxy_create(object, rv, member);
  55                 }
  56         } else {
  57                 php_com_throw_exception(E_INVALIDARG, "this variant has no properties");
  58         }
  59 
  60         return rv;
  61 }
  62 
  63 static void com_property_write(zval *object, zval *member, zval *value, void **cache_slot)
  64 {
  65         php_com_dotnet_object *obj;
  66         VARIANT v;
  67 
  68         obj = CDNO_FETCH(object);
  69 
  70         if (V_VT(&obj->v) == VT_DISPATCH) {
  71                 VariantInit(&v);
  72 
  73                 convert_to_string_ex(member);
  74                 if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
  75                                 DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF, &v, 1, value, 0)) {
  76                         VariantClear(&v);
  77                 }
  78         } else {
  79                 php_com_throw_exception(E_INVALIDARG, "this variant has no properties");
  80         }
  81 }
  82 
  83 static zval *com_read_dimension(zval *object, zval *offset, int type, zval *rv)
  84 {
  85         php_com_dotnet_object *obj;
  86         VARIANT v;
  87 
  88         ZVAL_NULL(rv);
  89 
  90         obj = CDNO_FETCH(object);
  91 
  92         if (V_VT(&obj->v) == VT_DISPATCH) {
  93                 VariantInit(&v);
  94 
  95                 if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE,
  96                                 DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, offset, 0, 0)) {
  97                         php_com_zval_from_variant(rv, &v, obj->code_page);
  98                         VariantClear(&v);
  99                 }
 100         } else if (V_ISARRAY(&obj->v)) {
 101                 convert_to_long(offset);
 102 
 103                 if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) {
 104                         if (php_com_safearray_get_elem(&obj->v, &v, (LONG)Z_LVAL_P(offset))) {
 105                                 php_com_wrap_variant(rv, &v, obj->code_page);
 106                                 VariantClear(&v);
 107                         }
 108                 } else {
 109                         php_com_saproxy_create(object, rv, offset);
 110                 }
 111 
 112         } else {
 113                 php_com_throw_exception(E_INVALIDARG, "this variant is not an array type");
 114         }
 115 
 116         return rv;
 117 }
 118 
 119 static void com_write_dimension(zval *object, zval *offset, zval *value)
 120 {
 121         php_com_dotnet_object *obj;
 122         zval args[2];
 123         VARIANT v;
 124         HRESULT res;
 125 
 126         obj = CDNO_FETCH(object);
 127 
 128         if (V_VT(&obj->v) == VT_DISPATCH) {
 129                 ZVAL_COPY_VALUE(&args[0], offset);
 130                 ZVAL_COPY_VALUE(&args[1], value);
 131 
 132                 VariantInit(&v);
 133 
 134                 if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE,
 135                                 DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args, 0, 0)) {
 136                         VariantClear(&v);
 137                 }
 138         } else if (V_ISARRAY(&obj->v)) {
 139                 LONG indices = 0;
 140                 VARTYPE vt;
 141 
 142                 if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) {
 143                         if (FAILED(SafeArrayGetVartype(V_ARRAY(&obj->v), &vt)) || vt == VT_EMPTY) {
 144                                 vt = V_VT(&obj->v) & ~VT_ARRAY;
 145                         }
 146 
 147                         convert_to_long(offset);
 148                         indices = (LONG)Z_LVAL_P(offset);
 149 
 150                         VariantInit(&v);
 151                         php_com_variant_from_zval(&v, value, obj->code_page);
 152 
 153                         if (V_VT(&v) != vt) {
 154                                 VariantChangeType(&v, &v, 0, vt);
 155                         }
 156 
 157                         if (vt == VT_VARIANT) {
 158                                 res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v);
 159                         } else {
 160                                 res = SafeArrayPutElement(V_ARRAY(&obj->v), &indices, &v.lVal);
 161                         }
 162 
 163                         VariantClear(&v);
 164 
 165                         if (FAILED(res)) {
 166                                 php_com_throw_exception(res, NULL);
 167                         }
 168 
 169                 } else {
 170                         php_com_throw_exception(DISP_E_BADINDEX, "this variant has multiple dimensions; you can't set a new value without specifying *all* dimensions");
 171                 }
 172 
 173         } else {
 174                 php_com_throw_exception(E_INVALIDARG, "this variant is not an array type");
 175         }
 176 }
 177 
 178 #if 0
 179 static void com_object_set(zval **property, zval *value)
 180 {
 181         /* Not yet implemented in the engine */
 182 }
 183 
 184 static zval *com_object_get(zval *property)
 185 {
 186         /* Not yet implemented in the engine */
 187         return NULL;
 188 }
 189 #endif
 190 
 191 static int com_property_exists(zval *object, zval *member, int check_empty, void **cache_slot)
 192 {
 193         DISPID dispid;
 194         php_com_dotnet_object *obj;
 195 
 196         obj = CDNO_FETCH(object);
 197 
 198         if (V_VT(&obj->v) == VT_DISPATCH) {
 199                 convert_to_string_ex(member);
 200                 if (SUCCEEDED(php_com_get_id_of_name(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), &dispid))) {
 201                         /* TODO: distinguish between property and method! */
 202                         return 1;
 203                 }
 204         } else {
 205                 /* TODO: check for safearray */
 206         }
 207 
 208         return 0;
 209 }
 210 
 211 static int com_dimension_exists(zval *object, zval *member, int check_empty)
 212 {
 213         php_error_docref(NULL, E_WARNING, "Operation not yet supported on a COM object");
 214         return 0;
 215 }
 216 
 217 static void com_property_delete(zval *object, zval *member, void **cache_slot)
 218 {
 219         php_error_docref(NULL, E_WARNING, "Cannot delete properties from a COM object");
 220 }
 221 
 222 static void com_dimension_delete(zval *object, zval *offset)
 223 {
 224         php_error_docref(NULL, E_WARNING, "Cannot delete properties from a COM object");
 225 }
 226 
 227 static HashTable *com_properties_get(zval *object)
 228 {
 229         /* TODO: use type-info to get all the names and values ?
 230          * DANGER: if we do that, there is a strong possibility for
 231          * infinite recursion when the hash is displayed via var_dump().
 232          * Perhaps it is best to leave it un-implemented.
 233          */
 234         return NULL;
 235 }
 236 
 237 static void function_dtor(zval *zv)
 238 {
 239         zend_internal_function *f = (zend_internal_function*)Z_PTR_P(zv);
 240 
 241         zend_string_release(f->function_name);
 242         if (f->arg_info) {
 243                 efree(f->arg_info);
 244         }
 245         efree(f);
 246 }
 247 
 248 static PHP_FUNCTION(com_method_handler)
 249 {
 250         zval *object = getThis();
 251 
 252         Z_OBJ_HANDLER_P(object, call_method)(
 253                         ((zend_internal_function*)EX(func))->function_name,
 254                         Z_OBJ_P(object),
 255                         INTERNAL_FUNCTION_PARAM_PASSTHRU);
 256 }
 257 
 258 static union _zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key)
 259 {
 260         zend_internal_function f, *fptr = NULL;
 261         union _zend_function *func;
 262         DISPID dummy;
 263         php_com_dotnet_object *obj = (php_com_dotnet_object*)*object_ptr;
 264 
 265         if (V_VT(&obj->v) != VT_DISPATCH) {
 266                 return NULL;
 267         }
 268 
 269         if (FAILED(php_com_get_id_of_name(obj, name->val, name->len, &dummy))) {
 270                 return NULL;
 271         }
 272 
 273         /* check cache */
 274         if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) {
 275                 f.type = ZEND_OVERLOADED_FUNCTION;
 276                 f.num_args = 0;
 277                 f.arg_info = NULL;
 278                 f.scope = obj->ce;
 279                 f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
 280                 f.function_name = zend_string_copy(name);
 281                 f.handler = PHP_FN(com_method_handler);
 282                 zend_set_function_arg_flags((zend_function*)&f);
 283 
 284                 fptr = &f;
 285 
 286                 if (obj->typeinfo) {
 287                         /* look for byref params */
 288                         ITypeComp *comp;
 289                         ITypeInfo *TI = NULL;
 290                         DESCKIND kind;
 291                         BINDPTR bindptr;
 292                         OLECHAR *olename;
 293                         ULONG lhash;
 294                         int i;
 295 
 296                         if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
 297                                 olename = php_com_string_to_olestring(name->val, name->len, obj->code_page);
 298                                 lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename);
 299 
 300                                 if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) {
 301                                         switch (kind) {
 302                                                 case DESCKIND_FUNCDESC:
 303                                                         f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info));
 304 
 305                                                         for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) {
 306                                                                 f.arg_info[i].allow_null = 1;
 307                                                                 if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) {
 308                                                                         f.arg_info[i].pass_by_reference = 1;
 309                                                                 }
 310                                                         }
 311 
 312                                                         f.num_args = bindptr.lpfuncdesc->cParams;
 313 
 314                                                         ITypeInfo_ReleaseFuncDesc(TI, bindptr.lpfuncdesc);
 315                                                         break;
 316 
 317                                                         /* these should not happen, but *might* happen if the user
 318                                                          * screws up; lets avoid a leak in that case */
 319                                                 case DESCKIND_VARDESC:
 320                                                         ITypeInfo_ReleaseVarDesc(TI, bindptr.lpvardesc);
 321                                                         break;
 322                                                 case DESCKIND_TYPECOMP:
 323                                                         ITypeComp_Release(bindptr.lptcomp);
 324                                                         break;
 325 
 326                                                 case DESCKIND_NONE:
 327                                                         break;
 328                                         }
 329                                         if (TI) {
 330                                                 ITypeInfo_Release(TI);
 331                                         }
 332                                 }
 333                                 ITypeComp_Release(comp);
 334                                 efree(olename);
 335                         }
 336                 }
 337 
 338                 if (fptr) {
 339                         /* save this method in the cache */
 340                         if (!obj->method_cache) {
 341                                 ALLOC_HASHTABLE(obj->method_cache);
 342                                 zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0);
 343                         }
 344 
 345                         zend_hash_update_mem(obj->method_cache, name, &f, sizeof(f));
 346                 }
 347         }
 348 
 349         if (fptr) {
 350                 /* duplicate this into a new chunk of emalloc'd memory,
 351                  * since the engine will efree it */
 352                 func = emalloc(sizeof(*fptr));
 353                 memcpy(func, fptr, sizeof(*fptr));
 354 
 355                 return func;
 356         }
 357 
 358         return NULL;
 359 }
 360 
 361 static int com_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
 362 {
 363         zval *args = NULL;
 364         php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
 365         int nargs;
 366         VARIANT v;
 367         int ret = FAILURE;
 368 
 369         if (V_VT(&obj->v) != VT_DISPATCH) {
 370                 return FAILURE;
 371         }
 372 
 373         nargs = ZEND_NUM_ARGS();
 374 
 375         if (nargs) {
 376                 args = (zval *)safe_emalloc(sizeof(zval), nargs, 0);
 377                 zend_get_parameters_array_ex(nargs, args);
 378         }
 379 
 380         VariantInit(&v);
 381 
 382         if (SUCCESS == php_com_do_invoke_byref(obj, (zend_internal_function*)EX(func), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args)) {
 383                 php_com_zval_from_variant(return_value, &v, obj->code_page);
 384                 ret = SUCCESS;
 385                 VariantClear(&v);
 386         }
 387 
 388         if (args) {
 389                 efree(args);
 390         }
 391 
 392         return ret;
 393 }
 394 
 395 static union _zend_function *com_constructor_get(zend_object *object)
 396 {
 397         php_com_dotnet_object *obj = (php_com_dotnet_object *) object;
 398         static zend_internal_function c, d, v;
 399 
 400 #define POPULATE_CTOR(f, fn)    \
 401         f.type = ZEND_INTERNAL_FUNCTION; \
 402         f.function_name = obj->ce->name; \
 403         f.scope = obj->ce; \
 404         f.arg_info = NULL; \
 405         f.num_args = 0; \
 406         f.fn_flags = 0; \
 407         f.handler = ZEND_FN(fn); \
 408         return (union _zend_function*)&f;
 409 
 410         switch (obj->ce->name->val[0]) {
 411 #if HAVE_MSCOREE_H
 412                 case 'd':
 413                         POPULATE_CTOR(d, com_dotnet_create_instance);
 414 #endif
 415 
 416                 case 'c':
 417                         POPULATE_CTOR(c, com_create_instance);
 418 
 419                 case 'v':
 420                         POPULATE_CTOR(v, com_variant_create_instance);
 421 
 422                 default:
 423                         return NULL;
 424         }
 425 }
 426 
 427 static zend_string* com_class_name_get(const zend_object *object)
 428 {
 429         php_com_dotnet_object *obj = (php_com_dotnet_object *)object;
 430 
 431         return zend_string_copy(obj->ce->name);
 432 }
 433 
 434 /* This compares two variants for equality */
 435 static int com_objects_compare(zval *object1, zval *object2)
 436 {
 437         php_com_dotnet_object *obja, *objb;
 438         int ret;
 439         /* strange header bug problem here... the headers define the proto without the
 440          * flags parameter.  However, the MSDN docs state that there is a flags parameter,
 441          * and my VC6 won't link unless the code uses the version with 4 parameters.
 442          * So, we have this declaration here to fix it */
 443         STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
 444 
 445         obja = CDNO_FETCH(object1);
 446         objb = CDNO_FETCH(object2);
 447 
 448         switch (VarCmp(&obja->v, &objb->v, LOCALE_SYSTEM_DEFAULT, 0)) {
 449                 case VARCMP_LT:
 450                         ret = -1;
 451                         break;
 452                 case VARCMP_GT:
 453                         ret = 1;
 454                         break;
 455                 case VARCMP_EQ:
 456                         ret = 0;
 457                         break;
 458                 default:
 459                         /* either or both operands are NULL...
 460                          * not 100% sure how to handle this */
 461                         ret = -2;
 462         }
 463 
 464         return ret;
 465 }
 466 
 467 static int com_object_cast(zval *readobj, zval *writeobj, int type)
 468 {
 469         php_com_dotnet_object *obj;
 470         VARIANT v;
 471         VARTYPE vt = VT_EMPTY;
 472         HRESULT res = S_OK;
 473 
 474         obj = CDNO_FETCH(readobj);
 475         ZVAL_NULL(writeobj);
 476         VariantInit(&v);
 477 
 478         if (V_VT(&obj->v) == VT_DISPATCH) {
 479                 if (SUCCESS != php_com_do_invoke_by_id(obj, DISPID_VALUE,
 480                                 DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL, 1, 0)) {
 481                         VariantCopy(&v, &obj->v);
 482                 }
 483         } else {
 484                 VariantCopy(&v, &obj->v);
 485         }
 486 
 487         switch(type) {
 488                 case IS_LONG:
 489                         vt = VT_INT;
 490                         break;
 491                 case IS_DOUBLE:
 492                         vt = VT_R8;
 493                         break;
 494                 case IS_FALSE:
 495                 case IS_TRUE:
 496                 case _IS_BOOL:
 497                         vt = VT_BOOL;
 498                         break;
 499                 case IS_STRING:
 500                         vt = VT_BSTR;
 501                         break;
 502                 default:
 503                         ;
 504         }
 505 
 506         if (vt != VT_EMPTY && vt != V_VT(&v)) {
 507                 res = VariantChangeType(&v, &v, 0, vt);
 508         }
 509 
 510         if (SUCCEEDED(res)) {
 511                 php_com_zval_from_variant(writeobj, &v, obj->code_page);
 512         }
 513 
 514         VariantClear(&v);
 515 
 516         if (SUCCEEDED(res)) {
 517                 return SUCCESS;
 518         }
 519 
 520         return zend_std_cast_object_tostring(readobj, writeobj, type);
 521 }
 522 
 523 static int com_object_count(zval *object, zend_long *count)
 524 {
 525         php_com_dotnet_object *obj;
 526         LONG ubound = 0, lbound = 0;
 527 
 528         obj = CDNO_FETCH(object);
 529 
 530         if (!V_ISARRAY(&obj->v)) {
 531                 return FAILURE;
 532         }
 533 
 534         SafeArrayGetLBound(V_ARRAY(&obj->v), 1, &lbound);
 535         SafeArrayGetUBound(V_ARRAY(&obj->v), 1, &ubound);
 536 
 537         *count = ubound - lbound + 1;
 538 
 539         return SUCCESS;
 540 }
 541 
 542 zend_object_handlers php_com_object_handlers = {
 543         0,
 544         php_com_object_free_storage,
 545         zend_objects_destroy_object,
 546         php_com_object_clone,
 547         com_property_read,
 548         com_property_write,
 549         com_read_dimension,
 550         com_write_dimension,
 551         NULL,
 552         NULL, /* com_object_get, */
 553         NULL, /* com_object_set, */
 554         com_property_exists,
 555         com_property_delete,
 556         com_dimension_exists,
 557         com_dimension_delete,
 558         com_properties_get,
 559         com_method_get,
 560         com_call_method,
 561         com_constructor_get,
 562         com_class_name_get,
 563         com_objects_compare,
 564         com_object_cast,
 565         com_object_count,
 566         NULL,                                                                   /* get_debug_info */
 567         NULL,                                                                   /* get_closure */
 568         NULL,                                                                   /* get_gc */
 569 };
 570 
 571 void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable)
 572 {
 573         if (obj->sink_dispatch) {
 574                 IConnectionPointContainer *cont;
 575                 IConnectionPoint *point;
 576 
 577                 if (SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v),
 578                                 &IID_IConnectionPointContainer, (void**)&cont))) {
 579 
 580                         if (SUCCEEDED(IConnectionPointContainer_FindConnectionPoint(cont,
 581                                         &obj->sink_id, &point))) {
 582 
 583                                 if (enable) {
 584                                         IConnectionPoint_Advise(point, (IUnknown*)obj->sink_dispatch, &obj->sink_cookie);
 585                                 } else {
 586                                         IConnectionPoint_Unadvise(point, obj->sink_cookie);
 587                                 }
 588                                 IConnectionPoint_Release(point);
 589                         }
 590                         IConnectionPointContainer_Release(cont);
 591                 }
 592         }
 593 }
 594 
 595 void php_com_object_free_storage(zend_object *object)
 596 {
 597         php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
 598 
 599         if (obj->typeinfo) {
 600                 ITypeInfo_Release(obj->typeinfo);
 601                 obj->typeinfo = NULL;
 602         }
 603 
 604         if (obj->sink_dispatch) {
 605                 php_com_object_enable_event_sink(obj, FALSE);
 606                 IDispatch_Release(obj->sink_dispatch);
 607                 obj->sink_dispatch = NULL;
 608         }
 609 
 610         VariantClear(&obj->v);
 611 
 612         if (obj->method_cache) {
 613                 zend_hash_destroy(obj->method_cache);
 614                 FREE_HASHTABLE(obj->method_cache);
 615         }
 616         if (obj->id_of_name_cache) {
 617                 zend_hash_destroy(obj->id_of_name_cache);
 618                 FREE_HASHTABLE(obj->id_of_name_cache);
 619         }
 620 }
 621 
 622 zend_object* php_com_object_clone(zval *object)
 623 {
 624         php_com_dotnet_object *cloneobj, *origobject;
 625 
 626         origobject = (php_com_dotnet_object*)Z_OBJ_P(object);
 627         cloneobj = (php_com_dotnet_object*)emalloc(sizeof(php_com_dotnet_object));
 628 
 629         memcpy(cloneobj, origobject, sizeof(*cloneobj));
 630 
 631         /* VariantCopy will perform VariantClear; we don't want to clobber
 632          * the IDispatch that we memcpy'd, so we init a new variant in the
 633          * clone structure */
 634         VariantInit(&cloneobj->v);
 635         /* We use the Indirection-following version of the API since we
 636          * want to clone as much as possible */
 637         VariantCopyInd(&cloneobj->v, &origobject->v);
 638 
 639         if (cloneobj->typeinfo) {
 640                 ITypeInfo_AddRef(cloneobj->typeinfo);
 641         }
 642 
 643         return (zend_object*)cloneobj;
 644 }
 645 
 646 zend_object* php_com_object_new(zend_class_entry *ce)
 647 {
 648         php_com_dotnet_object *obj;
 649 
 650         php_com_initialize();
 651         obj = emalloc(sizeof(*obj));
 652         memset(obj, 0, sizeof(*obj));
 653 
 654         VariantInit(&obj->v);
 655         obj->code_page = CP_ACP;
 656         obj->ce = ce;
 657 
 658         zend_object_std_init(&obj->zo, ce);
 659         obj->zo.handlers = &php_com_object_handlers;
 660 
 661         return (zend_object*)obj;
 662 }

/* [<][>][^][v][top][bottom][index][help] */