From: Harald Radi Date: Thu, 18 Jul 2002 18:31:37 +0000 (+0000) Subject: ext/rpc/com should work now, but there's still lots of work left. X-Git-Tag: dev~247 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c83f78dc9650a1a6c786f9bc0c0e1e04449dd3ae;p=php ext/rpc/com should work now, but there's still lots of work left. --- diff --git a/ext/rpc/com/com.c b/ext/rpc/com/com.c index c597e7a869..d2e850d0db 100644 --- a/ext/rpc/com/com.c +++ b/ext/rpc/com/com.c @@ -1,11 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #define _WIN32_DCOM -#include "../handler.h" +#include "../rpc.h" #include "../php_rpc.h" +#include "../handler.h" #include "com.h" #include "com_wrapper.h" #include "conversion.h" +#include "variant.h" #include @@ -14,8 +34,9 @@ static int com_hash(rpc_string, rpc_string *, void *, int, char *, int); static int com_name(rpc_string, rpc_string *, void *, int); static int com_ctor(rpc_string, void **, int , zval ***); -static int com_dtor(void **); -static int com_call(rpc_string, void **, zval **, int, zval ***); +static int com_dtor(void *); +static int com_describe(rpc_string, void *, char **); +static int com_call(rpc_string, void **, zval *, int, zval ***); static int com_get(rpc_string, zval *, void **); static int com_set(rpc_string, zval *, void **); static int com_compare(void **, void **); @@ -23,12 +44,11 @@ static int com_has_property(rpc_string, void **); static int com_unset_property(rpc_string, void **); static int com_get_properties(HashTable **, void **); -static PHP_INI_MH(OnTypelibFileChange); - +static PHP_INI_MH(com_typelib_file_change); /* globals */ static IBindCtx *pBindCtx; - +static unsigned char arg1and2_force_ref[] = { 2, BYREF_FORCE, BYREF_FORCE }; /* register rpc callback function */ RPC_REGISTER_HANDLERS_START(com) @@ -38,6 +58,7 @@ com_hash, com_name, com_ctor, com_dtor, +com_describe, com_call, com_get, com_set, @@ -53,20 +74,31 @@ PHP_INI_ENTRY_EX("com.allow_dcom", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_di PHP_INI_ENTRY_EX("com.autoregister_typelib", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) PHP_INI_ENTRY_EX("com.autoregister_verbose", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) PHP_INI_ENTRY_EX("com.autoregister_casesensitive", "1", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) -PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypelibFileChange) +PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, com_typelib_file_change) RPC_INI_END() /* register userspace functions */ RPC_FUNCTION_ENTRY_START(com) - ZEND_FALIAS(com_invoke, rpc_call, NULL) - ZEND_FE(com_addref, NULL) - ZEND_FE(com_release, NULL) + ZEND_FALIAS(com_invoke, rpc_call, NULL) + ZEND_FE(com_addref, NULL) + ZEND_FE(com_release, NULL) + ZEND_FE(com_next, NULL) + ZEND_FE(com_all, NULL) + ZEND_FE(com_reset, NULL) + ZEND_FE(com_skip, NULL) + ZEND_FE(com_event_sink, arg1and2_force_ref) + ZEND_FE(com_message_pump, NULL) + ZEND_FE(com_print_typeinfo, NULL) RPC_FUNCTION_ENTRY_END() /* register class methods */ RPC_METHOD_ENTRY_START(com) - ZEND_FALIAS(addref, com_addref, NULL) - ZEND_FALIAS(release, com_release, NULL) + ZEND_FALIAS(addref, com_addref, NULL) + ZEND_FALIAS(release, com_release, NULL) + ZEND_FALIAS(next, com_next, NULL) + ZEND_FALIAS(all, com_all, NULL) + ZEND_FALIAS(reset, com_reset, NULL) + ZEND_FALIAS(skip, com_skip, NULL) RPC_METHOD_ENTRY_END() @@ -76,10 +108,12 @@ RPC_METHOD_ENTRY_END() RPC_INIT_FUNCTION(com) { CreateBindCtx(0, &pBindCtx); + php_variant_init(module_number TSRMLS_CC); } RPC_SHUTDOWN_FUNCTION(com) { + php_variant_shutdown(TSRMLS_C); pBindCtx->lpVtbl->Release(pBindCtx); } @@ -295,7 +329,7 @@ static int com_ctor(rpc_string class_name, void **data, int num_args, zval **arg if (server_name) { hr = MK_E_SYNTAX; } else { - OLECHAR *olestr = php_char_to_OLECHAR(class_name.str, class_name.len, obj->codepage, FALSE); + OLECHAR *olestr = php_char_to_OLECHAR(class_name.str, class_name.len, C_CODEPAGE(obj), FALSE); if (SUCCEEDED(hr = MkParseDisplayNameEx(pBindCtx, olestr, &ulEaten, &pMoniker))) { hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); @@ -327,7 +361,7 @@ static int com_ctor(rpc_string class_name, void **data, int num_args, zval **arg server_info.dwReserved1=0; server_info.dwReserved2=0; - server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_PP(server_name), Z_STRLEN_PP(server_name), obj->codepage, FALSE); + server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_PP(server_name), Z_STRLEN_PP(server_name), C_CODEPAGE(obj), FALSE); if (user_name) { /* Parse Username into domain\username */ authid.User = (WCHAR *) Z_STRVAL_PP(user_name); @@ -410,30 +444,197 @@ static int com_ctor(rpc_string class_name, void **data, int num_args, zval **arg } } -#if 0 - RETURN_RESOURCE(zend_list_insert(obj, IS_COM)); -#endif + return SUCCESS; +} + +static int com_dtor(void *data) +{ + php_COM_destruct((comval *) data); return SUCCESS; } -static int com_dtor(void **data) +static int com_describe(rpc_string method_name, void *data, char **arg_types) { return SUCCESS; } -static int com_call(rpc_string method_name, void **data, zval **return_value, int num_args, zval **args[]) +static int com_call(rpc_string method_name, void **data, zval *return_value, int num_args, zval **args[]) { + DISPID dispid; + DISPPARAMS dispparams; + HRESULT hr; + OLECHAR *funcname; + VARIANT *variant_args, *result; + int current_arg, current_variant; + char *ErrString; + TSRMLS_FETCH(); + + funcname = php_char_to_OLECHAR(method_name.str, method_name.len, CP_ACP, FALSE); + + if (FAILED(hr = php_COM_get_ids_of_names((comval *) *data, funcname, &dispid))) { + char *error_message; + + error_message = php_COM_error_message(hr); + php_error(E_WARNING,"Unable to lookup %s: %s", method_name.str, error_message); + LocalFree(error_message); + efree(funcname); + + return FAILURE; + } + + variant_args = (VARIANT *) emalloc(sizeof(VARIANT) * num_args); + + for (current_arg = 0; current_arg < num_args; current_arg++) { + current_variant = num_args - current_arg - 1; + php_zval_to_variant(*args[current_arg], &variant_args[current_variant], C_CODEPAGE((comval *) *data)); + } + + dispparams.rgvarg = variant_args; + dispparams.rgdispidNamedArgs = NULL; + dispparams.cArgs = num_args; + dispparams.cNamedArgs = 0; + + result = (VARIANT *) emalloc(sizeof(VARIANT)); + VariantInit(result); + + hr = php_COM_invoke((comval *) *data, dispid, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, result, &ErrString); + + for (current_arg=0;current_argIDispatch */ + VariantClear(&variant_args[current_arg]); + } + } + + efree(result); + efree(funcname); + + if (FAILED(hr)) { + char *error_message; + + efree(result); + error_message = php_COM_error_message(hr); + if (ErrString) { + php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString); + efree(ErrString); + } else { + php_error(E_WARNING,"Invoke() failed: %s", error_message); + } + LocalFree(error_message); + return FAILURE; + } + + RETVAL_VARIANT(result, C_CODEPAGE((comval *) *data)); return SUCCESS; } static int com_get(rpc_string property_name, zval *return_value, void **data) { + char *ErrString; + VARIANT *result; + OLECHAR *propname; + DISPID dispid; + DISPPARAMS dispparams; + HRESULT hr; + TSRMLS_FETCH(); + + /* obtain property handler */ + propname = php_char_to_OLECHAR(property_name.str, property_name.len, CP_ACP, FALSE); + + if (FAILED(hr = php_COM_get_ids_of_names((comval *) *data, propname, &dispid))) { + char *error_message; + + efree(propname); + error_message = php_COM_error_message(hr); + rpc_error(E_WARNING,"Unable to lookup %s: %s", property_name.str, error_message); + LocalFree(error_message); + + return FAILURE; + } + + efree(propname); + + result = (VARIANT *) emalloc(sizeof(VARIANT)); + VariantInit(result); + + dispparams.cArgs = 0; + dispparams.cNamedArgs = 0; + + if (FAILED(hr = php_COM_invoke((comval *) data, dispid, DISPATCH_PROPERTYGET, &dispparams, result, &ErrString))) { + char *error_message; + + efree(result); + error_message = php_COM_error_message(hr); + if (ErrString != NULL) { + rpc_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString); + efree(ErrString); + } else { + rpc_error(E_WARNING,"PropGet() failed: %s", error_message); + } + LocalFree(error_message); + + return FAILURE; + } + + RETVAL_VARIANT(result, C_CODEPAGE((comval *) *data)); + return SUCCESS; } static int com_set(rpc_string property_name, zval *value, void **data) { + HRESULT hr; + OLECHAR *propname; + DISPID dispid, mydispid = DISPID_PROPERTYPUT; + DISPPARAMS dispparams; + VARIANT *var; + char *error_message, *ErrString; + + + /* obtain property handler */ + propname = php_char_to_OLECHAR(property_name.str, property_name.len, CP_ACP, FALSE); + + if (FAILED(hr = php_COM_get_ids_of_names((comval *) *data, propname, &dispid))) { + error_message = php_COM_error_message(hr); + php_error(E_WARNING,"Unable to lookup %s: %s", property_name.str, error_message); + LocalFree(error_message); + efree(propname); + + return FAILURE; + } + + efree(propname); + + var = (VARIANT *) emalloc(sizeof(VARIANT)); + VariantInit(var); + + php_zval_to_variant(value, var, C_CODEPAGE((comval *) *data)); + dispparams.rgvarg = var; + dispparams.rgdispidNamedArgs = &mydispid; + dispparams.cArgs = 1; + dispparams.cNamedArgs = 1; + + if (FAILED(hr = php_COM_invoke((comval *) *data, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString))) { + error_message = php_COM_error_message(hr); + if (ErrString) { + php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString); + efree(ErrString); + } else { + php_error(E_WARNING,"PropPut() failed: %s", error_message); + } + LocalFree(error_message); + VariantClear(var); + efree(var); + + return FAILURE; + } + + + VariantClear(var); + efree(var); + return SUCCESS; } @@ -457,17 +658,388 @@ static int com_get_properties(HashTable **properties, void **data) return SUCCESS; } + /* custom functions */ + +/* {{{ proto mixed com_addref(int module) + Increases the reference counter on a COM object */ ZEND_FUNCTION(com_addref) { + zval *object = getThis(); + rpc_internal *intern; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &object, com_class_entry); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + RETURN_LONG(php_COM_addref((comval *) intern->data)); } +/* }}} */ +/* {{{ proto mixed com_release(int module) + Releases a COM object */ ZEND_FUNCTION(com_release) { + zval *object = getThis(); + rpc_internal *intern; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &object, com_class_entry); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + RETURN_LONG(php_COM_release((comval *) intern->data)); +} +/* }}} */ + +PHP_FUNCTION(com_next) +{ + zval *object = getThis(); + rpc_internal *intern; + comval *obj; + unsigned long count = 1; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &object, com_class_entry, &count); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &count); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; + + if (C_HASENUM(obj)) { + SAFEARRAY *pSA; + SAFEARRAYBOUND rgsabound[1]; + VARIANT *result; + HRESULT hr; + + /* Grab one argument off the stack, allocate enough + * VARIANTs + * Get the IEnumVariant interface and call ->Next(); + */ + + rgsabound[0].lLbound = 0; + rgsabound[0].cElements = count; + + result = (VARIANT *) emalloc(sizeof(VARIANT)); + VariantInit(result); + + if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { + efree(result); + /* @todo exception */ + + RETURN_NULL(); + } else { + V_ARRAY(result) = pSA; + V_VT(result) = VT_VARIANT|VT_ARRAY; + } + + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) { + char *error_message; + + efree(result); + error_message = php_COM_error_message(hr); + rpc_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); + efree(error_message); + + RETURN_NULL(); + } + + if (count != rgsabound[0].cElements) { + rgsabound[0].cElements = count; + if (FAILED(SafeArrayRedim(pSA, rgsabound))) { + char *error_message; + + efree(result); + error_message = php_COM_error_message(hr); + php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); + efree(error_message); + + RETURN_NULL(); + } + } + + /* return a single element if next() was called without count */ + if ((ZEND_NUM_ARGS() == 0) && (count == 1)) { + long index[] = {0}; + + SafeArrayGetElement(pSA, index, result); + SafeArrayDestroy(pSA); + } + + RETURN_VARIANT(result, C_CODEPAGE(obj)); + } + + /* @todo exception */ + RETURN_NULL(); +} + +PHP_FUNCTION(com_all) +{ +#if 0 + } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "all")) { +#define FETCH_BLOCKSIZE 10 /* fetch blocks of 10 elements */ + + count = FETCH_BLOCKSIZE; + + rgsabound[0].lLbound = 0; + rgsabound[0].cElements = count; + + if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { + VariantInit(var_result); + return FAILURE; + } else { + V_ARRAY(var_result) = pSA; + V_VT(var_result) = VT_VARIANT|VT_ARRAY; + } + + /* blah*/ +#endif +} + +PHP_FUNCTION(com_reset) +{ + zval *object = getThis(); + rpc_internal *intern; + comval *obj; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &object, com_class_entry); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; + + if (C_HASENUM(obj)) { + HRESULT hr; + + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) { + char *error_message = php_COM_error_message(hr); + php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); + efree(error_message); + + RETURN_FALSE; + } + + RETURN_TRUE; + } + + /* @todo exception */ + RETURN_FALSE; +} + +PHP_FUNCTION(com_skip) +{ + zval *object = getThis(); + rpc_internal *intern; + comval *obj; + unsigned long count = 1; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|l", &object, com_class_entry, &count); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &count); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; + + if (C_HASENUM(obj)) { + HRESULT hr; + + if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) { + char *error_message = php_COM_error_message(hr); + php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); + efree(error_message); + RETURN_FALSE; + } + + RETURN_TRUE; + } + + /* @todo exception */ + RETURN_FALSE; } +/* {{{ proto bool com_isenum(object com_module) + Grabs an IEnumVariant */ +ZEND_FUNCTION(com_isenum) +{ + zval *object = getThis(); + rpc_internal *intern; + + if (object == NULL) { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &object, com_class_entry); + } else { + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, ""); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + RETURN_BOOL(C_HASENUM((comval *) intern->data)); +} +/* }}} */ + +/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitive]) + Loads a Typelib */ +PHP_FUNCTION(com_load_typelib) +{ + char *typelib; + int len, cis = FALSE; + int mode = CONST_CS; + ITypeLib *pTL; + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &typelib, &len, &cis); + + if (cis) { + mode &= ~CONST_CS; + } + + pTL = php_COM_find_typelib(typelib, mode); + if (php_COM_load_typelib(pTL, mode) == SUCCESS) { + pTL->lpVtbl->Release(pTL); + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto bool com_print_typeinfo(mixed comobject | string typelib, string dispinterface, bool wantsink) + Print out a PHP class definition for a dispatchable interface */ +PHP_FUNCTION(com_print_typeinfo) +{ + zval *object; + char *ifacename = NULL; + char *typelibname = NULL; + int typeliblen, ifacelen; + zend_bool wantsink = 0; + comval *obj = NULL; + rpc_internal *intern; + ITypeInfo *typeinfo; + + if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s/s!b", + &typelibname, &typeliblen, &ifacename, &ifacelen, &wantsink)) { + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O/s!b", + &object, com_class_entry, &ifacename, &ifacelen, &wantsink)) { + RETURN_FALSE; + } else { + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; + } + } + + typeinfo = php_COM_locate_typeinfo(typelibname, obj, ifacename, wantsink); + if (typeinfo) { + php_COM_process_typeinfo(typeinfo, NULL, 1, NULL); + typeinfo->lpVtbl->Release(typeinfo); + + RETURN_TRUE; + } else { + rpc_error(E_WARNING, "Unable to find typeinfo using the parameters supplied"); + } + + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto bool com_event_sink(mixed comobject, object sinkobject [, mixed sinkinterface]) + Connect events from a COM object to a PHP object */ +PHP_FUNCTION(com_event_sink) +{ + zval *object, *sinkobject, *sink=NULL; + char *dispname = NULL, *typelibname = NULL; + zend_bool gotguid = 0; + comval *obj; + rpc_internal *intern; + ITypeInfo *typeinfo = NULL; + + RETVAL_FALSE; + + if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|z/", &object, com_class_entry, &sinkobject, &sink)) { + RETURN_FALSE; + } + + if (sink && Z_TYPE_P(sink) == IS_ARRAY) { + /* 0 => typelibname, 1 => dispname */ + zval **tmp; + + if (zend_hash_index_find(Z_ARRVAL_P(sink), 0, (void**)&tmp) == SUCCESS) + typelibname = Z_STRVAL_PP(tmp); + if (zend_hash_index_find(Z_ARRVAL_P(sink), 1, (void**)&tmp) == SUCCESS) + dispname = Z_STRVAL_PP(tmp); + } else if (sink != NULL) { + convert_to_string_ex(&sink); + dispname = Z_STRVAL_P(sink); + } + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; + + typeinfo = php_COM_locate_typeinfo(typelibname, obj, dispname, 1); + + if (typeinfo) { + HashTable *id_to_name; + + ALLOC_HASHTABLE(id_to_name); + + if (php_COM_process_typeinfo(typeinfo, id_to_name, 0, &obj->sinkid)) { + + /* Create the COM wrapper for this sink */ + obj->sinkdispatch = php_COM_export_as_sink(sinkobject, &obj->sinkid, id_to_name); + + /* Now hook it up to the source */ + php_COM_enable_events(obj, TRUE); + + RETVAL_TRUE; + + } else { + FREE_HASHTABLE(id_to_name); + } + } + + if (typeinfo) + typeinfo->lpVtbl->Release(typeinfo); + +} +/* }}} */ + + + /* ini callbacks */ -static PHP_INI_MH(OnTypelibFileChange) + +static PHP_INI_MH(com_typelib_file_change) { FILE *typelib_file; char *typelib_name_buffer; @@ -535,4 +1107,4 @@ static PHP_INI_MH(OnTypelibFileChange) } return SUCCESS; -} +} \ No newline at end of file diff --git a/ext/rpc/com/com.h b/ext/rpc/com/com.h index ab638b518c..e343c3d89e 100644 --- a/ext/rpc/com/com.h +++ b/ext/rpc/com/com.h @@ -1,10 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef COM_H #define COM_H #include "../handler.h" #include "../php_rpc.h" +RPC_DECLARE_HANDLER(com); + ZEND_FUNCTION(com_addref); ZEND_FUNCTION(com_release); +ZEND_FUNCTION(com_isenum); +ZEND_FUNCTION(com_next); +ZEND_FUNCTION(com_all); +ZEND_FUNCTION(com_reset); +ZEND_FUNCTION(com_skip); +ZEND_FUNCTION(com_event_sink); +ZEND_FUNCTION(com_message_pump); +ZEND_FUNCTION(com_print_typeinfo); #endif \ No newline at end of file diff --git a/ext/rpc/com/com_wrapper.c b/ext/rpc/com/com_wrapper.c index bba515b5ec..9f066a6575 100644 --- a/ext/rpc/com/com_wrapper.c +++ b/ext/rpc/com/com_wrapper.c @@ -63,55 +63,20 @@ #include "php.h" #include "php_ini.h" -#include "php_COM.h" -#include "php_VARIANT.h" +#include "../rpc.h" +#include "../php_rpc.h" +#include "../handler.h" -static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC); -static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC); -static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC); -static void php_register_COM_class(TSRMLS_D); -static void php_COM_init(int module_number TSRMLS_DC); -static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC); -static int com_enable_events(comval *obj, int enable); - -static int le_comval; -static int codepage; +#include "com.h" +#include "com_wrapper.h" +#include "conversion.h" +#include "variant.h" #ifdef _DEBUG int resourcecounter = 1; #endif -static unsigned char arg1and2_force_ref[] = - { 2, BYREF_FORCE, BYREF_FORCE }; - -function_entry COM_functions[] = { - PHP_FE(com_load, NULL) - PHP_FE(com_invoke, NULL) - PHP_FE(com_addref, NULL) - PHP_FE(com_release, NULL) - PHP_FE(com_propget, NULL) - PHP_FE(com_propput, NULL) - PHP_FE(com_load_typelib, NULL) - PHP_FE(com_isenum, NULL) - PHP_FE(com_event_sink, arg1and2_force_ref) - PHP_FE(com_message_pump, NULL) - PHP_FE(com_print_typeinfo, NULL) - - PHP_FALIAS(com_get, com_propget, NULL) - PHP_FALIAS(com_propset, com_propput, NULL) - PHP_FALIAS(com_set, com_propput, NULL) - - { NULL, NULL, NULL } -}; - - -static PHP_MINFO_FUNCTION(COM) -{ - DISPLAY_INI_ENTRIES(); -} - - -PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC) +ZEND_API HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString) { HRESULT hr; int failed = FALSE; @@ -120,146 +85,119 @@ PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DIS *ErrString = NULL; /* @todo use DispInvoke here ? */ - if (C_ISREFD(obj)) { - if (C_HASTLIB(obj)) { - hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if (FAILED(hr)) { - hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); - if (SUCCEEDED(hr)) { - /* - * ITypLib doesn't work - * Release ITypeLib and fall back to IDispatch - */ - - C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); - C_HASTLIB(obj) = FALSE; - } - } - } else { + if (C_HASTLIB(obj)) { + hr = C_TYPEINFO_VT(obj)->Invoke(C_TYPEINFO(obj), C_DISPATCH(obj), dispIdMember, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); + if (FAILED(hr)) { hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); + if (SUCCEEDED(hr)) { + /* + * ITypLib doesn't work + * Release ITypeLib and fall back to IDispatch + */ + + C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); + C_HASTLIB(obj) = FALSE; + } } + } else { + hr = C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), dispIdMember, &IID_NULL, LOCALE_SYSTEM_DEFAULT, wFlags, pDispParams, pVarResult, &ExceptInfo, &ArgErr); + } - if (FAILED(hr)) { - switch (hr) { - case DISP_E_EXCEPTION: { - - char *src=estrdup("Unavailable"); - int srclen=strlen(src); - char *desc=estrdup("Unavailable"); - int desclen=strlen(desc); - - if (ExceptInfo.bstrSource) - { - efree(src); - src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, codepage TSRMLS_CC); - SysFreeString(ExceptInfo.bstrSource); - } - if (ExceptInfo.bstrDescription) - { - efree(desc); - desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, codepage TSRMLS_CC); - SysFreeString(ExceptInfo.bstrDescription); - } - - *ErrString = pemalloc(srclen+desclen+50, 1); - sprintf(*ErrString, "Source: %s Description: %s", src, desc); + if (FAILED(hr)) { + switch (hr) { + case DISP_E_EXCEPTION: { + + char *src=estrdup("Unavailable"); + int srclen=strlen(src); + char *desc=estrdup("Unavailable"); + int desclen=strlen(desc); + + if (ExceptInfo.bstrSource) + { efree(src); + src = php_OLECHAR_to_char(ExceptInfo.bstrSource, &srclen, C_CODEPAGE(obj), FALSE); + SysFreeString(ExceptInfo.bstrSource); + } + if (ExceptInfo.bstrDescription) + { efree(desc); - - if (ExceptInfo.bstrHelpFile) - { - SysFreeString(ExceptInfo.bstrHelpFile); - } + desc = php_OLECHAR_to_char(ExceptInfo.bstrDescription, &desclen, C_CODEPAGE(obj), FALSE); + SysFreeString(ExceptInfo.bstrDescription); } - break; - case DISP_E_PARAMNOTFOUND: - case DISP_E_TYPEMISMATCH: - *ErrString = pemalloc(25, 1); - sprintf(*ErrString, "Argument: %d", pDispParams->cArgs-ArgErr+1); - break; - } - } - - if (pVarResult && (V_VT(pVarResult) == VT_EMPTY)) { - V_VT(pVarResult) = VT_I4; - V_I4(pVarResult) = hr; + + *ErrString = emalloc(srclen+desclen+50); + zend_sprintf(*ErrString, "Source: %s Description: %s", src, desc); + efree(src); + efree(desc); + + if (ExceptInfo.bstrHelpFile) + { + SysFreeString(ExceptInfo.bstrHelpFile); + } + } + break; + case DISP_E_PARAMNOTFOUND: + case DISP_E_TYPEMISMATCH: + *ErrString = emalloc(25); + sprintf(*ErrString, "Argument: %d", pDispParams->cArgs-ArgErr+1); + break; } + } - return hr; - } else { - return DISP_E_UNKNOWNINTERFACE; + if (pVarResult && (V_VT(pVarResult) == VT_EMPTY)) { + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = hr; } + + return hr; } -PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC) +ZEND_API HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* rgszNames, DISPID FAR* rgDispId) { HRESULT hr; - if (C_ISREFD(obj)) { - if (C_HASTLIB(obj)) { - hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), rgszNames, 1, rgDispId); + if (C_HASTLIB(obj)) { + hr = C_TYPEINFO_VT(obj)->GetIDsOfNames(C_TYPEINFO(obj), &rgszNames, 1, rgDispId); - if (FAILED(hr)) { - hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); + if (FAILED(hr)) { + hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, &rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); - if (SUCCEEDED(hr)) { - /* - * ITypLib doesn't work - * Release ITypeLib and fall back to IDispatch - */ + if (SUCCEEDED(hr)) { + /* + * ITypLib doesn't work + * Release ITypeLib and fall back to IDispatch + */ - C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); - C_HASTLIB(obj) = FALSE; - } + C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); + C_HASTLIB(obj) = FALSE; } - } else { - hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); } - - return hr; } else { - return DISP_E_UNKNOWNINTERFACE; + hr = C_DISPATCH_VT(obj)->GetIDsOfNames(C_DISPATCH(obj), &IID_NULL, &rgszNames, 1, LOCALE_SYSTEM_DEFAULT, rgDispId); } + + return hr; } -PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC) +ZEND_API HRESULT php_COM_release(comval *obj) { - HRESULT hr; - - if (obj->refcount > 1) { - C_RELEASE(obj); - } else if (obj->refcount == 1) { - if (C_HASTLIB(obj)) { - C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); - } - if (C_HASENUM(obj)) { - hr = C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj)); - } - hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); - C_RELEASE(obj); - } - - return obj->refcount; + return C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); } -PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC) +ZEND_API HRESULT php_COM_addref(comval *obj) { - if (C_ISREFD(obj)) { - C_ADDREF(obj); - } - - return obj->refcount; + return C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); } -PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup TSRMLS_DC) +ZEND_API HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup) { HRESULT hr = 1; DISPPARAMS dispparams; - VARIANT *var_result; + VARIANT *result; IDispatch FAR* pDisp; pDisp = *ppDisp; @@ -267,7 +205,6 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup *ppDisp = NULL; } - C_REFCOUNT(obj) = 1; C_DISPATCH(obj) = pDisp; C_HASTLIB(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &C_TYPEINFO(obj))); @@ -276,22 +213,23 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup dispparams.cArgs = 0; dispparams.cNamedArgs = 0; - ALLOC_VARIANT(var_result); + result = (VARIANT *) emalloc(sizeof(VARIANT)); + VariantInit(result); if (C_HASENUM(obj) = SUCCEEDED(C_DISPATCH_VT(obj)->Invoke(C_DISPATCH(obj), DISPID_NEWENUM, &IID_NULL, LOCALE_SYSTEM_DEFAULT, - DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, var_result, NULL, NULL))) { - if (V_VT(var_result) == VT_UNKNOWN) { - V_UNKNOWN(var_result)->lpVtbl->AddRef(V_UNKNOWN(var_result)); - C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(var_result)->lpVtbl->QueryInterface(V_UNKNOWN(var_result), &IID_IEnumVARIANT, + DISPATCH_METHOD|DISPATCH_PROPERTYGET, &dispparams, result, NULL, NULL))) { + if (V_VT(result) == VT_UNKNOWN) { + V_UNKNOWN(result)->lpVtbl->AddRef(V_UNKNOWN(result)); + C_HASENUM(obj) = SUCCEEDED(V_UNKNOWN(result)->lpVtbl->QueryInterface(V_UNKNOWN(result), &IID_IEnumVARIANT, (void**)&C_ENUMVARIANT(obj))); - } else if (V_VT(var_result) == VT_DISPATCH) { - V_DISPATCH(var_result)->lpVtbl->AddRef(V_DISPATCH(var_result)); - C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(var_result)->lpVtbl->QueryInterface(V_DISPATCH(var_result), &IID_IEnumVARIANT, + } else if (V_VT(result) == VT_DISPATCH) { + V_DISPATCH(result)->lpVtbl->AddRef(V_DISPATCH(result)); + C_HASENUM(obj) = SUCCEEDED(V_DISPATCH(result)->lpVtbl->QueryInterface(V_DISPATCH(result), &IID_IEnumVARIANT, (void**)&C_ENUMVARIANT(obj))); } } - FREE_VARIANT(var_result); + efree(result); if (!cleanup) { hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); @@ -305,38 +243,9 @@ PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* ppDisp, int cleanup } -PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC) -{ - HRESULT hr; - - C_HASTLIB(obj) = C_HASTLIB(clone); - C_HASENUM(obj) = C_HASENUM(obj); - C_DISPATCH(obj) = C_DISPATCH(clone); - C_TYPEINFO(obj) = C_TYPEINFO(clone); - - if (cleanup || !C_ISREFD(obj)) { - obj->refcount = clone->refcount; - clone->refcount = 0; - } else { - if (C_HASTLIB(obj)) { - C_TYPEINFO_VT(obj)->AddRef(C_TYPEINFO(obj)); - } - if (C_HASENUM(obj)) { - C_ENUMVARIANT_VT(obj)->AddRef(C_ENUMVARIANT(obj)); - } - hr = C_DISPATCH_VT(obj)->AddRef(C_DISPATCH(obj)); - obj->refcount = 1; - } - -#ifdef _DEBUG - obj->resourceindex = resourcecounter++; -#endif - - return hr; -} -PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC) +ZEND_API char *php_COM_error_message(HRESULT hr) { void *pMsgBuf; @@ -352,1643 +261,398 @@ PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC) } -static char *php_string_from_clsid(const CLSID *clsid TSRMLS_DC) +ZEND_API char *php_COM_string_from_CLSID(const CLSID *clsid) { LPOLESTR ole_clsid; char *clsid_str; StringFromCLSID(clsid, &ole_clsid); - clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, codepage TSRMLS_CC); - LocalFree(ole_clsid); + clsid_str = php_OLECHAR_to_char(ole_clsid, NULL, CP_ACP, FALSE); + CoTaskMemFree(ole_clsid); return clsid_str; } -PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC) +ZEND_API HRESULT php_COM_destruct(comval *obj) { HRESULT hr = S_OK; - com_enable_events(obj, FALSE); + php_COM_enable_events(obj, FALSE); if (obj->sinkdispatch) obj->sinkdispatch->lpVtbl->Release(obj->sinkdispatch); - if (C_ISREFD(obj)) { - C_REFCOUNT(obj) = 1; - hr = php_COM_release(obj TSRMLS_CC); + if (C_HASTLIB(obj)) { + C_TYPEINFO_VT(obj)->Release(C_TYPEINFO(obj)); + } + if (C_HASENUM(obj)) { + C_ENUMVARIANT_VT(obj)->Release(C_ENUMVARIANT(obj)); } + + hr = C_DISPATCH_VT(obj)->Release(C_DISPATCH(obj)); efree(obj); return hr; } -static void php_comval_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - php_COM_destruct(rsrc->ptr TSRMLS_CC); -} - - -static PHP_INI_MH(OnTypelibFileChange) -{ - FILE *typelib_file; - char *typelib_name_buffer; - char *strtok_buf = NULL; - int interactive; - interactive = CG(interactive); - - if (!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) { - return FAILURE; - } - if (interactive) { - printf("Loading type libraries..."); - fflush(stdout); - } - typelib_name_buffer = (char *) emalloc(sizeof(char)*1024); - while (fgets(typelib_name_buffer, 1024, typelib_file)) { - ITypeLib *pTL; - char *typelib_name; - char *modifier, *ptr; - int mode = CONST_CS | CONST_PERSISTENT; /* CONST_PERSISTENT is ok here */ - if (typelib_name_buffer[0]==';') { - continue; - } - typelib_name = php_strtok_r(typelib_name_buffer, "\r\n", &strtok_buf); /* get rid of newlines */ - if (typelib_name == NULL) { - continue; - } - typelib_name = php_strtok_r(typelib_name, "#", &strtok_buf); - modifier = php_strtok_r(NULL, "#", &strtok_buf); - if (modifier != NULL) { - if (!strcmp(modifier, "cis") || !strcmp(modifier, "case_insensitive")) { - mode &= ~CONST_CS; - } - } - /* Remove leading/training white spaces on search_string */ - while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */ - typelib_name ++; - } - ptr = typelib_name + strlen(typelib_name) - 1; - while ((ptr != typelib_name) && isspace(*ptr)) { - *ptr = '\0'; - ptr--; - } - if (interactive) { - printf("\rLoading %-60s\r", typelib_name); - } +/* {{{ proto bool com_message_pump([int timeoutms]) + Process COM messages, sleeping for up to timeoutms milliseconds */ +PHP_FUNCTION(com_message_pump) +{ + long timeoutms = 0; + MSG msg; + DWORD result; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &timeoutms) == FAILURE) + RETURN_FALSE; + + result = MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutms, QS_ALLINPUT); - if ((pTL = php_COM_find_typelib(typelib_name, mode TSRMLS_CC)) != NULL) { - php_COM_load_typelib(pTL, mode TSRMLS_CC); - pTL->lpVtbl->Release(pTL); + if (result == WAIT_OBJECT_0) { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); } + /* we processed messages */ + RETVAL_TRUE; + } else { + /* we did not process messages (timed out) */ + RETVAL_FALSE; } - - efree(typelib_name_buffer); - fclose(typelib_file); - - if (interactive) { - printf("\r%70s\r", ""); - } - - return SUCCESS; } +/* }}} */ - -PHP_INI_BEGIN() -PHP_INI_ENTRY_EX("com.allow_dcom", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) -PHP_INI_ENTRY_EX("com.autoregister_typelib", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) -PHP_INI_ENTRY_EX("com.autoregister_verbose", "0", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) -PHP_INI_ENTRY_EX("com.autoregister_casesensitive", "1", PHP_INI_SYSTEM, NULL, php_ini_boolean_displayer_cb) -PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypelibFileChange) -PHP_INI_END() - - -/* {{{ proto int com_load(string module_name [, string remote_host [, int codepage [, string typelib]]]) - Loads a COM module */ -PHP_FUNCTION(com_load) +ZEND_API HRESULT php_COM_enable_events(comval *obj, int enable) { - pval *module_name, *code_page, *typelib = NULL, *server_name = NULL, *user_name=NULL, *password=NULL, *domain=NULL; - CLSID clsid; - HRESULT hr; - OLECHAR *ProgID; - comval *obj; - char *error_message; - char *clsid_str; - int mode = 0; - ITypeLib *pTL; - CLSCTX flags = CLSCTX_SERVER; - - codepage = CP_ACP; - - switch (ZEND_NUM_ARGS()) { - case 1: - zend_get_parameters(ht, 1, &module_name); - break; - - case 2: - zend_get_parameters(ht, 2, &module_name, &server_name); - break; - - case 3: - zend_get_parameters(ht, 3, &module_name, &server_name, &code_page); - - convert_to_long_ex(&code_page); - codepage = Z_LVAL_P(code_page); - break; - - case 4: - zend_get_parameters(ht, 4, &module_name, &server_name, &code_page, &typelib); - - convert_to_string_ex(&typelib); - convert_to_long_ex(&code_page); - codepage = Z_LVAL_P(code_page); - - break; - - default: - ZEND_WRONG_PARAM_COUNT(); - } - - if (server_name != NULL) { - /* What is server name? A String or an array? */ - - if (Z_TYPE_P(server_name) == IS_NULL) { - server_name = NULL; - } else if (Z_TYPE_P(server_name) == IS_ARRAY) { - pval **tmp; - /* DAB: 22 Sept 2001 - * Aha - we have a number of possible arguments. - * They are in the hash By name: Server, Domain, Username, Password - * Flags. - * This has been crafted to maintian maximum backward compatability. - * If the server name is specified as a string, then the function - * should behave as before by defaulting username and password and - * using the (I believe) incorrect CLSCTX_SERVER instantiation - * paramter. However if server is specified in this array then we - * use either CLSCTX_REMOTE_SERVER or whatever flags are specified - * in the array */ - HashTable *ht = Z_ARRVAL(*server_name); - if (FAILURE == zend_hash_find(ht, "Server", 7, (void **) &tmp)) { - server_name = NULL; - } else { - server_name = *tmp; - convert_to_string_ex(&server_name); - /* CLSCTX_SERVER includes INPROC and LOCAL SERVER. This means - * that any local server will be instantiated BEFORE even - * looking on a remote server. Thus if we have a server name, - * probably we want to access a remote machine or we would not - * have bothered specifying it. So it would be wrong to to - * connect locally. Futher, unless the name passed is a GUID, - * there has to be something to map the Prog.Id to GUID and - * unless that has been modified to remove the information - * about local instantiation CLSCTX_SERVER would force a local - * instantiation This setting can be overridden below if the - * user specifies a flags element */ - flags = CLSCTX_REMOTE_SERVER; - } - if (FAILURE == zend_hash_find(ht, "Username", 9, (void **) &tmp)) { - user_name = NULL; - } else { - user_name = *tmp; - convert_to_string_ex(&user_name); - } - if (FAILURE == zend_hash_find(ht, "Domain", 7, (void **) &tmp)) { - domain = NULL; - } else { - domain = *tmp; - convert_to_string_ex(&domain); - } - if (FAILURE == zend_hash_find(ht, "Password", 9, (void **) &tmp)) { - password=NULL; - } else { - password = *tmp; - convert_to_string_ex(&password); - } - if (SUCCESS == zend_hash_find(ht, "Flags", 6, (void **) &tmp)) { - convert_to_long_ex(tmp); - flags = (CLSCTX) Z_LVAL_PP(tmp); - } - } else { - if (!INI_INT("com.allow_dcom")) { - php_error(E_WARNING, "DCOM is disabled"); - RETURN_NULL(); - } else { - flags = CLSCTX_REMOTE_SERVER; - convert_to_string_ex(&server_name); - } - } - } - - ALLOC_COM(obj); - convert_to_string_ex(&module_name); - ProgID = php_char_to_OLECHAR(Z_STRVAL_P(module_name), Z_STRLEN_P(module_name), codepage TSRMLS_CC); - - /* obtain CLSID */ - if (FAILED(CLSIDFromString(ProgID, &clsid))) { - /* Perhaps this is a Moniker? */ - IBindCtx *pBindCtx; - IMoniker *pMoniker; - ULONG ulEaten; - - /* @todo if (server_name) */ - - if (!server_name) { - /* @todo shouldn't the bind context be fetched on module startup and kept as a global shared instance ? - * all calls to BindToObject would deliver the same instance then (as desired) - * IBindCtx::RegisterObjectBound() should be called then after mkparsedisplayname() - * - * @todo use mkparsedisplaynameex() ? - */ - if (SUCCEEDED(hr = CreateBindCtx(0, &pBindCtx))) { - if (SUCCEEDED(hr = MkParseDisplayName(pBindCtx, ProgID, &ulEaten, &pMoniker))) { - hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); - pMoniker->lpVtbl->Release(pMoniker); - } - pBindCtx->lpVtbl->Release(pBindCtx); - } - } else { - hr = MK_E_SYNTAX; - } - - efree(ProgID); - - if (FAILED(hr)) { - php_COM_destruct(obj TSRMLS_CC); - error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"Invalid ProgID, GUID string, or Moniker: %s", error_message); - LocalFree(error_message); - RETURN_NULL(); - } - } else { - efree(ProgID); - /* obtain IDispatch */ - if (!server_name) { - hr = CoCreateInstance(&clsid, NULL, flags, &IID_IDispatch, (LPVOID *) &C_DISPATCH(obj)); - } else { - COSERVERINFO server_info; - MULTI_QI pResults; - COAUTHIDENTITY authid; - COAUTHINFO authinfo = {RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, &authid, EOAC_NONE}; - - server_info.dwReserved1=0; - server_info.dwReserved2=0; - server_info.pwszName = php_char_to_OLECHAR(Z_STRVAL_P(server_name), Z_STRLEN_P(server_name), codepage TSRMLS_CC); - if (user_name) { - /* Z_STRVAL_P(user_name); */ - /* Parse Username into domain\username */ - authid.User = (WCHAR *) Z_STRVAL_P(user_name); - authid.UserLength = Z_STRLEN_P(user_name); - if (password) { - authid.Password = (USHORT *) Z_STRVAL_P(password); - authid.PasswordLength = Z_STRLEN_P(password); - } else { - authid.Password = (USHORT *) ""; - authid.PasswordLength = 0; - } - if (domain) { - authid.Domain = (USHORT *) Z_STRVAL_P(domain); - authid.DomainLength = Z_STRLEN_P(domain); + if (obj->sinkdispatch) { + IConnectionPointContainer *cont; + IConnectionPoint *point; + + if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IConnectionPointContainer, (void**)&cont))) { + if (SUCCEEDED(cont->lpVtbl->FindConnectionPoint(cont, &obj->sinkid, &point))) { + if (enable) { + point->lpVtbl->Advise(point, (IUnknown*)obj->sinkdispatch, &obj->sinkcookie); } else { - authid.Domain = (USHORT *) ""; - authid.DomainLength = 0; + point->lpVtbl->Unadvise(point, obj->sinkcookie); } - authid.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - - server_info.pAuthInfo=&authinfo; - } else { - server_info.pAuthInfo=NULL; - } - - pResults.pIID = &IID_IDispatch; - pResults.pItf = NULL; - pResults.hr = S_OK; - hr=CoCreateInstanceEx(&clsid, NULL, flags, &server_info, 1, &pResults); - if (SUCCEEDED(hr)) { - hr = pResults.hr; - C_DISPATCH(obj) = (IDispatch *) pResults.pItf; + point->lpVtbl->Release(point); } - efree(server_info.pwszName); - } - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - clsid_str = php_string_from_clsid(&clsid TSRMLS_CC); - php_error(E_WARNING,"Unable to obtain IDispatch interface for CLSID %s: %s",clsid_str,error_message); - LocalFree(error_message); - efree(clsid_str); - php_COM_destruct(obj TSRMLS_CC); - RETURN_NULL(); + cont->lpVtbl->Release(cont); } } - php_COM_set(obj, &C_DISPATCH(obj), TRUE TSRMLS_CC); - - if (INI_INT("com.autoregister_casesensitive")) { - mode |= CONST_CS; - } + return S_OK; +} - if (C_HASTLIB(obj)) { - if (INI_INT("com.autoregister_typelib")) { - unsigned int idx; +static const struct { + VARTYPE vt; + const char *name; +} vt_names[] = { + { VT_NULL, "VT_NULL" }, + { VT_EMPTY, "VT_EMPTY" }, + { VT_UI1, "VT_UI1" }, + { VT_I2, "VT_I2" }, + { VT_I4, "VT_I4" }, + { VT_R4, "VT_R4" }, + { VT_R8, "VT_R8" }, + { VT_BOOL, "VT_BOOL" }, + { VT_ERROR, "VT_ERROR" }, + { VT_CY, "VT_CY" }, + { VT_DATE, "VT_DATE" }, + { VT_BSTR, "VT_BSTR" }, + { VT_DECIMAL, "VT_DECIMAL" }, + { VT_UNKNOWN, "VT_UNKNOWN" }, + { VT_DISPATCH, "VT_DISPATCH" }, + { VT_VARIANT, "VT_VARIANT" }, + { VT_I1, "VT_I1" }, + { VT_UI2, "VT_UI2" }, + { VT_UI4, "VT_UI4" }, + { VT_INT, "VT_INT" }, + { VT_UINT, "VT_UINT" }, + { VT_ARRAY, "VT_ARRAY" }, + { VT_BYREF, "VT_BYREF" }, + { VT_VOID, "VT_VOID" }, + { VT_PTR, "VT_PTR" }, + { VT_HRESULT, "VT_HRESULT" }, + { 0, NULL } +}; - /* @todo check if typlib isn't already loaded */ - if (C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &pTL, &idx) == S_OK) { - php_COM_load_typelib(pTL, mode TSRMLS_CC); - pTL->lpVtbl->Release(pTL); - } - } - } else { - if (typelib != NULL) { - ITypeLib *pTL; - - if ((pTL = php_COM_find_typelib(Z_STRVAL_P(typelib), mode TSRMLS_CC)) != NULL) { - C_HASTLIB(obj) = SUCCEEDED(pTL->lpVtbl->GetTypeInfo(pTL, 0, &C_TYPEINFO(obj))); - /* idx 0 should deliver the ITypeInfo for the IDispatch Interface */ - if (INI_INT("com.autoregister_typelib")) { - php_COM_load_typelib(pTL, mode TSRMLS_CC); - } - pTL->lpVtbl->Release(pTL); - } - } +static inline const char *vt_to_string(VARTYPE vt) +{ + int i; + for (i = 0; vt_names[i].name != NULL; i++) { + if (vt_names[i].vt == vt) + return vt_names[i].name; } - - RETURN_RESOURCE(zend_list_insert(obj, IS_COM)); + return "?"; } -/* }}} */ - -int do_COM_invoke(comval *obj, pval *function_name, VARIANT *var_result, pval **arguments, int arg_count TSRMLS_DC) +ZEND_API int php_COM_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid) { - DISPID dispid; - DISPPARAMS dispparams; - HRESULT hr; - OLECHAR *funcname; - SAFEARRAY *pSA; - SAFEARRAYBOUND rgsabound[1]; - VARIANT *variant_args; - char *error_message; - int current_arg, current_variant; - unsigned long count; - - if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "next")) { - /* Grab one argument off the stack, allocate enough - * VARIANTs - * Get the IEnumVariant interface and call ->Next(); - */ - - switch (arg_count) { - case 0: - count = 1; - break; - - case 1: - convert_to_long_ex(&arguments[0]); - count = Z_LVAL_P(arguments[0]); - break; + TYPEATTR *attr; + FUNCDESC *func; + int i; + OLECHAR *olename; + char *ansiname = NULL; + unsigned int ansinamelen; + int ret = 0; - default: - php_error(E_WARNING,"Wrong argument count to IEnumVariant::Next()"); + if (FAILED(typeinfo->lpVtbl->GetTypeAttr(typeinfo, &attr))) + return 0; - return FAILURE; - } + /* verify that it is suitable */ + if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) { - rgsabound[0].lLbound = 0; - rgsabound[0].cElements = count; + if (guid) + memcpy(guid, &attr->guid, sizeof(GUID)); + + if (printdef) { + char *guidstring; - if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { - VariantInit(var_result); - return FAILURE; - } else { - V_ARRAY(var_result) = pSA; - V_VT(var_result) = VT_VARIANT|VT_ARRAY; - } + typeinfo->lpVtbl->GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL); + ansiname = php_OLECHAR_to_char(olename, &ansinamelen, CP_ACP, FALSE); + SysFreeString(olename); - if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Next(C_ENUMVARIANT(obj), count, pSA->pvData, &count))) { - char *error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); - efree(error_message); - VariantClear(var_result); - return FAILURE; - } + guidstring = php_COM_string_from_CLSID(&attr->guid); + php_printf("class %s { /* GUID=%s */\n", ansiname, guidstring); + efree(guidstring); - if (count != rgsabound[0].cElements) { - rgsabound[0].cElements = count; - if (FAILED(SafeArrayRedim(pSA, rgsabound))) { - char *error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); - efree(error_message); - VariantClear(var_result); - return FAILURE; - } + efree(ansiname); } - /* return a single element if next() was called without count */ - if ((arg_count == 0) && (count == 1)) { - long index[] = {0}; - - SafeArrayGetElement(pSA, index, var_result); - SafeArrayDestroy(pSA); - } - - return SUCCESS; - } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "all")) { -#define FETCH_BLOCKSIZE 10 /* fetch blocks of 10 elements */ - - count = FETCH_BLOCKSIZE; - - rgsabound[0].lLbound = 0; - rgsabound[0].cElements = count; - - if ((pSA = SafeArrayCreate(VT_VARIANT, 1, rgsabound)) == NULL) { - VariantInit(var_result); - return FAILURE; - } else { - V_ARRAY(var_result) = pSA; - V_VT(var_result) = VT_VARIANT|VT_ARRAY; - } - - /* blah*/ - - - } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "reset")) { - if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Reset(C_ENUMVARIANT(obj)))) { - char *error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); - efree(error_message); - return FAILURE; - } - return SUCCESS; - } else if (C_HASENUM(obj) && strstr(Z_STRVAL_P(function_name), "skip")) { - unsigned long count; - - switch (arg_count) { - case 0: - count = 1; - break; - - case 1: - convert_to_long_ex(&arguments[0]); - count = Z_LVAL_P(arguments[0]); - break; - - default: - php_error(E_WARNING,"Wrong argument count to IEnumVariant::Skip()"); - return FAILURE; - } - if (FAILED(hr = C_ENUMVARIANT_VT(obj)->Skip(C_ENUMVARIANT(obj), count))) { - char *error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"IEnumVariant::Next() failed: %s", error_message); - efree(error_message); - return FAILURE; - } - return SUCCESS; - - } else { - char *ErrString; - - funcname = php_char_to_OLECHAR(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), codepage TSRMLS_CC); - - hr = php_COM_get_ids_of_names(obj, &funcname, &dispid TSRMLS_CC); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(function_name), error_message); - LocalFree(error_message); - efree(funcname); - return FAILURE; - } - - variant_args = (VARIANT *) emalloc(sizeof(VARIANT) * arg_count); - - for (current_arg=0; current_argIDispatch */ - VariantClear(&variant_args[current_arg]); - } - } - efree(variant_args); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) { - php_error(E_WARNING,"Invoke() failed: %s %s", error_message, ErrString); - pefree(ErrString, 1); - } else { - php_error(E_WARNING,"Invoke() failed: %s", error_message); - } - LocalFree(error_message); - return FAILURE; - } - } - return SUCCESS; -} - - -/* {{{ proto mixed com_invoke(int module, string handler_name [, mixed arg [, mixed ...]]) - Invokes a COM module */ -PHP_FUNCTION(com_invoke) -{ - pval **arguments; - pval *object, *function_name; - comval *obj; - int type; - int arg_count = ZEND_NUM_ARGS(); - VARIANT *var_result; - - if (arg_count<2) { - 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[1]; - - /* obtain IDispatch interface */ - convert_to_long(object); - obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if (!obj || (type != IS_COM)) { - php_error(E_WARNING,"%d is not a COM object handler", Z_STRVAL_P(function_name)); - RETURN_NULL(); - } - - /* obtain property/method handler */ - convert_to_string_ex(&function_name); - - ALLOC_VARIANT(var_result); - - if (do_COM_invoke(obj, 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 mixed com_release(int module) - Releases a COM object */ -PHP_FUNCTION(com_release) -{ - pval *object; - comval *obj; - int type; - int arg_count = ZEND_NUM_ARGS(); - - if (arg_count != 1) { - ZEND_WRONG_PARAM_COUNT(); - } - - if (zend_get_parameters(ht, 1, &object)==FAILURE) { - RETURN_FALSE; - } - - /* obtain IDispatch interface */ - convert_to_long_ex(&object); - obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if (!obj || (type != IS_COM)) { - php_error(E_WARNING,"%d is not a COM object handler"); - RETURN_FALSE; - } - - RETURN_LONG(php_COM_release(obj TSRMLS_CC)) -} -/* }}} */ - - -/* {{{ proto mixed com_addref(int module) - Increases the reference counter on a COM object */ -PHP_FUNCTION(com_addref) -{ - pval *object; - comval *obj; - int type; - int arg_count = ZEND_NUM_ARGS(); - - if (arg_count != 1) { - ZEND_WRONG_PARAM_COUNT(); - } - - if (zend_get_parameters(ht, 1, &object)==FAILURE) { - RETURN_FALSE; - } - - /* obtain IDispatch interface */ - convert_to_long_ex(&object); - obj = (comval *)zend_list_find(Z_LVAL_P(object), &type); - if (!obj || (type != IS_COM)) - { - php_error(E_WARNING,"%d is not a COM object handler"); - RETURN_FALSE; - } - - RETURN_LONG(php_COM_addref(obj TSRMLS_CC)); -} -/* }}} */ - -/* {{{ proto bool com_message_pump([int timeoutms]) - Process COM messages, sleeping for up to timeoutms milliseconds */ -PHP_FUNCTION(com_message_pump) -{ - long timeoutms = 0; - MSG msg; - DWORD result; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &timeoutms) == FAILURE) - RETURN_FALSE; - - result = MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutms, QS_ALLINPUT); - - if (result == WAIT_OBJECT_0) { - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - /* we processed messages */ - RETVAL_TRUE; - } else { - /* we did not process messages (timed out) */ - RETVAL_FALSE; - } -} -/* }}} */ - - -static int com_enable_events(comval *obj, int enable) -{ - if (obj->sinkdispatch) { - IConnectionPointContainer *cont; - IConnectionPoint *point; - - if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IConnectionPointContainer, (void**)&cont))) { - - if (SUCCEEDED(cont->lpVtbl->FindConnectionPoint(cont, &obj->sinkid, &point))) { - - if (enable) { - point->lpVtbl->Advise(point, (IUnknown*)obj->sinkdispatch, &obj->sinkcookie); - } else { - point->lpVtbl->Unadvise(point, obj->sinkcookie); - } - point->lpVtbl->Release(point); - } - cont->lpVtbl->Release(cont); - } - } - return 0; -} - -static const struct { - VARTYPE vt; - const char *name; -} vt_names[] = { - { VT_NULL, "VT_NULL" }, - { VT_EMPTY, "VT_EMPTY" }, - { VT_UI1, "VT_UI1" }, - { VT_I2, "VT_I2" }, - { VT_I4, "VT_I4" }, - { VT_R4, "VT_R4" }, - { VT_R8, "VT_R8" }, - { VT_BOOL, "VT_BOOL" }, - { VT_ERROR, "VT_ERROR" }, - { VT_CY, "VT_CY" }, - { VT_DATE, "VT_DATE" }, - { VT_BSTR, "VT_BSTR" }, - { VT_DECIMAL, "VT_DECIMAL" }, - { VT_UNKNOWN, "VT_UNKNOWN" }, - { VT_DISPATCH, "VT_DISPATCH" }, - { VT_VARIANT, "VT_VARIANT" }, - { VT_I1, "VT_I1" }, - { VT_UI2, "VT_UI2" }, - { VT_UI4, "VT_UI4" }, - { VT_INT, "VT_INT" }, - { VT_UINT, "VT_UINT" }, - { VT_ARRAY, "VT_ARRAY" }, - { VT_BYREF, "VT_BYREF" }, - { VT_VOID, "VT_VOID" }, - { VT_PTR, "VT_PTR" }, - { VT_HRESULT, "VT_HRESULT" }, - { 0, NULL } -}; - -static inline const char *vt_to_string(VARTYPE vt) -{ - int i; - for (i = 0; vt_names[i].name != NULL; i++) { - if (vt_names[i].vt == vt) - return vt_names[i].name; - } - return "?"; -} - -static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid TSRMLS_DC) -{ - TYPEATTR *attr; - FUNCDESC *func; - int i; - OLECHAR *olename; - char *ansiname = NULL; - unsigned int ansinamelen; - int ret = 0; - - if (FAILED(typeinfo->lpVtbl->GetTypeAttr(typeinfo, &attr))) - return 0; - - /* verify that it is suitable */ - if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) { - - if (guid) - memcpy(guid, &attr->guid, sizeof(GUID)); - - if (printdef) { - char *guidstring; - - typeinfo->lpVtbl->GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL); - ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); - SysFreeString(olename); - - guidstring = php_string_from_clsid(&attr->guid TSRMLS_CC); - php_printf("class %s { /* GUID=%s */\n", ansiname, guidstring); - efree(guidstring); - - efree(ansiname); - } - - if (id_to_name) - zend_hash_init(id_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); + if (id_to_name) + zend_hash_init(id_to_name, 0, NULL, ZVAL_PTR_DTOR, 0); /* So we've got the dispatch interface; lets list the event methods */ for (i = 0; i < attr->cFuncs; i++) { zval *tmp; - DISPID lastid = 0; /* for props */ - int isprop; - - if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func))) - break; - - isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT); - - if (!isprop || lastid != func->memid) { - - lastid = func->memid; - - typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL); - ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); - SysFreeString(olename); - - if (printdef) { - int j; - char *funcdesc; - unsigned int funcdesclen, cnames = 0; - BSTR *names; - - names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR)); - - typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames); - /* first element is the function name */ - SysFreeString(names[0]); - - php_printf("\t/* DISPID=%d */\n", func->memid); - - if (func->elemdescFunc.tdesc.vt != VT_VOID) { - php_printf("\t/* %s [%d] */\n", - vt_to_string(func->elemdescFunc.tdesc.vt), - func->elemdescFunc.tdesc.vt - ); - } - - if (isprop) { - - typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); - if (olename) { - funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, codepage TSRMLS_CC); - SysFreeString(olename); - php_printf("\t/* %s */\n", funcdesc); - efree(funcdesc); - } - - php_printf("\tvar $%s;\n\n", ansiname); - - } else { - /* a function */ - - php_printf("\tfunction %s(\n", ansiname); - - for (j = 0; j < func->cParams; j++) { - ELEMDESC *elem = &func->lprgelemdescParam[j]; - - php_printf("\t\t/* %s [%d] ", vt_to_string(elem->tdesc.vt), elem->tdesc.vt); - - if (elem->paramdesc.wParamFlags & PARAMFLAG_FIN) - php_printf("[in]"); - if (elem->paramdesc.wParamFlags & PARAMFLAG_FOUT) - php_printf("[out]"); - - if (elem->tdesc.vt == VT_PTR) { - /* what does it point to ? */ - php_printf(" --> %s [%d] ", - vt_to_string(elem->tdesc.lptdesc->vt), - elem->tdesc.lptdesc->vt - ); - } - - /* when we handle prop put and get, this will look nicer */ - if (j+1 < (int)cnames) { - funcdesc = php_OLECHAR_to_char(names[j+1], &funcdesclen, codepage TSRMLS_CC); - SysFreeString(names[j+1]); - } else { - funcdesc = "???"; - } - - php_printf(" */ %s%s%c\n", - elem->tdesc.vt == VT_PTR ? "&$" : "$", - funcdesc, - j == func->cParams - 1 ? ' ' : ',' - ); - - if (j+1 < (int)cnames) - efree(funcdesc); - } - - php_printf("\t\t)\n\t{\n"); - - typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); - if (olename) { - funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, codepage TSRMLS_CC); - SysFreeString(olename); - php_printf("\t\t/* %s */\n", funcdesc); - efree(funcdesc); - } - - php_printf("\t}\n"); - } - - efree(names); - } - - if (id_to_name) { - zend_str_tolower(ansiname, ansinamelen); - MAKE_STD_ZVAL(tmp); - ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0); - zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL); - } - } - typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func); - - } - - if (printdef) - php_printf("}\n"); - - ret = 1; - } else { - zend_error(E_WARNING, "Thats not a dispatchable interface!! type kind = %08x\n", attr->typekind); - } - - typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr); - - return ret; -} - -static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname, int sink TSRMLS_DC) -{ - ITypeInfo *typeinfo = NULL; - ITypeLib *typelib = NULL; - int gotguid = 0; - GUID iid; - - if (obj) { - if (dispname == NULL && sink) { - IProvideClassInfo2 *pci2; - IProvideClassInfo *pci; - - if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo2, (void**)&pci2))) { - gotguid = SUCCEEDED(pci2->lpVtbl->GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid)); - pci2->lpVtbl->Release(pci2); - } - if (!gotguid && SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo, (void**)&pci))) { - /* examine the available interfaces */ - /* TODO: write some code here */ - pci->lpVtbl->Release(pci); - } - } else if (dispname && C_HASTLIB(obj)) { - unsigned int idx; - /* get the library from the object; the rest will be dealt with later */ - C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx); - } else if (typelibname == NULL) { - C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &typeinfo); - } - } else if (typelibname) { - /* Fetch the typelibrary and use that to look things up */ - typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC); - } - - if (!gotguid && dispname && typelib) { - unsigned short cfound; - MEMBERID memid; - OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC); - - cfound = 1; - if (FAILED(typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) { - CLSID coclass; - ITypeInfo *coinfo; - - /* assume that it might be a progid instead */ - if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) && - SUCCEEDED(typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) { - - /* enumerate implemented interfaces and pick the one as indicated by sink */ - TYPEATTR *attr; - int i; - - coinfo->lpVtbl->GetTypeAttr(coinfo, &attr); - - for (i = 0; i < attr->cImplTypes; i++) { - HREFTYPE rt; - int tf; - - if (FAILED(coinfo->lpVtbl->GetImplTypeFlags(coinfo, i, &tf))) - continue; - - if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) || - (!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) { - - /* flags match what we are looking for */ - - if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeOfImplType(coinfo, i, &rt))) - if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeInfo(coinfo, rt, &typeinfo))) - break; - - } - } - - coinfo->lpVtbl->ReleaseTypeAttr(coinfo, attr); - coinfo->lpVtbl->Release(coinfo); - } - } - - - efree(olename); - } else if (gotguid) { - typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &iid, &typeinfo); - } - - if (typelib) - typelib->lpVtbl->Release(typelib); - - return typeinfo; -} - -/* {{{ proto bool com_print_typeinfo(mixed comobject | string typelib, string dispinterface, bool wantsink) - Print out a PHP class definition for a dispatchable interface */ -PHP_FUNCTION(com_print_typeinfo) -{ - zval *arg1; - char *ifacename = NULL; - char *typelibname = NULL; - int ifacelen; - zend_bool wantsink = 0; - comval *obj = NULL; - ITypeInfo *typeinfo; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/s!b", &arg1, &ifacename, - &ifacelen, &wantsink)) { - RETURN_FALSE; - } - - if (Z_TYPE_P(arg1) == IS_OBJECT && (Z_OBJCE_P(arg1) == &COM_class_entry || !strcmp(Z_OBJCE_P(arg1)->name, "COM"))) { - zval **tmp; - zend_hash_index_find(Z_OBJPROP_P(arg1), 0, (void**)&tmp); - ZEND_FETCH_RESOURCE(obj, comval*, tmp, -1, "comval", IS_COM); - } else if (Z_TYPE_P(arg1) == IS_RESOURCE) { - ZEND_FETCH_RESOURCE(obj, comval*, &arg1, -1, "comval", IS_COM); - } else { - convert_to_string(arg1); - typelibname = Z_STRVAL_P(arg1); - } - - typeinfo = locate_typeinfo(typelibname, obj, ifacename, wantsink TSRMLS_CC); - if (typeinfo) { - process_typeinfo(typeinfo, NULL, 1, NULL TSRMLS_CC); - typeinfo->lpVtbl->Release(typeinfo); - RETURN_TRUE; - } else { - zend_error(E_WARNING, "Unable to find typeinfo using the parameters supplied"); - } - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool com_event_sink(mixed comobject, object sinkobject [, mixed sinkinterface]) - Connect events from a COM object to a PHP object */ -PHP_FUNCTION(com_event_sink) -{ - zval *object, *sinkobject, *sink=NULL; - char *dispname = NULL, *typelibname = NULL; - zend_bool gotguid = 0; - comval *obj; - ITypeInfo *typeinfo = NULL; - - RETVAL_FALSE; - - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z/", &object, &sinkobject, &sink)) { - RETURN_FALSE; - } - - 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 { - ZEND_FETCH_RESOURCE(obj, comval*, &object, -1, "comval", IS_COM); - } - - if (sink && Z_TYPE_P(sink) == IS_ARRAY) { - /* 0 => typelibname, 1 => dispname */ - zval **tmp; - - if (zend_hash_index_find(Z_ARRVAL_P(sink), 0, (void**)&tmp) == SUCCESS) - typelibname = Z_STRVAL_PP(tmp); - if (zend_hash_index_find(Z_ARRVAL_P(sink), 1, (void**)&tmp) == SUCCESS) - dispname = Z_STRVAL_PP(tmp); - } else if (sink != NULL) { - convert_to_string(sink); - dispname = Z_STRVAL_P(sink); - } - - typeinfo = locate_typeinfo(typelibname, obj, dispname, 1 TSRMLS_CC); - - if (typeinfo) { - HashTable *id_to_name; - - ALLOC_HASHTABLE(id_to_name); - - if (process_typeinfo(typeinfo, id_to_name, 0, &obj->sinkid TSRMLS_CC)) { - - /* Create the COM wrapper for this sink */ - obj->sinkdispatch = php_COM_export_as_sink(sinkobject, &obj->sinkid, id_to_name TSRMLS_CC); - - /* Now hook it up to the source */ - com_enable_events(obj, TRUE); - RETVAL_TRUE; - - } else { - FREE_HASHTABLE(id_to_name); - } - } - - if (typeinfo) - typeinfo->lpVtbl->Release(typeinfo); - -} -/* }}} */ - -static int do_COM_offget(VARIANT *result, comval *array, pval *property, int cleanup TSRMLS_DC) -{ - pval function_name; - int retval; - - ZVAL_STRINGL(&function_name, "Item", 4, 0); - retval = do_COM_invoke(array, &function_name, result, &property, 1 TSRMLS_CC); - if (cleanup) { - php_COM_destruct(array TSRMLS_CC); - } - - return retval; -} - - -static int do_COM_propget(VARIANT *var_result, comval *obj, pval *arg_property, int cleanup TSRMLS_DC) -{ - DISPID dispid; - HRESULT hr; - OLECHAR *propname; - char *error_message; - DISPPARAMS dispparams; - char *ErrString; - - /* obtain property handler */ - propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC); - - hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); - LocalFree(error_message); - efree(propname); - if (cleanup) { - php_COM_destruct(obj TSRMLS_CC); - } - return FAILURE; - } - - dispparams.cArgs = 0; - dispparams.cNamedArgs = 0; - - hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) { - php_error(E_WARNING,"PropGet() failed: %s %s", error_message, ErrString); - pefree(ErrString, 1); - } else { - php_error(E_WARNING,"PropGet() failed: %s", error_message); - } - LocalFree(error_message); - efree(propname); - if (cleanup) { - php_COM_destruct(obj TSRMLS_CC); - } - return FAILURE; - } - - efree(propname); - if (cleanup) { - php_COM_destruct(obj TSRMLS_CC); - } - return SUCCESS; -} - - -static void do_COM_propput(pval *return_value, comval *obj, pval *arg_property, pval *value TSRMLS_DC) -{ - DISPID dispid; - HRESULT hr; - OLECHAR *propname; - char *error_message; - VARIANT *var_result, *new_value; - DISPPARAMS dispparams; - DISPID mydispid = DISPID_PROPERTYPUT; - char *ErrString; - - ALLOC_VARIANT(var_result); - ALLOC_VARIANT(new_value); - - /* obtain property handler */ - propname = php_char_to_OLECHAR(Z_STRVAL_P(arg_property), Z_STRLEN_P(arg_property), codepage TSRMLS_CC); - - hr = php_COM_get_ids_of_names(obj, &propname, &dispid TSRMLS_CC); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - php_error(E_WARNING,"Unable to lookup %s: %s", Z_STRVAL_P(arg_property), error_message); - LocalFree(error_message); - efree(propname); - - FREE_VARIANT(var_result); - FREE_VARIANT(new_value); - - RETURN_NULL(); - } - - php_pval_to_variant(value, new_value, codepage TSRMLS_CC); - dispparams.rgvarg = new_value; - dispparams.rgdispidNamedArgs = &mydispid; - dispparams.cArgs = 1; - dispparams.cNamedArgs = 1; - - hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYPUT, &dispparams, NULL, &ErrString TSRMLS_CC); - - if (FAILED(hr)) { - error_message = php_COM_error_message(hr TSRMLS_CC); - if (ErrString) { - php_error(E_WARNING,"PropPut() failed: %s %s", error_message, ErrString); - pefree(ErrString, 1); - } else { - php_error(E_WARNING,"PropPut() failed: %s", error_message); - } - LocalFree(error_message); - - FREE_VARIANT(var_result); - - efree(new_value); - efree(propname); - - RETURN_NULL(); - } - - if (return_value) { - dispparams.cArgs = 0; - dispparams.cNamedArgs = 0; - - hr = php_COM_invoke(obj, dispid, DISPATCH_PROPERTYGET, &dispparams, var_result, &ErrString TSRMLS_CC); - - if (SUCCEEDED(hr)) { - php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); - } else { - *return_value = *value; - zval_copy_ctor(return_value); - } - - if (ErrString) { - pefree(ErrString, 1); - } - } - - FREE_VARIANT(var_result); - - efree(new_value); // FREE_VARIANT does a VariantClear() which is not desired here ! - efree(propname); -} - - -/* {{{ proto mixed com_propget(int module, string property_name) - Gets properties from a COM module */ -PHP_FUNCTION(com_propget) -{ - pval *arg_comval, *arg_property; - int type; - comval *obj; - VARIANT *var_result; - - if ((ZEND_NUM_ARGS() != 2) || (zend_get_parameters(ht, 2, &arg_comval, &arg_property) == FAILURE)) { - ZEND_WRONG_PARAM_COUNT(); - } - - /* 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,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); - RETURN_NULL(); - } - convert_to_string_ex(&arg_property); - - ALLOC_VARIANT(var_result); - - if (do_COM_propget(var_result, obj, arg_property, FALSE TSRMLS_CC) == FAILURE) { - FREE_VARIANT(var_result); - RETURN_NULL(); - } - - RETVAL_VARIANT(var_result); -} -/* }}} */ - - -/* {{{ 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; - comval *obj; - - if (ZEND_NUM_ARGS()!=3 || zend_get_parameters(ht, 3, &arg_comval, &arg_property, &arg_value)==FAILURE) { - ZEND_WRONG_PARAM_COUNT(); - } - - /* 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,"%d is not a COM object handler", Z_LVAL_P(arg_comval)); - RETURN_NULL(); - } - convert_to_string_ex(&arg_property); - - do_COM_propput(return_value, obj, arg_property, arg_value TSRMLS_CC); -} -/* }}} */ - - -/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitive]) - Loads a Typelib */ -PHP_FUNCTION(com_load_typelib) -{ - pval *arg_typelib, *arg_cis; - ITypeLib *pTL; - int mode = CONST_CS; - - switch (ZEND_NUM_ARGS()) { - case 1: - zend_get_parameters(ht, 1, &arg_typelib); - break; - - case 2: - zend_get_parameters(ht, 2, &arg_typelib, &arg_cis); - convert_to_boolean_ex(&arg_cis); - if (Z_LVAL_P(arg_cis)) { - mode &= ~CONST_CS; - } - break; - - default: - ZEND_WRONG_PARAM_COUNT(); - } - - convert_to_string_ex(&arg_typelib); - pTL = php_COM_find_typelib(Z_STRVAL_P(arg_typelib), mode TSRMLS_CC); - if (php_COM_load_typelib(pTL, mode TSRMLS_CC) == SUCCESS) { - pTL->lpVtbl->Release(pTL); - RETURN_TRUE; - } else { - RETURN_FALSE; - } -} -/* }}} */ - - -PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference) -{ - zend_overloaded_element *overloaded_property; - zend_llist_element *element; - pval return_value; - pval **comval_handle; - pval *object = property_reference->object; - int type; - comval *obj, *obj_prop; - VARIANT *var_result; - TSRMLS_FETCH(); + DISPID lastid = 0; /* for props */ + int isprop; - INIT_ZVAL(return_value); - ZVAL_NULL(&return_value); + if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func))) + break; - /* fetch the IDispatch interface */ - zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); - obj = (comval *) zend_list_find(Z_LVAL_P(*comval_handle), &type); - if (!obj || (type != IS_COM)) { - return return_value; - } + isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT); - ALLOC_COM(obj_prop); - ALLOC_VARIANT(var_result); + if (!isprop || lastid != func->memid) { - for (element=property_reference->elements_list->head; element; element=element->next) { - overloaded_property = (zend_overloaded_element *) element->data; - switch (Z_TYPE_P(overloaded_property)) { - case OE_IS_ARRAY: - if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); + lastid = func->memid; + + typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL); + ansiname = php_OLECHAR_to_char(olename, &ansinamelen, CP_ACP, FALSE); + SysFreeString(olename); - return return_value; - } - break; + if (printdef) { + int j; + char *funcdesc; + unsigned int funcdesclen, cnames = 0; + BSTR *names; - case OE_IS_OBJECT: - if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); + names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR)); - return return_value; - } - break; + typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames); + /* first element is the function name */ + SysFreeString(names[0]); - case OE_IS_METHOD: { - FREE_VARIANT(var_result); - if (obj != obj_prop) { - FREE_COM(obj_prop); + php_printf("\t/* DISPID=%d */\n", func->memid); - return_value = *object; - ZVAL_ADDREF(&return_value); - } else { - RETVAL_COM(obj); + if (func->elemdescFunc.tdesc.vt != VT_VOID) { + php_printf("\t/* %s [%d] */\n", + vt_to_string(func->elemdescFunc.tdesc.vt), + func->elemdescFunc.tdesc.vt + ); } - return return_value; - } - break; - } - if (V_VT(var_result) == VT_DISPATCH) { - if (V_DISPATCH(var_result) == NULL) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); - - return return_value; - } + if (isprop) { - obj = obj_prop; - php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - VariantInit(var_result); // to protect C_DISPATCH(obj) from being freed when var_result is destructed - } else { - php_variant_to_pval(var_result, &return_value, codepage TSRMLS_CC); + typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); + if (olename) { + funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, CP_ACP, FALSE); + SysFreeString(olename); + php_printf("\t/* %s */\n", funcdesc); + efree(funcdesc); + } - FREE_COM(obj_prop); - obj_prop = NULL; - } + php_printf("\tvar $%s;\n\n", ansiname); - pval_destructor(&overloaded_property->element); - } + } else { + /* a function */ - if (obj_prop != NULL) { - RETVAL_COM(obj); - } + php_printf("\tfunction %s(\n", ansiname); + for (j = 0; j < func->cParams; j++) { + ELEMDESC *elem = &func->lprgelemdescParam[j]; - FREE_VARIANT(var_result); + php_printf("\t\t/* %s [%d] ", vt_to_string(elem->tdesc.vt), elem->tdesc.vt); - return return_value; -} + if (elem->paramdesc.wParamFlags & PARAMFLAG_FIN) + php_printf("[in]"); + if (elem->paramdesc.wParamFlags & PARAMFLAG_FOUT) + php_printf("[out]"); + if (elem->tdesc.vt == VT_PTR) { + /* what does it point to ? */ + php_printf(" --> %s [%d] ", + vt_to_string(elem->tdesc.lptdesc->vt), + elem->tdesc.lptdesc->vt + ); + } -PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value) -{ - zend_overloaded_element *overloaded_property; - zend_llist_element *element; - pval **comval_handle; - pval *object = property_reference->object; - comval *obj, *obj_prop; - int type; - VARIANT *var_result; - TSRMLS_FETCH(); + /* when we handle prop put and get, this will look nicer */ + if (j+1 < (int)cnames) { + funcdesc = php_OLECHAR_to_char(names[j+1], &funcdesclen, CP_ACP, FALSE); + SysFreeString(names[j+1]); + } else { + funcdesc = "???"; + } - /* fetch the IDispatch interface */ - zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); - obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type); - if (!obj || (type != IS_COM)) { - return FAILURE; - } + php_printf(" */ %s%s%c\n", + elem->tdesc.vt == VT_PTR ? "&$" : "$", + funcdesc, + j == func->cParams - 1 ? ' ' : ',' + ); - ALLOC_COM(obj_prop); - ALLOC_VARIANT(var_result); + if (j+1 < (int)cnames) + efree(funcdesc); + } - for (element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) { - overloaded_property = (zend_overloaded_element *) element->data; - switch (Z_TYPE_P(overloaded_property)) { - case OE_IS_ARRAY: - if (do_COM_offget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); + php_printf("\t\t)\n\t{\n"); - return FAILURE; - } - break; + typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL); + if (olename) { + funcdesc = php_OLECHAR_to_char(olename, &funcdesclen, CP_ACP, FALSE); + SysFreeString(olename); + php_printf("\t\t/* %s */\n", funcdesc); + efree(funcdesc); + } - case OE_IS_OBJECT: - if (do_COM_propget(var_result, obj, &overloaded_property->element, FALSE TSRMLS_CC) == FAILURE) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); + php_printf("\t}\n"); + } - return FAILURE; + efree(names); } - break; - case OE_IS_METHOD: - /* this shouldn't happen */ - return FAILURE; - break; - } - - if (V_VT(var_result) == VT_DISPATCH) { - if (V_DISPATCH(var_result) == NULL) { - FREE_VARIANT(var_result); - FREE_COM(obj_prop); - - return FAILURE; + if (id_to_name) { + zend_str_tolower(ansiname, ansinamelen); + MAKE_STD_ZVAL(tmp); + ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0); + zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL); + } } + typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func); - obj = obj_prop; - php_COM_set(obj, &V_DISPATCH(var_result), TRUE TSRMLS_CC); - } else { - FREE_COM(obj_prop); - FREE_VARIANT(var_result); - - return FAILURE; } - VariantInit(var_result); // to protect C_DISPATCH(obj) from being freed when var_result is destructed - pval_destructor(&overloaded_property->element); - } - FREE_VARIANT(var_result); + if (printdef) + php_printf("}\n"); - overloaded_property = (zend_overloaded_element *) element->data; - do_COM_propput(NULL, obj, &overloaded_property->element, value TSRMLS_CC); - FREE_COM(obj_prop); + ret = 1; + } else { + zend_error(E_WARNING, "Thats not a dispatchable interface!! type kind = %08x\n", attr->typekind); + } - pval_destructor(&overloaded_property->element); + typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr); - return SUCCESS; + return ret; } -/* create an overloaded COM object from a dispatch pointer */ -PHPAPI zval *php_COM_object_from_dispatch(IDispatch *disp, zval *val TSRMLS_DC) +ZEND_API ITypeInfo *php_COM_locate_typeinfo(char *typelibname, comval *obj, char *dispname, int sink) { - comval *obj; - zval *zobj; - - ALLOC_COM(obj); - MAKE_STD_ZVAL(zobj); - php_COM_set(obj, &disp, FALSE TSRMLS_CC); - ZVAL_COM_EX(zobj, obj, val); - - return zobj; -} + ITypeInfo *typeinfo = NULL; + ITypeLib *typelib = NULL; + int gotguid = 0; + GUID iid; + if (obj) { + if (dispname == NULL && sink) { + IProvideClassInfo2 *pci2; + IProvideClassInfo *pci; -PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) -{ - pval property, **handle; - pval *object = property_reference->object; - zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data; - comval *obj; - int type; - - if (zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL(function_name->element), "com")) { - /* constructor */ - pval *object_handle; - - PHP_FN(com_load)(INTERNAL_FUNCTION_PARAM_PASSTHRU); - if (zend_is_true(return_value)) { - ALLOC_ZVAL(object_handle); - *object_handle = *return_value; - pval_copy_constructor(object_handle); - INIT_PZVAL(object_handle); - zend_hash_index_update(Z_OBJPROP_P(object), 0, &object_handle, sizeof(pval *), NULL); - pval_destructor(&function_name->element); - } else { - ZVAL_NULL(object); + if (SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo2, (void**)&pci2))) { + gotguid = SUCCEEDED(pci2->lpVtbl->GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid)); + pci2->lpVtbl->Release(pci2); + } + if (!gotguid && SUCCEEDED(C_DISPATCH_VT(obj)->QueryInterface(C_DISPATCH(obj), &IID_IProvideClassInfo, (void**)&pci))) { + /* examine the available interfaces */ + /* TODO: write some code here */ + pci->lpVtbl->Release(pci); + } + } else if (dispname && C_HASTLIB(obj)) { + unsigned int idx; + /* get the library from the object; the rest will be dealt with later */ + C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx); + } else if (typelibname == NULL) { + C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &typeinfo); } + } else if (typelibname) { + /* Fetch the typelibrary and use that to look things up */ + typelib = php_COM_find_typelib(typelibname, CONST_CS); + } - return; - } - - RETVAL_NULL(); - property = php_COM_get_property_handler(property_reference); - - if (Z_TYPE(property) != IS_OBJECT) { - pval_destructor(&property); - pval_destructor(&function_name->element); - - /* error message - function call on a non-object */ - return; - } + if (!gotguid && dispname && typelib) { + unsigned short cfound; + MEMBERID memid; + OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP, FALSE); + + cfound = 1; + if (FAILED(typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) { + CLSID coclass; + ITypeInfo *coinfo; + + /* assume that it might be a progid instead */ + if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) && + SUCCEEDED(typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) { - zend_hash_index_find(Z_OBJPROP(property), 0, (void **) &handle); - obj = (comval *)zend_list_find(Z_LVAL_PP(handle), &type); + /* enumerate implemented interfaces and pick the one as indicated by sink */ + TYPEATTR *attr; + int i; - if (!obj || (type != IS_COM)) { - pval_destructor(&property); - pval_destructor(&function_name->element); + coinfo->lpVtbl->GetTypeAttr(coinfo, &attr); - return; - } + for (i = 0; i < attr->cImplTypes; i++) { + HREFTYPE rt; + int tf; - if (zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL_P(&function_name->element), "release")) { - RETVAL_LONG(php_COM_release(obj TSRMLS_CC)); - } else if (zend_llist_count(property_reference->elements_list)==1 - && !strcmp(Z_STRVAL_P(&function_name->element), "addref")) { - RETVAL_LONG(php_COM_addref(obj TSRMLS_CC)); - } else { - pval **arguments; - VARIANT *var_result; - int arg_count = ZEND_NUM_ARGS(); + if (FAILED(coinfo->lpVtbl->GetImplTypeFlags(coinfo, i, &tf))) + continue; - ALLOC_VARIANT(var_result); + if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) || + (!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) { - arguments = (pval **) emalloc(sizeof(pval *)*arg_count); - zend_get_parameters_array(ht, arg_count, arguments); + /* flags match what we are looking for */ - if (do_COM_invoke(obj , &function_name->element, var_result, arguments, arg_count TSRMLS_CC) == SUCCESS) { - php_variant_to_pval(var_result, return_value, codepage TSRMLS_CC); + if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeOfImplType(coinfo, i, &rt))) + if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeInfo(coinfo, rt, &typeinfo))) + break; + + } + } + + coinfo->lpVtbl->ReleaseTypeAttr(coinfo, attr); + coinfo->lpVtbl->Release(coinfo); + } } - FREE_VARIANT(var_result); - efree(arguments); + + efree(olename); + } else if (gotguid) { + typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &iid, &typeinfo); } - if (zend_llist_count(property_reference->elements_list) > 1) { - /* destruct temporary object */ - zend_list_delete(Z_LVAL_PP(handle)); - pval_destructor(&property); - } - - pval_destructor(&function_name->element); -} + if (typelib) + typelib->lpVtbl->Release(typelib); + return typeinfo; +} -static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) +static ITypeLib *php_COM_find_typelib(char *search_string, int mode) { ITypeLib *TypeLib = NULL; char *strtok_buf, *major, *minor; @@ -2013,7 +677,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) major = php_strtok_r(NULL, ",", &strtok_buf); minor = php_strtok_r(NULL, ",", &strtok_buf); - p = php_char_to_OLECHAR(search_string, strlen(search_string), codepage TSRMLS_CC); + p = php_char_to_OLECHAR(search_string, strlen(search_string), CP_ACP, FALSE); /* Is the string a GUID ? */ if (!FAILED(CLSIDFromString(p, &clsid))) { @@ -2132,7 +796,7 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) str = emalloc(strlen(keyname)+strlen(version)+20); /* 18 == safety, 2 == extra comma and \0 */ sprintf(str, "%s,%d,%d", keyname, major, minor); efree(keyname); - TypeLib = php_COM_find_typelib(str, mode TSRMLS_CC); + TypeLib = php_COM_find_typelib(str, mode); efree(str); /* This is probbaly much harder to read and follow */ /* But it is MUCH more effiecient than trying to */ @@ -2156,11 +820,12 @@ static ITypeLib *php_COM_find_typelib(char *search_string, int mode TSRMLS_DC) } -PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) +ZEND_API int php_COM_load_typelib(ITypeLib *TypeLib, int mode) { ITypeComp *TypeComp; int i; int interfaces; + TSRMLS_FETCH(); if (NULL == TypeLib) { return FAILURE; @@ -2178,15 +843,13 @@ PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) VARDESC *pVarDesc; UINT NameCount; int j; -#if 0 BSTR bstr_EnumId; char *EnumId; TypeLib->lpVtbl->GetDocumentation(TypeLib, i, &bstr_EnumId, NULL, NULL, NULL); - EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, codepage); + EnumId = php_OLECHAR_to_char(bstr_EnumId, NULL, CP_ACP, FALSE); printf("Enumeration %d - %s:\n", i, EnumId); efree(EnumId); -#endif TypeLib->lpVtbl->GetTypeInfo(TypeLib, i, &TypeInfo); @@ -2202,7 +865,7 @@ PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) j++; continue; } - const_name = php_OLECHAR_to_char(bstr_ids, &c.name_len, codepage TSRMLS_CC); + const_name = php_OLECHAR_to_char(bstr_ids, &c.name_len, CP_ACP, FALSE); c.name = zend_strndup(const_name, c.name_len); efree(const_name); c.name_len++; /* length should include the NULL */ @@ -2220,11 +883,7 @@ PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) continue; } - php_variant_to_pval(pVarDesc->lpvarValue, &c.value, codepage TSRMLS_CC); - if (mode & CONST_PERSISTENT) { - zval_persist(&c.value TSRMLS_CC); - mode |= CONST_EFREE_PERSISTENT; - } + php_variant_to_zval(pVarDesc->lpvarValue, &c.value, CP_ACP); c.flags = mode; zend_register_constant(&c TSRMLS_CC); @@ -2238,100 +897,20 @@ PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC) return SUCCESS; } -/* {{{ proto bool com_isenum(object com_module) - Grabs an IEnumVariant */ -PHP_FUNCTION(com_isenum) -{ - pval *object; - pval **comval_handle; - comval *obj; - int type; - - if (ZEND_NUM_ARGS() != 1) { - ZEND_WRONG_PARAM_COUNT(); - } - - zend_get_parameters(ht, 1, &object); - - /* obtain IDispatch interface */ - zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &comval_handle); - obj = (comval *) zend_list_find(Z_LVAL_PP(comval_handle), &type); - if (!obj || (type != IS_COM)) { - php_error(E_WARNING,"%s is not a COM object handler", ""); - RETURN_FALSE; - } - - RETURN_BOOL(C_HASENUM(obj)); -} -/* }}} */ - - -static void php_register_COM_class(TSRMLS_D) -{ - INIT_OVERLOADED_CLASS_ENTRY(COM_class_entry, "COM", NULL, - php_COM_call_function_handler, - php_COM_get_property_handler, - php_COM_set_property_handler); - - zend_register_internal_class(&COM_class_entry TSRMLS_CC); -} - - -static void php_COM_init(int module_number TSRMLS_DC) -{ - le_comval = zend_register_list_destructors_ex(php_comval_destructor, NULL, "COM", module_number); - php_register_COM_class(TSRMLS_C); -} - -PHPAPI ZEND_DECLARE_MODULE_GLOBALS(com) - -static void php_com_init_globals(zend_com_globals *com_globals) -{ -} - -PHP_MINIT_FUNCTION(COM) -{ - ZEND_INIT_MODULE_GLOBALS(com, php_com_init_globals, NULL); - php_COM_init(module_number TSRMLS_CC); - php_VARIANT_init(module_number TSRMLS_CC); - php_COM_dispatch_init(module_number TSRMLS_CC); - - REGISTER_LONG_CONSTANT("CLSCTX_INPROC_SERVER", CLSCTX_INPROC_SERVER, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("CLSCTX_INPROC_HANDLER", CLSCTX_INPROC_HANDLER, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("CLSCTX_LOCAL_SERVER", CLSCTX_LOCAL_SERVER, CONST_CS | CONST_PERSISTENT); - 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_INI_ENTRIES(); - - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(COM) -{ - UNREGISTER_INI_ENTRIES(); - return SUCCESS; -} - -/* exports for external object creation */ - -zend_module_entry COM_module_entry = { - STANDARD_MODULE_HEADER, - "com", - COM_functions, - PHP_MINIT(COM), - PHP_MSHUTDOWN(COM), - NULL, - NULL, - PHP_MINFO(COM), - NO_VERSION_YET, - STANDARD_MODULE_PROPERTIES -}; -PHPAPI int php_COM_get_le_comval() +/* create an overloaded COM object from a dispatch pointer */ +PHPAPI zval *php_COM_object_from_dispatch(IDispatch *disp) { - return le_comval; + comval *obj; + zval *zobj; + TSRMLS_FETCH(); + + ALLOC_COM(obj); + MAKE_STD_ZVAL(zobj); + php_COM_set(obj, &disp, FALSE); + ZVAL_COM(zobj, obj); + + return zobj; } #endif diff --git a/ext/rpc/com/com_wrapper.h b/ext/rpc/com/com_wrapper.h index 5ec791dd43..ff40f5116e 100644 --- a/ext/rpc/com/com_wrapper.h +++ b/ext/rpc/com/com_wrapper.h @@ -1,70 +1,98 @@ -#ifndef COM_H -#define COM_H +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Zeev Suraski | + | Harald Radi | + | Alan Brown | + | Wez Furlong | + +----------------------------------------------------------------------+ + */ + +#ifndef COM_WRAPPER_H +#define COM_WRAPPER_H #if PHP_WIN32 BEGIN_EXTERN_C() -#include - typedef struct comval_ { -#ifdef _DEBUG - int resourceindex; -#endif BOOL typelib; BOOL enumeration; int refcount; + int codepage; struct { IDispatch *dispatch; ITypeInfo *typeinfo; IEnumVARIANT *enumvariant; } i; + +#if 1 IDispatch *sinkdispatch; GUID sinkid; DWORD sinkcookie; +#endif + +#ifdef _DEBUG + int resourceindex; +#endif + } comval; -END_EXTERN_C() +ZEND_API HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString); +ZEND_API HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* rgszNames, DISPID FAR* rgDispId); +ZEND_API HRESULT php_COM_release(comval *obj); +ZEND_API HRESULT php_COM_addref(comval *obj); +ZEND_API HRESULT php_COM_destruct(comval *obj); +ZEND_API HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* pDisp, int cleanup); +ZEND_API HRESULT php_COM_enable_events(comval *obj, int enable); + +ZEND_API char* php_COM_string_from_CLSID(const CLSID *clsid); +ZEND_API char* php_COM_error_message(HRESULT hr); +ZEND_API int php_COM_load_typelib(ITypeLib *TypeLib, int mode); +ZEND_API int php_COM_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid); +ZEND_API ITypeInfo* php_COM_locate_typeinfo(char *typelibname, comval *obj, char *dispname, int sink); +ZEND_API ITypeLib* php_COM_find_typelib(char *search_string, int mode); + +ZEND_API IDispatch* php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name); +ZEND_API IDispatch* php_COM_export_object(zval *val); +ZEND_API zval* php_COM_object_from_dispatch(IDispatch *disp); -#define ZVAL_COM(z,o) { \ - zval *handle = NULL; \ - ZVAL_COM_EX(z,o,handle) \ - } +END_EXTERN_C() -#define ZVAL_COM_EX(z,o,handle) { \ - HashTable *properties; \ - \ - ALLOC_HASHTABLE(properties); \ - zend_hash_init(properties, 0, NULL, ZVAL_PTR_DTOR, 0); \ - \ - if (handle == NULL) { \ - MAKE_STD_ZVAL(handle); \ - } \ - ZVAL_RESOURCE(handle, zend_list_insert((o), IS_COM)); \ - \ - zval_copy_ctor(handle); \ - zend_hash_index_update(properties, 0, &handle, sizeof(zval *), NULL); \ - object_and_properties_init(z, &COM_class_entry, properties); \ +#define ZVAL_COM(z,o) { \ + rpc_internal *intern; \ + Z_TYPE_P(z) = IS_OBJECT; \ + (z)->value.obj = rpc_objects_new(com_class_entry TSRMLS_CC); \ + if (GET_INTERNAL_EX(intern, (z)) != SUCCESS) { \ + /* TODO: exception */ \ + } \ + intern->data = (o); \ } #define RETVAL_COM(o) ZVAL_COM(&return_value, o); -#define RETURN_COM(o) RETVAL_COM(o) \ +#define RETURN_COM(o) RETVAL_COM(o) \ return; -#define ALLOC_COM(z) (z) = (comval *) ecalloc(1, sizeof(comval)); \ - C_REFCOUNT(z) = 0; +#define ALLOC_COM(z) (z) = (comval *) ecalloc(1, sizeof(comval)); \ + C_CODEPAGE(z) = CP_ACP; -#define FREE_COM(z) php_COM_destruct(z TSRMLS_CC); +#define FREE_COM(z) php_COM_destruct(z); -#define IS_COM php_COM_get_le_comval() +#define C_CODEPAGE(x) ((x)->codepage) #define C_HASTLIB(x) ((x)->typelib) #define C_HASENUM(x) ((x)->enumeration) -#define C_REFCOUNT(x) ((x)->refcount) -#define C_ISREFD(x) C_REFCOUNT(x) - -#define C_ADDREF(x) (++((x)->refcount)) -#define C_RELEASE(x) (--((x)->refcount)) #define C_DISPATCH(x) ((x)->i.dispatch) #define C_TYPEINFO(x) ((x)->i.typeinfo) diff --git a/ext/rpc/com/conversion.c b/ext/rpc/com/conversion.c index 189a578f53..fc03784d7a 100644 --- a/ext/rpc/com/conversion.c +++ b/ext/rpc/com/conversion.c @@ -32,19 +32,25 @@ #ifdef PHP_WIN32 #include "php.h" -#include "php_COM.h" -#include "php_VARIANT.h" + +#include "../rpc.h" +#include "../handler.h" + +#include "com.h" +#include "com_wrapper.h" +#include "conversion.h" +#include "variant.h" /* prototypes */ -static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC); +static int comval_to_variant(zval *zval_arg, VARIANT *var_arg); /* implementations */ -PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC) +PHPAPI void php_zval_to_variant(zval *zval_arg, VARIANT *var_arg, int codepage) { int type = VT_EMPTY; /* default variant type */ - switch (Z_TYPE_P(pval_arg)) { + switch (Z_TYPE_P(zval_arg)) { case IS_NULL: type = VT_NULL; break; @@ -54,7 +60,7 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T break; case IS_OBJECT: - if (!strcmp(Z_OBJCE_P(pval_arg)->name, "VARIANT")) { + if (!strcmp(Z_OBJCE_P(zval_arg)->name, "VARIANT")) { type = VT_VARIANT|VT_BYREF; } else { type = VT_DISPATCH; @@ -84,19 +90,13 @@ PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage T break; } - php_pval_to_variant_ex2(pval_arg, var_arg, type, codepage TSRMLS_CC); + php_zval_to_variant_ex(zval_arg, var_arg, type, codepage); } -PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC) +PHPAPI void php_zval_to_variant_ex(zval *zval_arg, VARIANT *var_arg, int type, int codepage) { - php_pval_to_variant_ex2(pval_arg, var_arg, Z_LVAL_P(pval_type), codepage TSRMLS_CC); -} - - -PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, int codepage TSRMLS_DC) -{ - OLECHAR *unicode_str; + OLECHAR *unicode_str = NULL; VariantInit(var_arg); V_VT(var_arg) = type; @@ -104,7 +104,7 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, if (V_VT(var_arg) & VT_ARRAY) { /* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the output data type */ - HashTable *ht = Z_ARRVAL(*pval_arg); + HashTable *ht = Z_ARRVAL(*zval_arg); int numberOfElements = zend_hash_num_elements(ht); SAFEARRAY *safeArray; SAFEARRAYBOUND bounds[1]; @@ -115,7 +115,7 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, if (V_VT(var_arg) == (VT_ARRAY|VT_BYREF)) { /* == is intended, because VT_*|VT_BYREF|VT_ARRAY means something diffrent */ type &= ~VT_BYREF; - ALLOC_VARIANT(V_VARIANTREF(var_arg)); + V_VARIANTREF(var_arg) = (VARIANT *) emalloc(sizeof(VARIANT)); var_arg = V_VARIANTREF(var_arg); /* put the array in that VARIANT */ } @@ -125,7 +125,7 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, if (NULL == safeArray) { php_error( E_WARNING,"Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)"); - ZVAL_FALSE(pval_arg); + ZVAL_FALSE(zval_arg); } else { V_ARRAY(var_arg) = safeArray; V_VT(var_arg) = VT_ARRAY|VT_VARIANT; /* Now have a valid safe array allocated */ @@ -138,9 +138,9 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, /* Add another value to the safe array */ if (SUCCEEDED(SafeArrayPtrOfIndex( safeArray, &i, &v))) { /* Pointer to output element entry retrieved successfully */ if (type) { /* explicit type */ - php_pval_to_variant_ex2(*entry, v, type, codepage TSRMLS_CC); /* Do the required conversion */ + php_zval_to_variant_ex(*entry, v, type, codepage); /* Do the required conversion */ } else { - php_pval_to_variant(*entry, v, codepage TSRMLS_CC); /* Do the required conversion */ + php_zval_to_variant(*entry, v, codepage); /* Do the required conversion */ } } else { php_error( E_WARNING,"phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i); @@ -158,37 +158,37 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, case VT_NULL: case VT_VOID: - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); break; case VT_UI1: - convert_to_long_ex(&pval_arg); - V_UI1(var_arg) = (unsigned char) Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_UI1(var_arg) = (unsigned char) Z_LVAL_P(zval_arg); break; case VT_I2: - convert_to_long_ex(&pval_arg); - V_I2(var_arg) = (short) Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_I2(var_arg) = (short) Z_LVAL_P(zval_arg); break; case VT_I4: - convert_to_long_ex(&pval_arg); - V_I4(var_arg) = Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_I4(var_arg) = Z_LVAL_P(zval_arg); break; case VT_R4: - convert_to_double_ex(&pval_arg); - V_R4(var_arg) = (float) Z_DVAL_P(pval_arg); + convert_to_double_ex(&zval_arg); + V_R4(var_arg) = (float) Z_DVAL_P(zval_arg); break; case VT_R8: - convert_to_double_ex(&pval_arg); - V_R8(var_arg) = Z_DVAL_P(pval_arg); + convert_to_double_ex(&zval_arg); + V_R8(var_arg) = Z_DVAL_P(zval_arg); break; case VT_BOOL: - convert_to_boolean_ex(&pval_arg); - if (Z_LVAL_P(pval_arg)) { + convert_to_boolean_ex(&zval_arg); + if (Z_LVAL_P(zval_arg)) { V_BOOL(var_arg) = VT_TRUE; } else { V_BOOL(var_arg) = VT_FALSE; @@ -196,23 +196,23 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, break; case VT_ERROR: - convert_to_long_ex(&pval_arg); - V_ERROR(var_arg) = Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_ERROR(var_arg) = Z_LVAL_P(zval_arg); break; case VT_CY: - convert_to_double_ex(&pval_arg); - VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg)); + convert_to_double_ex(&zval_arg); + VarCyFromR8(Z_DVAL_P(zval_arg), &V_CY(var_arg)); break; case VT_DATE: { SYSTEMTIME wintime; struct tm *phptime; - switch (Z_TYPE_P(pval_arg)) { + switch (Z_TYPE_P(zval_arg)) { case IS_DOUBLE: /* already a VariantTime value */ - V_DATE(var_arg) = Z_DVAL_P(pval_arg); + V_DATE(var_arg) = Z_DVAL_P(zval_arg); break; /** @todo @@ -222,8 +222,8 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, default: /* a PHP time value ? */ - convert_to_long_ex(&pval_arg); - phptime = gmtime(&(Z_LVAL_P(pval_arg))); + convert_to_long_ex(&zval_arg); + phptime = gmtime(&(Z_LVAL_P(zval_arg))); memset(&wintime, 0, sizeof(wintime)); wintime.wYear = phptime->tm_year + 1900; @@ -240,39 +240,36 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, break; case VT_BSTR: - convert_to_string_ex(&pval_arg); - unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); - V_BSTR(var_arg) = SysAllocStringByteLen((char *) unicode_str, Z_STRLEN_P(pval_arg) * sizeof(OLECHAR)); - efree(unicode_str); + convert_to_string_ex(&zval_arg); + unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(zval_arg), Z_STRLEN_P(zval_arg), codepage, FALSE); + V_BSTR(var_arg) = SysAllocStringByteLen((char *) unicode_str, Z_STRLEN_P(zval_arg) * sizeof(OLECHAR)); break; case VT_DECIMAL: - convert_to_string_ex(&pval_arg); - unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); + convert_to_string_ex(&zval_arg); + unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(zval_arg), Z_STRLEN_P(zval_arg), codepage, FALSE); VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg)); break; case VT_DECIMAL|VT_BYREF: - convert_to_string_ex(&pval_arg); - unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); + convert_to_string_ex(&zval_arg); + unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(zval_arg), Z_STRLEN_P(zval_arg), codepage, FALSE); VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg)); break; case VT_UNKNOWN: - comval_to_variant(pval_arg, var_arg TSRMLS_CC); - if (V_VT(var_arg) != VT_DISPATCH) { - VariantInit(var_arg); - } else { + if (comval_to_variant(zval_arg, var_arg) == SUCCESS) { V_VT(var_arg) = VT_UNKNOWN; V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg); } break; case VT_DISPATCH: - if (!strcmp(Z_OBJCE_P(pval_arg)->name, "COM")) { - comval_to_variant(pval_arg, var_arg TSRMLS_CC); + if (Z_OBJCE_P(zval_arg) == com_class_entry) { + comval_to_variant(zval_arg, var_arg); } else { - V_DISPATCH(var_arg) = php_COM_export_object(pval_arg TSRMLS_CC); + V_DISPATCH(var_arg) = php_COM_export_object(zval_arg); + if (V_DISPATCH(var_arg)) { V_VT(var_arg) = VT_DISPATCH; } @@ -283,35 +280,35 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, break; case VT_UI1|VT_BYREF: - convert_to_long(pval_arg); - V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(zval_arg); break; case VT_I2|VT_BYREF: - convert_to_long(pval_arg); - V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(zval_arg); break; case VT_I4|VT_BYREF: - convert_to_long(pval_arg); - V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(zval_arg); break; case VT_R4|VT_BYREF: - convert_to_double(pval_arg); - V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg); + convert_to_double(zval_arg); + V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(zval_arg); break; case VT_R8|VT_BYREF: - convert_to_double(pval_arg); - V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg); + convert_to_double(zval_arg); + V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(zval_arg); break; case VT_BOOL|VT_BYREF: - convert_to_boolean(pval_arg); + convert_to_boolean(zval_arg); /* emalloc or malloc ? */ V_BOOLREF(var_arg) = (short FAR*) pemalloc(sizeof(short), 1); - if (Z_LVAL_P(pval_arg)) { + if (Z_LVAL_P(zval_arg)) { *V_BOOLREF(var_arg) = VT_TRUE; } else { *V_BOOLREF(var_arg) = VT_TRUE; @@ -319,20 +316,20 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, break; case VT_ERROR|VT_BYREF: - convert_to_long(pval_arg); - V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(zval_arg); break; case VT_CY|VT_BYREF: - convert_to_double_ex(&pval_arg); - VarCyFromR8(Z_DVAL_P(pval_arg), var_arg->pcyVal); + convert_to_double_ex(&zval_arg); + VarCyFromR8(Z_DVAL_P(zval_arg), var_arg->pcyVal); break; case VT_DATE|VT_BYREF: { SYSTEMTIME wintime; struct tm *phptime; - phptime = gmtime(&(Z_LVAL_P(pval_arg))); + phptime = gmtime(&(Z_LVAL_P(zval_arg))); memset(&wintime, 0, sizeof(wintime)); wintime.wYear = phptime->tm_year + 1900; @@ -347,28 +344,21 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, break; case VT_BSTR|VT_BYREF: - convert_to_string(pval_arg); + convert_to_string(zval_arg); V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*)); - unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); + unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(zval_arg), Z_STRLEN_P(zval_arg), codepage, FALSE); *V_BSTRREF(var_arg) = SysAllocString(unicode_str); - efree(unicode_str); break; case VT_UNKNOWN|VT_BYREF: - comval_to_variant(pval_arg, var_arg TSRMLS_CC); - if (V_VT(var_arg) != VT_DISPATCH) { - VariantInit(var_arg); - } else { + if (comval_to_variant(zval_arg, var_arg) == SUCCESS) { V_VT(var_arg) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(var_arg) = (IUnknown **) &V_DISPATCH(var_arg); } break; case VT_DISPATCH|VT_BYREF: - comval_to_variant(pval_arg, var_arg TSRMLS_CC); - if (V_VT(var_arg) != VT_DISPATCH) { - VariantInit(var_arg); - } else { + if (comval_to_variant(zval_arg, var_arg) == SUCCESS) { V_VT(var_arg) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(var_arg) = &V_DISPATCH(var_arg); } @@ -378,93 +368,85 @@ PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, php_error(E_WARNING,"VT_VARIANT is invalid. Use VT_VARIANT|VT_BYREF instead."); /* break missing intentionally */ case VT_VARIANT|VT_BYREF: { - int tp; - pval **var_handle; - - /* fetch the VARIANT structure */ - zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &var_handle); + variantval *var; + TSRMLS_FETCH(); - V_VT(var_arg) = VT_VARIANT|VT_BYREF; - V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &tp); - - if (!V_VARIANTREF(var_arg) && (tp != IS_VARIANT)) { - VariantInit(var_arg); + if ((var = zend_object_store_get_object(zval_arg TSRMLS_CC)) == NULL) { + /* TODO exception */ } - } - /* - should be, but isn't :) - if (V_VT(var_arg) != (VT_VARIANT|VT_BYREF)) { - VariantInit(var_arg); + V_VARIANTREF(var_arg) = var->var; } - */ break; case VT_I1: - convert_to_long_ex(&pval_arg); - V_I1(var_arg) = (char)Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_I1(var_arg) = (char)Z_LVAL_P(zval_arg); break; case VT_UI2: - convert_to_long_ex(&pval_arg); - V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_UI2(var_arg) = (unsigned short)Z_LVAL_P(zval_arg); break; case VT_UI4: - convert_to_long_ex(&pval_arg); - V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_UI4(var_arg) = (unsigned long)Z_LVAL_P(zval_arg); break; case VT_INT: - convert_to_long_ex(&pval_arg); - V_INT(var_arg) = (int)Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_INT(var_arg) = (int)Z_LVAL_P(zval_arg); break; case VT_UINT: - convert_to_long_ex(&pval_arg); - V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg); + convert_to_long_ex(&zval_arg); + V_UINT(var_arg) = (unsigned int)Z_LVAL_P(zval_arg); break; case VT_I1|VT_BYREF: - convert_to_long(pval_arg); - V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(zval_arg); break; case VT_UI2|VT_BYREF: - convert_to_long(pval_arg); - V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(zval_arg); break; case VT_UI4|VT_BYREF: - convert_to_long(pval_arg); - V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(zval_arg); break; case VT_INT|VT_BYREF: - convert_to_long(pval_arg); - V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(zval_arg); break; case VT_UINT|VT_BYREF: - convert_to_long(pval_arg); - V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg); + convert_to_long(zval_arg); + V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(zval_arg); break; default: php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg)); } + + if (unicode_str != NULL) { + efree(unicode_str); + } } } - -PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TSRMLS_DC) +PHPAPI int php_variant_to_zval(VARIANT *var_arg, zval *zval_arg, int codepage) { /* Changed the function to return a value for recursive error testing */ /* Existing calls will be unaffected by the change - so it */ /* seemed like the smallest impact on unfamiliar code */ int ret = SUCCESS; - INIT_PZVAL(pval_arg); + INIT_PZVAL(zval_arg); /* Add SafeArray support */ if (V_ISARRAY(var_arg)) { @@ -475,14 +457,14 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS register int ii; UINT Dims; VARIANT vv; - pval *element; + zval *element; HRESULT hr; /* TODO: Add support for multi-dimensional SafeArrays */ /* For now just validate that the SafeArray has one dimension */ if (1 != (Dims = SafeArrayGetDim(array))) { php_error(E_WARNING,"Unsupported: multi-dimensional (%d) SafeArrays", Dims); - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); return FAILURE; } SafeArrayLock(array); @@ -501,7 +483,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS /* Since COM returned an array we set up the php */ /* return value to be an array */ - array_init(pval_arg); + array_init(zval_arg); /* Walk the safe array */ for (ii=lbound;ii<=ubound;ii++) { @@ -527,7 +509,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS /* If SafeArrayGetElement proclaims to allocate */ /* memory for a BSTR, so the recursive call frees */ /* the string correctly */ - if (FAILURE == php_variant_to_pval(&vv, element, codepage TSRMLS_CC)) { + if (FAILURE == php_variant_to_zval(&vv, element, codepage)) { /* Error occurred setting up array element */ /* Error was displayed by the recursive call */ FREE_ZVAL(element); @@ -541,52 +523,52 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS /* break; */ } else { /* Just insert the element into our return array */ - add_index_zval(pval_arg, ii, element); + add_index_zval(zval_arg, ii, element); } } SafeArrayUnlock(array); } else switch (var_arg->vt & ~VT_BYREF) { case VT_EMPTY: - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); break; case VT_UI1: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_UI1REF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_UI1REF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_UI1(var_arg)); + ZVAL_LONG(zval_arg, (long)V_UI1(var_arg)); } break; case VT_I2: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long )*V_I2REF(var_arg)); + ZVAL_LONG(zval_arg, (long )*V_I2REF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_I2(var_arg)); + ZVAL_LONG(zval_arg, (long)V_I2(var_arg)); } break; case VT_I4: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, *V_I4REF(var_arg)); + ZVAL_LONG(zval_arg, *V_I4REF(var_arg)); } else { - ZVAL_LONG(pval_arg, V_I4(var_arg)); + ZVAL_LONG(zval_arg, V_I4(var_arg)); } break; case VT_R4: if (V_ISBYREF(var_arg)) { - ZVAL_DOUBLE(pval_arg, (double)*V_R4REF(var_arg)); + ZVAL_DOUBLE(zval_arg, (double)*V_R4REF(var_arg)); } else { - ZVAL_DOUBLE(pval_arg, (double)V_R4(var_arg)); + ZVAL_DOUBLE(zval_arg, (double)V_R4(var_arg)); } break; case VT_R8: if (V_ISBYREF(var_arg)) { - ZVAL_DOUBLE(pval_arg, *V_R8REF(var_arg)); + ZVAL_DOUBLE(zval_arg, *V_R8REF(var_arg)); } else { - ZVAL_DOUBLE(pval_arg, V_R8(var_arg)); + ZVAL_DOUBLE(zval_arg, V_R8(var_arg)); } break; @@ -595,12 +577,12 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS OLECHAR *unicode_str; switch (VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str)) { case S_OK: - Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); - Z_TYPE_P(pval_arg) = IS_STRING; + Z_STRVAL_P(zval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(zval_arg), codepage, FALSE); + Z_TYPE_P(zval_arg) = IS_STRING; break; default: - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); ret = FAILURE; php_error(E_WARNING, "Error converting DECIMAL value to PHP string"); break; @@ -611,53 +593,53 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS /* Currency */ case VT_CY: if (V_ISBYREF(var_arg)) { - VarR8FromCy(*V_CYREF(var_arg), &Z_DVAL_P(pval_arg)); + VarR8FromCy(*V_CYREF(var_arg), &Z_DVAL_P(zval_arg)); } else { - VarR8FromCy(V_CY(var_arg), &Z_DVAL_P(pval_arg)); + VarR8FromCy(V_CY(var_arg), &Z_DVAL_P(zval_arg)); } - Z_TYPE_P(pval_arg) = IS_DOUBLE; + Z_TYPE_P(zval_arg) = IS_DOUBLE; break; case VT_BOOL: if (V_ISBYREF(var_arg)) { if (*V_BOOLREF(var_arg)) { - ZVAL_BOOL(pval_arg, Z_TRUE); + ZVAL_BOOL(zval_arg, Z_TRUE); } else { - ZVAL_BOOL(pval_arg, Z_FALSE); + ZVAL_BOOL(zval_arg, Z_FALSE); } } else { if (V_BOOL(var_arg)) { - ZVAL_BOOL(pval_arg, Z_TRUE); + ZVAL_BOOL(zval_arg, Z_TRUE); } else { - ZVAL_BOOL(pval_arg, Z_FALSE); + ZVAL_BOOL(zval_arg, Z_FALSE); } } break; case VT_NULL: case VT_VOID: - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); break; case VT_VARIANT: - php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, codepage TSRMLS_CC); + php_variant_to_zval(V_VARIANTREF(var_arg), zval_arg, codepage); break; case VT_BSTR: - Z_TYPE_P(pval_arg) = IS_STRING; + Z_TYPE_P(zval_arg) = IS_STRING; if (V_ISBYREF(var_arg)) { if (*V_BSTR(var_arg)) { - Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); + Z_STRVAL_P(zval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(zval_arg), codepage, FALSE); } else { - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); } efree(V_BSTRREF(var_arg)); } else { if (V_BSTR(var_arg)) { - Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC); + Z_STRVAL_P(zval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(zval_arg), codepage, FALSE); } else { - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); } } @@ -686,7 +668,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS phptime.tm_isdst = -1; tzset(); - ZVAL_LONG(pval_arg, mktime(&phptime)); + ZVAL_LONG(zval_arg, mktime(&phptime)); } else { ret = FAILURE; } @@ -704,7 +686,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS if (FAILED(hr)) { char *error_message; - error_message = php_COM_error_message(hr TSRMLS_CC); + error_message = php_COM_error_message(hr); php_error(E_WARNING,"Unable to obtain IDispatch interface: %s", error_message); LocalFree(error_message); @@ -714,63 +696,64 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS /* break missing intentionaly */ case VT_DISPATCH: { comval *obj; + TSRMLS_FETCH(); if (V_DISPATCH(var_arg) == NULL) { ret = FAILURE; - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); } else { ALLOC_COM(obj); - php_COM_set(obj, &V_DISPATCH(var_arg), FALSE TSRMLS_CC); + php_COM_set(obj, &V_DISPATCH(var_arg), FALSE); - ZVAL_COM(pval_arg, obj); - VariantInit(var_arg); // to protect C_DISPATCH(obj) from being freed when var_result is destructed + ZVAL_COM(zval_arg, obj); + VariantInit(var_arg); /* to protect C_DISPATCH(obj) from being freed when var_result is destructed */ } } break; case VT_I1: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_I1REF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_I1REF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_I1(var_arg)); + ZVAL_LONG(zval_arg, (long)V_I1(var_arg)); } break; case VT_UI2: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_UI2REF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_UI2REF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_UI2(var_arg)); + ZVAL_LONG(zval_arg, (long)V_UI2(var_arg)); } break; case VT_UI4: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_UI4REF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_UI4(var_arg)); + ZVAL_LONG(zval_arg, (long)V_UI4(var_arg)); } break; case VT_INT: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_INTREF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_INTREF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_INT(var_arg)); + ZVAL_LONG(zval_arg, (long)V_INT(var_arg)); } break; case VT_UINT: if (V_ISBYREF(var_arg)) { - ZVAL_LONG(pval_arg, (long)*V_UINTREF(var_arg)); + ZVAL_LONG(zval_arg, (long)*V_UINTREF(var_arg)); } else { - ZVAL_LONG(pval_arg, (long)V_UINT(var_arg)); + ZVAL_LONG(zval_arg, (long)V_UINT(var_arg)); } break; default: php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg)); - ZVAL_NULL(pval_arg); + ZVAL_NULL(zval_arg); ret = FAILURE; break; } @@ -778,7 +761,7 @@ PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TS } -PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC) +PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage, int persist) { BOOL error = FALSE; OLECHAR *unicode_str; @@ -792,13 +775,13 @@ PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRML } if (strlen >= 0) { - unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR) * strlen); + unicode_str = (OLECHAR *) pemalloc(sizeof(OLECHAR) * strlen, persist); /* convert string */ error = !MultiByteToWideChar(codepage, (codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS), C_str, strlen, unicode_str, strlen); } else { /* return a zero-length string */ - unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR)); + unicode_str = (OLECHAR *) pemalloc(sizeof(OLECHAR), persist); *unicode_str = 0; error = TRUE; @@ -821,7 +804,7 @@ PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRML } -PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage TSRMLS_DC) +PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage, int persist) { char *C_str; uint length = 0; @@ -830,12 +813,12 @@ PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int cod uint reqSize = WideCharToMultiByte(codepage, codepage == CP_UTF8 ? 0 : WC_COMPOSITECHECK, unicode_str, -1, NULL, 0, NULL, NULL); if (reqSize) { - C_str = (char *) emalloc(sizeof(char) * reqSize); + C_str = (char *) pemalloc(sizeof(char) * reqSize, persist); /* convert string */ length = WideCharToMultiByte(codepage, codepage == CP_UTF8 ? 0 : WC_COMPOSITECHECK, unicode_str, -1, C_str, reqSize, NULL, NULL) - 1; } else { - C_str = (char *) emalloc(sizeof(char)); + C_str = (char *) pemalloc(sizeof(char), persist); *C_str = 0; php_error(E_WARNING,"Error in php_OLECHAR_to_char()"); @@ -848,21 +831,21 @@ PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int cod return C_str; } - -static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC) +static int comval_to_variant(zval *object, VARIANT *var_arg) { - pval **comval_handle; - comval *obj; - int type; - - /* fetch the comval structure */ - zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &comval_handle); - obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type); - if (!obj || (type != IS_COM) || !C_ISREFD(obj)) { + rpc_internal *intern; + TSRMLS_FETCH(); + + if (GET_INTERNAL_EX(intern, object) != SUCCESS) { + /* TODO exception */ VariantInit(var_arg); + + return FAILURE; } else { V_VT(var_arg) = VT_DISPATCH; - V_DISPATCH(var_arg) = C_DISPATCH(obj); + V_DISPATCH(var_arg) = C_DISPATCH((comval *) intern->data); + + return SUCCESS; } } diff --git a/ext/rpc/com/conversion.h b/ext/rpc/com/conversion.h index b8c534fa22..3f243eb607 100644 --- a/ext/rpc/com/conversion.h +++ b/ext/rpc/com/conversion.h @@ -1,3 +1,22 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + | Alan Brown | + +----------------------------------------------------------------------+ + */ + #ifndef CONVERSION_H #define CONVERSION_H @@ -11,12 +30,12 @@ BEGIN_EXTERN_C() -PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC); -PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC); -PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, int type, int codepage TSRMLS_DC); -PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TSRMLS_DC); -PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC); -PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage TSRMLS_DC); +ZEND_API void php_zval_to_variant(zval *zval_arg, VARIANT *var_arg, int codepage); +ZEND_API void php_zval_to_variant_ex(zval *zval_arg, VARIANT *var_arg, int type, int codepage); +ZEND_API int php_variant_to_zval(VARIANT *var_arg, zval *zval_arg, int codepage); + +ZEND_API OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage, int persist); +ZEND_API char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage, int persist); END_EXTERN_C() diff --git a/ext/rpc/com/dispatch.c b/ext/rpc/com/dispatch.c index 23c3b0dd91..1a9b28b357 100644 --- a/ext/rpc/com/dispatch.c +++ b/ext/rpc/com/dispatch.c @@ -23,9 +23,11 @@ * them as objects implementing IDispatch. * */ +#include "../rpc.h" + #include "php.h" -#include "php_COM.h" -#include "php_VARIANT.h" +#include "com.h" +#include "com_wrapper.h" #include "conversion.h" #include "variant.h" @@ -177,7 +179,7 @@ static HRESULT STDMETHODCALLTYPE disp_getidsofnames( unsigned int namelen; zval **tmp; - name = php_OLECHAR_to_char(rgszNames[i], &namelen, CP_ACP TSRMLS_CC); + name = php_OLECHAR_to_char(rgszNames[i], &namelen, CP_ACP, FALSE); /* Lookup the name in the hash */ if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == FAILURE) { @@ -223,7 +225,7 @@ static HRESULT STDMETHODCALLTYPE disp_getdispid( TSRMLS_FETCH(); FETCH_DISP("GetDispID"); - name = php_OLECHAR_to_char(bstrName, &namelen, CP_ACP TSRMLS_CC); + name = php_OLECHAR_to_char(bstrName, &namelen, CP_ACP, FALSE); /* Lookup the name in the hash */ if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) { @@ -275,13 +277,13 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex( if (V_VT(arg) == VT_DISPATCH) { trace("arg %d is dispatchable\n", i); - if (NULL == php_COM_object_from_dispatch(V_DISPATCH(arg), zarg TSRMLS_CC)) { + if ((zarg = php_COM_object_from_dispatch(V_DISPATCH(arg))) == NULL) { trace("failed to convert arg %d to zval\n", i); ZVAL_NULL(zarg); } } else { - // arg can't be an idispatch, so we don't care for the implicit AddRef() call here - if (FAILURE == php_variant_to_pval(arg, zarg, codepage TSRMLS_CC)) { + /* arg can't be an idispatch, so we don't care for the implicit AddRef() call here */ + if (FAILURE == php_variant_to_zval(arg, zarg, codepage)) { trace("failed to convert arg %d to zval\n", i); ZVAL_NULL(zarg); } @@ -322,9 +324,9 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex( /* export the object using a dispatch like ourselves */ VariantInit(pvarRes); V_VT(pvarRes) = VT_DISPATCH; - V_DISPATCH(pvarRes) = php_COM_export_object(retval TSRMLS_CC); + V_DISPATCH(pvarRes) = php_COM_export_object(retval); } else { - php_pval_to_variant(retval, pvarRes, codepage TSRMLS_CC); + php_zval_to_variant(retval, pvarRes, codepage); } } zval_ptr_dtor(&retval); @@ -379,7 +381,7 @@ static HRESULT STDMETHODCALLTYPE disp_getmembername( FETCH_DISP("GetMemberName"); if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) { - OLECHAR *olestr = php_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP TSRMLS_CC); + OLECHAR *olestr = php_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP, FALSE); *pbstrName = SysAllocString(olestr); efree(olestr); return S_OK; @@ -511,7 +513,7 @@ static void generate_dispids(php_dispatchex *disp TSRMLS_DC) } } -static php_dispatchex *disp_constructor(zval *object TSRMLS_DC) +static php_dispatchex *disp_constructor(zval *object) { php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex)); @@ -559,9 +561,9 @@ static void disp_destructor(php_dispatchex *disp) CoTaskMemFree(disp); } -PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC) +PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name) { - php_dispatchex *disp = disp_constructor(val TSRMLS_CC); + php_dispatchex *disp = disp_constructor(val); HashPosition pos; char *name = NULL; zval *tmp, **ntmp; @@ -596,31 +598,32 @@ PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_ return (IDispatch*)disp; } -PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC) +PHPAPI IDispatch *php_COM_export_object(zval *val) { php_dispatchex *disp = NULL; + TSRMLS_FETCH(); if (Z_TYPE_P(val) != IS_OBJECT) return NULL; - if (Z_OBJCE_P(val) == &COM_class_entry || !strcmp(Z_OBJCE_P(val)->name, "COM")) { + if (Z_OBJCE_P(val) == com_class_entry) { /* pass back it's IDispatch directly */ - zval **tmp; comval *obj; - int type; - - zend_hash_index_find(Z_OBJPROP_P(val), 0, (void**)&tmp); - obj = (comval *)zend_list_find(Z_LVAL_PP(tmp), &type); - if (type != IS_COM) - return NULL; + rpc_internal *intern; + + if (GET_INTERNAL_EX(intern, val) != SUCCESS) { + /* TODO: exception */ + } + + obj = (comval *) intern->data; C_DISPATCH(obj)->lpVtbl->AddRef(C_DISPATCH(obj)); return C_DISPATCH(obj); } - disp = disp_constructor(val TSRMLS_CC); + disp = disp_constructor(val); generate_dispids(disp TSRMLS_CC); - + return (IDispatch*)disp; } diff --git a/ext/rpc/com/php_com.h b/ext/rpc/com/php_com.h deleted file mode 100644 index d26441f6a3..0000000000 --- a/ext/rpc/com/php_com.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef PHP_COM_H -#define PHP_COM_H - -#if PHP_WIN32 - -#include "com.h" - -BEGIN_EXTERN_C() - -PHP_MINIT_FUNCTION(COM); -PHP_MSHUTDOWN_FUNCTION(COM); - -PHP_FUNCTION(com_load); -PHP_FUNCTION(com_invoke); -PHP_FUNCTION(com_addref); -PHP_FUNCTION(com_release); -PHP_FUNCTION(com_propget); -PHP_FUNCTION(com_propput); -PHP_FUNCTION(com_load_typelib); -PHP_FUNCTION(com_isenum); -PHP_FUNCTION(com_event_sink); -PHP_FUNCTION(com_message_pump); -PHP_FUNCTION(com_print_typeinfo); - -PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC); -PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC); -PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC); -PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC); -PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC); -PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* pDisp, int cleanup TSRMLS_DC); -PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC); -PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC); -PHPAPI int php_COM_get_le_comval(); -PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value); -PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference); -PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference); -PHPAPI zval *php_COM_object_from_dispatch(IDispatch *disp, zval *val TSRMLS_DC); -PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC); - -/* dispatch.c */ -PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC); -PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC); -int php_COM_dispatch_init(int module_number TSRMLS_DC); - -zend_module_entry COM_module_entry; -zend_class_entry COM_class_entry; - -#ifdef DEBUG - extern int resourcecounter; -#endif - -END_EXTERN_C() - -#define phpext_com_ptr &COM_module_entry - -ZEND_BEGIN_MODULE_GLOBALS(com) - int nothing; -ZEND_END_MODULE_GLOBALS(com) - -PHPAPI ZEND_EXTERN_MODULE_GLOBALS(com); - -#ifdef ZTS -#define COMG(v) TSRMG(com_globals_id, zend_com_globals *, v) -#else -#define COMG(v) (com_globals.v) -#endif - -#else - -#define phpext_com_ptr NULL - -#endif /* PHP_WIN32 */ - -#endif /* PHP_COM_H */ diff --git a/ext/rpc/com/php_variant.h b/ext/rpc/com/php_variant.h deleted file mode 100644 index 54347461c8..0000000000 --- a/ext/rpc/com/php_variant.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PHP_TYPEDEF_VARIANT_H -#define PHP_TYPEDEF_VARIANT_H - -#if PHP_WIN32 - -BEGIN_EXTERN_C() - -#include "conversion.h" -#include "variant.h" - -void php_VARIANT_init(int module_number TSRMLS_DC); - -PHPAPI int php_VARIANT_get_le_variant(); - -END_EXTERN_C() - -#endif /* PHP_WIN32 */ - -#endif /* PHP_TYPEDEF_VARIANT_H */ diff --git a/ext/rpc/com/variant.c b/ext/rpc/com/variant.c index e06dd23e9e..a827cde602 100644 --- a/ext/rpc/com/variant.c +++ b/ext/rpc/com/variant.c @@ -13,6 +13,7 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Harald Radi | + | Alan Brown | +----------------------------------------------------------------------+ */ @@ -29,25 +30,52 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" -#include "php_VARIANT.h" +#include "conversion.h" +#include "variant.h" #include -static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC); -static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value); -static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference); -static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference); -static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC); -static void php_register_VARIANT_class(TSRMLS_D); - -static int le_variant; -static int codepage; -static zend_class_entry VARIANT_class_entry; - - -void php_VARIANT_init(int module_number TSRMLS_DC) +static zend_object_value variant_objects_new(zend_class_entry * TSRMLS_DC); +static void variant_objects_delete(void *, zend_object_handle TSRMLS_DC); + +/* object handler */ +static zval* variant_read(zval *, zval *, int TSRMLS_DC); +static void variant_write(zval *, zval *, zval * TSRMLS_DC); +static union _zend_function* variant_get_constructor(zval * TSRMLS_DC); +static zend_class_entry* variant_get_class_entry(zval * TSRMLS_DC); +/**/ + +static HashTable types; +static zend_class_entry *variant_class_entry; +static zend_function *variant_ctor; +static zend_object_handlers variant_handlers = { + ZEND_OBJECTS_STORE_HANDLERS, + + variant_read, + variant_write, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + variant_get_constructor, + variant_get_class_entry, + NULL, + NULL +}; + +/**/ +void php_variant_init(int module_number TSRMLS_DC) { - le_variant = zend_register_list_destructors_ex(php_VARIANT_destructor, NULL, "VARIANT", module_number); + zend_internal_function *zif; + zend_class_entry ce; + int type; /* variant datatypes */ REGISTER_LONG_CONSTANT("VT_NULL", VT_NULL, CONST_CS | CONST_PERSISTENT); @@ -84,259 +112,211 @@ void php_VARIANT_init(int module_number TSRMLS_DC) #ifdef CP_SYMBOL REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT); #else -# error "CP_SYMBOL undefined" +#error "CP_SYMBOL undefined" #endif #ifdef CP_THREAD_ACP REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT); #else -# error "CP_THREAD_ACP undefined" +#error "CP_THREAD_ACP undefined" #endif - php_register_VARIANT_class(TSRMLS_C); + INIT_CLASS_ENTRY(ce, "variant", NULL); + ce.create_object = variant_objects_new; + variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC); + + zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); + + zif->type = ZEND_INTERNAL_FUNCTION; + zif->function_name = variant_class_entry->name; + zif->scope = variant_class_entry; + zif->arg_types = NULL; + zif->handler = ZEND_FN(variant_load); + + /* add new constructor to the method table */ + zend_hash_add(&(variant_class_entry->function_table), variant_class_entry->name, + variant_class_entry->name_length + 1, zif, sizeof(zend_function), &variant_ctor); + efree(zif); + + zend_hash_init(&types, 0, NULL, NULL, TRUE); + + type = VT_UI1; + zend_hash_add(&types, "bVal", 5, (void *) &type, sizeof(int), NULL); + type = VT_UI2; + zend_hash_add(&types, "uiVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_UI4; + zend_hash_add(&types, "ulVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_UINT; + zend_hash_add(&types, "uintVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_I1; + zend_hash_add(&types, "cVal", 5, (void *) &type, sizeof(int), NULL); + type = VT_I2; + zend_hash_add(&types, "iVal", 5, (void *) &type, sizeof(int), NULL); + type = VT_I4; + zend_hash_add(&types, "lVal", 5, (void *) &type, sizeof(int), NULL); + type = VT_INT; + zend_hash_add(&types, "intVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_R4; + zend_hash_add(&types, "fltVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_R8; + zend_hash_add(&types, "dblVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_BOOL; + zend_hash_add(&types, "boolVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_ERROR; + zend_hash_add(&types, "scode", 6, (void *) &type, sizeof(int), NULL); + type = VT_CY; + zend_hash_add(&types, "cyVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_DATE; + zend_hash_add(&types, "date", 5, (void *) &type, sizeof(int), NULL); + type = VT_BSTR; + zend_hash_add(&types, "bstrVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_UNKNOWN; + zend_hash_add(&types, "punkVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_DISPATCH; + zend_hash_add(&types, "pdispVal", 9, (void *) &type, sizeof(int), NULL); + type = VT_ARRAY; + zend_hash_add(&types, "parray", 7, (void *) &type, sizeof(int), NULL); + type = VT_BYREF; + zend_hash_add(&types, "byref", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_UI1; + zend_hash_add(&types, "pbVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_UI2; + zend_hash_add(&types, "puiVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_UI4; + zend_hash_add(&types, "pulVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_UINT; + zend_hash_add(&types, "puintVal", 9, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_I1; + zend_hash_add(&types, "pcVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_I2; + zend_hash_add(&types, "piVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_I4; + zend_hash_add(&types, "plVal", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_INT; + zend_hash_add(&types, "pintVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_R4; + zend_hash_add(&types, "pfltVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_R8; + zend_hash_add(&types, "pdblVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_BOOL; + zend_hash_add(&types, "pboolVal", 9, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_ERROR; + zend_hash_add(&types, "pscode", 7, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_CY; + zend_hash_add(&types, "pcyVal", 7, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_DATE; + zend_hash_add(&types, "pdate", 6, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_BSTR; + zend_hash_add(&types, "pbstrVal", 9, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_DECIMAL; + zend_hash_add(&types, "pdecVal", 8, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_UNKNOWN; + zend_hash_add(&types, "ppunkVal", 9, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_DISPATCH; + zend_hash_add(&types, "ppdispVal", 10, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_ARRAY; + zend_hash_add(&types, "pparray", 8, (void *) &type, sizeof(int), NULL); + type = VT_BYREF|VT_VARIANT; + zend_hash_add(&types, "pvarVal", 8, (void *) &type, sizeof(int), NULL); } - -PHPAPI int php_VARIANT_get_le_variant() +void php_variant_shutdown(TSRMLS_D) { - return le_variant; + zend_hash_destroy(&types); } - -static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) +static zend_object_value variant_objects_new(zend_class_entry *ce TSRMLS_DC) { - pval *object = property_reference->object; - zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data; - VARIANT *pVar; - - if ((zend_llist_count(property_reference->elements_list)==1) && !strcmp(Z_STRVAL(function_name->element), "variant")) { - /* constructor */ - pval *object_handle, *data, *type, *code_page; - - ALLOC_VARIANT(pVar); - VariantInit(pVar); - - switch (ZEND_NUM_ARGS()) { - case 0: - /* nothing to do */ - break; - case 1: - zend_get_parameters(ht, 1, &data); - php_pval_to_variant(data, pVar, codepage TSRMLS_CC); - codepage = CP_ACP; - break; - case 2: - zend_get_parameters(ht, 2, &data, &type); - php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC); - codepage = CP_ACP; - break; - case 3: - zend_get_parameters(ht, 3, &data, &type, &code_page); - php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC); - convert_to_long(code_page); - codepage = Z_LVAL_P(code_page); - break; - default: - ZEND_WRONG_PARAM_COUNT(); - break; - } + zend_object_value *zov; + variantval *var; - RETVAL_LONG(zend_list_insert(pVar, IS_VARIANT)); - - if (!zend_is_true(return_value)) { - ZVAL_FALSE(object); - return; - } + ALLOC_VARIANT(var); + + /* set up the object value struct */ + zov = (zend_object_value*) emalloc(sizeof(zend_object_value)); + zov->handlers = &variant_handlers; + zov->handle = zend_objects_store_put(var, variant_objects_delete, NULL TSRMLS_CC); - ALLOC_ZVAL(object_handle); - *object_handle = *return_value; - pval_copy_constructor(object_handle); - INIT_PZVAL(object_handle); - zend_hash_index_update(Z_OBJPROP_P(object), 0, &object_handle, sizeof(pval *), NULL); - zval_dtor(&function_name->element); - } + return *zov; } +static void variant_objects_delete(void *object, zend_object_handle handle TSRMLS_DC) +{ + FREE_VARIANT((variantval *)object); +} -static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference) +static zval* variant_read(zval *object, zval *member, int type TSRMLS_DC) { - zend_overloaded_element *overloaded_property; - int type; - pval result, **var_handle, *object = property_reference->object; - VARIANT *var_arg; - TSRMLS_FETCH(); + variantval *var; + zval *result; + ALLOC_ZVAL(result); - /* fetch the VARIANT structure */ - zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle); - var_arg = zend_list_find(Z_LVAL_PP(var_handle), &type); + if ((var = zend_object_store_get_object(object TSRMLS_CC)) == NULL) { + /* exception */ + } - if (!var_arg || (type != IS_VARIANT)) { - ZVAL_FALSE(&result); + if (!strcmp(Z_STRVAL_P(member), "value")) { + /* var_arg can't be an idispatch, so we don't care for the implicit AddRef() call here */ + php_variant_to_zval(var->var, result, var->codepage); + } else if (!strcmp(Z_STRVAL_P(member), "type")) { + ZVAL_LONG(result, V_VT(var->var)); } else { - overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data; - switch (Z_TYPE_P(overloaded_property)) { - case OE_IS_ARRAY: - ZVAL_FALSE(&result); - break; - - case OE_IS_OBJECT: - if (!strcmp(Z_STRVAL(overloaded_property->element), "value")) { - // var_arg can't be an idispatch, so we don't care for the implicit AddRef() call here - php_variant_to_pval(var_arg, &result, codepage TSRMLS_CC); - } else if (!strcmp(Z_STRVAL(overloaded_property->element), "type")) { - ZVAL_LONG(&result, V_VT(var_arg)) - } else { - ZVAL_FALSE(&result); - php_error(E_WARNING, "Unknown member."); - } - break; - case OE_IS_METHOD: - ZVAL_FALSE(&result); - php_error(E_WARNING, "Unknown method."); - break; - - zval_dtor(&overloaded_property->element); - } + ZVAL_FALSE(result); + php_error(E_WARNING, "Unknown member."); } return result; } - -static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value) +static void variant_write(zval *object, zval *member, zval *value TSRMLS_DC) { - zend_overloaded_element *overloaded_property; - int type; - pval **var_handle, *object = property_reference->object; - VARIANT *var_arg; - TSRMLS_FETCH(); + int *type; + variantval *var; - - /* fetch the VARIANT structure */ - zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle); - var_arg = zend_list_find(Z_LVAL_PP(var_handle), &type); - - if (!var_arg || (type != IS_VARIANT)) { - return FAILURE; + if ((var = zend_object_store_get_object(object TSRMLS_CC)) == NULL) { + /* exception */ } - overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data; - do_VARIANT_propset(var_arg, &overloaded_property->element, value TSRMLS_CC); - zval_dtor(&overloaded_property->element); - return SUCCESS; -} - - -static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC) -{ - int type; - - if (!strcmp(Z_STRVAL_P(arg_property), "value")) { - php_pval_to_variant(value, var_arg, codepage TSRMLS_CC); - - return SUCCESS; - } else if (!strcmp(Z_STRVAL_P(arg_property), "bVal")) { - type = VT_UI1; - } else if (!strcmp(Z_STRVAL_P(arg_property), "iVal")) { - type = VT_I2; - } else if (!strcmp(Z_STRVAL_P(arg_property), "lVal")) { - type = VT_I4; - } else if (!strcmp(Z_STRVAL_P(arg_property), "fltVal")) { - type = VT_R4; - } else if (!strcmp(Z_STRVAL_P(arg_property), "dblVal")) { - type = VT_R8; - } else if (!strcmp(Z_STRVAL_P(arg_property), "boolVal")) { - type = VT_BOOL; - } else if (!strcmp(Z_STRVAL_P(arg_property), "scode")) { - type = VT_ERROR; - } else if (!strcmp(Z_STRVAL_P(arg_property), "cyVal")) { - type = VT_CY; - } else if (!strcmp(Z_STRVAL_P(arg_property), "date")) { - type = VT_DATE; - } else if (!strcmp(Z_STRVAL_P(arg_property), "bstrVal")) { - type = VT_BSTR; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pdecVal")) { - type = VT_DECIMAL|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "punkVal")) { - type = VT_UNKNOWN; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pdispVal")) { - type = VT_DISPATCH; - } else if (!strcmp(Z_STRVAL_P(arg_property), "parray")) { - type = VT_ARRAY; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pbVal")) { - type = VT_UI1|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "piVal")) { - type = VT_I2|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "plVal")) { - type = VT_I4|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pfltVal")) { - type = VT_R4|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pdblVal")) { - type = VT_R8|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pboolVal")) { - type = VT_BOOL|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pscode")) { - type = VT_ERROR|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pcyVal")) { - type = VT_CY|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pdate")) { - type = VT_DATE|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pbstrVal")) { - type = VT_BSTR|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "ppunkVal")) { - type = VT_UNKNOWN|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "ppdispVal")) { - type = VT_DISPATCH|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pparray")) { - type = VT_ARRAY|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pvarVal")) { - type = VT_VARIANT|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "byref")) { - type = VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "cVal")) { - type = VT_I1; - } else if (!strcmp(Z_STRVAL_P(arg_property), "uiVal")) { - type = VT_UI2; - } else if (!strcmp(Z_STRVAL_P(arg_property), "ulVal")) { - type = VT_UI4; - } else if (!strcmp(Z_STRVAL_P(arg_property), "intVal")) { - type = VT_INT; - } else if (!strcmp(Z_STRVAL_P(arg_property), "uintVal")) { - type = VT_UINT|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pcVal")) { - type = VT_I1|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "puiVal")) { - type = VT_UI2|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pulVal")) { - type = VT_UI4|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "pintVal")) { - type = VT_INT|VT_BYREF; - } else if (!strcmp(Z_STRVAL_P(arg_property), "puintVal")) { - type = VT_UINT|VT_BYREF; + if (!strcmp(Z_STRVAL_P(member), "value")) { + php_zval_to_variant(value, var->var, var->codepage); + } else if (zend_hash_find(&types, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **) &type) == SUCCESS) { + php_zval_to_variant_ex(value, var->var, *type, var->codepage); } else { php_error(E_WARNING, "Unknown member."); - return FAILURE; } - - php_pval_to_variant_ex2(value, var_arg, type, codepage TSRMLS_CC); - - return SUCCESS; } +static union _zend_function* variant_get_constructor(zval *object TSRMLS_DC) +{ + return variant_ctor; +} -static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC) +static zend_class_entry* variant_get_class_entry(zval *object TSRMLS_DC) { - FREE_VARIANT(rsrc->ptr); + return variant_class_entry; } -static void php_register_VARIANT_class(TSRMLS_D) +/**/ +/* constructor */ +ZEND_FUNCTION(variant_load) { - INIT_OVERLOADED_CLASS_ENTRY(VARIANT_class_entry, "VARIANT", NULL, - php_VARIANT_call_function_handler, - php_VARIANT_get_property_handler, - php_VARIANT_set_property_handler); + zval *value = NULL, *object = getThis(); + variantval *var; + long type = 0; + + if (!object || ((var = zend_object_store_get_object(object TSRMLS_CC)) == NULL)) { + /*TODO exception */ + } + + zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|zll", &value, &type, &(var->codepage)); - zend_register_internal_class(&VARIANT_class_entry TSRMLS_CC); + if (value) { + if (type) { + php_zval_to_variant_ex(value, var->var, type, var->codepage); + } else { + php_zval_to_variant(value, var->var, var->codepage); + } + } } #endif /* PHP_WIN32 */ diff --git a/ext/rpc/com/variant.h b/ext/rpc/com/variant.h index 31ea342d66..96b18b5fac 100644 --- a/ext/rpc/com/variant.h +++ b/ext/rpc/com/variant.h @@ -1,31 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + + #ifndef VARIANT_H #define VARIANT_H #if PHP_WIN32 -#define ALLOC_VARIANT(v) (v) = (VARIANT *) emalloc(sizeof(VARIANT)); \ - VariantInit(v); +#define ALLOC_VARIANT(v) (v) = (variantval *) emalloc(sizeof(variantval)); \ + (v)->var = (VARIANT *) emalloc(sizeof(VARIANT)); \ + (v)->codepage = CP_ACP; \ + VariantInit((v)->var); -#define FREE_VARIANT(v) VariantClear(v); \ - efree(v); +#define FREE_VARIANT(v) VariantClear((v)->var); \ + efree((v)->var); \ + efree((v)); +#define ZVAL_VARIANT(z, v, cp) \ + if (V_VT(v) == VT_DISPATCH) { \ + rpc_internal *intern; \ + comval *obj; \ + ALLOC_COM(obj); \ + Z_TYPE_P(z) = IS_OBJECT; \ + (z)->value.obj = rpc_objects_new(com_class_entry TSRMLS_CC); \ + if (GET_INTERNAL_EX(intern, (z)) != SUCCESS) { \ + /* TODO: exception */ \ + } \ + php_COM_set(obj, &V_DISPATCH(v), TRUE); \ + intern->data = obj; \ + } else { \ + php_variant_to_zval((v), (z), cp); \ + VariantClear(v); \ + efree(v); \ + } -#define IS_VARIANT php_VARIANT_get_le_variant() +#define RETVAL_VARIANT(v, cp) ZVAL_VARIANT(return_value, v, cp) +#define RETURN_VARIANT(v, cp) RETVAL_VARIANT(v, cp) \ + return; -#define ZVAL_VARIANT(z, v) if (V_VT(v) == VT_DISPATCH) { \ - comval *obj; \ - ALLOC_COM(obj); \ - php_COM_set(obj, &V_DISPATCH(v), TRUE TSRMLS_CC); \ - ZVAL_RESOURCE((z), zend_list_insert(obj, IS_COM)); \ - } else { \ - php_variant_to_pval((v), (z), codepage TSRMLS_CC); \ - FREE_VARIANT(v); \ - } +typedef struct variantval_ { + VARIANT* var; + long codepage; +} variantval; -#define RETVAL_VARIANT(v) ZVAL_VARIANT(return_value, (v)); -#define RETURN_VARIANT(v) RETVAL_VARIANT(v) \ - return; +void php_variant_init(int module_number TSRMLS_DC); +void php_variant_shutdown(TSRMLS_D); +ZEND_FUNCTION(variant_load); #endif /* PHP_WIN32 */ diff --git a/ext/rpc/handler.h b/ext/rpc/handler.h index e28c9b69e6..70dfb61bee 100644 --- a/ext/rpc/handler.h +++ b/ext/rpc/handler.h @@ -1,23 +1,44 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef HANDLER_H #define HANDLER_H #include "php.h" #include "php_ini.h" -#define RPC_HANDLER(layer) {#layer, layer##_handler_init, &layer##_object_handlers, \ - &layer##_class_entry, layer##_function_entry, \ - layer##_method_entry, layer##_ini_entry} - -#define RPC_DECLARE_HANDLER(layer) void layer##_handler_init(); \ - rpc_object_handlers layer##_object_handlers; \ - zend_class_entry layer##_class_entry; \ - function_entry layer##_function_entry[]; \ - function_entry layer##_method_entry[]; \ +#define RPC_HANDLER(layer) {#layer, layer##_handler_init, layer##_handler_shutdown, \ + &layer##_object_handlers, &layer##_class_entry, \ + layer##_function_entry, layer##_method_entry, \ + layer##_ini_entry} + +#define RPC_DECLARE_HANDLER(layer) void layer##_handler_init(int module_number TSRMLS_DC); \ + void layer##_handler_shutdown(TSRMLS_D); \ + rpc_object_handlers layer##_object_handlers; \ + zend_class_entry *layer##_class_entry; \ + function_entry layer##_function_entry[]; \ + function_entry layer##_method_entry[]; \ zend_ini_entry layer##_ini_entry[]; -#define RPC_INIT_FUNCTION(layer) void layer##_handler_init() +#define RPC_INIT_FUNCTION(layer) void layer##_handler_init(int module_number TSRMLS_DC) +#define RPC_SHUTDOWN_FUNCTION(layer) void layer##_handler_shutdown(TSRMLS_D) -#define RPC_REGISTER_HANDLERS_START(layer) zend_class_entry layer##_class_entry; \ +#define RPC_REGISTER_HANDLERS_START(layer) zend_class_entry *layer##_class_entry; \ rpc_object_handlers layer##_object_handlers = { #define RPC_REGISTER_HANDLERS_END() }; @@ -65,11 +86,12 @@ typedef struct _rpc_string { typedef struct _rpc_object_handlers { const zend_bool poolable; const zend_uint hash_type; - int (*rpc_hash)(rpc_string name, rpc_string *hash, int num_args, char *arg_types, int type); - int (*rpc_name)(rpc_string hash, rpc_string *name, int type); + int (*rpc_hash)(rpc_string name, rpc_string *hash, void *data, int num_args, char *arg_types, int type); + int (*rpc_name)(rpc_string hash, rpc_string *name, void *data, int type); int (*rpc_ctor)(rpc_string class_name, void **data, int num_args, zval **args[]); - int (*rpc_dtor)(void **data); - int (*rpc_call)(rpc_string method_name, void **data, zval **return_value, int num_args, zval **args[]); + int (*rpc_dtor)(void *data); + int (*rpc_describe)(rpc_string method_name, void *data, char **arg_types); + int (*rpc_call)(rpc_string method_name, void **data, zval *return_value, int num_args, zval **args[]); int (*rpc_get)(rpc_string property_name, zval *return_value, void **data); int (*rpc_set)(rpc_string property_name, zval *value, void **data); int (*rpc_compare)(void **data1, void **data2); @@ -82,8 +104,9 @@ typedef struct _rpc_object_handlers { typedef struct _rpc_handler_entry { char *name; void (*rpc_handler_init)(); + void (*rpc_handler_shutdown)(); rpc_object_handlers *handlers; - zend_class_entry *ce; + zend_class_entry **ce; function_entry *functions; function_entry *methods; zend_ini_entry *ini; diff --git a/ext/rpc/hash.h b/ext/rpc/hash.h new file mode 100644 index 0000000000..d2f558df5b --- /dev/null +++ b/ext/rpc/hash.h @@ -0,0 +1,74 @@ +#ifndef HASH_H +#define HASH_H + +static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData); + +static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData) +{ + uint nIndex; + uint h = nKeyLength; + uint result; + void **ppData; + Bucket *p; + + tsrm_mutex_lock(ht->mx_writer); + + if (arKey) { + result = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, (void **) &ppData); + } else { + result = zend_hash_index_find(TS_HASH(ht), h, (void **) &ppData); + } + + if (result == SUCCESS) { + *pData = *ppData; + + if (arKey) { + h = zend_inline_hash_func(arKey, nKeyLength); + } + + nIndex = h & TS_HASH(ht)->nTableMask; + + p = TS_HASH(ht)->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */ + ((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) { + HANDLE_BLOCK_INTERRUPTIONS(); + if (p == TS_HASH(ht)->arBuckets[nIndex]) { + TS_HASH(ht)->arBuckets[nIndex] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + TS_HASH(ht)->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + TS_HASH(ht)->pListTail = p->pListLast; + } + if (TS_HASH(ht)->pInternalPointer == p) { + TS_HASH(ht)->pInternalPointer = p->pListNext; + } + if (!p->pDataPtr) { + pefree(p->pData, TS_HASH(ht)->persistent); + } + pefree(p, TS_HASH(ht)->persistent); + HANDLE_UNBLOCK_INTERRUPTIONS(); + TS_HASH(ht)->nNumOfElements--; + return SUCCESS; + } + p = p->pNext; + } + } + tsrm_mutex_unlock(ht->mx_writer); + + return FAILURE; +} + +#endif /* HASH_H */ diff --git a/ext/rpc/layer.h b/ext/rpc/layer.h index 0d77ae28a3..ec08f7dfd4 100644 --- a/ext/rpc/layer.h +++ b/ext/rpc/layer.h @@ -1,9 +1,26 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef LAYER_H #define LAYER_H #include "handler.h" - -RPC_DECLARE_HANDLER(com); +#include "com/com.h" rpc_handler_entry handler_entries[] = { RPC_HANDLER(com) diff --git a/ext/rpc/php_rpc.h b/ext/rpc/php_rpc.h index 165f3e07ac..2b12b57e46 100644 --- a/ext/rpc/php_rpc.h +++ b/ext/rpc/php_rpc.h @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef PHP_RPC_H #define PHP_RPC_H @@ -6,12 +24,6 @@ extern zend_module_entry rpc_module_entry; #define phpext_rpc_ptr &rpc_module_entry -#ifdef PHP_WIN32 -#define PHP_RPC_API __declspec(dllexport) -#else -#define PHP_RPC_API -#endif - #ifdef ZTS #include "TSRM.h" #endif @@ -29,6 +41,9 @@ ZEND_FUNCTION(rpc_get); ZEND_FUNCTION(rpc_singleton); ZEND_FUNCTION(rpc_poolable); +ZEND_API void rpc_error(int type, const char *format, ...); +ZEND_API zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC); + #define phpext_rpc_ptr &rpc_module_entry #endif /* PHP_RPC_H */ \ No newline at end of file diff --git a/ext/rpc/rpc.c b/ext/rpc/rpc.c index eb49110feb..8ed2f2bd77 100644 --- a/ext/rpc/rpc.c +++ b/ext/rpc/rpc.c @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -9,15 +27,13 @@ #include "php_rpc.h" #include "rpc.h" #include "layer.h" +#include "hash.h" static void rpc_instance_dtor(void *); static void rpc_class_dtor(void *); static void rpc_string_dtor(void *); -static zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC); -static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC); - -static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData); +static void rpc_objects_delete(void *, zend_object_handle TSRMLS_DC); /* object handler */ static zval* rpc_read(zval *, zval *, int TSRMLS_DC); @@ -30,7 +46,7 @@ static void rpc_unset_property(zval *, zval * TSRMLS_DC); static HashTable* rpc_get_properties(zval * TSRMLS_DC); static union _zend_function* rpc_get_method(zval *, char *, int TSRMLS_DC); static union _zend_function* rpc_get_constructor(zval * TSRMLS_DC); -static zend_class_entry* rpc_get_class_entry(zval *object TSRMLS_DC); +static zend_class_entry* rpc_get_class_entry(zval * TSRMLS_DC); static int rpc_compare(zval *, zval * TSRMLS_DC); /**/ @@ -88,6 +104,7 @@ zend_module_entry rpc_module_entry = { zend_class_entry rpc_class_entry; +static zend_function *rpc_ctor; static HashTable *handlers; static TsHashTable *pool; static TsHashTable *classes; @@ -104,6 +121,7 @@ ZEND_INI_END() */ ZEND_MINIT_FUNCTION(rpc) { + zend_internal_function *zif; zend_class_entry *rpc_entry; /* rpc base class entry */ @@ -121,24 +139,39 @@ ZEND_MINIT_FUNCTION(rpc) zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE); FOREACH_HANDLER { - HANDLER.rpc_handler_init(); + zend_class_entry ce; + + HANDLER.rpc_handler_init(module_number TSRMLS_CC); /* create a class entry for every rpc handler */ - INIT_CLASS_ENTRY((*(HANDLER.ce)), - HANDLER.name, - HANDLER.methods); + INIT_CLASS_ENTRY(ce, + HANDLER.name, + HANDLER.methods); - HANDLER.ce->create_object = rpc_objects_new; + ce.create_object = rpc_objects_new; /* load all available rpc handler into a hash */ zend_hash_add(handlers, HANDLER.name, strlen(HANDLER.name) + 1, &(HANDLER.handlers), sizeof(rpc_object_handlers *), NULL); /* register classes and functions */ - zend_register_internal_class_ex(HANDLER.ce, rpc_entry, NULL TSRMLS_CC); + *HANDLER.ce = zend_register_internal_class_ex(&ce, rpc_entry, NULL TSRMLS_CC); zend_register_functions(HANDLER.functions, NULL, MODULE_PERSISTENT TSRMLS_CC); zend_register_ini_entries(HANDLER.ini, module_number TSRMLS_CC); } + + zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); + + zif->type = ZEND_INTERNAL_FUNCTION; + zif->function_name = rpc_entry->name; + zif->scope = rpc_entry; + zif->arg_types = NULL; + zif->handler = ZEND_FN(rpc_load); + + /* add new constructor to the method table */ + zend_hash_add(&(rpc_entry->function_table), rpc_entry->name, rpc_entry->name_length + 1, zif, sizeof(zend_function), &rpc_ctor); + efree(zif); + REGISTER_INI_ENTRIES(); return SUCCESS; @@ -149,6 +182,10 @@ ZEND_MINIT_FUNCTION(rpc) */ ZEND_MSHUTDOWN_FUNCTION(rpc) { + FOREACH_HANDLER { + HANDLER.rpc_handler_shutdown(TSRMLS_C); + } + /* destroy instances first */ zend_ts_hash_destroy(pool); @@ -214,35 +251,6 @@ static void rpc_instance_dtor(void *pDest) pefree(*intern, TRUE); } -static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC) -{ - zend_object_value *zov; - rpc_internal *intern; - - /* set up the object value struct */ - zov = (zend_object_value*) pemalloc(sizeof(zend_object_value), TRUE); - zov->handlers = &rpc_handlers; - - /* set up the internal representation of our rpc instance */ - intern = (rpc_internal *) pemalloc(sizeof(rpc_internal), TRUE); - - intern->ce = class_type; - intern->data = NULL; - intern->function_table.hash = intern->ce->function_table; - intern->function_table.reader = 0; - intern->function_table.mx_reader = tsrm_mutex_alloc(); - intern->function_table.mx_writer = tsrm_mutex_alloc(); - intern->mx_handler = tsrm_mutex_alloc(); - - if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) != SUCCESS) { - /* TODO: exception */ - } - - zov->handle = zend_objects_store_put(intern, rpc_objects_delete, NULL TSRMLS_CC); - - return *zov; -} - static zend_object_value rpc_create_proxy(TSRMLS_D) { zend_object_value *zov; @@ -283,7 +291,9 @@ static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC zend_ts_hash_index_update(pool, RPC_CLASS(intern)->name.len + 1, &intern, sizeof(rpc_internal *), NULL); } } else { - RPC_HT(intern)->rpc_dtor(intern->data); + if (intern->data != NULL) { + RPC_HT(intern)->rpc_dtor(intern->data); + } pefree(intern, TRUE); } } @@ -351,7 +361,6 @@ static void rpc_set(zval **property, zval *value TSRMLS_DC) static int rpc_has_property(zval *object, zval *member, int check_empty TSRMLS_DC) { // GET_INTERNAL(intern); - /* FIXME */ return FAILURE; } @@ -365,7 +374,6 @@ static void rpc_unset_property(zval *object, zval *member TSRMLS_DC) static HashTable* rpc_get_properties(zval *object TSRMLS_DC) { // GET_INTERNAL(intern); - /* FIXME */ return NULL; } @@ -378,11 +386,22 @@ static union _zend_function* rpc_get_method(zval *object, char *method, int meth if (zend_ts_hash_find(&(intern->function_table), method, method_len + 1, &function) != SUCCESS) { zend_internal_function *zif; + /* get reftypes */ + if (RPC_HT(intern)->rpc_describe) { + char *arg_types; + rpc_string method_name; + + method_name.str = method; + method_name.len = method_len; + + RPC_HT(intern)->rpc_describe(method_name, intern->data, &arg_types); + } + zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); zif->arg_types = NULL; zif->function_name = method; zif->handler = ZEND_FN(rpc_call); - zif->scope = NULL; + zif->scope = intern->ce; zif->type = ZEND_INTERNAL_FUNCTION; /* add new method to the method table */ @@ -395,25 +414,6 @@ static union _zend_function* rpc_get_method(zval *object, char *method, int meth static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC) { - zend_function *rpc_ctor; - GET_INTERNAL(intern); - - if (zend_ts_hash_find(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, &rpc_ctor) != SUCCESS) { - zend_internal_function *zif; - - zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); - - zif->type = ZEND_INTERNAL_FUNCTION; - zif->function_name = intern->ce->name; - zif->scope = intern->ce; - zif->arg_types = NULL; - zif->handler = ZEND_FN(rpc_load); - - /* add new constructor to the method table */ - zend_ts_hash_add(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, zif, sizeof(zend_function), &rpc_ctor); - efree(zif); - } - return rpc_ctor; } @@ -484,7 +484,9 @@ ZEND_FUNCTION(rpc_load) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "s", &class_val.str, &class_val.len) != SUCCESS) { /* none of the two possibilities */ /* TODO: exception */ - php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); + rpc_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); + ZVAL_NULL(object); + return; } else { /* hash classname if hashing function exists */ if (RPC_HT(intern)->rpc_hash) { @@ -492,7 +494,7 @@ ZEND_FUNCTION(rpc_load) GET_SIGNATURE(intern, class_val.str, class_val.len, hash_val, num_args, arg_types); /* check if already hashed */ - if (zend_ts_hash_find(classes, hash_val.str, hash_val.len + 1, (void **) &class_hash_find) != SUCCESS) { + if (zend_ts_hash_find(classes, hash_val.str, hash_val.len + 1, (void **) &class_hash_find) != SUCCESS) { class_hash = pemalloc(sizeof(rpc_class_hash), TRUE); /* set up the cache */ @@ -504,12 +506,14 @@ ZEND_FUNCTION(rpc_load) class_hash->data = NULL; /* do hashing */ - if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), num_args, arg_types, CLASS) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), NULL, num_args, arg_types, CLASS) != SUCCESS) { /* TODO: exception */ + ZVAL_NULL(object); + return; } /* overload class entry */ - RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS); + RPC_HT(intern)->rpc_name(class_val, &class_val, NULL, CLASS); INIT_CLASS_ENTRY(overloaded_class_entry, NULL, NULL); overloaded_class_entry.name = class_val.str; overloaded_class_entry.name_length = class_val.len; @@ -561,7 +565,7 @@ ZEND_FUNCTION(rpc_load) zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE); /* overload class entry */ - RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS); + RPC_HT(intern)->rpc_name(class_val, &class_val, NULL, CLASS); INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); intern->ce = class_hash->ce; @@ -606,6 +610,7 @@ ZEND_FUNCTION(rpc_load) if (retval != SUCCESS) { /* TODO: exception */ + RETURN_NULL(); } } @@ -628,7 +633,7 @@ ZEND_FUNCTION(rpc_call) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Os", &object, *ce, &hash, &hash_len) != SUCCESS) { /* none of the two possibilities */ /* TODO: exception */ - php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); + rpc_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); } } @@ -660,8 +665,9 @@ ZEND_FUNCTION(rpc_call) /* check if already hashed */ if (zend_ts_hash_find(&(intern->hash->methods), hash_val.str, hash_val.len + 1, (void **) &method_hash_find) != SUCCESS) { - if (RPC_HT(intern)->rpc_hash(*method_hash, method_hash, num_args, arg_types, METHOD) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(*method_hash, method_hash, intern->data, num_args, arg_types, METHOD) != SUCCESS) { /* TODO: exception */ + RETURN_NULL(); } /* register with non-hashed key */ @@ -680,7 +686,7 @@ ZEND_FUNCTION(rpc_call) * and srm it is better to do concurrency checks */ tsrm_mutex_lock(intern->mx_handler); - retval = RPC_HT(intern)->rpc_call(*method_hash, &(intern->data), &return_value, num_args, args); + retval = RPC_HT(intern)->rpc_call(*method_hash, &(intern->data), return_value, num_args, args); tsrm_mutex_unlock(intern->mx_handler); } @@ -704,7 +710,7 @@ ZEND_FUNCTION(rpc_set) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 3 TSRMLS_CC, "Osz", &object, *ce, &property, &property_len, &value) != SUCCESS) { /* none of the two possibilities */ /* TODO: exception */ - php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); + rpc_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); } } @@ -729,7 +735,7 @@ ZEND_FUNCTION(rpc_get) if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Os", &object, *ce, &property, &property_len) != SUCCESS) { /* none of the two possibilities */ /* TODO: exception */ - php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); + rpc_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); } } @@ -778,6 +784,44 @@ ZEND_FUNCTION(rpc_poolable) } } +ZEND_API void rpc_error(int type, const char *format, ...) +{ + va_list args; + + va_start(args, format); + zend_error(type, format, args); + va_end(args); +} + +ZEND_API zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value *zov; + rpc_internal *intern; + + /* set up the object value struct */ + zov = (zend_object_value*) pemalloc(sizeof(zend_object_value), TRUE); + zov->handlers = &rpc_handlers; + + /* set up the internal representation of our rpc instance */ + intern = (rpc_internal *) pemalloc(sizeof(rpc_internal), TRUE); + + intern->ce = class_type; + intern->data = NULL; + intern->function_table.hash = intern->ce->function_table; + intern->function_table.reader = 0; + intern->function_table.mx_reader = tsrm_mutex_alloc(); + intern->function_table.mx_writer = tsrm_mutex_alloc(); + intern->mx_handler = tsrm_mutex_alloc(); + + if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) != SUCCESS) { + /* TODO: exception */ + } + + zov->handle = zend_objects_store_put(intern, rpc_objects_delete, NULL TSRMLS_CC); + + return *zov; +} + /*******************/ static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint property_len, zval *return_value) @@ -799,8 +843,9 @@ static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint pro } else if(property) { /* check if already hashed */ if (zend_ts_hash_find(&(intern->hash->properties), property, property_len + 1, (void **) &property_hash_find) != SUCCESS) { - if (RPC_HT(intern)->rpc_hash(*property_hash, property_hash, 0, NULL, PROPERTY) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(*property_hash, property_hash, intern->data, 0, NULL, PROPERTY) != SUCCESS) { /* TODO: exception */ + RETURN_NULL(); } /* register with non-hashed key */ @@ -839,78 +884,6 @@ static void rpc_internal_set(rpc_internal *intern, char *property, zend_uint pro } } -/***********************************/ - -static int zend_ts_hash_remove_key_or_index(TsHashTable *ht, char *arKey, uint nKeyLength, void **pData) -{ - uint nIndex; - uint h = nKeyLength; - uint result; - void **ppData; - Bucket *p; - - tsrm_mutex_lock(ht->mx_writer); - - if (arKey) { - result = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, (void **) &ppData); - } else { - result = zend_hash_index_find(TS_HASH(ht), h, (void **) &ppData); - } - - if (result == SUCCESS) { - *pData = *ppData; - - if (arKey) { - h = zend_inline_hash_func(arKey, nKeyLength); - } - - nIndex = h & TS_HASH(ht)->nTableMask; - - p = TS_HASH(ht)->arBuckets[nIndex]; - while (p != NULL) { - if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */ - ((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) { - HANDLE_BLOCK_INTERRUPTIONS(); - if (p == TS_HASH(ht)->arBuckets[nIndex]) { - TS_HASH(ht)->arBuckets[nIndex] = p->pNext; - } else { - p->pLast->pNext = p->pNext; - } - if (p->pNext) { - p->pNext->pLast = p->pLast; - } - if (p->pListLast != NULL) { - p->pListLast->pListNext = p->pListNext; - } else { - /* Deleting the head of the list */ - TS_HASH(ht)->pListHead = p->pListNext; - } - if (p->pListNext != NULL) { - p->pListNext->pListLast = p->pListLast; - } else { - TS_HASH(ht)->pListTail = p->pListLast; - } - if (TS_HASH(ht)->pInternalPointer == p) { - TS_HASH(ht)->pInternalPointer = p->pListNext; - } - if (!p->pDataPtr) { - pefree(p->pData, TS_HASH(ht)->persistent); - } - pefree(p, TS_HASH(ht)->persistent); - HANDLE_UNBLOCK_INTERRUPTIONS(); - TS_HASH(ht)->nNumOfElements--; - return SUCCESS; - } - p = p->pNext; - } - } - tsrm_mutex_unlock(ht->mx_writer); - - return FAILURE; -} - - - /* * Local variables: diff --git a/ext/rpc/rpc.h b/ext/rpc/rpc.h index 5412544648..538192f6af 100644 --- a/ext/rpc/rpc.h +++ b/ext/rpc/rpc.h @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef RPC_H #define RPC_H diff --git a/ext/rpc/rpc_proxy.c b/ext/rpc/rpc_proxy.c index e36303a3fc..48ea70c5c2 100644 --- a/ext/rpc/rpc_proxy.c +++ b/ext/rpc/rpc_proxy.c @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #include "php.h" #include "rpc_proxy.h" diff --git a/ext/rpc/rpc_proxy.h b/ext/rpc/rpc_proxy.h index 179caa988a..f3f0d01dd3 100644 --- a/ext/rpc/rpc_proxy.h +++ b/ext/rpc/rpc_proxy.h @@ -1,3 +1,21 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2002 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Harald Radi | + +----------------------------------------------------------------------+ + */ + #ifndef RPC_PROXY_H #define RPC_PROXY_H