Annotation of embedaddon/php/ext/com_dotnet/com_saproxy.c, revision 1.1.1.2

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: 
1.1.1.2 ! misho      19: /* $Id$ */
1.1       misho      20: 
                     21: /* This module implements a SafeArray proxy which is used internally
                     22:  * by the engine when resolving multi-dimensional array accesses on
                     23:  * SafeArray types.
                     24:  * In addition, the proxy is now able to handle properties of COM objects
                     25:  * that smell like PHP arrays.
                     26:  * */
                     27: 
                     28: #ifdef HAVE_CONFIG_H
                     29: #include "config.h"
                     30: #endif
                     31: 
                     32: #include "php.h"
                     33: #include "php_ini.h"
                     34: #include "ext/standard/info.h"
                     35: #include "php_com_dotnet.h"
                     36: #include "php_com_dotnet_internal.h"
                     37: #include "Zend/zend_exceptions.h"
                     38: 
                     39: typedef struct {
                     40:        /* the object we a proxying for; we hold a refcount to it */
                     41:        zval *zobj;
                     42:        php_com_dotnet_object *obj;
                     43: 
                     44:        /* how many dimensions we are indirecting to get into this element */
                     45:        LONG dimensions;
                     46:        
                     47:        /* this is an array whose size_is(dimensions) */
                     48:        zval **indices;
                     49: 
                     50: } php_com_saproxy;
                     51: 
                     52: typedef struct {
                     53:        zend_object_iterator iter;
                     54:        zval *proxy_obj;
                     55:        php_com_saproxy *proxy;
                     56:        LONG key;
                     57:        LONG imin, imax;
                     58:        LONG *indices;
                     59: } php_com_saproxy_iter;
                     60: 
                     61: #define SA_FETCH(zv)                   (php_com_saproxy*)zend_object_store_get_object(zv TSRMLS_CC)
                     62: 
                     63: static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims)
                     64: {
                     65:        int i;
                     66: 
                     67:        for (i = 0; i < ndims; i++) {
                     68:                MAKE_STD_ZVAL(dest->indices[i]);
                     69:                *dest->indices[i] = *src->indices[i];
                     70:                zval_copy_ctor(dest->indices[i]);
                     71:        }
                     72: }
                     73: 
1.1.1.2 ! misho      74: static zval *saproxy_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
1.1       misho      75: {
                     76:        zval *return_value;
                     77:        
                     78:        MAKE_STD_ZVAL(return_value);
                     79:        ZVAL_NULL(return_value);
                     80: 
                     81:        php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
                     82: 
                     83:        return return_value;
                     84: }
                     85: 
1.1.1.2 ! misho      86: static void saproxy_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
1.1       misho      87: {
                     88:        php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
                     89: }
                     90: 
                     91: static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
                     92: {
                     93:        php_com_saproxy *proxy = SA_FETCH(object);
                     94:        zval *return_value;
                     95:        UINT dims, i;
                     96:        SAFEARRAY *sa;
                     97:        LONG ubound, lbound;
                     98:        HRESULT res;
                     99:        
                    100:        MAKE_STD_ZVAL(return_value);
                    101:        ZVAL_NULL(return_value);
                    102:        
                    103:        if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
                    104:                VARIANT v;
                    105:                zval **args;
                    106: 
                    107:                /* prop-get using first dimension as the property name,
                    108:                 * all subsequent dimensions and the offset as parameters */
                    109: 
                    110:                args = safe_emalloc(proxy->dimensions + 1, sizeof(zval *), 0);
                    111: 
                    112:                for (i = 1; i < (UINT) proxy->dimensions; i++) {
                    113:                        args[i-1] = proxy->indices[i];
                    114:                }
                    115:                args[i-1] = offset;
                    116: 
                    117:                convert_to_string(proxy->indices[0]);
                    118:                VariantInit(&v);
                    119: 
                    120:                res = php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
                    121:                                Z_STRLEN_P(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
                    122:                                proxy->dimensions, args, 0 TSRMLS_CC);
                    123: 
                    124:                if (res == SUCCESS) {
                    125:                        php_com_zval_from_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
                    126:                        VariantClear(&v);
                    127:                } else if (res == DISP_E_BADPARAMCOUNT) {
                    128:                        /* return another proxy */
                    129:                        php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
                    130:                }
                    131: 
                    132:                return return_value;
                    133: 
                    134:        } else if (!V_ISARRAY(&proxy->obj->v)) {
                    135:                php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy object" TSRMLS_CC);
                    136:                return return_value;
                    137:        }
                    138: 
                    139:        /* the SafeArray case */
                    140:        
                    141:        /* offset/index must be an integer */
                    142:        convert_to_long(offset);
                    143:        
                    144:        sa = V_ARRAY(&proxy->obj->v);
                    145:        dims = SafeArrayGetDim(sa);
                    146: 
                    147:        if ((UINT) proxy->dimensions >= dims) {
                    148:                /* too many dimensions */
                    149:                php_com_throw_exception(E_INVALIDARG, "too many dimensions!" TSRMLS_CC);
                    150:                return return_value;
                    151:        }
                    152: 
                    153:        /* bounds check */
                    154:        SafeArrayGetLBound(sa, proxy->dimensions, &lbound);
                    155:        SafeArrayGetUBound(sa, proxy->dimensions, &ubound);
                    156: 
                    157:        if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) {
                    158:                php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds" TSRMLS_CC);
                    159:                return return_value;
                    160:        }
                    161:        
                    162:        if (dims - 1 == proxy->dimensions) {
                    163:                LONG *indices;
                    164:                VARTYPE vt;
                    165:                VARIANT v;
                    166:                
                    167:                VariantInit(&v);
                    168:                
                    169:                /* we can return a real value */
                    170:                indices = safe_emalloc(dims, sizeof(LONG), 0);
                    171: 
                    172:                /* copy indices from proxy */
                    173:                for (i = 0; i < dims; i++) {
                    174:                        convert_to_long(proxy->indices[i]);
                    175:                        indices[i] = Z_LVAL_P(proxy->indices[i]);
                    176:                }
                    177: 
                    178:                /* add user-supplied index */
                    179:                indices[dims-1] = Z_LVAL_P(offset);
                    180: 
                    181:                /* now fetch the value */
                    182:                if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
                    183:                        vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
                    184:                }
                    185: 
                    186:                if (vt == VT_VARIANT) {
                    187:                        res = SafeArrayGetElement(sa, indices, &v);
                    188:                } else {
                    189:                        V_VT(&v) = vt;
                    190:                        res = SafeArrayGetElement(sa, indices, &v.lVal);
                    191:                }
                    192: 
                    193:                efree(indices);
                    194: 
                    195:                if (SUCCEEDED(res)) {
                    196:                        php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
                    197:                } else {
                    198:                        php_com_throw_exception(res, NULL TSRMLS_CC);
                    199:                }
                    200: 
                    201:                VariantClear(&v);
                    202:                
                    203:        } else {
                    204:                /* return another proxy */
                    205:                php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
                    206:        }
                    207: 
                    208:        return return_value;
                    209: }
                    210: 
                    211: static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
                    212: {
                    213:        php_com_saproxy *proxy = SA_FETCH(object);
                    214:        UINT dims, i;
                    215:        HRESULT res;
                    216:        VARIANT v;
                    217:        
                    218:        if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
                    219:                /* We do a prop-set using the first dimension as the property name,
                    220:                 * all subsequent dimensions and offset as parameters, with value as
                    221:                 * the final value */
                    222:                zval **args = safe_emalloc(proxy->dimensions + 2, sizeof(zval *), 0);
                    223: 
                    224:                for (i = 1; i < (UINT) proxy->dimensions; i++) {
                    225:                        args[i-1] = proxy->indices[i];
                    226:                }
                    227:                args[i-1] = offset;
                    228:                args[i] = value;
                    229: 
                    230:                convert_to_string(proxy->indices[0]);
                    231:                VariantInit(&v);
                    232:                if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
                    233:                                        Z_STRLEN_P(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
                    234:                                        args, 0 TSRMLS_CC)) {
                    235:                        VariantClear(&v);
                    236:                }
                    237: 
                    238:                efree(args);
                    239:                
                    240:        } else if (V_ISARRAY(&proxy->obj->v)) {
                    241:                LONG *indices;
                    242:                VARTYPE vt;
                    243: 
                    244:                dims = SafeArrayGetDim(V_ARRAY(&proxy->obj->v));
                    245:                indices = safe_emalloc(dims, sizeof(LONG), 0);
                    246:                /* copy indices from proxy */
                    247:                for (i = 0; i < dims; i++) {
                    248:                        convert_to_long(proxy->indices[i]);
                    249:                        indices[i] = Z_LVAL_P(proxy->indices[i]);
                    250:                }
                    251: 
                    252:                /* add user-supplied index */
                    253:                convert_to_long(offset);
                    254:                indices[dims-1] = Z_LVAL_P(offset);
                    255: 
                    256:                if (FAILED(SafeArrayGetVartype(V_ARRAY(&proxy->obj->v), &vt)) || vt == VT_EMPTY) {
                    257:                        vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
                    258:                }
                    259: 
                    260:                VariantInit(&v);
                    261:                php_com_variant_from_zval(&v, value, proxy->obj->code_page TSRMLS_CC);
                    262: 
                    263:                if (V_VT(&v) != vt) {
                    264:                        VariantChangeType(&v, &v, 0, vt);
                    265:                }
                    266: 
                    267:                if (vt == VT_VARIANT) {
                    268:                        res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v);
                    269:                } else {
                    270:                        res = SafeArrayPutElement(V_ARRAY(&proxy->obj->v), indices, &v.lVal);
                    271:                }
                    272:        
                    273:                efree(indices);
                    274:                VariantClear(&v);
                    275: 
                    276:                if (FAILED(res)) {
                    277:                        php_com_throw_exception(res, NULL TSRMLS_CC);
                    278:                }
                    279:        } else {
                    280:                php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object" TSRMLS_CC);
                    281:        }
                    282: }
                    283: 
                    284: #if 0
                    285: static void saproxy_object_set(zval **property, zval *value TSRMLS_DC)
                    286: {
                    287: }
                    288: 
                    289: static zval *saproxy_object_get(zval *property TSRMLS_DC)
                    290: {
                    291:        /* Not yet implemented in the engine */
                    292:        return NULL;
                    293: }
                    294: #endif
                    295: 
1.1.1.2 ! misho     296: static int saproxy_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
1.1       misho     297: {
                    298:        /* no properties */
                    299:        return 0;
                    300: }
                    301: 
                    302: static int saproxy_dimension_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
                    303: {
                    304:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Operation not yet supported on a COM object");
                    305:        return 0;
                    306: }
                    307: 
1.1.1.2 ! misho     308: static void saproxy_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
1.1       misho     309: {
                    310:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
                    311: }
                    312: 
                    313: static void saproxy_dimension_delete(zval *object, zval *offset TSRMLS_DC)
                    314: {
                    315:        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
                    316: }
                    317: 
                    318: static HashTable *saproxy_properties_get(zval *object TSRMLS_DC)
                    319: {
                    320:        /* no properties */
                    321:        return NULL;
                    322: }
                    323: 
1.1.1.2 ! misho     324: static union _zend_function *saproxy_method_get(zval **object, const char *name, int len, const zend_literal *key TSRMLS_DC)
1.1       misho     325: {
                    326:        /* no methods */
                    327:        return NULL;
                    328: }
                    329: 
1.1.1.2 ! misho     330: static int saproxy_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
1.1       misho     331: {
                    332:        return FAILURE;
                    333: }
                    334: 
                    335: static union _zend_function *saproxy_constructor_get(zval *object TSRMLS_DC)
                    336: {
                    337:        /* user cannot instantiate */
                    338:        return NULL;
                    339: }
                    340: 
                    341: static zend_class_entry *saproxy_class_entry_get(const zval *object TSRMLS_DC)
                    342: {
                    343:        return php_com_saproxy_class_entry;
                    344: }
                    345: 
1.1.1.2 ! misho     346: static int saproxy_class_name_get(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
1.1       misho     347: {
                    348:        *class_name = estrndup(php_com_saproxy_class_entry->name, php_com_saproxy_class_entry->name_length);
                    349:        *class_name_len = php_com_saproxy_class_entry->name_length;
                    350:        return 0;
                    351: }
                    352: 
                    353: static int saproxy_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
                    354: {
                    355:        return -1;
                    356: }
                    357: 
                    358: static int saproxy_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
                    359: {
                    360:        return FAILURE;
                    361: }
                    362: 
                    363: static int saproxy_count_elements(zval *object, long *count TSRMLS_DC)
                    364: {
                    365:        php_com_saproxy *proxy = SA_FETCH(object);
                    366:        LONG ubound, lbound;
                    367:        
                    368:        if (!V_ISARRAY(&proxy->obj->v)) {
                    369:                return FAILURE;
                    370:        }
                    371: 
                    372:        SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &lbound);
                    373:        SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &ubound);
                    374: 
                    375:        *count = ubound - lbound + 1;
                    376: 
                    377:        return SUCCESS;
                    378: }
                    379: 
                    380: zend_object_handlers php_com_saproxy_handlers = {
                    381:        ZEND_OBJECTS_STORE_HANDLERS,
                    382:        saproxy_property_read,
                    383:        saproxy_property_write,
                    384:        saproxy_read_dimension,
                    385:        saproxy_write_dimension,
                    386:        NULL,
                    387:        NULL, /* saproxy_object_get, */
                    388:        NULL, /* saproxy_object_set, */
                    389:        saproxy_property_exists,
                    390:        saproxy_property_delete,
                    391:        saproxy_dimension_exists,
                    392:        saproxy_dimension_delete,
                    393:        saproxy_properties_get,
                    394:        saproxy_method_get,
                    395:        saproxy_call_method,
                    396:        saproxy_constructor_get,
                    397:        saproxy_class_entry_get,
                    398:        saproxy_class_name_get,
                    399:        saproxy_objects_compare,
                    400:        saproxy_object_cast,
                    401:        saproxy_count_elements
                    402: };
                    403: 
                    404: static void saproxy_free_storage(void *object TSRMLS_DC)
                    405: {
                    406:        php_com_saproxy *proxy = (php_com_saproxy *)object;
                    407:        int i;
                    408: 
                    409:        for (i = 0; i < proxy->dimensions; i++) {
                    410:                if (proxy->indices) {
                    411:                                FREE_ZVAL(proxy->indices[i]);
                    412:                }
                    413:        }
                    414: 
                    415:        zval_ptr_dtor(&proxy->zobj);
                    416:        efree(proxy->indices);
                    417:        efree(proxy);
                    418: }
                    419: 
                    420: static void saproxy_clone(void *object, void **clone_ptr TSRMLS_DC)
                    421: {
                    422:        php_com_saproxy *proxy = (php_com_saproxy *)object;
                    423:        php_com_saproxy *cloneproxy;
                    424: 
                    425:        cloneproxy = emalloc(sizeof(*cloneproxy));
                    426:        memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
                    427: 
                    428:        Z_ADDREF_P(cloneproxy->zobj);
                    429:        cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
                    430:        clone_indices(cloneproxy, proxy, proxy->dimensions);
                    431: 
                    432:        *clone_ptr = cloneproxy;
                    433: }
                    434: 
                    435: int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC)
                    436: {
                    437:        php_com_saproxy *proxy, *rel = NULL;
                    438: 
                    439:        proxy = ecalloc(1, sizeof(*proxy));
                    440:        proxy->dimensions = 1;
                    441: 
                    442:        if (Z_OBJCE_P(com_object) == php_com_saproxy_class_entry) {
                    443:                rel = SA_FETCH(com_object);
                    444:                proxy->obj = rel->obj;
                    445:                proxy->zobj = rel->zobj;
                    446:                proxy->dimensions += rel->dimensions;
                    447:        } else {
                    448:                proxy->obj = CDNO_FETCH(com_object);
                    449:                proxy->zobj = com_object;
                    450:        }
                    451: 
                    452:        Z_ADDREF_P(proxy->zobj);
                    453:        proxy->indices = safe_emalloc(proxy->dimensions, sizeof(zval *), 0);
                    454: 
                    455:        if (rel) {
                    456:                clone_indices(proxy, rel, rel->dimensions);
                    457:        }
                    458: 
                    459:        MAKE_STD_ZVAL(proxy->indices[proxy->dimensions-1]);
                    460:        *proxy->indices[proxy->dimensions-1] = *index;
                    461:        zval_copy_ctor(proxy->indices[proxy->dimensions-1]);
                    462: 
                    463:        Z_TYPE_P(proxy_out) = IS_OBJECT;
                    464:        Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, NULL, saproxy_free_storage, saproxy_clone TSRMLS_CC);
                    465:        Z_OBJ_HT_P(proxy_out) = &php_com_saproxy_handlers;
                    466:        
                    467:        return 1;
                    468: }
                    469: 
                    470: /* iterator */
                    471: 
                    472: static void saproxy_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
                    473: {
                    474:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
                    475: 
                    476:        zval_ptr_dtor(&I->proxy_obj);
                    477: 
                    478:        efree(I->indices);
                    479:        efree(I);
                    480: }
                    481: 
                    482: static int saproxy_iter_valid(zend_object_iterator *iter TSRMLS_DC)
                    483: {
                    484:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
                    485: 
                    486:        return (I->key < I->imax) ? SUCCESS : FAILURE;
                    487: }
                    488: 
                    489: static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
                    490: {
                    491:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
                    492:        VARIANT v;
                    493:        VARTYPE vt;
                    494:        zval *return_value, **ptr_ptr;
                    495:        SAFEARRAY *sa;
                    496: 
                    497:        I->indices[I->proxy->dimensions-1] = I->key;
                    498:        
                    499:        sa = V_ARRAY(&I->proxy->obj->v);
                    500:        
                    501:        if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
                    502:                vt = V_VT(&I->proxy->obj->v) & ~VT_ARRAY;
                    503:        }
                    504: 
                    505:        VariantInit(&v);
                    506:        if (vt == VT_VARIANT) {
                    507:                SafeArrayGetElement(sa, I->indices, &v);
                    508:        } else {
                    509:                V_VT(&v) = vt;
                    510:                SafeArrayGetElement(sa, I->indices, &v.lVal);
                    511:        }
                    512: 
                    513:        MAKE_STD_ZVAL(return_value);
                    514:        php_com_wrap_variant(return_value, &v, I->proxy->obj->code_page TSRMLS_CC);
                    515:        VariantClear(&v);
                    516: 
                    517:        ptr_ptr = emalloc(sizeof(*ptr_ptr));
                    518:        *ptr_ptr = return_value;
                    519:        *data = ptr_ptr;
                    520: }
                    521: 
                    522: static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
                    523:        ulong *int_key TSRMLS_DC)
                    524: {
                    525:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
                    526: 
                    527:        if (I->key == -1) {
                    528:                return HASH_KEY_NON_EXISTANT;
                    529:        }
                    530:        *int_key = (ulong)I->key;
                    531:        return HASH_KEY_IS_LONG;
                    532: }
                    533: 
                    534: static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
                    535: {
                    536:        php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
                    537: 
                    538:        if (++I->key >= I->imax) {
                    539:                I->key = -1;
                    540:                return FAILURE;
                    541:        }
                    542:        return SUCCESS;
                    543: }
                    544: 
                    545: static zend_object_iterator_funcs saproxy_iter_funcs = {
                    546:        saproxy_iter_dtor,
                    547:        saproxy_iter_valid,
                    548:        saproxy_iter_get_data,
                    549:        saproxy_iter_get_key,
                    550:        saproxy_iter_move_forwards,
                    551:        NULL
                    552: };
                    553: 
                    554: 
                    555: zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
                    556: {
                    557:        php_com_saproxy *proxy = SA_FETCH(object);
                    558:        php_com_saproxy_iter *I;
                    559:        int i;
                    560: 
                    561:        if (by_ref) {
                    562:                zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
                    563:        }
                    564: 
                    565:        I = ecalloc(1, sizeof(*I));
                    566:        I->iter.funcs = &saproxy_iter_funcs;
                    567:        I->iter.data = I;
                    568: 
                    569:        I->proxy = proxy;
                    570:        I->proxy_obj = object;
                    571:        Z_ADDREF_P(I->proxy_obj);
                    572: 
                    573:        I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
                    574:        for (i = 0; i < proxy->dimensions; i++) {
                    575:                convert_to_long(proxy->indices[i]);
                    576:                I->indices[i] = Z_LVAL_P(proxy->indices[i]);
                    577:        }
                    578: 
                    579:        SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
                    580:        SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax);
                    581: 
                    582:        I->key = I->imin;       
                    583:        
                    584:        return &I->iter;
                    585: }
                    586: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>