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