root/ext/com_dotnet/com_variant.c

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

DEFINITIONS

This source file includes following definitions.
  1. safe_array_from_zval
  2. php_com_variant_from_zval
  3. php_com_zval_from_variant
  4. php_com_copy_variant
  5. PHP_FUNCTION
  6. PHP_FUNCTION
  7. variant_binary_operation
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. PHP_FUNCTION
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. PHP_FUNCTION
  17. PHP_FUNCTION
  18. PHP_FUNCTION
  19. PHP_FUNCTION
  20. PHP_FUNCTION
  21. variant_unary_operation
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. PHP_FUNCTION
  28. PHP_FUNCTION
  29. PHP_FUNCTION
  30. PHP_FUNCTION
  31. PHP_FUNCTION
  32. PHP_FUNCTION
  33. PHP_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   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 
  31 /* create an automation SafeArray from a PHP array.
  32  * Only creates a single-dimensional array of variants.
  33  * The keys of the PHP hash MUST be numeric.  If the array
  34  * is sparse, then the gaps will be filled with NULL variants */
  35 static void safe_array_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
  36 {
  37         SAFEARRAY *sa = NULL;
  38         SAFEARRAYBOUND bound;
  39         HashPosition pos;
  40         int keytype;
  41         char *strindex;
  42         int strindexlen;
  43         long intindex = -1;
  44         long max_index = 0;
  45         VARIANT *va;
  46         zval **item;
  47                 
  48         /* find the largest array index, and assert that all keys are integers */
  49         zend_hash_internal_pointer_reset_ex(HASH_OF(z), &pos);
  50         for (;; zend_hash_move_forward_ex(HASH_OF(z), &pos)) {
  51 
  52                 keytype = zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &strindexlen, &intindex, 0, &pos);
  53 
  54                 if (HASH_KEY_IS_STRING == keytype) {
  55                         goto bogus;
  56                 } else if (HASH_KEY_NON_EXISTENT == keytype) {
  57                         break;
  58                 }
  59                 if (intindex > max_index) {
  60                         max_index = intindex;
  61                 }
  62         }
  63 
  64         /* allocate the structure */    
  65         bound.lLbound = 0;
  66         bound.cElements = intindex + 1;
  67         sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
  68 
  69         /* get a lock on the array itself */
  70         SafeArrayAccessData(sa, &va);
  71         va = (VARIANT*)sa->pvData;
  72         
  73         /* now fill it in */
  74         zend_hash_internal_pointer_reset_ex(HASH_OF(z), &pos);
  75         for (;; zend_hash_move_forward_ex(HASH_OF(z), &pos)) {
  76                 if (FAILURE == zend_hash_get_current_data_ex(HASH_OF(z), (void**)&item, &pos)) {
  77                         break;
  78                 }
  79                 zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &strindexlen, &intindex, 0, &pos);
  80                 php_com_variant_from_zval(&va[intindex], *item, codepage TSRMLS_CC);            
  81         }
  82 
  83         /* Unlock it and stuff it into our variant */
  84         SafeArrayUnaccessData(sa);
  85         V_VT(v) = VT_ARRAY|VT_VARIANT;
  86         V_ARRAY(v) = sa;
  87 
  88         return;
  89 
  90 bogus:
  91         php_error_docref(NULL TSRMLS_CC, E_WARNING, "COM: converting from PHP array to VARIANT array; only arrays with numeric keys are allowed");
  92 
  93         V_VT(v) = VT_NULL;
  94 
  95         if (sa) {
  96                 SafeArrayUnlock(sa);
  97                 SafeArrayDestroy(sa);
  98         }
  99 }
 100 
 101 PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
 102 {
 103         OLECHAR *olestring;
 104         php_com_dotnet_object *obj;
 105         zend_uchar ztype = (z == NULL ? IS_NULL : Z_TYPE_P(z));
 106         
 107         switch (ztype) {
 108                 case IS_NULL:
 109                         V_VT(v) = VT_NULL;
 110                         break;
 111 
 112                 case IS_BOOL:
 113                         V_VT(v) = VT_BOOL;
 114                         V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE;
 115                         break;
 116 
 117                 case IS_OBJECT:
 118                         if (php_com_is_valid_object(z TSRMLS_CC)) {
 119                                 obj = CDNO_FETCH(z);
 120                                 if (V_VT(&obj->v) == VT_DISPATCH) {
 121                                         /* pass the underlying object */
 122                                         V_VT(v) = VT_DISPATCH;
 123                                         if (V_DISPATCH(&obj->v)) {
 124                                                 IDispatch_AddRef(V_DISPATCH(&obj->v));
 125                                         }
 126                                         V_DISPATCH(v) = V_DISPATCH(&obj->v);
 127                                 } else {
 128                                         /* pass the variant by reference */
 129                                         V_VT(v) = VT_VARIANT | VT_BYREF;
 130                                         V_VARIANTREF(v) = &obj->v;
 131                                 }
 132                         } else {
 133                                 /* export the PHP object using our COM wrapper */
 134                                 V_VT(v) = VT_DISPATCH;
 135                                 V_DISPATCH(v) = php_com_wrapper_export(z TSRMLS_CC);
 136                         }
 137                         break;
 138                         
 139                 case IS_ARRAY:
 140                         /* map as safe array */
 141                         safe_array_from_zval(v, z, codepage TSRMLS_CC);
 142                         break;
 143 
 144                 case IS_LONG:
 145                         V_VT(v) = VT_I4;
 146                         V_I4(v) = Z_LVAL_P(z);
 147                         break;
 148 
 149                 case IS_DOUBLE:
 150                         V_VT(v) = VT_R8;
 151                         V_R8(v) = Z_DVAL_P(z);
 152                         break;
 153 
 154                 case IS_STRING:
 155                         V_VT(v) = VT_BSTR;
 156                         olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage TSRMLS_CC);
 157                         if (CP_UTF8 == codepage) {
 158                                 V_BSTR(v) = SysAllocStringByteLen((char*)olestring, wcslen(olestring) * sizeof(OLECHAR));
 159                         } else {
 160                                 V_BSTR(v) = SysAllocStringByteLen((char*)olestring, Z_STRLEN_P(z) * sizeof(OLECHAR));
 161                         }
 162                         efree(olestring);
 163                         break;
 164 
 165                 case IS_RESOURCE:
 166                 case IS_CONSTANT:
 167                 case IS_CONSTANT_AST:
 168                 default:
 169                         V_VT(v) = VT_NULL;
 170                         break;
 171         }
 172 }
 173 
 174 PHP_COM_DOTNET_API int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC)
 175 {
 176         OLECHAR *olestring = NULL;
 177         int ret = SUCCESS;
 178 
 179         switch (V_VT(v)) {
 180                 case VT_EMPTY:
 181                 case VT_NULL:
 182                 case VT_VOID:
 183                         ZVAL_NULL(z);
 184                         break;
 185                 case VT_UI1:
 186                         ZVAL_LONG(z, (long)V_UI1(v));
 187                         break;
 188                 case VT_I1:
 189                         ZVAL_LONG(z, (long)V_I1(v));
 190                         break;
 191                 case VT_UI2:
 192                         ZVAL_LONG(z, (long)V_UI2(v));
 193                         break;
 194                 case VT_I2:
 195                         ZVAL_LONG(z, (long)V_I2(v));
 196                         break;
 197                 case VT_UI4:  /* TODO: promote to double if large? */
 198                         ZVAL_LONG(z, (long)V_UI4(v));
 199                         break;
 200                 case VT_I4:
 201                         ZVAL_LONG(z, (long)V_I4(v));
 202                         break;
 203                 case VT_INT:
 204                         ZVAL_LONG(z, V_INT(v));
 205                         break;
 206                 case VT_UINT: /* TODO: promote to double if large? */
 207                         ZVAL_LONG(z, (long)V_UINT(v));
 208                         break;
 209                 case VT_R4:
 210                         ZVAL_DOUBLE(z, (double)V_R4(v));
 211                         break;
 212                 case VT_R8:
 213                         ZVAL_DOUBLE(z, V_R8(v));
 214                         break;
 215                 case VT_BOOL:
 216                         ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0);
 217                         break;
 218                 case VT_BSTR:
 219                         olestring = V_BSTR(v);
 220                         if (olestring) {
 221                                 Z_TYPE_P(z) = IS_STRING;
 222                                 Z_STRVAL_P(z) = php_com_olestring_to_string(olestring,
 223                                         &Z_STRLEN_P(z), codepage TSRMLS_CC);
 224                                 olestring = NULL;
 225                         }
 226                         break;
 227                 case VT_UNKNOWN:
 228                         if (V_UNKNOWN(v) != NULL) {
 229                                 IDispatch *disp;
 230 
 231                                 if (SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, &disp))) {
 232                                         php_com_wrap_dispatch(z, disp, codepage TSRMLS_CC);
 233                                         IDispatch_Release(disp);
 234                                 } else {
 235                                         ret = FAILURE;
 236                                 }
 237                         }
 238                         break;
 239 
 240                 case VT_DISPATCH:
 241                         if (V_DISPATCH(v) != NULL) {
 242                                 php_com_wrap_dispatch(z, V_DISPATCH(v), codepage TSRMLS_CC);
 243                         }
 244                         break;
 245 
 246                 case VT_VARIANT:
 247                         /* points to another variant */
 248                         return php_com_zval_from_variant(z, V_VARIANTREF(v), codepage TSRMLS_CC);
 249                         
 250                 default:
 251                         php_com_wrap_variant(z, v, codepage TSRMLS_CC);
 252         }
 253 
 254         if (olestring) {
 255                 efree(olestring);
 256         }
 257 
 258         if (ret == FAILURE) {
 259                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->zval: conversion from 0x%x ret=%d", V_VT(v), ret);
 260         }
 261 
 262         return ret;
 263 }
 264 
 265 
 266 PHP_COM_DOTNET_API int php_com_copy_variant(VARIANT *dstvar, VARIANT *srcvar TSRMLS_DC)
 267 {
 268         int ret = SUCCESS;
 269         
 270         switch (V_VT(dstvar) & ~VT_BYREF) {
 271         case VT_EMPTY:
 272         case VT_NULL:
 273         case VT_VOID:
 274                 /* should not be possible */
 275                 break;
 276 
 277         case VT_UI1:
 278                 if (V_VT(dstvar) & VT_BYREF) {
 279                         *V_UI1REF(dstvar) = V_UI1(srcvar);
 280                 } else {
 281                          V_UI1(dstvar) = V_UI1(srcvar);
 282                 }
 283                 break;
 284 
 285         case VT_I1:
 286                 if (V_VT(dstvar) & VT_BYREF) {
 287                         *V_I1REF(dstvar) = V_I1(srcvar);
 288                 } else {
 289                         V_I1(dstvar) = V_I1(srcvar);
 290                 }
 291                 break;
 292 
 293         case VT_UI2:
 294                 if (V_VT(dstvar) & VT_BYREF) {
 295                         *V_UI2REF(dstvar) = V_UI2(srcvar);
 296                 } else {
 297                         V_UI2(dstvar) = V_UI2(srcvar); 
 298                 }
 299                 break;
 300 
 301         case VT_I2:
 302                 if (V_VT(dstvar) & VT_BYREF) {
 303                         *V_I2REF(dstvar) = V_I2(srcvar);
 304                 } else {
 305                         V_I2(dstvar) = V_I2(srcvar);
 306                 }
 307                 break;
 308 
 309         case VT_UI4: 
 310                 if (V_VT(dstvar) & VT_BYREF) {
 311                         *V_UI4REF(dstvar) = V_UI4(srcvar);
 312                 } else {
 313                         V_UI4(dstvar) = V_UI4(srcvar);
 314                 }
 315                 break;
 316 
 317         case VT_I4:
 318                 if (V_VT(dstvar) & VT_BYREF) {
 319                         *V_I4REF(dstvar) = V_I4(srcvar);
 320                 } else {
 321                         V_I4(dstvar) = V_I4(srcvar);
 322                 }
 323                 break;
 324 
 325         case VT_INT:
 326                 if (V_VT(dstvar) & VT_BYREF) {
 327                         *V_INTREF(dstvar) = V_INT(srcvar);
 328                 } else {
 329                         V_INT(dstvar) = V_INT(srcvar);
 330                 }
 331                 break;
 332 
 333         case VT_UINT:
 334                 if (V_VT(dstvar) & VT_BYREF) {
 335                         *V_UINTREF(dstvar) = V_UINT(srcvar);
 336                 } else {
 337                         V_UINT(dstvar) = V_UINT(srcvar);       
 338                 }
 339                 break;
 340 
 341         case VT_R4:
 342                 if (V_VT(dstvar) & VT_BYREF) {
 343                         *V_R4REF(dstvar) = V_R4(srcvar);
 344                 } else {
 345                         V_R4(dstvar) = V_R4(srcvar);
 346                 }
 347                 break;
 348 
 349         case VT_R8:
 350                 if (V_VT(dstvar) & VT_BYREF) {
 351                         *V_R8REF(dstvar) = V_R8(srcvar);
 352                 } else {
 353                         V_R8(dstvar) = V_R8(srcvar);
 354                 }
 355                 break;
 356 
 357         case VT_BOOL:
 358                 if (V_VT(dstvar) & VT_BYREF) {
 359                         *V_BOOLREF(dstvar) = V_BOOL(srcvar);
 360                 } else {
 361                         V_BOOL(dstvar) = V_BOOL(srcvar);
 362                 }
 363         break;
 364 
 365         case VT_BSTR:
 366                 if (V_VT(dstvar) & VT_BYREF) {
 367                         *V_BSTRREF(dstvar) = V_BSTR(srcvar);
 368                 } else {
 369                         V_BSTR(dstvar) = V_BSTR(srcvar);
 370         }
 371                 break;
 372 
 373         case VT_UNKNOWN:
 374                 if (V_VT(dstvar) & VT_BYREF) {
 375                         *V_UNKNOWNREF(dstvar) = V_UNKNOWN(srcvar);
 376                 } else {
 377                         V_UNKNOWN(dstvar) = V_UNKNOWN(srcvar);
 378                 }
 379                 break;
 380 
 381         case VT_DISPATCH:
 382                 if (V_VT(dstvar) & VT_BYREF) {
 383                         *V_DISPATCHREF(dstvar) = V_DISPATCH(srcvar);
 384                 } else {
 385                         V_DISPATCH(dstvar) = V_DISPATCH(srcvar);
 386                 }
 387                 break;
 388 
 389         case VT_VARIANT:
 390                 return php_com_copy_variant(V_VARIANTREF(dstvar), srcvar TSRMLS_CC);
 391                 
 392         default:
 393                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->variant: failed to copy from 0x%x to 0x%x", V_VT(dstvar), V_VT(srcvar));
 394                 ret = FAILURE;
 395         }
 396         return ret;
 397 }
 398 
 399 /* {{{ com_variant_create_instance - ctor for new VARIANT() */
 400 PHP_FUNCTION(com_variant_create_instance)
 401 {
 402         /* VARTYPE == unsigned short */ long vt = VT_EMPTY;
 403         long codepage = CP_ACP;
 404         zval *object = getThis();
 405         php_com_dotnet_object *obj;
 406         zval *zvalue = NULL;
 407         HRESULT res;
 408 
 409         if (ZEND_NUM_ARGS() == 0) {
 410                 /* just leave things as-is - an empty variant */
 411                 return;
 412         }
 413         
 414         obj = CDNO_FETCH(object);
 415         
 416         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 417                 "z!|ll", &zvalue, &vt, &codepage)) {
 418                         php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
 419                         return;
 420         }
 421 
 422         php_com_initialize(TSRMLS_C);
 423         if (ZEND_NUM_ARGS() == 3) {
 424                 obj->code_page = codepage;
 425         }
 426 
 427         if (zvalue) {
 428                 php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
 429         }
 430 
 431         /* Only perform conversion if variant not already of type passed */
 432         if ((ZEND_NUM_ARGS() >= 2) && (vt != V_VT(&obj->v))) {
 433 
 434                 /* If already an array and VT_ARRAY is passed then:
 435                         - if only VT_ARRAY passed then do not perform a conversion
 436                         - if VT_ARRAY plus other type passed then perform conversion 
 437                           but will probably fail (original behavior)
 438                 */
 439                 if ((vt & VT_ARRAY) && (V_VT(&obj->v) & VT_ARRAY)) {
 440                         long orig_vt = vt;
 441 
 442                         vt &= ~VT_ARRAY;
 443                         if (vt) {
 444                                 vt = orig_vt;
 445                         }
 446                 }
 447 
 448                 if (vt) {
 449                         res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
 450 
 451                         if (FAILED(res)) {
 452                                 char *werr, *msg;
 453 
 454                                 werr = php_win32_error_to_msg(res);
 455                                 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
 456                                 LocalFree(werr);
 457 
 458                                 php_com_throw_exception(res, msg TSRMLS_CC);
 459                                 efree(msg);
 460                         }
 461                 }
 462         }
 463 
 464         if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) {
 465                 ITypeInfo_Release(obj->typeinfo);
 466                 obj->typeinfo = NULL;
 467         }
 468 }
 469 /* }}} */
 470 
 471 /* {{{ proto void variant_set(object variant, mixed value)
 472    Assigns a new value for a variant object */
 473 PHP_FUNCTION(variant_set)
 474 {
 475         zval *zobj, *zvalue = NULL;
 476         php_com_dotnet_object *obj;
 477 
 478         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 479                         "Oz!", &zobj, php_com_variant_class_entry, &zvalue)) {
 480                 return;
 481         }
 482 
 483         obj = CDNO_FETCH(zobj);
 484 
 485         /* dtor the old value */
 486         if (obj->typeinfo) {
 487                 ITypeInfo_Release(obj->typeinfo);
 488                 obj->typeinfo = NULL;
 489         }
 490         if (obj->sink_dispatch) {
 491                 php_com_object_enable_event_sink(obj, FALSE TSRMLS_CC);
 492                 IDispatch_Release(obj->sink_dispatch);
 493                 obj->sink_dispatch = NULL;
 494         }
 495 
 496         VariantClear(&obj->v);
 497 
 498         php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
 499         /* remember we modified this variant */
 500         obj->modified = 1;
 501 }
 502 /* }}} */
 503 
 504 enum variant_binary_opcode {
 505         VOP_ADD, VOP_CAT, VOP_SUB, VOP_MUL, VOP_AND, VOP_DIV,
 506         VOP_EQV, VOP_IDIV, VOP_IMP, VOP_MOD, VOP_OR, VOP_POW,
 507         VOP_XOR
 508 };
 509 
 510 enum variant_unary_opcode {
 511         VOP_ABS, VOP_FIX, VOP_INT, VOP_NEG, VOP_NOT
 512 };
 513 
 514 static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
 515 {
 516         VARIANT vres;
 517         VARIANT left_val, right_val;
 518         VARIANT *vleft = NULL, *vright = NULL;
 519         zval *zleft = NULL, *zright = NULL;
 520         php_com_dotnet_object *obj;
 521         HRESULT result;
 522         int codepage = CP_ACP;
 523 
 524         VariantInit(&left_val);
 525         VariantInit(&right_val);
 526         VariantInit(&vres);
 527 
 528         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 529                         ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zleft, php_com_variant_class_entry,
 530                         &zright, php_com_variant_class_entry)) {
 531                 obj = CDNO_FETCH(zleft);
 532                 vleft = &obj->v;
 533                 obj = CDNO_FETCH(zright);
 534                 vright = &obj->v;
 535         } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 536                         ZEND_NUM_ARGS() TSRMLS_CC, "Oz!", &zleft, php_com_variant_class_entry,
 537                         &zright)) {
 538                 obj = CDNO_FETCH(zleft);
 539                 vleft = &obj->v;
 540                 vright = &right_val;
 541                 php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
 542         } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 543                         ZEND_NUM_ARGS() TSRMLS_CC, "z!O", &zleft, &zright, php_com_variant_class_entry)) {
 544                 obj = CDNO_FETCH(zright);
 545                 vright = &obj->v;
 546                 vleft = &left_val;
 547                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 548         } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 549                         "z!z!", &zleft, &zright)) {
 550 
 551                 vleft = &left_val;
 552                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 553 
 554                 vright = &right_val;
 555                 php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
 556 
 557         } else {
 558                 return;
 559         }
 560 
 561         switch (op) {
 562                 case VOP_ADD:
 563                         result = VarAdd(vleft, vright, &vres);
 564                         break;
 565                 case VOP_CAT:
 566                         result = VarCat(vleft, vright, &vres);
 567                         break;
 568                 case VOP_SUB:
 569                         result = VarSub(vleft, vright, &vres);
 570                         break;
 571                 case VOP_MUL:
 572                         result = VarMul(vleft, vright, &vres);
 573                         break;
 574                 case VOP_AND:
 575                         result = VarAnd(vleft, vright, &vres);
 576                         break;
 577                 case VOP_DIV:
 578                         result = VarDiv(vleft, vright, &vres);
 579                         break;
 580                 case VOP_EQV:
 581                         result = VarEqv(vleft, vright, &vres);
 582                         break;
 583                 case VOP_IDIV:
 584                         result = VarIdiv(vleft, vright, &vres);
 585                         break;
 586                 case VOP_IMP:
 587                         result = VarImp(vleft, vright, &vres);
 588                         break;
 589                 case VOP_MOD:
 590                         result = VarMod(vleft, vright, &vres);
 591                         break;
 592                 case VOP_OR:
 593                         result = VarOr(vleft, vright, &vres);
 594                         break;
 595                 case VOP_POW:
 596                         result = VarPow(vleft, vright, &vres);
 597                         break;
 598                 case VOP_XOR:
 599                         result = VarXor(vleft, vright, &vres);
 600                         break;
 601                 /*Let say it fails as no valid op has been given */
 602                 default:
 603                         result = E_INVALIDARG;
 604         }
 605 
 606         if (SUCCEEDED(result)) {
 607                 php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
 608         } else {
 609                 php_com_throw_exception(result, NULL TSRMLS_CC);
 610         }
 611 
 612         VariantClear(&vres);
 613         VariantClear(&left_val);
 614         VariantClear(&right_val);
 615 }
 616 /* }}} */
 617 
 618 /* {{{ proto mixed variant_add(mixed left, mixed right)
 619    "Adds" two variant values together and returns the result */
 620 PHP_FUNCTION(variant_add)
 621 {
 622         variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 623 }
 624 /* }}} */
 625 
 626 /* {{{ proto mixed variant_cat(mixed left, mixed right)
 627    concatenates two variant values together and returns the result */
 628 PHP_FUNCTION(variant_cat)
 629 {
 630         variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 631 }
 632 /* }}} */
 633 
 634 /* {{{ proto mixed variant_sub(mixed left, mixed right)
 635    subtracts the value of the right variant from the left variant value and returns the result */
 636 PHP_FUNCTION(variant_sub)
 637 {
 638         variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 639 }
 640 /* }}} */
 641 
 642 /* {{{ proto mixed variant_mul(mixed left, mixed right)
 643    multiplies the values of the two variants and returns the result */
 644 PHP_FUNCTION(variant_mul)
 645 {
 646         variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 647 }
 648 /* }}} */
 649 
 650 /* {{{ proto mixed variant_and(mixed left, mixed right)
 651    performs a bitwise AND operation between two variants and returns the result */
 652 PHP_FUNCTION(variant_and)
 653 {
 654         variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 655 }
 656 /* }}} */
 657 
 658 /* {{{ proto mixed variant_div(mixed left, mixed right)
 659    Returns the result from dividing two variants */
 660 PHP_FUNCTION(variant_div)
 661 {
 662         variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 663 }
 664 /* }}} */
 665 
 666 /* {{{ proto mixed variant_eqv(mixed left, mixed right)
 667    Performs a bitwise equivalence on two variants */
 668 PHP_FUNCTION(variant_eqv)
 669 {
 670         variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 671 }
 672 /* }}} */
 673 
 674 /* {{{ proto mixed variant_idiv(mixed left, mixed right)
 675    Converts variants to integers and then returns the result from dividing them */
 676 PHP_FUNCTION(variant_idiv)
 677 {
 678         variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 679 }
 680 /* }}} */
 681 
 682 /* {{{ proto mixed variant_imp(mixed left, mixed right)
 683    Performs a bitwise implication on two variants */
 684 PHP_FUNCTION(variant_imp)
 685 {
 686         variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 687 }
 688 /* }}} */
 689 
 690 /* {{{ proto mixed variant_mod(mixed left, mixed right)
 691    Divides two variants and returns only the remainder */
 692 PHP_FUNCTION(variant_mod)
 693 {
 694         variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 695 }
 696 /* }}} */
 697 
 698 /* {{{ proto mixed variant_or(mixed left, mixed right)
 699    Performs a logical disjunction on two variants */
 700 PHP_FUNCTION(variant_or)
 701 {
 702         variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 703 }
 704 /* }}} */
 705 
 706 /* {{{ proto mixed variant_pow(mixed left, mixed right)
 707    Returns the result of performing the power function with two variants */
 708 PHP_FUNCTION(variant_pow)
 709 {
 710         variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 711 }
 712 /* }}} */
 713 
 714 /* {{{ proto mixed variant_xor(mixed left, mixed right)
 715    Performs a logical exclusion on two variants */
 716 PHP_FUNCTION(variant_xor)
 717 {
 718         variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 719 }
 720 /* }}} */
 721 
 722 static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
 723 {
 724         VARIANT vres;
 725         VARIANT left_val;
 726         VARIANT *vleft = NULL;
 727         zval *zleft = NULL;
 728         php_com_dotnet_object *obj;
 729         HRESULT result;
 730         int codepage = CP_ACP;
 731 
 732         VariantInit(&left_val);
 733         VariantInit(&vres);
 734 
 735         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 736                         ZEND_NUM_ARGS() TSRMLS_CC, "O", &zleft, php_com_variant_class_entry)) {
 737                 obj = CDNO_FETCH(zleft);
 738                 vleft = &obj->v;
 739         } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 740                         "z!", &zleft)) {
 741                 vleft = &left_val;
 742                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 743         } else {
 744                 return;
 745         }
 746 
 747         switch (op) {
 748                 case VOP_ABS:
 749                         result = VarAbs(vleft, &vres);
 750                         break;
 751                 case VOP_FIX:
 752                         result = VarFix(vleft, &vres);
 753                         break;
 754                 case VOP_INT:
 755                         result = VarInt(vleft, &vres);
 756                         break;
 757                 case VOP_NEG:
 758                         result = VarNeg(vleft, &vres);
 759                         break;
 760                 case VOP_NOT:
 761                         result = VarNot(vleft, &vres);
 762                         break;
 763                 default:
 764                         result = E_INVALIDARG;
 765         }
 766 
 767         if (SUCCEEDED(result)) {
 768                 php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
 769         } else {
 770                 php_com_throw_exception(result, NULL TSRMLS_CC);
 771         }
 772 
 773         VariantClear(&vres);
 774         VariantClear(&left_val);
 775 }
 776 /* }}} */
 777 
 778 /* {{{ proto mixed variant_abs(mixed left)
 779    Returns the absolute value of a variant */
 780 PHP_FUNCTION(variant_abs)
 781 {
 782         variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 783 }
 784 /* }}} */
 785 
 786 /* {{{ proto mixed variant_fix(mixed left)
 787    Returns the integer part ? of a variant */
 788 PHP_FUNCTION(variant_fix)
 789 {
 790         variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 791 }
 792 /* }}} */
 793 
 794 /* {{{ proto mixed variant_int(mixed left)
 795    Returns the integer portion of a variant */
 796 PHP_FUNCTION(variant_int)
 797 {
 798         variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 799 }
 800 /* }}} */
 801 
 802 /* {{{ proto mixed variant_neg(mixed left)
 803    Performs logical negation on a variant */
 804 PHP_FUNCTION(variant_neg)
 805 {
 806         variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 807 }
 808 /* }}} */
 809 
 810 /* {{{ proto mixed variant_not(mixed left)
 811    Performs bitwise not negation on a variant */
 812 PHP_FUNCTION(variant_not)
 813 {
 814         variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
 815 }
 816 /* }}} */
 817 
 818 /* {{{ proto mixed variant_round(mixed left, int decimals)
 819    Rounds a variant to the specified number of decimal places */
 820 PHP_FUNCTION(variant_round)
 821 {
 822         VARIANT vres;
 823         VARIANT left_val;
 824         VARIANT *vleft = NULL;
 825         zval *zleft = NULL;
 826         php_com_dotnet_object *obj;
 827         int codepage = CP_ACP;
 828         long decimals = 0;
 829 
 830         VariantInit(&left_val);
 831         VariantInit(&vres);
 832 
 833         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 834                         ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zleft, php_com_variant_class_entry, &decimals)) {
 835                 obj = CDNO_FETCH(zleft);
 836                 vleft = &obj->v;
 837         } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 838                         "z!l", &zleft, &decimals)) {
 839                 vleft = &left_val;
 840                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 841         } else {
 842                 return;
 843         }
 844 
 845         if (SUCCEEDED(VarRound(vleft, decimals, &vres))) {
 846                 php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
 847         }
 848 
 849         VariantClear(&vres);
 850         VariantClear(&left_val);
 851 }
 852 /* }}} */
 853 
 854 /* {{{ proto int variant_cmp(mixed left, mixed right [, int lcid [, int flags]])
 855    Compares two variants */
 856 PHP_FUNCTION(variant_cmp)
 857 {
 858         VARIANT left_val, right_val;
 859         VARIANT *vleft = NULL, *vright = NULL;
 860         zval *zleft = NULL, *zright = NULL;
 861         php_com_dotnet_object *obj;
 862         int codepage = CP_ACP;
 863         long lcid = LOCALE_SYSTEM_DEFAULT;
 864         long flags = 0;
 865         /* it is safe to ignore the warning for this line; see the comments in com_handlers.c */
 866         STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
 867 
 868         VariantInit(&left_val);
 869         VariantInit(&right_val);
 870 
 871         if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 872                         ZEND_NUM_ARGS() TSRMLS_CC, "OO|ll", &zleft, php_com_variant_class_entry,
 873                         &zright, php_com_variant_class_entry, &lcid, &flags)) {
 874                 obj = CDNO_FETCH(zleft);
 875                 vleft = &obj->v;
 876                 obj = CDNO_FETCH(zright);
 877                 vright = &obj->v;
 878         } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 879                         ZEND_NUM_ARGS() TSRMLS_CC, "Oz!|ll", &zleft, php_com_variant_class_entry,
 880                         &zright, &lcid, &flags)) {
 881                 obj = CDNO_FETCH(zleft);
 882                 vleft = &obj->v;
 883                 vright = &right_val;
 884                 php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
 885         } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
 886                         ZEND_NUM_ARGS() TSRMLS_CC, "z!O|ll", &zleft, &zright, php_com_variant_class_entry,
 887                         &lcid, &flags)) {
 888                 obj = CDNO_FETCH(zright);
 889                 vright = &obj->v;
 890                 vleft = &left_val;
 891                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 892         } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 893                         "z!z!|ll", &zleft, &zright, &lcid, &flags)) {
 894 
 895                 vleft = &left_val;
 896                 php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
 897 
 898                 vright = &right_val;
 899                 php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
 900 
 901         } else {
 902                 return;
 903         }
 904 
 905         ZVAL_LONG(return_value, VarCmp(vleft, vright, lcid, flags));
 906 
 907         VariantClear(&left_val);
 908         VariantClear(&right_val);
 909 }
 910 /* }}} */
 911 
 912 /* {{{ proto int variant_date_to_timestamp(object variant)
 913    Converts a variant date/time value to unix timestamp */
 914 PHP_FUNCTION(variant_date_to_timestamp)
 915 {
 916         VARIANT vres;
 917         zval *zleft = NULL;
 918         php_com_dotnet_object *obj;
 919 
 920         VariantInit(&vres);
 921 
 922         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
 923                 "O", &zleft, php_com_variant_class_entry)) {
 924                 return;
 925         }
 926         obj = CDNO_FETCH(zleft);
 927 
 928         if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) {
 929                 SYSTEMTIME systime;
 930                 struct tm tmv;
 931 
 932                 VariantTimeToSystemTime(V_DATE(&vres), &systime);
 933 
 934                 memset(&tmv, 0, sizeof(tmv));
 935                 tmv.tm_year = systime.wYear - 1900;
 936                 tmv.tm_mon = systime.wMonth - 1;
 937                 tmv.tm_mday = systime.wDay;
 938                 tmv.tm_hour = systime.wHour;
 939                 tmv.tm_min = systime.wMinute;
 940                 tmv.tm_sec = systime.wSecond;
 941                 tmv.tm_isdst = -1;
 942 
 943                 tzset();
 944                 RETVAL_LONG(mktime(&tmv));
 945         }
 946 
 947         VariantClear(&vres);
 948 }
 949 /* }}} */
 950 
 951 /* {{{ proto object variant_date_from_timestamp(int timestamp)
 952    Returns a variant date representation of a unix timestamp */
 953 PHP_FUNCTION(variant_date_from_timestamp)
 954 {
 955         long timestamp;
 956         time_t ttstamp;
 957         SYSTEMTIME systime;
 958         struct tm *tmv;
 959         VARIANT res;
 960 
 961         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
 962                         &timestamp)) {
 963                 return;
 964         }
 965 
 966         if (timestamp < 0) {
 967                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Timestamp value must be a positive value.");
 968                 RETURN_FALSE;
 969         }
 970 
 971         VariantInit(&res);
 972         tzset();
 973         ttstamp = timestamp;
 974         tmv = localtime(&ttstamp);
 975         memset(&systime, 0, sizeof(systime));
 976 
 977         systime.wDay = tmv->tm_mday;
 978         systime.wHour = tmv->tm_hour;
 979         systime.wMinute = tmv->tm_min;
 980         systime.wMonth = tmv->tm_mon + 1;
 981         systime.wSecond = tmv->tm_sec;
 982         systime.wYear = tmv->tm_year + 1900;
 983 
 984         V_VT(&res) = VT_DATE;
 985         SystemTimeToVariantTime(&systime, &V_DATE(&res));
 986 
 987         php_com_wrap_variant(return_value, &res, CP_ACP TSRMLS_CC);
 988 
 989         VariantClear(&res);
 990 }
 991 /* }}} */
 992 
 993 /* {{{ proto int variant_get_type(object variant)
 994    Returns the VT_XXX type code for a variant */
 995 PHP_FUNCTION(variant_get_type)
 996 {
 997         zval *zobj;
 998         php_com_dotnet_object *obj;
 999 
1000         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
1001                 "O", &zobj, php_com_variant_class_entry)) {
1002                 return;
1003         }
1004         obj = CDNO_FETCH(zobj);
1005                 
1006         RETURN_LONG(V_VT(&obj->v));
1007 }
1008 /* }}} */
1009 
1010 /* {{{ proto void variant_set_type(object variant, int type)
1011    Convert a variant into another type.  Variant is modified "in-place" */
1012 PHP_FUNCTION(variant_set_type)
1013 {
1014         zval *zobj;
1015         php_com_dotnet_object *obj;
1016         /* VARTYPE == unsigned short */ long vt;
1017         HRESULT res;
1018 
1019         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
1020                 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1021                 return;
1022         }
1023         obj = CDNO_FETCH(zobj);
1024 
1025         res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
1026 
1027         if (SUCCEEDED(res)) {
1028                 if (vt != VT_DISPATCH && obj->typeinfo) {
1029                         ITypeInfo_Release(obj->typeinfo);
1030                         obj->typeinfo = NULL;
1031                 }
1032         } else {
1033                 char *werr, *msg;
1034 
1035                 werr = php_win32_error_to_msg(res);
1036                 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1037                 LocalFree(werr);
1038 
1039                 php_com_throw_exception(res, msg TSRMLS_CC);
1040                 efree(msg);
1041         }
1042 }
1043 /* }}} */
1044 
1045 /* {{{ proto object variant_cast(object variant, int type)
1046    Convert a variant into a new variant object of another type */
1047 PHP_FUNCTION(variant_cast)
1048 {
1049         zval *zobj;
1050         php_com_dotnet_object *obj;
1051         /* VARTYPE == unsigned short */ long vt;
1052         VARIANT vres;
1053         HRESULT res;
1054 
1055         if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
1056                 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1057                 return;
1058         }
1059         obj = CDNO_FETCH(zobj);
1060 
1061         VariantInit(&vres);
1062         res = VariantChangeType(&vres, &obj->v, 0, (VARTYPE)vt);
1063 
1064         if (SUCCEEDED(res)) {
1065                 php_com_wrap_variant(return_value, &vres, obj->code_page TSRMLS_CC);
1066         } else {
1067                 char *werr, *msg;
1068 
1069                 werr = php_win32_error_to_msg(res);
1070                 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1071                 LocalFree(werr);
1072 
1073                 php_com_throw_exception(res, msg TSRMLS_CC);
1074                 efree(msg);
1075         }
1076 
1077         VariantClear(&vres);
1078 }
1079 /* }}} */
1080 

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