[prev in list] [next in list] [prev in thread] [next in thread] 

List:       php-cvs
Subject:    [PHP-CVS] cvs: php-src /ext/com_dotnet com_com.c com_extension.c com_handlers.c com_saproxy.c php_co
From:       "Wez Furlong" <wez () php ! net>
Date:       2004-04-28 8:23:23
Message-ID: cvswez1083140603 () cvsserver
[Download RAW message or body]

wez		Wed Apr 28 04:23:23 2004 EDT

  Modified files:              
    /php-src/ext/com_dotnet	com_com.c com_extension.c com_handlers.c 
                           	com_saproxy.c php_com_dotnet_internal.h 
  Log:
  Fix for Bug #28161 (and probably others that I can't find in the bug db;
  the search interface sucks).
  
  Expand the proxy object so it can handle psuedo array style properties.
  
  ASP/VB code like this:
  
  	headObj.Attribute("RID") = rid 
  
  can be expressed like this in PHP:
  
  	$headObj->Attribute['RID'] = $rid;
  
  In theory, this feature can be used for "multi dimensional" properties:
  
  	headObj.Attribute("RID", "Foo") = rid;
  
  like this:
  
  	$headObj->Attribute['RID']['Foo'] = $rid;
  
  
  
["wez-20040428042323.txt" (text/plain)]

http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_com.c?r1=1.11&r2=1.12&ty=u
Index: php-src/ext/com_dotnet/com_com.c
diff -u php-src/ext/com_dotnet/com_com.c:1.11 php-src/ext/com_dotnet/com_com.c:1.12
--- php-src/ext/com_dotnet/com_com.c:1.11	Thu Feb 12 05:43:19 2004
+++ php-src/ext/com_dotnet/com_com.c	Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_com.c,v 1.11 2004/02/12 10:43:19 zeev Exp $ */
+/* $Id: com_com.c,v 1.12 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -333,6 +333,17 @@
 				spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc);
 				LocalFree(desc);
 				break;
+
+			case DISP_E_BADPARAMCOUNT:
+				if ((disp_params->cArgs + disp_params->cNamedArgs == 0) && (flags == \
DISPATCH_PROPERTYGET)) { +					/* if getting a property and they are missing all \
parameters, +					 * we want to create a proxy object for them; so lets not create an
+					 * exception here */
+					msg = NULL;
+					break;
+				}
+				/* else fall through */
+				
 			default:
 				desc = php_win_err(hr);
 				spprintf(&msg, 0, "Error %s", desc);
@@ -557,6 +568,10 @@
 		efree(vargs);
 	}
 
+	/* a bit strange this, but... */
+	if (hr == DISP_E_BADPARAMCOUNT)
+		return hr;
+	
 	return SUCCEEDED(hr) ? SUCCESS : FAILURE;
 }
 
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_extension.c?r1=1.9&r2=1.10&ty=u
                
Index: php-src/ext/com_dotnet/com_extension.c
diff -u php-src/ext/com_dotnet/com_extension.c:1.9 \
                php-src/ext/com_dotnet/com_extension.c:1.10
--- php-src/ext/com_dotnet/com_extension.c:1.9	Thu Feb 12 05:43:19 2004
+++ php-src/ext/com_dotnet/com_extension.c	Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_extension.c,v 1.9 2004/02/12 10:43:19 zeev Exp $ */
+/* $Id: com_extension.c,v 1.10 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -197,18 +197,16 @@
 	INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL);
 	php_com_saproxy_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 	php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL;
-//	php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED;
+	php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED;
 	php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
 	
 	INIT_CLASS_ENTRY(ce, "variant", NULL);
 	ce.create_object = php_com_object_new;
-//	ce.get_iterator = php_com_iter_get;
 	php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 	php_com_variant_class_entry->get_iterator = php_com_iter_get;
 
 	INIT_CLASS_ENTRY(ce, "com", NULL);
 	ce.create_object = php_com_object_new;
-//	ce.get_iterator = php_com_iter_get;
 	tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" \
TSRMLS_CC);  tmp->get_iterator = php_com_iter_get;
 
@@ -217,7 +215,6 @@
 #if HAVE_MSCOREE_H
 	INIT_CLASS_ENTRY(ce, "dotnet", NULL);
 	ce.create_object = php_com_object_new;
-//	ce.get_iterator = php_com_iter_get;
 	tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" \
TSRMLS_CC);  tmp->get_iterator = php_com_iter_get;
 #endif
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_handlers.c?r1=1.18&r2=1.19&ty=u
                
Index: php-src/ext/com_dotnet/com_handlers.c
diff -u php-src/ext/com_dotnet/com_handlers.c:1.18 \
                php-src/ext/com_dotnet/com_handlers.c:1.19
--- php-src/ext/com_dotnet/com_handlers.c:1.18	Mon Mar 22 17:47:05 2004
+++ php-src/ext/com_dotnet/com_handlers.c	Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_handlers.c,v 1.18 2004/03/22 22:47:05 wez Exp $ */
+/* $Id: com_handlers.c,v 1.19 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -34,6 +34,7 @@
 	zval *return_value;
 	php_com_dotnet_object *obj;
 	VARIANT v;
+	HRESULT res;
 
 	MAKE_STD_ZVAL(return_value);
 	ZVAL_NULL(return_value);
@@ -46,10 +47,15 @@
 		VariantInit(&v);
 
 		convert_to_string_ex(&member);
-		if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
-				DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) {
+
+		res = php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
+				DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC);
+
+		if (res == SUCCESS) {
 			php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
 			VariantClear(&v);
+		} else if (res == DISP_E_BADPARAMCOUNT) {
+			php_com_saproxy_create(object, return_value, member TSRMLS_CC);
 		}
 	} else {
 		php_com_throw_exception(E_INVALIDARG, "this variant has no properties" TSRMLS_CC);
@@ -137,7 +143,7 @@
 				VariantClear(&v);
 			}
 		} else {
-			php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) TSRMLS_CC);
+			php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
 		}
 
 	} else {
@@ -555,7 +561,6 @@
 void php_com_object_free_storage(void *object TSRMLS_DC)
 {
 	php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
-
 	if (obj->typeinfo) {
 		ITypeInfo_Release(obj->typeinfo);
 		obj->typeinfo = NULL;
@@ -614,7 +619,6 @@
 	obj->code_page = CP_ACP;
 	obj->ce = ce;
 
-	
 	retval.handle = zend_objects_store_put(obj, NULL, php_com_object_free_storage, \
php_com_object_clone TSRMLS_CC);  retval.handlers = &php_com_object_handlers;
 
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_saproxy.c?r1=1.8&r2=1.9&ty=u
Index: php-src/ext/com_dotnet/com_saproxy.c
diff -u php-src/ext/com_dotnet/com_saproxy.c:1.8 \
                php-src/ext/com_dotnet/com_saproxy.c:1.9
--- php-src/ext/com_dotnet/com_saproxy.c:1.8	Tue Apr 13 13:51:36 2004
+++ php-src/ext/com_dotnet/com_saproxy.c	Wed Apr 28 04:23:22 2004
@@ -16,11 +16,13 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_saproxy.c,v 1.8 2004/04/13 17:51:36 wez Exp $ */
+/* $Id: com_saproxy.c,v 1.9 2004/04/28 08:23:22 wez Exp $ */
 
 /* This module implements a SafeArray proxy which is used internally
  * by the engine when resolving multi-dimensional array accesses on
- * SafeArray types
+ * SafeArray types.
+ * In addition, the proxy is now able to handle properties of COM objects
+ * that smell like PHP arrays.
  * */
 
 #ifdef HAVE_CONFIG_H
@@ -43,7 +45,7 @@
 	LONG dimensions;
 	
 	/* this is an array whose size_is(dimensions) */
-	LONG *indices;
+	zval **indices;
 
 } php_com_saproxy;
 
@@ -58,6 +60,17 @@
 
 #define SA_FETCH(zv)			(php_com_saproxy*)zend_object_store_get_object(zv TSRMLS_CC)
 
+static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int \
ndims) +{
+	int i;
+
+	for (i = 0; i < ndims; i++) {
+		MAKE_STD_ZVAL(dest->indices[i]);
+		*dest->indices[i] = *src->indices[i];
+		zval_copy_ctor(dest->indices[i]);
+	}
+}
+
 static zval *saproxy_property_read(zval *object, zval *member, int type TSRMLS_DC)
 {
 	zval *return_value;
@@ -82,15 +95,50 @@
 	UINT dims;
 	SAFEARRAY *sa;
 	LONG ubound, lbound;
+	int i;
+	HRESULT res;
 	
 	MAKE_STD_ZVAL(return_value);
 	ZVAL_NULL(return_value);
 	
-	if (!V_ISARRAY(&proxy->obj->v)) {
-		php_com_throw_exception(E_INVALIDARG, "proxied object is no longer a safe array!" \
TSRMLS_CC); +	if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
+		VARIANT v;
+		zval **args;
+
+		/* prop-get using first dimension as the property name,
+		 * all subsequent dimensions and the offset as parameters */
+
+		args = safe_emalloc(proxy->dimensions + 1, sizeof(zval *), 0);
+
+		for (i = 1; i < proxy->dimensions; i++) {
+			args[i-1] = proxy->indices[i];
+		}
+		args[i-1] = offset;
+
+		convert_to_string(proxy->indices[0]);
+		VariantInit(&v);
+
+		res = php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
+			   	Z_STRLEN_P(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
+			   	proxy->dimensions, args TSRMLS_CC);
+
+		if (res == SUCCESS) {
+			php_com_zval_from_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
+			VariantClear(&v);
+		} else if (res == DISP_E_BADPARAMCOUNT) {
+			/* return another proxy */
+			php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
+		}
+
+		return return_value;
+
+	} else if (!V_ISARRAY(&proxy->obj->v)) {
+		php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy object" \
TSRMLS_CC);  return return_value;
 	}
 
+	/* the SafeArray case */
+	
 	/* offset/index must be an integer */
 	convert_to_long(offset);
 	
@@ -123,7 +171,10 @@
 		indices = do_alloca(dims * sizeof(LONG));
 
 		/* copy indices from proxy */
-		memcpy(indices, proxy->indices, (dims-1) * sizeof(LONG));
+		for (i = 0; i < dims; i++) {
+			convert_to_long(proxy->indices[i]);
+			indices[i] = Z_LVAL_P(proxy->indices[i]);
+		}
 
 		/* add user-supplied index */
 		indices[dims-1] = Z_LVAL_P(offset);
@@ -148,7 +199,7 @@
 		
 	} else {
 		/* return another proxy */
-		php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) TSRMLS_CC);
+		php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
 	}
 
 	return return_value;
@@ -156,7 +207,41 @@
 
 static void saproxy_write_dimension(zval *object, zval *offset, zval *value \
TSRMLS_DC)  {
-	php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet implemented" \
TSRMLS_CC); +	php_com_saproxy *proxy = SA_FETCH(object);
+	UINT dims;
+	SAFEARRAY *sa;
+	LONG ubound, lbound;
+	int i;
+	HRESULT res;
+	VARIANT v;
+	
+	if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
+		/* We do a prop-set using the first dimension as the property name,
+		 * all subsequent dimensions and offset as parameters, with value as
+		 * the final value */
+		zval **args = safe_emalloc(proxy->dimensions + 2, sizeof(zval *), 0);
+
+		for (i = 1; i < proxy->dimensions; i++) {
+			args[i-1] = proxy->indices[i];
+		}
+		args[i-1] = offset;
+		args[i] = value;
+
+		convert_to_string(proxy->indices[0]);
+		VariantInit(&v);
+		if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
+					Z_STRLEN_P(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
+					args TSRMLS_CC)) {
+			VariantClear(&v);
+		}
+
+		efree(args);
+		
+	} else if (V_ISARRAY(&proxy->obj->v)) {
+		php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet implemented" \
TSRMLS_CC); +	} else {
+		php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object" TSRMLS_CC);
+	}
 }
 
 static void saproxy_object_set(zval **property, zval *value TSRMLS_DC)
@@ -262,6 +347,13 @@
 static void saproxy_free_storage(void *object TSRMLS_DC)
 {
 	php_com_saproxy *proxy = (php_com_saproxy *)object;
+	int i;
+
+	for (i = 0; i < proxy->dimensions; i++) {
+		if (proxy->indices) {
+				FREE_ZVAL(proxy->indices[i]);
+		}
+	}
 
 	zval_ptr_dtor(&proxy->zobj);
 	efree(proxy->indices);
@@ -272,43 +364,45 @@
 {
 	php_com_saproxy *proxy = (php_com_saproxy *)object;
 	php_com_saproxy *cloneproxy;
+	int i;
 
 	cloneproxy = emalloc(sizeof(*cloneproxy));
 	memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
 
 	ZVAL_ADDREF(cloneproxy->zobj);
-	cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(LONG), 0);
-	memcpy(cloneproxy->indices, proxy->indices, cloneproxy->dimensions * sizeof(LONG));
+	cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
+	clone_indices(cloneproxy, proxy, proxy->dimensions);
 
 	*clone_ptr = cloneproxy;
 }
 
-int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC)
+int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC)
 {
 	php_com_saproxy *proxy, *rel = NULL;
-	php_com_dotnet_object *obj;
 
 	proxy = ecalloc(1, sizeof(*proxy));
 	proxy->dimensions = 1;
 
 	if (Z_OBJCE_P(com_object) == php_com_saproxy_class_entry) {
 		rel = SA_FETCH(com_object);
-		obj = rel->obj;
+		proxy->obj = rel->obj;
 		proxy->zobj = rel->zobj;
 		proxy->dimensions += rel->dimensions;
 	} else {
-		obj = CDNO_FETCH(com_object);
+		proxy->obj = CDNO_FETCH(com_object);
 		proxy->zobj = com_object;
 	}
 
 	ZVAL_ADDREF(proxy->zobj);
-	proxy->indices = safe_emalloc(proxy->dimensions, sizeof(LONG), 0);
+	proxy->indices = safe_emalloc(proxy->dimensions, sizeof(zval *), 0);
 
 	if (rel) {
-		memcpy(proxy->indices, rel->indices, (proxy->dimensions-1) * sizeof(LONG));
+		clone_indices(proxy, rel, rel->dimensions);
 	}
 
-	proxy->indices[proxy->dimensions-1] = index;
+	MAKE_STD_ZVAL(proxy->indices[proxy->dimensions-1]);
+	*proxy->indices[proxy->dimensions-1] = *index;
+	zval_copy_ctor(proxy->indices[proxy->dimensions-1]);
 
 	Z_TYPE_P(proxy_out) = IS_OBJECT;
 	Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, NULL, \
saproxy_free_storage, saproxy_clone TSRMLS_CC); @@ -406,6 +500,7 @@
 {
 	php_com_saproxy *proxy = SA_FETCH(object);
 	php_com_saproxy_iter *I;
+	int i;
 
 	I = ecalloc(1, sizeof(*I));
 	I->iter.funcs = &saproxy_iter_funcs;
@@ -416,7 +511,10 @@
 	ZVAL_ADDREF(I->proxy_obj);
 
 	I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
-	memcpy(I->indices, proxy->indices, proxy->dimensions * sizeof(LONG));
+	for (i = 0; i < proxy->dimensions; i++) {
+		convert_to_long(proxy->indices[i]);
+		I->indices[i] = Z_LVAL_P(proxy->indices[i]);
+	}
 
 	SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
 	SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax);
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/php_com_dotnet_internal.h?r1=1.9&r2=1.10&ty=u
                
Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h
diff -u php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.9 \
                php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.10
--- php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.9	Wed Feb  4 06:14:30 2004
+++ php-src/ext/com_dotnet/php_com_dotnet_internal.h	Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_com_dotnet_internal.h,v 1.9 2004/02/04 11:14:30 zeev Exp $ */
+/* $Id: php_com_dotnet_internal.h,v 1.10 2004/04/28 08:23:22 wez Exp $ */
 
 #ifndef PHP_COM_DOTNET_INTERNAL_H
 #define PHP_COM_DOTNET_INTERNAL_H
@@ -83,7 +83,7 @@
 
 /* com_saproxy.c */
 zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object \
                TSRMLS_DC);
-int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC);
+int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index \
TSRMLS_DC);  
 /* com_olechar.c */
 PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring,



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic