summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2002-08-26 13:36:35 +0000
committerWez Furlong <wez@php.net>2002-08-26 13:36:35 +0000
commitcfb5002e0ba8f8c077c4739cd964747dc2616d1d (patch)
treee585a015f273d0bb46f324480c733d4e218d9f15
parentfc7eb838fcdbbc1ac776b5724dfe42e80da7e91e (diff)
downloadphp-git-cfb5002e0ba8f8c077c4739cd964747dc2616d1d.tar.gz
Implement com_invoke_ex, which allows the user to specify the invoke kind
flags, so that custom invocations can be made. Tidy up code for com_propget and com_propset, so that it can work with objects as well as resources. # This code is from a couple of months ago, and has been hanging around # on my windows dev box; I'm not entirely sure where I needed com_invoke_ex, # but the additions to propget and propset are useful.
-rw-r--r--ext/com/COM.c203
-rw-r--r--ext/com/php_COM.h1
2 files changed, 161 insertions, 43 deletions
diff --git a/ext/com/COM.c b/ext/com/COM.c
index 022d9d93d0..384d3b5f2a 100644
--- a/ext/com/COM.c
+++ b/ext/com/COM.c
@@ -87,6 +87,7 @@ static unsigned char arg1and2_force_ref[] =
function_entry COM_functions[] = {
PHP_FE(com_load, NULL)
PHP_FE(com_invoke, NULL)
+ PHP_FE(com_invoke_ex, NULL)
PHP_FE(com_addref, NULL)
PHP_FE(com_release, NULL)
PHP_FE(com_propget, NULL)
@@ -133,6 +134,7 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
C_HASTLIB(obj) = FALSE;
+ C_TYPEINFO(obj) = NULL;
}
}
} else {
@@ -143,22 +145,25 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS
switch (hr) {
case DISP_E_EXCEPTION: {
- char *src=estrdup("Unavailable");
- int srclen=strlen(src);
- char *desc=estrdup("Unavailable");
- int desclen=strlen(desc);
+ char *src = NULL;
+ int srclen = 0;
+ char *desc = NULL;
+ int desclen = 0;
- if (ExceptInfo.bstrSource)
- {
- efree(src);
+ if (ExceptInfo.bstrSource) {
src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC);
SysFreeString(ExceptInfo.bstrSource);
+ } else {
+ src = estrdup("Unavailable");
+ srclen = strlen(src);
}
- if (ExceptInfo.bstrDescription)
- {
- efree(desc);
+
+ if (ExceptInfo.bstrDescription) {
desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, codepage TSRMLS_CC);
SysFreeString(ExceptInfo.bstrDescription);
+ } else {
+ desc = estrdup("Unavailable");
+ desclen = strlen(desc);
}
*ErrString = pemalloc(srclen+desclen+50, 1);
@@ -211,6 +216,7 @@ PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames
C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
C_HASTLIB(obj) = FALSE;
+ C_TYPEINFO(obj) = NULL;
}
}
} else {
@@ -233,12 +239,17 @@ PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC)
} else if (obj->refcount == 1) {
if (C_HASTLIB(obj)) {
C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj));
+ C_TYPEINFO(obj) = NULL;
+ C_HASTLIB(obj) = FALSE;
}
if (C_HASENUM(obj)) {
hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj));
+ C_ENUMVARIANT(obj) = NULL;
+ C_HASENUM(obj) = FALSE;
}
hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj));
C_RELEASE(obj);
+ C_DISPATCH(obj) = NULL;
}
return obj->refcount;
@@ -250,7 +261,6 @@ PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC)
if (C_ISREFD(obj)) {
C_ADDREF(obj);
}
-
return obj->refcount;
}
@@ -723,9 +733,9 @@ PHP_FUNCTION(com_load)
/* }}} */
-int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count TSRMLS_DC)
+static int do_COM_invoke(comval *obj, WORD dispflags, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count TSRMLS_DC)
{
- DISPID dispid;
+ DISPID dispid, altdispid;
DISPPARAMS dispparams;
HRESULT hr;
OLECHAR *funcname;
@@ -876,7 +886,14 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
dispparams.cArgs = arg_count;
dispparams.cNamedArgs = 0;
- hr = php_COM_invoke(obj, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC);
+ if (dispflags & DISPATCH_PROPERTYPUT) {
+ /* Make this work for property set-ing */
+ altdispid = DISPID_PROPERTYPUT;
+ dispparams.rgdispidNamedArgs = &altdispid;
+ dispparams.cNamedArgs = 1;
+ }
+
+ hr = php_COM_invoke(obj, dispid, dispflags, &dispparams, var_result, &ErrString TSRMLS_CC);
efree(funcname);
for (current_arg=0;current_arg<arg_count;current_arg++) {
@@ -903,6 +920,62 @@ int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **
return SUCCESS;
}
+/* {{{ proto mixed com_invoke_ex(int module, int invokeflags, string handler_name [, mixed arg [, mixed ...]])
+ Invokes a COM module */
+PHP_FUNCTION(com_invoke_ex)
+{
+ pval **arguments;
+ pval *object, *function_name, *invokeflags;
+ comval *obj = NULL;
+ WORD dispflags = 0;
+ int arg_count = ZEND_NUM_ARGS();
+ VARIANT *var_result;
+
+ if (arg_count<3) {
+ ZEND_WRONG_PARAM_COUNT();
+ }
+ arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
+ if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) {
+ RETURN_NULL();
+ }
+
+ object = arguments[0];
+ function_name = arguments[2];
+ invokeflags = arguments[1];
+
+ /* obtain property/method handler */
+ convert_to_string_ex(&function_name);
+ convert_to_long(invokeflags);
+ dispflags = (WORD)Z_LVAL_P(invokeflags);
+
+ /* obtain IDispatch interface */
+ if (Z_TYPE_P(object) == IS_OBJECT && (Z_OBJCE_P(object) == &COM_class_entry || !strcmp(Z_OBJCE_P(object)->name, "COM"))) {
+ zval **tmp;
+ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void**)&tmp);
+ ZEND_FETCH_RESOURCE(obj, comval*, tmp, -1, "comval", IS_COM);
+ } else if (Z_TYPE_P(object) == IS_RESOURCE) {
+ ZEND_FETCH_RESOURCE(obj, comval*, &object, -1, "comval", IS_COM);
+ }
+ if (obj == NULL) {
+ php_error(E_WARNING, "%d is not a COM object handler", Z_LVAL_P(object));
+ RETURN_NULL();
+ }
+
+ ALLOC_VARIANT(var_result);
+
+ if (do_COM_invoke(obj, dispflags, function_name, var_result, arguments+3, arg_count-3 TSRMLS_CC)==FAILURE) {
+ FREE_VARIANT(var_result);
+ efree(arguments);
+
+ RETURN_NULL();
+ }
+
+ RETVAL_VARIANT(var_result);
+
+ efree(arguments);
+}
+/* }}} */
+
/* {{{ proto mixed com_invoke(int module, string handler_name [, mixed arg [, mixed ...]])
Invokes a COM module */
@@ -930,7 +1003,7 @@ PHP_FUNCTION(com_invoke)
convert_to_long(object);
obj = (comval *)zend_list_find(Z_LVAL_P(object), &type);
if (!obj || (type != IS_COM)) {
- php_error(E_WARNING,"%s(): %d is not a COM object handler", get_active_function_name(TSRMLS_C), Z_STRVAL_P(function_name));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a COM object handler", Z_STRVAL_P(function_name));
RETURN_NULL();
}
@@ -939,7 +1012,7 @@ PHP_FUNCTION(com_invoke)
ALLOC_VARIANT(var_result);
- if (do_COM_invoke(obj, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) {
+ if (do_COM_invoke(obj, DISPATCH_METHOD|DISPATCH_PROPERTYGET, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) {
FREE_VARIANT(var_result);
efree(arguments);
@@ -1475,7 +1548,7 @@ static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cle
int retval;
ZVAL_STRINGL(&function_name, "Item", 4, 0);
- retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC);
+ retval = do_COM_invoke(array, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &function_name, result, &property, 1 TSRMLS_CC);
if (cleanup) {
php_COM_destruct(array TSRMLS_CC);
}
@@ -1629,63 +1702,105 @@ static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property,
}
-/* {{{ proto mixed com_propget(int module, string property_name)
+/* {{{ proto mixed com_propget(int module, string property_name [, mixed arg ... ])
Gets properties from a COM module */
PHP_FUNCTION(com_propget)
{
- pval *arg_comval, *arg_property;
- int type;
- comval *obj;
+ zval **arguments;
+ zval *object, *function_name;
+ comval *obj = NULL;
+ int arg_count = ZEND_NUM_ARGS();
VARIANT *var_result;
- if ((ZEND_NUM_ARGS() != 2) || (zend_get_parameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) {
+ if (arg_count<3) {
ZEND_WRONG_PARAM_COUNT();
}
+ arguments = (zval **) emalloc(sizeof(pval *)*arg_count);
+ if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) {
+ RETURN_NULL();
+ }
- /* obtain IDispatch interface */
- convert_to_long(arg_comval);
- obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
- if (!obj || (type != IS_COM)) {
- php_error(E_WARNING, "%s(): %d is not a COM object handler", get_active_function_name(TSRMLS_C), Z_LVAL_P(arg_comval));
+ object = arguments[0];
+ function_name = arguments[1];
+
+ if (Z_TYPE_P(object) == IS_OBJECT && (Z_OBJCE_P(object) == &COM_class_entry || !strcmp(Z_OBJCE_P(object)->name, "COM"))) {
+ zval **tmp;
+ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void**)&tmp);
+ ZEND_FETCH_RESOURCE(obj, comval*, tmp, -1, "comval", IS_COM);
+ } else if (Z_TYPE_P(object) == IS_RESOURCE) {
+ ZEND_FETCH_RESOURCE(obj, comval*, &object, -1, "comval", IS_COM);
+ }
+ if (obj == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 1 is not a COM object handler");
RETURN_NULL();
}
- convert_to_string_ex(&arg_property);
+
+ /* obtain property/method handler */
+ convert_to_string_ex(&function_name);
ALLOC_VARIANT(var_result);
- if (do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) {
+ if (do_COM_invoke(obj, DISPATCH_PROPERTYGET, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) {
FREE_VARIANT(var_result);
+ efree(arguments);
+
RETURN_NULL();
}
RETVAL_VARIANT(var_result);
+
+ efree(arguments);
}
/* }}} */
-/* {{{ proto bool com_propput(int module, string property_name, mixed value)
+/* {{{ proto bool com_propput(int module, string property_name, mixed value, ...)
Puts the properties for a module */
PHP_FUNCTION(com_propput)
{
- pval *arg_comval, *arg_property, *arg_value;
- int type;
+ zval **arguments;
+ zval *object, *function_name;
comval *obj;
+ int arg_count = ZEND_NUM_ARGS();
+ VARIANT *var_result;
- if (ZEND_NUM_ARGS()!=3 || zend_get_parameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) {
+ if (arg_count<3) {
ZEND_WRONG_PARAM_COUNT();
}
+ arguments = (zval **) emalloc(sizeof(pval *)*arg_count);
+ if (zend_get_parameters_array(ht, arg_count, arguments) == FAILURE) {
+ RETURN_NULL();
+ }
- /* obtain comval interface */
- convert_to_long(arg_comval);
- /* obtain comval interface */
- obj = (comval *)zend_list_find(Z_LVAL_P(arg_comval), &type);
- if (!obj || (type != IS_COM)) {
- php_error(E_WARNING, "%s(): %d is not a COM object handler", get_active_function_name(TSRMLS_C), Z_LVAL_P(arg_comval));
+ object = arguments[0];
+ function_name = arguments[1];
+
+ if (Z_TYPE_P(object) == IS_OBJECT && (Z_OBJCE_P(object) == &COM_class_entry || !strcmp(Z_OBJCE_P(object)->name, "COM"))) {
+ zval **tmp;
+ zend_hash_index_find(Z_OBJPROP_P(object), 0, (void**)&tmp);
+ ZEND_FETCH_RESOURCE(obj, comval*, tmp, -1, "comval", IS_COM);
+ } else if (Z_TYPE_P(object) == IS_RESOURCE) {
+ ZEND_FETCH_RESOURCE(obj, comval*, &object, -1, "comval", IS_COM);
+ }
+ if (obj == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "parameter 1 is not a COM object handler");
+ RETURN_NULL();
+ }
+
+ /* obtain property/method handler */
+ convert_to_string_ex(&function_name);
+
+ ALLOC_VARIANT(var_result);
+
+ if (do_COM_invoke(obj, DISPATCH_PROPERTYPUT, function_name, var_result, arguments+2, arg_count-2 TSRMLS_CC)==FAILURE) {
+ FREE_VARIANT(var_result);
+ efree(arguments);
RETURN_NULL();
}
- convert_to_string_ex(&arg_property);
- do_COM_propput(return_value, obj, arg_property, arg_value TSRMLS_CC);
+ RETVAL_VARIANT(var_result);
+
+ efree(arguments);
}
/* }}} */
@@ -1979,7 +2094,7 @@ PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_pro
arguments = (pval **) emalloc(sizeof(pval *)*arg_count);
zend_get_parameters_array(ht, arg_count, arguments);
- if (do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == SUCCESS) {
+ if (do_COM_invoke(obj , DISPATCH_METHOD|DISPATCH_PROPERTYGET, &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == SUCCESS) {
php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC);
}
@@ -2313,7 +2428,9 @@ PHP_MINIT_FUNCTION(COM)
REGISTER_LONG_CONSTANT("CLSCTX_REMOTE_SERVER", CLSCTX_REMOTE_SERVER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CLSCTX_SERVER", CLSCTX_SERVER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("CLSCTX_ALL", CLSCTX_ALL, CONST_CS | CONST_PERSISTENT);
-
+ REGISTER_LONG_CONSTANT("DISPATCH_METHOD", DISPATCH_METHOD, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("DISPATCH_PROPERTYGET", DISPATCH_PROPERTYGET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("DISPATCH_PROPERTYPUT", DISPATCH_PROPERTYPUT, CONST_CS | CONST_PERSISTENT);
REGISTER_INI_ENTRIES();
return SUCCESS;
diff --git a/ext/com/php_COM.h b/ext/com/php_COM.h
index d26441f6a3..1b2b3b0316 100644
--- a/ext/com/php_COM.h
+++ b/ext/com/php_COM.h
@@ -12,6 +12,7 @@ PHP_MSHUTDOWN_FUNCTION(COM);
PHP_FUNCTION(com_load);
PHP_FUNCTION(com_invoke);
+PHP_FUNCTION(com_invoke_ex);
PHP_FUNCTION(com_addref);
PHP_FUNCTION(com_release);
PHP_FUNCTION(com_propget);