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:                        &timestamp)) {
        !           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>