mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Port other major parts of PHP 4 COM extension into PHP 5 com_dotnet
extension. This enables: - iteration of SafeArray types via foreach() - proxying of multi-dimensional SafeArray types so that multi-dimension array accesses work (untested!) - Fix COM exceptions, and expose them as their own class of exception "com_exception" - auto typelib file import (com.typelib_file ini option) - event sinking - wrapper to map PHP objects to COM - fix mapping of variant values to PHP values # Could someone please add com_saproxy.c and com_wrapper.c to the .dsp # file?
This commit is contained in:
parent
48b96c10d2
commit
e10c206dac
14 changed files with 1957 additions and 159 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -64,7 +64,7 @@ PHP_FUNCTION(com_create_instance)
|
||||||
&module_name, &module_name_len, &server_params, &obj->code_page,
|
&module_name, &module_name_len, &server_params, &obj->code_page,
|
||||||
&typelib_name, &typelib_name_len)) {
|
&typelib_name, &typelib_name_len)) {
|
||||||
|
|
||||||
php_com_throw_exception("Could not create COM object - invalid arguments!" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "Could not create COM object - invalid arguments!" TSRMLS_CC);
|
||||||
ZVAL_NULL(object);
|
ZVAL_NULL(object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,7 @@ PHP_FUNCTION(com_create_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server_name && !COMG(allow_dcom)) {
|
if (server_name && !COMG(allow_dcom)) {
|
||||||
php_com_throw_exception("DCOM has been disabled by your administrator [com.allow_dcom=0]" TSRMLS_CC);
|
php_com_throw_exception(E_ERROR, "DCOM has been disabled by your administrator [com.allow_dcom=0]" TSRMLS_CC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ PHP_FUNCTION(com_create_instance)
|
||||||
spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr);
|
spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr);
|
||||||
LocalFree(werr);
|
LocalFree(werr);
|
||||||
|
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(res, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
ZVAL_NULL(object);
|
ZVAL_NULL(object);
|
||||||
return;
|
return;
|
||||||
|
@ -240,7 +240,7 @@ PHP_FUNCTION(com_create_instance)
|
||||||
/* load up the library from the named file */
|
/* load up the library from the named file */
|
||||||
int cached;
|
int cached;
|
||||||
|
|
||||||
TL = php_com_load_typelib_via_cache(typelib_name, mode, obj->code_page, &cached TSRMLS_CC);
|
TL = php_com_load_typelib_via_cache(typelib_name, obj->code_page, &cached TSRMLS_CC);
|
||||||
|
|
||||||
if (TL) {
|
if (TL) {
|
||||||
if (COMG(autoreg_on) && !cached) {
|
if (COMG(autoreg_on) && !cached) {
|
||||||
|
@ -341,7 +341,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg) {
|
if (msg) {
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(hr, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
|
||||||
winerr = php_win_err(hr);
|
winerr = php_win_err(hr);
|
||||||
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
|
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
|
||||||
LocalFree(winerr);
|
LocalFree(winerr);
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(hr, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -442,6 +442,8 @@ int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
|
||||||
return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args TSRMLS_CC);
|
return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* {{{ proto string com_create_guid()
|
||||||
|
Generate a globally unique identifier (GUID) */
|
||||||
PHP_FUNCTION(com_create_guid)
|
PHP_FUNCTION(com_create_guid)
|
||||||
{
|
{
|
||||||
GUID retval;
|
GUID retval;
|
||||||
|
@ -460,4 +462,169 @@ PHP_FUNCTION(com_create_guid)
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool com_event_sink(object 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;
|
||||||
|
php_com_dotnet_object *obj;
|
||||||
|
ITypeInfo *typeinfo = NULL;
|
||||||
|
|
||||||
|
RETVAL_FALSE;
|
||||||
|
|
||||||
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oo|z/",
|
||||||
|
&object, php_com_variant_class_entry, &sinkobject, &sink)) {
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = CDNO_FETCH(object);
|
||||||
|
|
||||||
|
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 = php_com_locate_typeinfo(typelibname, obj, dispname, 1 TSRMLS_CC);
|
||||||
|
|
||||||
|
if (typeinfo) {
|
||||||
|
HashTable *id_to_name;
|
||||||
|
|
||||||
|
ALLOC_HASHTABLE(id_to_name);
|
||||||
|
|
||||||
|
if (php_com_process_typeinfo(typeinfo, id_to_name, 0, &obj->sink_id, obj->code_page TSRMLS_CC)) {
|
||||||
|
|
||||||
|
/* Create the COM wrapper for this sink */
|
||||||
|
obj->sink_dispatch = php_com_wrapper_export_as_sink(sinkobject, &obj->sink_id, id_to_name TSRMLS_CC);
|
||||||
|
|
||||||
|
/* Now hook it up to the source */
|
||||||
|
php_com_object_enable_event_sink(obj, TRUE TSRMLS_CC);
|
||||||
|
RETVAL_TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
FREE_HASHTABLE(id_to_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeinfo) {
|
||||||
|
ITypeInfo_Release(typeinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool com_print_typeinfo(object 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;
|
||||||
|
php_com_dotnet_object *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) {
|
||||||
|
CDNO_FETCH_VERIFY(obj, arg1);
|
||||||
|
} else {
|
||||||
|
convert_to_string(arg1);
|
||||||
|
typelibname = Z_STRVAL_P(arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeinfo = php_com_locate_typeinfo(typelibname, obj, ifacename, wantsink ? 1 : 0 TSRMLS_CC);
|
||||||
|
if (typeinfo) {
|
||||||
|
php_com_process_typeinfo(typeinfo, NULL, 1, NULL, obj ? obj->code_page : COMG(code_page) TSRMLS_CC);
|
||||||
|
ITypeInfo_Release(typeinfo);
|
||||||
|
RETURN_TRUE;
|
||||||
|
} else {
|
||||||
|
zend_error(E_WARNING, "Unable to find typeinfo using the parameters supplied");
|
||||||
|
}
|
||||||
|
RETURN_FALSE;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitive])
|
||||||
|
Loads a Typelibrary and registers its constants */
|
||||||
|
PHP_FUNCTION(com_load_typelib)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
long namelen;
|
||||||
|
ITypeLib *pTL = NULL;
|
||||||
|
zend_bool cs = TRUE;
|
||||||
|
int codepage = COMG(code_page);
|
||||||
|
int cached = 0;
|
||||||
|
|
||||||
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &name, &namelen, &cs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RETVAL_FALSE;
|
||||||
|
|
||||||
|
pTL = php_com_load_typelib_via_cache(name, codepage, &cached TSRMLS_CC);
|
||||||
|
if (pTL) {
|
||||||
|
if (cached) {
|
||||||
|
RETVAL_TRUE;
|
||||||
|
} else if (php_com_import_typelib(pTL, cs ? CONST_CS : 0, codepage TSRMLS_CC) == SUCCESS) {
|
||||||
|
RETVAL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeLib_Release(pTL);
|
||||||
|
pTL = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* End:
|
||||||
|
* vim600: noet sw=4 ts=4 fdm=marker
|
||||||
|
* vim<600: noet sw=4 ts=4
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -109,7 +109,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||||
|
|
||||||
if (COMG(dotnet_runtime_stuff) == NULL) {
|
if (COMG(dotnet_runtime_stuff) == NULL) {
|
||||||
if (FAILURE == dotnet_init(TSRMLS_C)) {
|
if (FAILURE == dotnet_init(TSRMLS_C)) {
|
||||||
php_com_throw_exception("Failed to initialize .Net runtime" TSRMLS_CC);
|
php_com_throw_exception(E_ERROR, "Failed to initialize .Net runtime" TSRMLS_CC);
|
||||||
ZVAL_NULL(object);
|
ZVAL_NULL(object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||||
&assembly_name, &assembly_name_len,
|
&assembly_name, &assembly_name_len,
|
||||||
&datatype_name, &datatype_name_len,
|
&datatype_name, &datatype_name_len,
|
||||||
&obj->code_page)) {
|
&obj->code_page)) {
|
||||||
php_com_throw_exception("Could not create .Net object - invalid arguments!" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "Could not create .Net object - invalid arguments!" TSRMLS_CC);
|
||||||
ZVAL_NULL(object);
|
ZVAL_NULL(object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||||
VariantClear(&vargs[1]);
|
VariantClear(&vargs[1]);
|
||||||
|
|
||||||
if (ret == FAILURE) {
|
if (ret == FAILURE) {
|
||||||
php_com_throw_exception("Failed to instantiate .Net object" TSRMLS_CC);
|
php_com_throw_exception(hr, "Failed to instantiate .Net object" TSRMLS_CC);
|
||||||
ZVAL_NULL(object);
|
ZVAL_NULL(object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -31,7 +31,10 @@
|
||||||
|
|
||||||
ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
|
ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
|
||||||
TsHashTable php_com_typelibraries;
|
TsHashTable php_com_typelibraries;
|
||||||
zend_class_entry *php_com_variant_class_entry;
|
zend_class_entry
|
||||||
|
*php_com_variant_class_entry,
|
||||||
|
*php_com_exception_class_entry,
|
||||||
|
*php_com_saproxy_class_entry;
|
||||||
|
|
||||||
function_entry com_dotnet_functions[] = {
|
function_entry com_dotnet_functions[] = {
|
||||||
PHP_FE(variant_set, NULL)
|
PHP_FE(variant_set, NULL)
|
||||||
|
@ -60,7 +63,12 @@ function_entry com_dotnet_functions[] = {
|
||||||
PHP_FE(variant_get_type, NULL)
|
PHP_FE(variant_get_type, NULL)
|
||||||
PHP_FE(variant_set_type, NULL)
|
PHP_FE(variant_set_type, NULL)
|
||||||
PHP_FE(variant_cast, NULL)
|
PHP_FE(variant_cast, NULL)
|
||||||
|
/* com_com.c */
|
||||||
PHP_FE(com_create_guid, NULL)
|
PHP_FE(com_create_guid, NULL)
|
||||||
|
PHP_FE(com_event_sink, NULL)
|
||||||
|
PHP_FE(com_print_typeinfo, NULL)
|
||||||
|
PHP_FE(com_message_pump, NULL)
|
||||||
|
PHP_FE(com_load_typelib, NULL)
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,11 +94,77 @@ ZEND_GET_MODULE(com_dotnet)
|
||||||
|
|
||||||
/* {{{ PHP_INI
|
/* {{{ PHP_INI
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* com.typelib_file is the path to a file containing a
|
||||||
|
* list of typelibraries to register *persistently*.
|
||||||
|
* lines starting with ; are comments
|
||||||
|
* append #cis to end of typelib name to cause its constants
|
||||||
|
* to be loaded case insensitively */
|
||||||
|
static PHP_INI_MH(OnTypeLibFileUpdate)
|
||||||
|
{
|
||||||
|
FILE *typelib_file;
|
||||||
|
char *typelib_name_buffer;
|
||||||
|
char *strtok_buf = NULL;
|
||||||
|
int cached;
|
||||||
|
|
||||||
|
if (!new_value || (typelib_file = VCWD_FOPEN(new_value, "r"))==NULL) {
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ((pTL = php_com_load_typelib_via_cache(typelib_name, COMG(code_page), &cached TSRMLS_CC)) != NULL) {
|
||||||
|
if (!cached) {
|
||||||
|
php_com_import_typelib(pTL, mode, COMG(code_page) TSRMLS_CC);
|
||||||
|
}
|
||||||
|
ITypeLib_Release(pTL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
efree(typelib_name_buffer);
|
||||||
|
fclose(typelib_file);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
PHP_INI_BEGIN()
|
PHP_INI_BEGIN()
|
||||||
STD_PHP_INI_ENTRY("com.allow_dcom", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
|
STD_PHP_INI_ENTRY("com.allow_dcom", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
|
||||||
STD_PHP_INI_ENTRY("com.autoregister_verbose", "0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
|
STD_PHP_INI_ENTRY("com.autoregister_verbose", "0", PHP_INI_ALL, OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
|
||||||
STD_PHP_INI_ENTRY("com.autoregister_typelib", "0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
|
STD_PHP_INI_ENTRY("com.autoregister_typelib", "0", PHP_INI_ALL, OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
|
||||||
STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "0", PHP_INI_ALL, OnUpdateBool, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
|
STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "1", PHP_INI_ALL, OnUpdateBool, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
|
||||||
|
STD_PHP_INI_ENTRY("com.code_page", "", PHP_INI_ALL, OnUpdateLong, code_page, zend_com_dotnet_globals, com_dotnet_globals)
|
||||||
|
PHP_INI_ENTRY("com.typelib_file", "", PHP_INI_SYSTEM, OnTypeLibFileUpdate)
|
||||||
PHP_INI_END()
|
PHP_INI_END()
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -99,6 +173,7 @@ PHP_INI_END()
|
||||||
static void php_com_dotnet_init_globals(zend_com_dotnet_globals *com_dotnet_globals)
|
static void php_com_dotnet_init_globals(zend_com_dotnet_globals *com_dotnet_globals)
|
||||||
{
|
{
|
||||||
memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
|
memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
|
||||||
|
com_dotnet_globals->code_page = CP_ACP;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -106,28 +181,44 @@ static void php_com_dotnet_init_globals(zend_com_dotnet_globals *com_dotnet_glob
|
||||||
*/
|
*/
|
||||||
PHP_MINIT_FUNCTION(com_dotnet)
|
PHP_MINIT_FUNCTION(com_dotnet)
|
||||||
{
|
{
|
||||||
zend_class_entry ce;
|
zend_class_entry ce, *tmp;
|
||||||
|
|
||||||
ZEND_INIT_MODULE_GLOBALS(com_dotnet, php_com_dotnet_init_globals, NULL);
|
ZEND_INIT_MODULE_GLOBALS(com_dotnet, php_com_dotnet_init_globals, NULL);
|
||||||
REGISTER_INI_ENTRIES();
|
REGISTER_INI_ENTRIES();
|
||||||
|
|
||||||
|
php_com_wrapper_minit(INIT_FUNC_ARGS_PASSTHRU);
|
||||||
|
|
||||||
|
INIT_CLASS_ENTRY(ce, "com_exception", NULL);
|
||||||
|
php_com_exception_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(), NULL TSRMLS_CC);
|
||||||
|
php_com_exception_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||||
|
php_com_exception_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED;
|
||||||
|
|
||||||
|
INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL);
|
||||||
|
php_com_saproxy_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
|
||||||
|
php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL;
|
||||||
|
// php_com_saproxy_class_entry->constructor->common.fn_flags |= ZEND_ACC_PROTECTED;
|
||||||
|
php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(ce, "variant", NULL);
|
INIT_CLASS_ENTRY(ce, "variant", NULL);
|
||||||
ce.create_object = php_com_object_new;
|
ce.create_object = php_com_object_new;
|
||||||
ce.get_iterator = php_com_iter_get;
|
// ce.get_iterator = php_com_iter_get;
|
||||||
php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
|
php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
|
||||||
|
php_com_variant_class_entry->get_iterator = php_com_iter_get;
|
||||||
|
|
||||||
INIT_CLASS_ENTRY(ce, "com", NULL);
|
INIT_CLASS_ENTRY(ce, "com", NULL);
|
||||||
ce.create_object = php_com_object_new;
|
ce.create_object = php_com_object_new;
|
||||||
ce.get_iterator = php_com_iter_get;
|
// ce.get_iterator = php_com_iter_get;
|
||||||
zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC);
|
tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC);
|
||||||
|
tmp->get_iterator = php_com_iter_get;
|
||||||
|
|
||||||
zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 1);
|
zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor, 1);
|
||||||
|
|
||||||
#if HAVE_MSCOREE_H
|
#if HAVE_MSCOREE_H
|
||||||
INIT_CLASS_ENTRY(ce, "dotnet", NULL);
|
INIT_CLASS_ENTRY(ce, "dotnet", NULL);
|
||||||
ce.create_object = php_com_object_new;
|
ce.create_object = php_com_object_new;
|
||||||
ce.get_iterator = php_com_iter_get;
|
// ce.get_iterator = php_com_iter_get;
|
||||||
zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC);
|
tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant" TSRMLS_CC);
|
||||||
|
tmp->get_iterator = php_com_iter_get;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT)
|
#define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -51,7 +51,7 @@ static zval *com_property_read(zval *object, zval *member, zend_bool silent TSRM
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!silent) {
|
if (!silent) {
|
||||||
php_com_throw_exception("this variant has no properties" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this variant has no properties" TSRMLS_CC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ static void com_property_write(zval *object, zval *member, zval *value TSRMLS_DC
|
||||||
VariantClear(&v);
|
VariantClear(&v);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
php_com_throw_exception("this variant has no properties" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this variant has no properties" TSRMLS_CC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ static zval *com_read_dimension(zval *object, zval *offset TSRMLS_DC)
|
||||||
|
|
||||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||||
if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) {
|
if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) {
|
||||||
php_com_throw_exception("this COM object has no default property" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this COM object has no default property" TSRMLS_CC);
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,49 +127,19 @@ static zval *com_read_dimension(zval *object, zval *offset TSRMLS_DC)
|
||||||
VariantClear(&v);
|
VariantClear(&v);
|
||||||
}
|
}
|
||||||
} else if (V_ISARRAY(&obj->v)) {
|
} else if (V_ISARRAY(&obj->v)) {
|
||||||
SAFEARRAY *sa = V_ARRAY(&obj->v);
|
|
||||||
UINT dims;
|
|
||||||
VARTYPE vt;
|
|
||||||
LONG bound_low = 0, bound_high = 0;
|
|
||||||
LONG indices[1];
|
|
||||||
|
|
||||||
dims = SafeArrayGetDim(sa);
|
|
||||||
|
|
||||||
if (dims != 1) {
|
|
||||||
php_com_throw_exception("can only handle single dimension arrays" TSRMLS_CC);
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
|
|
||||||
vt = V_VT(&obj->v) & ~VT_ARRAY;
|
|
||||||
}
|
|
||||||
SafeArrayGetUBound(sa, 1, &bound_high);
|
|
||||||
SafeArrayGetLBound(sa, 1, &bound_low);
|
|
||||||
|
|
||||||
convert_to_long(offset);
|
convert_to_long(offset);
|
||||||
|
|
||||||
/* check bounds */
|
if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) {
|
||||||
if (Z_LVAL_P(offset) < bound_low || Z_LVAL_P(offset) > bound_high) {
|
if (php_com_safearray_get_elem(&obj->v, &v, Z_LVAL_P(offset) TSRMLS_CC)) {
|
||||||
php_com_throw_exception("index out of bounds" TSRMLS_CC);
|
php_com_wrap_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
||||||
return return_value;
|
VariantClear(&v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
indices[0] = Z_LVAL_P(offset);
|
|
||||||
|
|
||||||
VariantInit(&v);
|
|
||||||
V_VT(&v) = vt;
|
|
||||||
/* store the value into "lVal" member of the variant.
|
|
||||||
* This works because it is a union; since we know the variant
|
|
||||||
* type, we end up with a working variant */
|
|
||||||
SafeArrayGetElement(sa, indices, &v.lVal);
|
|
||||||
|
|
||||||
/* now we can set the return value from that element */
|
|
||||||
php_com_wrap_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
|
||||||
|
|
||||||
VariantClear(&v);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
php_com_throw_exception("this variant is not an array type" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this variant is not an array type" TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
|
@ -185,7 +155,7 @@ static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_D
|
||||||
|
|
||||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||||
if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) {
|
if (!obj->have_default_bind && !com_get_default_binding(obj TSRMLS_CC)) {
|
||||||
php_com_throw_exception("this COM object has no default property" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this COM object has no default property" TSRMLS_CC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +170,7 @@ static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_D
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* TODO: check for safearray */
|
/* TODO: check for safearray */
|
||||||
php_com_throw_exception("this variant is not an array type" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "this variant is not an array type" TSRMLS_CC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +315,6 @@ static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||||
obj = CDNO_FETCH(getThis());
|
obj = CDNO_FETCH(getThis());
|
||||||
|
|
||||||
if (V_VT(&obj->v) != VT_DISPATCH) {
|
if (V_VT(&obj->v) != VT_DISPATCH) {
|
||||||
//php_com_throw_exception("call to member function of non-object");
|
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,6 +498,30 @@ zend_object_handlers php_com_object_handlers = {
|
||||||
com_object_cast
|
com_object_cast
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable TSRMLS_DC)
|
||||||
|
{
|
||||||
|
if (obj->sink_dispatch) {
|
||||||
|
IConnectionPointContainer *cont;
|
||||||
|
IConnectionPoint *point;
|
||||||
|
|
||||||
|
if (SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v),
|
||||||
|
&IID_IConnectionPointContainer, (void**)&cont))) {
|
||||||
|
|
||||||
|
if (SUCCEEDED(IConnectionPointContainer_FindConnectionPoint(cont,
|
||||||
|
&obj->sink_id, &point))) {
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
IConnectionPoint_Advise(point, (IUnknown*)obj->sink_dispatch, &obj->sink_cookie);
|
||||||
|
} else {
|
||||||
|
IConnectionPoint_Unadvise(point, obj->sink_cookie);
|
||||||
|
}
|
||||||
|
IConnectionPoint_Release(point);
|
||||||
|
}
|
||||||
|
IConnectionPointContainer_Release(cont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
||||||
{
|
{
|
||||||
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
|
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
|
||||||
|
@ -538,8 +531,13 @@ void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
||||||
obj->typeinfo = NULL;
|
obj->typeinfo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantClear(&obj->v);
|
if (obj->sink_dispatch) {
|
||||||
|
php_com_object_enable_event_sink(obj, FALSE TSRMLS_CC);
|
||||||
|
IDispatch_Release(obj->sink_dispatch);
|
||||||
|
obj->sink_dispatch = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantClear(&obj->v);
|
||||||
efree(obj);
|
efree(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -33,8 +33,11 @@ struct php_com_iterator {
|
||||||
zend_object_iterator iter;
|
zend_object_iterator iter;
|
||||||
IEnumVARIANT *ev;
|
IEnumVARIANT *ev;
|
||||||
ulong key;
|
ulong key;
|
||||||
VARIANT v;
|
VARIANT v; /* cached element */
|
||||||
int code_page;
|
int code_page;
|
||||||
|
VARIANT safe_array;
|
||||||
|
VARTYPE sa_type;
|
||||||
|
LONG sa_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||||
|
@ -45,6 +48,7 @@ static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||||
IEnumVARIANT_Release(I->ev);
|
IEnumVARIANT_Release(I->ev);
|
||||||
}
|
}
|
||||||
VariantClear(&I->v);
|
VariantClear(&I->v);
|
||||||
|
VariantClear(&I->safe_array);
|
||||||
efree(I);
|
efree(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +75,8 @@ static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_STD_ZVAL(ptr);
|
MAKE_STD_ZVAL(ptr);
|
||||||
php_com_wrap_variant(ptr, &I->v, I->code_page TSRMLS_CC);
|
php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
|
||||||
|
/* php_com_wrap_variant(ptr, &I->v, I->code_page TSRMLS_CC); */
|
||||||
ptr_ptr = emalloc(sizeof(*ptr_ptr));
|
ptr_ptr = emalloc(sizeof(*ptr_ptr));
|
||||||
*ptr_ptr = ptr;
|
*ptr_ptr = ptr;
|
||||||
*data = ptr_ptr;
|
*data = ptr_ptr;
|
||||||
|
@ -98,15 +103,30 @@ static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
|
||||||
|
|
||||||
/* release current cached element */
|
/* release current cached element */
|
||||||
VariantClear(&I->v);
|
VariantClear(&I->v);
|
||||||
|
|
||||||
/* Get the next element */
|
if (I->ev) {
|
||||||
if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
|
/* Get the next element */
|
||||||
I->key++;
|
if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
|
||||||
return SUCCESS;
|
I->key++;
|
||||||
|
return SUCCESS;
|
||||||
|
} else {
|
||||||
|
/* indicate that there are no more items */
|
||||||
|
I->key = (ulong)-1;
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* indicate that there are no more items */
|
/* safe array */
|
||||||
I->key = (ulong)-1;
|
if (I->key >= I->sa_max) {
|
||||||
return FAILURE;
|
I->key = (ulong)-1;
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
I->key++;
|
||||||
|
if (php_com_safearray_get_elem(&I->safe_array, &I->v, (LONG)I->key TSRMLS_CC)) {
|
||||||
|
return SUCCESS;
|
||||||
|
} else {
|
||||||
|
I->key = (ulong)-1;
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,49 +151,89 @@ zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object TSRMLS
|
||||||
|
|
||||||
obj = CDNO_FETCH(object);
|
obj = CDNO_FETCH(object);
|
||||||
|
|
||||||
/* TODO: support enumerating through SafeArrays */
|
if (V_VT(&obj->v) != VT_DISPATCH && !V_ISARRAY(&obj->v)) {
|
||||||
if (V_VT(&obj->v) != VT_DISPATCH) {
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant is not an object or array VT=%d", V_VT(&obj->v));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&dp, 0, sizeof(dp));
|
memset(&dp, 0, sizeof(dp));
|
||||||
VariantInit(&v);
|
VariantInit(&v);
|
||||||
|
|
||||||
/* can we enumerate it? */
|
|
||||||
if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM,
|
|
||||||
&IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET,
|
|
||||||
&dp, &v, NULL, NULL))) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get something useful out of it */
|
|
||||||
if (V_VT(&v) == VT_UNKNOWN) {
|
|
||||||
IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev);
|
|
||||||
} else if (V_VT(&v) == VT_DISPATCH) {
|
|
||||||
IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantClear(&v);
|
|
||||||
|
|
||||||
if (iev == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
I = (struct php_com_iterator*)ecalloc(1, sizeof(*I));
|
I = (struct php_com_iterator*)ecalloc(1, sizeof(*I));
|
||||||
I->iter.funcs = &com_iter_funcs;
|
I->iter.funcs = &com_iter_funcs;
|
||||||
I->iter.data = I;
|
I->iter.data = I;
|
||||||
I->ev = iev;
|
|
||||||
I->code_page = obj->code_page;
|
I->code_page = obj->code_page;
|
||||||
|
VariantInit(&I->safe_array);
|
||||||
|
VariantInit(&I->v);
|
||||||
|
|
||||||
/* Get the first element now */
|
if (V_ISARRAY(&obj->v)) {
|
||||||
if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
|
LONG bound;
|
||||||
/* indicate that we have element 0 */
|
UINT dims;
|
||||||
I->key = 0;
|
|
||||||
|
dims = SafeArrayGetDim(V_ARRAY(&obj->v));
|
||||||
|
|
||||||
|
if (dims != 1) {
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||||
|
"Can only handle single dimension variant arrays (this array has %d)", dims);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* same semantics as foreach on a PHP array;
|
||||||
|
* make a copy and enumerate that copy */
|
||||||
|
VariantCopy(&I->safe_array, &obj->v);
|
||||||
|
|
||||||
|
/* determine the key value for the array */
|
||||||
|
SafeArrayGetLBound(V_ARRAY(&I->safe_array), 1, &bound);
|
||||||
|
SafeArrayGetUBound(V_ARRAY(&I->safe_array), 1, &I->sa_max);
|
||||||
|
|
||||||
|
/* pre-fetch the element */
|
||||||
|
if (php_com_safearray_get_elem(&I->safe_array, &I->v, bound TSRMLS_CC)) {
|
||||||
|
I->key = bound;
|
||||||
|
} else {
|
||||||
|
I->key = (ulong)-1;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* indicate that there are no more items */
|
/* can we enumerate it? */
|
||||||
I->key = (ulong)-1;
|
if (FAILED(IDispatch_Invoke(V_DISPATCH(&obj->v), DISPID_NEWENUM,
|
||||||
|
&IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD|DISPATCH_PROPERTYGET,
|
||||||
|
&dp, &v, NULL, NULL))) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get something useful out of it */
|
||||||
|
if (V_VT(&v) == VT_UNKNOWN) {
|
||||||
|
IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IEnumVARIANT, (void**)&iev);
|
||||||
|
} else if (V_VT(&v) == VT_DISPATCH) {
|
||||||
|
IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IEnumVARIANT, (void**)&iev);
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantClear(&v);
|
||||||
|
|
||||||
|
if (iev == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
I->ev = iev;
|
||||||
|
|
||||||
|
/* Get the first element now */
|
||||||
|
if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
|
||||||
|
/* indicate that we have element 0 */
|
||||||
|
I->key = 0;
|
||||||
|
} else {
|
||||||
|
/* indicate that there are no more items */
|
||||||
|
I->key = (ulong)-1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &I->iter;
|
return &I->iter;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (I) {
|
||||||
|
VariantClear(&I->safe_array);
|
||||||
|
VariantClear(&I->v);
|
||||||
|
free(I);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -29,31 +29,17 @@
|
||||||
#include "php_com_dotnet_internal.h"
|
#include "php_com_dotnet_internal.h"
|
||||||
#include "Zend/zend_default_classes.h"
|
#include "Zend/zend_default_classes.h"
|
||||||
|
|
||||||
zval *php_com_throw_exception(char *message TSRMLS_DC)
|
void php_com_throw_exception(HRESULT code, char *message TSRMLS_DC)
|
||||||
{
|
{
|
||||||
zval *e, *tmp;
|
int free_msg = 0;
|
||||||
|
if (message == NULL) {
|
||||||
ALLOC_ZVAL(e);
|
message = php_win_err(code);
|
||||||
Z_TYPE_P(e) = IS_OBJECT;
|
free_msg = 1;
|
||||||
object_init_ex(e, zend_exception_get_default());
|
}
|
||||||
e->refcount = 1;
|
zend_throw_exception(php_com_exception_class_entry, message, (long)code TSRMLS_CC);
|
||||||
e->is_ref = 1;
|
if (free_msg) {
|
||||||
|
efree(message);
|
||||||
MAKE_STD_ZVAL(tmp);
|
}
|
||||||
ZVAL_STRING(tmp, message, 1);
|
|
||||||
zend_hash_update(Z_OBJPROP_P(e), "message", sizeof("message"), (void**)&tmp, sizeof(zval*), NULL);
|
|
||||||
|
|
||||||
MAKE_STD_ZVAL(tmp);
|
|
||||||
ZVAL_STRING(tmp, zend_get_executed_filename(TSRMLS_C), 1);
|
|
||||||
zend_hash_update(Z_OBJPROP_P(e), "file", sizeof("file"), (void**)&tmp, sizeof(zval*), NULL);
|
|
||||||
|
|
||||||
MAKE_STD_ZVAL(tmp);
|
|
||||||
ZVAL_LONG(tmp, zend_get_executed_lineno(TSRMLS_C));
|
|
||||||
zend_hash_update(Z_OBJPROP_P(e), "line", sizeof("line"), (void**)&tmp, sizeof(zval*), NULL);
|
|
||||||
|
|
||||||
EG(exception) = e;
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
|
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
|
||||||
|
@ -89,7 +75,7 @@ PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
|
||||||
obj->ce = php_com_variant_class_entry;
|
obj->ce = php_com_variant_class_entry;
|
||||||
|
|
||||||
VariantInit(&obj->v);
|
VariantInit(&obj->v);
|
||||||
VariantCopy(&obj->v, v);
|
VariantCopyInd(&obj->v, v);
|
||||||
|
|
||||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||||
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
|
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
|
||||||
|
@ -100,3 +86,56 @@ PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
|
||||||
z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor, php_com_object_clone TSRMLS_CC);
|
z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor, php_com_object_clone TSRMLS_CC);
|
||||||
z->value.obj.handlers = &php_com_object_handlers;
|
z->value.obj.handlers = &php_com_object_handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this is a convenience function for fetching a particular
|
||||||
|
* element from a (possibly multi-dimensional) safe array */
|
||||||
|
PHPAPI int php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1 TSRMLS_DC)
|
||||||
|
{
|
||||||
|
UINT dims;
|
||||||
|
LONG lbound, ubound;
|
||||||
|
LONG indices[1];
|
||||||
|
VARTYPE vt;
|
||||||
|
|
||||||
|
if (!V_ISARRAY(array)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dims = SafeArrayGetDim(V_ARRAY(array));
|
||||||
|
|
||||||
|
if (dims != 1) {
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING,
|
||||||
|
"Can only handle single dimension variant arrays (this array has %d)", dims);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(SafeArrayGetVartype(V_ARRAY(array), &vt)) || vt == VT_EMPTY) {
|
||||||
|
vt = V_VT(array) & ~VT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* determine the bounds */
|
||||||
|
SafeArrayGetLBound(V_ARRAY(array), 1, &lbound);
|
||||||
|
SafeArrayGetUBound(V_ARRAY(array), 1, &ubound);
|
||||||
|
|
||||||
|
/* check bounds */
|
||||||
|
if (dim1 < lbound || dim1 > ubound) {
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "index out of bounds" TSRMLS_CC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now fetch that element */
|
||||||
|
VariantInit(dest);
|
||||||
|
|
||||||
|
indices[0] = dim1;
|
||||||
|
|
||||||
|
if (vt == VT_VARIANT) {
|
||||||
|
SafeArrayGetElement(V_ARRAY(array), indices, dest);
|
||||||
|
} else {
|
||||||
|
V_VT(dest) = vt;
|
||||||
|
/* store the value into "lVal" member of the variant.
|
||||||
|
* This works because it is a union; since we know the variant
|
||||||
|
* type, we end up with a working variant */
|
||||||
|
SafeArrayGetElement(V_ARRAY(array), indices, &dest->lVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -100,4 +100,4 @@ PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring, uint *string_len, i
|
||||||
}
|
}
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
430
ext/com_dotnet/com_saproxy.c
Normal file
430
ext/com_dotnet/com_saproxy.c
Normal file
|
@ -0,0 +1,430 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| PHP Version 5 |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.0 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| http://www.php.net/license/3_0.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: Wez Furlong <wez@thebrainroom.com> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/* This module implements a SafeArray proxy which is used internally
|
||||||
|
* by the engine when resolving multi-dimensional array accesses on
|
||||||
|
* SafeArray types
|
||||||
|
* */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_ini.h"
|
||||||
|
#include "ext/standard/info.h"
|
||||||
|
#include "php_com_dotnet.h"
|
||||||
|
#include "php_com_dotnet_internal.h"
|
||||||
|
#include "Zend/zend_default_classes.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* the object we a proxying for; we hold a refcount to it */
|
||||||
|
zval *zobj;
|
||||||
|
php_com_dotnet_object *obj;
|
||||||
|
|
||||||
|
/* how many dimensions we are indirecting to get into this element */
|
||||||
|
LONG dimensions;
|
||||||
|
|
||||||
|
/* this is an array whose size_is(dimensions) */
|
||||||
|
LONG *indices;
|
||||||
|
|
||||||
|
} php_com_saproxy;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
zend_object_iterator iter;
|
||||||
|
zval *proxy_obj;
|
||||||
|
php_com_saproxy *proxy;
|
||||||
|
LONG key;
|
||||||
|
LONG imin, imax;
|
||||||
|
LONG *indices;
|
||||||
|
} php_com_saproxy_iter;
|
||||||
|
|
||||||
|
#define SA_FETCH(zv) (php_com_saproxy*)zend_object_store_get_object(zv TSRMLS_CC)
|
||||||
|
|
||||||
|
static zval *saproxy_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC)
|
||||||
|
{
|
||||||
|
zval *return_value;
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(return_value);
|
||||||
|
ZVAL_NULL(return_value);
|
||||||
|
|
||||||
|
if (!silent) {
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static zval *saproxy_read_dimension(zval *object, zval *offset TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy *proxy = SA_FETCH(object);
|
||||||
|
zval *return_value;
|
||||||
|
UINT dims;
|
||||||
|
SAFEARRAY *sa;
|
||||||
|
LONG ubound, lbound;
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(return_value);
|
||||||
|
ZVAL_NULL(return_value);
|
||||||
|
|
||||||
|
if (!V_ISARRAY(&proxy->obj->v)) {
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "proxied object is no longer a safe array!" TSRMLS_CC);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* offset/index must be an integer */
|
||||||
|
convert_to_long(offset);
|
||||||
|
|
||||||
|
sa = V_ARRAY(&proxy->obj->v);
|
||||||
|
dims = SafeArrayGetDim(sa);
|
||||||
|
|
||||||
|
if (proxy->dimensions >= dims) {
|
||||||
|
/* too many dimensions */
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "too many dimensions!" TSRMLS_CC);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bounds check */
|
||||||
|
SafeArrayGetLBound(sa, proxy->dimensions, &lbound);
|
||||||
|
SafeArrayGetUBound(sa, proxy->dimensions, &ubound);
|
||||||
|
|
||||||
|
if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) {
|
||||||
|
php_com_throw_exception(E_INVALIDARG, "index out of bounds" TSRMLS_CC);
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dims - 1 == proxy->dimensions) {
|
||||||
|
LONG *indices;
|
||||||
|
VARTYPE vt;
|
||||||
|
VARIANT v;
|
||||||
|
|
||||||
|
VariantInit(&v);
|
||||||
|
|
||||||
|
/* we can return a real value */
|
||||||
|
indices = do_alloca(dims * sizeof(LONG));
|
||||||
|
|
||||||
|
/* copy indices from proxy */
|
||||||
|
memcpy(indices, proxy->indices, (dims-1) * sizeof(LONG));
|
||||||
|
|
||||||
|
/* add user-supplied index */
|
||||||
|
indices[dims-1] = Z_LVAL_P(offset);
|
||||||
|
|
||||||
|
/* now fetch the value */
|
||||||
|
if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
|
||||||
|
vt = V_VT(&proxy->obj->v) & ~VT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vt == VT_VARIANT) {
|
||||||
|
SafeArrayGetElement(sa, indices, &v);
|
||||||
|
} else {
|
||||||
|
V_VT(&v) = vt;
|
||||||
|
SafeArrayGetElement(sa, indices, &v.lVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_alloca(indices);
|
||||||
|
|
||||||
|
php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
|
||||||
|
|
||||||
|
VariantClear(&v);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* return another proxy */
|
||||||
|
php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet implemented" TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_object_set(zval **property, zval *value TSRMLS_DC)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static zval *saproxy_object_get(zval *property TSRMLS_DC)
|
||||||
|
{
|
||||||
|
/* Not yet implemented in the engine */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
|
||||||
|
{
|
||||||
|
/* no properties */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_dimension_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Operation not yet supported on a COM object");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_property_delete(zval *object, zval *member TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_dimension_delete(zval *object, zval *offset TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
|
||||||
|
}
|
||||||
|
|
||||||
|
static HashTable *saproxy_properties_get(zval *object TSRMLS_DC)
|
||||||
|
{
|
||||||
|
/* no properties */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static union _zend_function *saproxy_method_get(zval *object, char *name, int len TSRMLS_DC)
|
||||||
|
{
|
||||||
|
/* no methods */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||||
|
{
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static union _zend_function *saproxy_constructor_get(zval *object TSRMLS_DC)
|
||||||
|
{
|
||||||
|
/* user cannot instanciate */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_class_entry *saproxy_class_entry_get(zval *object TSRMLS_DC)
|
||||||
|
{
|
||||||
|
return php_com_saproxy_class_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_class_name_get(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
|
||||||
|
{
|
||||||
|
*class_name = estrndup(php_com_saproxy_class_entry->name, php_com_saproxy_class_entry->name_length);
|
||||||
|
*class_name_len = php_com_saproxy_class_entry->name_length;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
|
||||||
|
{
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_object_handlers php_com_saproxy_handlers = {
|
||||||
|
ZEND_OBJECTS_STORE_HANDLERS,
|
||||||
|
saproxy_property_read,
|
||||||
|
saproxy_property_write,
|
||||||
|
saproxy_read_dimension,
|
||||||
|
saproxy_write_dimension,
|
||||||
|
NULL,
|
||||||
|
saproxy_object_get,
|
||||||
|
saproxy_object_set,
|
||||||
|
saproxy_property_exists,
|
||||||
|
saproxy_property_delete,
|
||||||
|
saproxy_dimension_exists,
|
||||||
|
saproxy_dimension_delete,
|
||||||
|
saproxy_properties_get,
|
||||||
|
saproxy_method_get,
|
||||||
|
saproxy_call_method,
|
||||||
|
saproxy_constructor_get,
|
||||||
|
saproxy_class_entry_get,
|
||||||
|
saproxy_class_name_get,
|
||||||
|
saproxy_objects_compare,
|
||||||
|
saproxy_object_cast
|
||||||
|
};
|
||||||
|
|
||||||
|
static void saproxy_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy *proxy = (php_com_saproxy *)object;
|
||||||
|
|
||||||
|
ZVAL_DELREF(proxy->zobj);
|
||||||
|
efree(proxy->indices);
|
||||||
|
efree(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_clone(void *object, void **clone_ptr TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy *proxy = (php_com_saproxy *)object;
|
||||||
|
php_com_saproxy *cloneproxy;
|
||||||
|
|
||||||
|
cloneproxy = emalloc(sizeof(*cloneproxy));
|
||||||
|
memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
|
||||||
|
|
||||||
|
ZVAL_ADDREF(cloneproxy->zobj);
|
||||||
|
cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(LONG), 0);
|
||||||
|
memcpy(cloneproxy->indices, proxy->indices, cloneproxy->dimensions * sizeof(LONG));
|
||||||
|
|
||||||
|
*clone_ptr = cloneproxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy *proxy, *rel = NULL;
|
||||||
|
php_com_dotnet_object *obj;
|
||||||
|
|
||||||
|
proxy = ecalloc(1, sizeof(*proxy));
|
||||||
|
proxy->dimensions = 1;
|
||||||
|
|
||||||
|
if (Z_OBJCE_P(com_object) == php_com_saproxy_class_entry) {
|
||||||
|
rel = SA_FETCH(com_object);
|
||||||
|
obj = rel->obj;
|
||||||
|
proxy->zobj = rel->zobj;
|
||||||
|
proxy->dimensions += rel->dimensions;
|
||||||
|
} else {
|
||||||
|
obj = CDNO_FETCH(com_object);
|
||||||
|
proxy->zobj = com_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZVAL_ADDREF(proxy->zobj);
|
||||||
|
proxy->indices = safe_emalloc(proxy->dimensions, sizeof(LONG), 0);
|
||||||
|
|
||||||
|
if (rel) {
|
||||||
|
memcpy(proxy->indices, rel->indices, (proxy->dimensions-1) * sizeof(LONG));
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy->indices[proxy->dimensions-1] = index;
|
||||||
|
|
||||||
|
Z_TYPE_P(proxy_out) = IS_OBJECT;
|
||||||
|
Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, saproxy_dtor, saproxy_clone TSRMLS_CC);
|
||||||
|
Z_OBJ_HT_P(proxy_out) = &php_com_saproxy_handlers;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iterator */
|
||||||
|
|
||||||
|
static void saproxy_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||||
|
|
||||||
|
ZVAL_DELREF(I->proxy_obj);
|
||||||
|
|
||||||
|
efree(I->indices);
|
||||||
|
efree(I);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_iter_has_more(zend_object_iterator *iter TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||||
|
|
||||||
|
return (I->key < I->imax) ? SUCCESS : FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||||
|
VARIANT v;
|
||||||
|
VARTYPE vt;
|
||||||
|
zval *return_value, **ptr_ptr;
|
||||||
|
SAFEARRAY *sa;
|
||||||
|
|
||||||
|
I->indices[I->proxy->dimensions-1] = I->key;
|
||||||
|
|
||||||
|
sa = V_ARRAY(&I->proxy->obj->v);
|
||||||
|
|
||||||
|
if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
|
||||||
|
vt = V_VT(&I->proxy->obj->v) & ~VT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantInit(&v);
|
||||||
|
if (vt == VT_VARIANT) {
|
||||||
|
SafeArrayGetElement(sa, I->indices, &v);
|
||||||
|
} else {
|
||||||
|
V_VT(&v) = vt;
|
||||||
|
SafeArrayGetElement(sa, I->indices, &v.lVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(return_value);
|
||||||
|
php_com_wrap_variant(return_value, &v, I->proxy->obj->code_page TSRMLS_CC);
|
||||||
|
VariantClear(&v);
|
||||||
|
|
||||||
|
ptr_ptr = emalloc(sizeof(*ptr_ptr));
|
||||||
|
*ptr_ptr = return_value;
|
||||||
|
*data = ptr_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_iter_get_key(zend_object_iterator *iter, char **str_key, uint *str_key_len,
|
||||||
|
ulong *int_key TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||||
|
|
||||||
|
if (I->key == -1) {
|
||||||
|
return HASH_KEY_NON_EXISTANT;
|
||||||
|
}
|
||||||
|
*int_key = (ulong)I->key;
|
||||||
|
return HASH_KEY_IS_LONG;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||||
|
|
||||||
|
if (++I->key >= I->imax) {
|
||||||
|
I->key = -1;
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static zend_object_iterator_funcs saproxy_iter_funcs = {
|
||||||
|
saproxy_iter_dtor,
|
||||||
|
saproxy_iter_has_more,
|
||||||
|
saproxy_iter_get_data,
|
||||||
|
saproxy_iter_get_key,
|
||||||
|
saproxy_iter_move_forwards,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_com_saproxy *proxy = SA_FETCH(object);
|
||||||
|
php_com_saproxy_iter *I;
|
||||||
|
|
||||||
|
I = ecalloc(1, sizeof(*I));
|
||||||
|
I->iter.funcs = &saproxy_iter_funcs;
|
||||||
|
I->iter.data = I;
|
||||||
|
|
||||||
|
I->proxy = proxy;
|
||||||
|
I->proxy_obj = object;
|
||||||
|
ZVAL_ADDREF(I->proxy_obj);
|
||||||
|
|
||||||
|
I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
|
||||||
|
memcpy(I->indices, proxy->indices, proxy->dimensions * sizeof(LONG));
|
||||||
|
|
||||||
|
SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
|
||||||
|
SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax);
|
||||||
|
|
||||||
|
I->key = I->imin;
|
||||||
|
|
||||||
|
return &I->iter;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -35,8 +35,7 @@
|
||||||
* b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0"
|
* b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0"
|
||||||
* c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library"
|
* c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library"
|
||||||
*/
|
*/
|
||||||
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
|
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int codepage TSRMLS_DC)
|
||||||
int codepage TSRMLS_DC)
|
|
||||||
{
|
{
|
||||||
ITypeLib *TL = NULL;
|
ITypeLib *TL = NULL;
|
||||||
char *strtok_buf, *major, *minor;
|
char *strtok_buf, *major, *minor;
|
||||||
|
@ -119,7 +118,7 @@ PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
|
||||||
/* get the default value for this key and compare */
|
/* get the default value for this key and compare */
|
||||||
libnamelen = strlen(search_string)+1;
|
libnamelen = strlen(search_string)+1;
|
||||||
if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) {
|
if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) {
|
||||||
if (0 == ((mode & CONST_CS) ? strcmp(libname, search_string) : stricmp(libname, search_string))) {
|
if (0 == stricmp(libname, search_string)) {
|
||||||
char *str = NULL;
|
char *str = NULL;
|
||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
|
@ -130,7 +129,7 @@ PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
|
||||||
}
|
}
|
||||||
spprintf(&str, 0, "%s,%d,%d", keyname, major, minor);
|
spprintf(&str, 0, "%s,%d,%d", keyname, major, minor);
|
||||||
/* recurse */
|
/* recurse */
|
||||||
TL = php_com_load_typelib(str, mode, codepage TSRMLS_CC);
|
TL = php_com_load_typelib(str, codepage TSRMLS_CC);
|
||||||
|
|
||||||
efree(str);
|
efree(str);
|
||||||
break;
|
break;
|
||||||
|
@ -226,7 +225,7 @@ void php_com_typelibrary_dtor(void *pDest)
|
||||||
}
|
}
|
||||||
|
|
||||||
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||||
int mode, int codepage, int *cached TSRMLS_DC)
|
int codepage, int *cached TSRMLS_DC)
|
||||||
{
|
{
|
||||||
ITypeLib **TL;
|
ITypeLib **TL;
|
||||||
char *name_dup;
|
char *name_dup;
|
||||||
|
@ -244,7 +243,7 @@ PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||||
|
|
||||||
*cached = 0;
|
*cached = 0;
|
||||||
name_dup = estrndup(search_string, l);
|
name_dup = estrndup(search_string, l);
|
||||||
*TL = php_com_load_typelib(name_dup, mode, codepage TSRMLS_CC);
|
*TL = php_com_load_typelib(name_dup, codepage TSRMLS_CC);
|
||||||
efree(name_dup);
|
efree(name_dup);
|
||||||
|
|
||||||
if (*TL) {
|
if (*TL) {
|
||||||
|
@ -257,3 +256,346 @@ PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||||
|
|
||||||
return *TL;
|
return *TL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ITypeInfo *php_com_locate_typeinfo(char *typelibname, php_com_dotnet_object *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(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo2, (void**)&pci2))) {
|
||||||
|
gotguid = SUCCEEDED(IProvideClassInfo2_GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid));
|
||||||
|
IProvideClassInfo2_Release(pci2);
|
||||||
|
}
|
||||||
|
if (!gotguid && SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo, (void**)&pci))) {
|
||||||
|
/* examine the available interfaces */
|
||||||
|
/* TODO: write some code here */
|
||||||
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "IProvideClassInfo: this code not yet written!");
|
||||||
|
IProvideClassInfo_Release(pci);
|
||||||
|
}
|
||||||
|
} else if (dispname == NULL) {
|
||||||
|
if (obj->typeinfo) {
|
||||||
|
ITypeInfo_AddRef(obj->typeinfo);
|
||||||
|
return obj->typeinfo;
|
||||||
|
} else {
|
||||||
|
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
|
||||||
|
if (typeinfo) {
|
||||||
|
return typeinfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (dispname && obj->typeinfo) {
|
||||||
|
unsigned int idx;
|
||||||
|
/* get the library from the object; the rest will be dealt with later */
|
||||||
|
ITypeInfo_GetContainingTypeLib(obj->typeinfo, &typelib, &idx);
|
||||||
|
} else if (typelibname == NULL) {
|
||||||
|
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
|
||||||
|
if (dispname) {
|
||||||
|
unsigned int idx;
|
||||||
|
/* get the library from the object; the rest will be dealt with later */
|
||||||
|
ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, &idx);
|
||||||
|
|
||||||
|
if (typelib) {
|
||||||
|
ITypeInfo_Release(typeinfo);
|
||||||
|
typeinfo = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (typelibname) {
|
||||||
|
/* Fetch the typelibrary and use that to look things up */
|
||||||
|
typelib = php_com_load_typelib(typelibname, obj->code_page TSRMLS_CC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gotguid && dispname && typelib) {
|
||||||
|
unsigned short cfound;
|
||||||
|
MEMBERID memid;
|
||||||
|
OLECHAR *olename = php_com_string_to_olestring(dispname, strlen(dispname), CP_ACP TSRMLS_CC);
|
||||||
|
|
||||||
|
cfound = 1;
|
||||||
|
if (FAILED(ITypeLib_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(ITypeLib_GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {
|
||||||
|
|
||||||
|
/* enumerate implemented interfaces and pick the one as indicated by sink */
|
||||||
|
TYPEATTR *attr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ITypeInfo_GetTypeAttr(coinfo, &attr);
|
||||||
|
|
||||||
|
for (i = 0; i < attr->cImplTypes; i++) {
|
||||||
|
HREFTYPE rt;
|
||||||
|
int tf;
|
||||||
|
|
||||||
|
if (FAILED(ITypeInfo_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(ITypeInfo_GetRefTypeOfImplType(coinfo, i, &rt)))
|
||||||
|
if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(coinfo, rt, &typeinfo)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeInfo_ReleaseTypeAttr(coinfo, attr);
|
||||||
|
ITypeInfo_Release(coinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
efree(olename);
|
||||||
|
} else if (gotguid) {
|
||||||
|
ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &typeinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typelib) {
|
||||||
|
ITypeLib_Release(typelib);
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 char *php_com_string_from_clsid(const CLSID *clsid, int codepage TSRMLS_DC)
|
||||||
|
{
|
||||||
|
LPOLESTR ole_clsid;
|
||||||
|
char *clsid_str;
|
||||||
|
|
||||||
|
StringFromCLSID(clsid, &ole_clsid);
|
||||||
|
clsid_str = php_com_olestring_to_string(ole_clsid, NULL, codepage TSRMLS_CC);
|
||||||
|
LocalFree(ole_clsid);
|
||||||
|
|
||||||
|
return clsid_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid, int codepage TSRMLS_DC)
|
||||||
|
{
|
||||||
|
TYPEATTR *attr;
|
||||||
|
FUNCDESC *func;
|
||||||
|
int i;
|
||||||
|
OLECHAR *olename;
|
||||||
|
char *ansiname = NULL;
|
||||||
|
unsigned int ansinamelen;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (FAILED(ITypeInfo_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;
|
||||||
|
|
||||||
|
ITypeInfo_GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL);
|
||||||
|
ansiname = php_com_olestring_to_string(olename, &ansinamelen, codepage TSRMLS_CC);
|
||||||
|
SysFreeString(olename);
|
||||||
|
|
||||||
|
guidstring = php_com_string_from_clsid(&attr->guid, codepage 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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(ITypeInfo_GetFuncDesc(typeinfo, i, &func)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT);
|
||||||
|
|
||||||
|
if (!isprop || lastid != func->memid) {
|
||||||
|
|
||||||
|
lastid = func->memid;
|
||||||
|
|
||||||
|
ITypeInfo_GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL);
|
||||||
|
ansiname = php_com_olestring_to_string(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));
|
||||||
|
|
||||||
|
ITypeInfo_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) {
|
||||||
|
|
||||||
|
ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
|
||||||
|
if (olename) {
|
||||||
|
funcdesc = php_com_olestring_to_string(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_com_olestring_to_string(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");
|
||||||
|
|
||||||
|
ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
|
||||||
|
if (olename) {
|
||||||
|
funcdesc = php_com_olestring_to_string(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ITypeInfo_ReleaseFuncDesc(typeinfo, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printdef) {
|
||||||
|
php_printf("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
zend_error(E_WARNING, "That's not a dispatchable interface!! type kind = %08x", attr->typekind);
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -59,8 +59,9 @@ PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_D
|
||||||
V_VARIANTREF(v) = &obj->v;
|
V_VARIANTREF(v) = &obj->v;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* TODO: export the object using our COM wrapper */
|
/* export the PHP object using our COM wrapper */
|
||||||
V_VT(v) = VT_NULL;
|
V_VT(v) = VT_DISPATCH;
|
||||||
|
V_DISPATCH(v) = php_com_wrapper_export(z TSRMLS_CC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -168,6 +169,9 @@ PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VT_VARIANT:
|
case VT_VARIANT:
|
||||||
|
/* points to another variant */
|
||||||
|
return php_com_zval_from_variant(z, V_VARIANTREF(v), codepage TSRMLS_CC);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
php_com_wrap_variant(z, v, codepage TSRMLS_CC);
|
php_com_wrap_variant(z, v, codepage TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
@ -202,7 +206,7 @@ PHP_FUNCTION(com_variant_create_instance)
|
||||||
|
|
||||||
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
|
||||||
"z!|ll", &zvalue, &vt, &codepage)) {
|
"z!|ll", &zvalue, &vt, &codepage)) {
|
||||||
php_com_throw_exception("Invalid arguments" TSRMLS_CC);
|
php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +227,7 @@ PHP_FUNCTION(com_variant_create_instance)
|
||||||
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
||||||
LocalFree(werr);
|
LocalFree(werr);
|
||||||
|
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(res, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,6 +258,11 @@ PHP_FUNCTION(variant_set)
|
||||||
ITypeInfo_Release(obj->typeinfo);
|
ITypeInfo_Release(obj->typeinfo);
|
||||||
obj->typeinfo = NULL;
|
obj->typeinfo = NULL;
|
||||||
}
|
}
|
||||||
|
if (obj->sink_dispatch) {
|
||||||
|
php_com_object_enable_event_sink(obj, FALSE TSRMLS_CC);
|
||||||
|
IDispatch_Release(obj->sink_dispatch);
|
||||||
|
obj->sink_dispatch = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
VariantClear(&obj->v);
|
VariantClear(&obj->v);
|
||||||
|
|
||||||
|
@ -779,7 +788,7 @@ PHP_FUNCTION(variant_set_type)
|
||||||
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
||||||
LocalFree(werr);
|
LocalFree(werr);
|
||||||
|
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(res, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,7 +822,7 @@ PHP_FUNCTION(variant_cast)
|
||||||
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
|
||||||
LocalFree(werr);
|
LocalFree(werr);
|
||||||
|
|
||||||
php_com_throw_exception(msg TSRMLS_CC);
|
php_com_throw_exception(res, msg TSRMLS_CC);
|
||||||
efree(msg);
|
efree(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
640
ext/com_dotnet/com_wrapper.c
Normal file
640
ext/com_dotnet/com_wrapper.c
Normal file
|
@ -0,0 +1,640 @@
|
||||||
|
/*
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| PHP Version 5 |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
| This source file is subject to version 3.0 of the PHP license, |
|
||||||
|
| that is bundled with this package in the file LICENSE, and is |
|
||||||
|
| available through the world-wide-web at the following url: |
|
||||||
|
| http://www.php.net/license/3_0.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: Wez Furlong <wez@thebrainroom.com> |
|
||||||
|
+----------------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/* This module exports a PHP object as a COM object by wrapping it
|
||||||
|
* using IDispatchEx */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "php.h"
|
||||||
|
#include "php_ini.h"
|
||||||
|
#include "ext/standard/info.h"
|
||||||
|
#include "php_com_dotnet.h"
|
||||||
|
#include "php_com_dotnet_internal.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* This first part MUST match the declaration
|
||||||
|
* of interface IDispatchEx */
|
||||||
|
CONST_VTBL struct IDispatchExVtbl *lpVtbl;
|
||||||
|
|
||||||
|
/* now the PHP stuff */
|
||||||
|
|
||||||
|
THREAD_T engine_thread; /* for sanity checking */
|
||||||
|
zval *object; /* the object exported */
|
||||||
|
LONG refcount; /* COM reference count */
|
||||||
|
|
||||||
|
HashTable *dispid_to_name; /* keep track of dispid -> name mappings */
|
||||||
|
HashTable *name_to_dispid; /* keep track of name -> dispid mappings */
|
||||||
|
|
||||||
|
GUID sinkid; /* iid that we "implement" for event sinking */
|
||||||
|
|
||||||
|
int id;
|
||||||
|
} php_dispatchex;
|
||||||
|
|
||||||
|
static int le_dispatch;
|
||||||
|
|
||||||
|
static void disp_destructor(php_dispatchex *disp);
|
||||||
|
|
||||||
|
static void dispatch_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_dispatchex *disp = (php_dispatchex *)rsrc->ptr;
|
||||||
|
disp_destructor(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int php_com_wrapper_minit(INIT_FUNC_ARGS)
|
||||||
|
{
|
||||||
|
le_dispatch = zend_register_list_destructors_ex(dispatch_dtor,
|
||||||
|
NULL, "com_dotnet_dispatch_wrapper", module_number);
|
||||||
|
return le_dispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ trace */
|
||||||
|
static inline void trace(char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
|
sprintf(buf, "T=%08x ", tsrm_thread_id());
|
||||||
|
OutputDebugString(buf);
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
|
|
||||||
|
OutputDebugString(buf);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
#define FETCH_DISP(methname) \
|
||||||
|
php_dispatchex *disp = (php_dispatchex*)This; \
|
||||||
|
trace(" PHP:%s %s\n", Z_OBJCE_P(disp->object)->name, methname); \
|
||||||
|
if (tsrm_thread_id() != disp->engine_thread) \
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_queryinterface(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [iid_is][out] */ void **ppvObject)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("QueryInterface");
|
||||||
|
|
||||||
|
if (IsEqualGUID(&IID_IUnknown, riid) ||
|
||||||
|
IsEqualGUID(&IID_IDispatch, riid) ||
|
||||||
|
IsEqualGUID(&IID_IDispatchEx, riid) ||
|
||||||
|
IsEqualGUID(&disp->sinkid, riid)) {
|
||||||
|
*ppvObject = This;
|
||||||
|
InterlockedIncrement(&disp->refcount);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE disp_addref(IDispatchEx *This)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("AddRef");
|
||||||
|
|
||||||
|
return InterlockedIncrement(&disp->refcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG STDMETHODCALLTYPE disp_release(IDispatchEx *This)
|
||||||
|
{
|
||||||
|
ULONG ret;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("Release");
|
||||||
|
|
||||||
|
ret = InterlockedDecrement(&disp->refcount);
|
||||||
|
trace("-- refcount now %d\n", ret);
|
||||||
|
if (ret == 0) {
|
||||||
|
/* destroy it */
|
||||||
|
if (disp->id)
|
||||||
|
zend_list_delete(disp->id);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_gettypeinfocount(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [out] */ UINT *pctinfo)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetTypeInfoCount");
|
||||||
|
|
||||||
|
*pctinfo = 0;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_gettypeinfo(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ UINT iTInfo,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [out] */ ITypeInfo **ppTInfo)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetTypeInfo");
|
||||||
|
|
||||||
|
*ppTInfo = NULL;
|
||||||
|
return DISP_E_BADINDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getidsofnames(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [size_is][in] */ LPOLESTR *rgszNames,
|
||||||
|
/* [in] */ UINT cNames,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [size_is][out] */ DISPID *rgDispId)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
HRESULT ret = S_OK;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetIDsOfNames");
|
||||||
|
|
||||||
|
for (i = 0; i < cNames; i++) {
|
||||||
|
char *name;
|
||||||
|
unsigned int namelen;
|
||||||
|
zval **tmp;
|
||||||
|
|
||||||
|
name = php_com_olestring_to_string(rgszNames[i], &namelen, COMG(code_page) TSRMLS_CC);
|
||||||
|
|
||||||
|
/* Lookup the name in the hash */
|
||||||
|
if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == FAILURE) {
|
||||||
|
ret = DISP_E_UNKNOWNNAME;
|
||||||
|
rgDispId[i] = 0;
|
||||||
|
} else {
|
||||||
|
rgDispId[i] = Z_LVAL_PP(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
efree(name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_invoke(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DISPID dispIdMember,
|
||||||
|
/* [in] */ REFIID riid,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [in] */ WORD wFlags,
|
||||||
|
/* [out][in] */ DISPPARAMS *pDispParams,
|
||||||
|
/* [out] */ VARIANT *pVarResult,
|
||||||
|
/* [out] */ EXCEPINFO *pExcepInfo,
|
||||||
|
/* [out] */ UINT *puArgErr)
|
||||||
|
{
|
||||||
|
return This->lpVtbl->InvokeEx(This, dispIdMember,
|
||||||
|
lcid, wFlags, pDispParams,
|
||||||
|
pVarResult, pExcepInfo, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getdispid(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ BSTR bstrName,
|
||||||
|
/* [in] */ DWORD grfdex,
|
||||||
|
/* [out] */ DISPID *pid)
|
||||||
|
{
|
||||||
|
HRESULT ret = DISP_E_UNKNOWNNAME;
|
||||||
|
char *name;
|
||||||
|
unsigned int namelen;
|
||||||
|
zval **tmp;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetDispID");
|
||||||
|
|
||||||
|
name = php_com_olestring_to_string(bstrName, &namelen, COMG(code_page) TSRMLS_CC);
|
||||||
|
|
||||||
|
/* Lookup the name in the hash */
|
||||||
|
if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) {
|
||||||
|
*pid = Z_LVAL_PP(tmp);
|
||||||
|
ret = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
efree(name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_invokeex(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DISPID id,
|
||||||
|
/* [in] */ LCID lcid,
|
||||||
|
/* [in] */ WORD wFlags,
|
||||||
|
/* [in] */ DISPPARAMS *pdp,
|
||||||
|
/* [out] */ VARIANT *pvarRes,
|
||||||
|
/* [out] */ EXCEPINFO *pei,
|
||||||
|
/* [unique][in] */ IServiceProvider *pspCaller)
|
||||||
|
{
|
||||||
|
zval **name;
|
||||||
|
UINT i;
|
||||||
|
zval *retval = NULL;
|
||||||
|
zval ***params = NULL;
|
||||||
|
HRESULT ret = DISP_E_MEMBERNOTFOUND;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("InvokeEx");
|
||||||
|
|
||||||
|
if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) {
|
||||||
|
/* TODO: add support for overloaded objects */
|
||||||
|
|
||||||
|
trace("-- Invoke: %d %20s flags=%08x args=%d\n", id, Z_STRVAL_PP(name), wFlags, pdp->cArgs);
|
||||||
|
|
||||||
|
/* convert args into zvals.
|
||||||
|
* Args are in reverse order */
|
||||||
|
params = (zval ***)emalloc(sizeof(zval **) * pdp->cArgs);
|
||||||
|
for (i = 0; i < pdp->cArgs; i++) {
|
||||||
|
VARIANT *arg;
|
||||||
|
zval *zarg;
|
||||||
|
|
||||||
|
arg = &pdp->rgvarg[ pdp->cArgs - 1 - i];
|
||||||
|
|
||||||
|
trace("alloc zval for arg %d VT=%08x\n", i, V_VT(arg));
|
||||||
|
|
||||||
|
ALLOC_INIT_ZVAL(zarg);
|
||||||
|
php_com_wrap_variant(zarg, arg, COMG(code_page) TSRMLS_CC);
|
||||||
|
params[i] = &zarg;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("arguments processed, prepare to do some work\n");
|
||||||
|
|
||||||
|
/* TODO: if PHP raises an exception here, we should catch it
|
||||||
|
* and expose it as a COM exception */
|
||||||
|
|
||||||
|
if (wFlags & DISPATCH_PROPERTYGET) {
|
||||||
|
retval = zend_read_property(Z_OBJCE_P(disp->object), disp->object, Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, 1 TSRMLS_CC);
|
||||||
|
} else if (wFlags & DISPATCH_PROPERTYPUT) {
|
||||||
|
zend_update_property(Z_OBJCE_P(disp->object), disp->object, Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, *params[0] TSRMLS_CC);
|
||||||
|
} else if (wFlags & DISPATCH_METHOD) {
|
||||||
|
if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name,
|
||||||
|
&retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) {
|
||||||
|
ret = S_OK;
|
||||||
|
} else {
|
||||||
|
ret = DISP_E_EXCEPTION;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace("Don't know how to handle this invocation %08x\n", wFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release arguments */
|
||||||
|
for (i = 0; i < pdp->cArgs; i++)
|
||||||
|
zval_ptr_dtor(params[i]);
|
||||||
|
efree(params);
|
||||||
|
|
||||||
|
/* return value */
|
||||||
|
if (retval) {
|
||||||
|
if (pvarRes) {
|
||||||
|
if (Z_TYPE_P(retval) == IS_OBJECT) {
|
||||||
|
/* export the object using a dispatch like ourselves */
|
||||||
|
VariantInit(pvarRes);
|
||||||
|
V_VT(pvarRes) = VT_DISPATCH;
|
||||||
|
V_DISPATCH(pvarRes) = php_com_wrapper_export(retval TSRMLS_CC);
|
||||||
|
} else {
|
||||||
|
php_com_variant_from_zval(pvarRes, retval, COMG(code_page) TSRMLS_CC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zval_ptr_dtor(&retval);
|
||||||
|
} else if (pvarRes) {
|
||||||
|
VariantInit(pvarRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
trace("InvokeEx: I don't support DISPID=%d\n", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_deletememberbyname(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ BSTR bstrName,
|
||||||
|
/* [in] */ DWORD grfdex)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("DeleteMemberByName");
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_deletememberbydispid(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DISPID id)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("DeleteMemberByDispID");
|
||||||
|
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getmemberproperties(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DISPID id,
|
||||||
|
/* [in] */ DWORD grfdexFetch,
|
||||||
|
/* [out] */ DWORD *pgrfdex)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetMemberProperties");
|
||||||
|
|
||||||
|
return DISP_E_UNKNOWNNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getmembername(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DISPID id,
|
||||||
|
/* [out] */ BSTR *pbstrName)
|
||||||
|
{
|
||||||
|
zval *name;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetMemberName");
|
||||||
|
|
||||||
|
if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) {
|
||||||
|
OLECHAR *olestr = php_com_string_to_olestring(Z_STRVAL_P(name), Z_STRLEN_P(name), COMG(code_page) TSRMLS_CC);
|
||||||
|
*pbstrName = SysAllocString(olestr);
|
||||||
|
efree(olestr);
|
||||||
|
return S_OK;
|
||||||
|
} else {
|
||||||
|
return DISP_E_UNKNOWNNAME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getnextdispid(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [in] */ DWORD grfdex,
|
||||||
|
/* [in] */ DISPID id,
|
||||||
|
/* [out] */ DISPID *pid)
|
||||||
|
{
|
||||||
|
ulong next = id+1;
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetNextDispID");
|
||||||
|
|
||||||
|
while(!zend_hash_index_exists(disp->dispid_to_name, next))
|
||||||
|
next++;
|
||||||
|
|
||||||
|
if (zend_hash_index_exists(disp->dispid_to_name, next)) {
|
||||||
|
*pid = next;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT STDMETHODCALLTYPE disp_getnamespaceparent(
|
||||||
|
IDispatchEx *This,
|
||||||
|
/* [out] */ IUnknown **ppunk)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
FETCH_DISP("GetNameSpaceParent");
|
||||||
|
|
||||||
|
*ppunk = NULL;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct IDispatchExVtbl php_dispatch_vtbl = {
|
||||||
|
disp_queryinterface,
|
||||||
|
disp_addref,
|
||||||
|
disp_release,
|
||||||
|
disp_gettypeinfocount,
|
||||||
|
disp_gettypeinfo,
|
||||||
|
disp_getidsofnames,
|
||||||
|
disp_invoke,
|
||||||
|
disp_getdispid,
|
||||||
|
disp_invokeex,
|
||||||
|
disp_deletememberbyname,
|
||||||
|
disp_deletememberbydispid,
|
||||||
|
disp_getmemberproperties,
|
||||||
|
disp_getmembername,
|
||||||
|
disp_getnextdispid,
|
||||||
|
disp_getnamespaceparent
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* enumerate functions and properties of the object and assign
|
||||||
|
* dispatch ids */
|
||||||
|
static void generate_dispids(php_dispatchex *disp TSRMLS_DC)
|
||||||
|
{
|
||||||
|
HashPosition pos;
|
||||||
|
char *name = NULL;
|
||||||
|
zval *tmp;
|
||||||
|
int namelen;
|
||||||
|
int keytype;
|
||||||
|
ulong pid;
|
||||||
|
|
||||||
|
if (disp->dispid_to_name == NULL) {
|
||||||
|
ALLOC_HASHTABLE(disp->dispid_to_name);
|
||||||
|
ALLOC_HASHTABLE(disp->name_to_dispid);
|
||||||
|
zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||||
|
zend_hash_init(disp->dispid_to_name, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* properties */
|
||||||
|
if (Z_OBJPROP_P(disp->object)) {
|
||||||
|
zend_hash_internal_pointer_reset_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||||
|
while (HASH_KEY_NON_EXISTANT != (keytype =
|
||||||
|
zend_hash_get_current_key_ex(Z_OBJPROP_P(disp->object), &name,
|
||||||
|
&namelen, &pid, 0, &pos))) {
|
||||||
|
char namebuf[32];
|
||||||
|
if (keytype == HASH_KEY_IS_LONG) {
|
||||||
|
sprintf(namebuf, "%d", pid);
|
||||||
|
name = namebuf;
|
||||||
|
namelen = strlen(namebuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_hash_move_forward_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||||
|
|
||||||
|
/* Find the existing id */
|
||||||
|
if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* add the mappings */
|
||||||
|
MAKE_STD_ZVAL(tmp);
|
||||||
|
ZVAL_STRINGL(tmp, name, namelen, 1);
|
||||||
|
zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL);
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(tmp);
|
||||||
|
ZVAL_LONG(tmp, pid);
|
||||||
|
zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
if (Z_OBJCE_P(disp->object)) {
|
||||||
|
zend_hash_internal_pointer_reset_ex(&Z_OBJCE_P(disp->object)->function_table, &pos);
|
||||||
|
while (HASH_KEY_NON_EXISTANT != (keytype =
|
||||||
|
zend_hash_get_current_key_ex(&Z_OBJCE_P(disp->object)->function_table,
|
||||||
|
&name, &namelen, &pid, 0, &pos))) {
|
||||||
|
|
||||||
|
char namebuf[32];
|
||||||
|
if (keytype == HASH_KEY_IS_LONG) {
|
||||||
|
sprintf(namebuf, "%d", pid);
|
||||||
|
name = namebuf;
|
||||||
|
namelen = strlen(namebuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_hash_move_forward_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||||
|
|
||||||
|
/* Find the existing id */
|
||||||
|
if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* add the mappings */
|
||||||
|
MAKE_STD_ZVAL(tmp);
|
||||||
|
ZVAL_STRINGL(tmp, name, namelen, 1);
|
||||||
|
zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL);
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(tmp);
|
||||||
|
ZVAL_LONG(tmp, pid);
|
||||||
|
zend_hash_update(disp->name_to_dispid, name, namelen+1, (void*)&tmp, sizeof(zval *), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static php_dispatchex *disp_constructor(zval *object TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex));
|
||||||
|
|
||||||
|
trace("constructing a COM proxy\n");
|
||||||
|
|
||||||
|
if (disp == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(disp, 0, sizeof(php_dispatchex));
|
||||||
|
|
||||||
|
disp->engine_thread = tsrm_thread_id();
|
||||||
|
disp->lpVtbl = &php_dispatch_vtbl;
|
||||||
|
disp->refcount = 1;
|
||||||
|
|
||||||
|
|
||||||
|
if (object)
|
||||||
|
ZVAL_ADDREF(object);
|
||||||
|
disp->object = object;
|
||||||
|
|
||||||
|
disp->id = zend_list_insert(disp, le_dispatch);
|
||||||
|
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disp_destructor(php_dispatchex *disp)
|
||||||
|
{
|
||||||
|
TSRMLS_FETCH();
|
||||||
|
|
||||||
|
trace("destroying COM wrapper for PHP object %s\n", Z_OBJCE_P(disp->object)->name);
|
||||||
|
|
||||||
|
disp->id = 0;
|
||||||
|
|
||||||
|
if (disp->refcount > 0)
|
||||||
|
CoDisconnectObject((IUnknown*)disp, 0);
|
||||||
|
|
||||||
|
zend_hash_destroy(disp->dispid_to_name);
|
||||||
|
zend_hash_destroy(disp->name_to_dispid);
|
||||||
|
FREE_HASHTABLE(disp->dispid_to_name);
|
||||||
|
FREE_HASHTABLE(disp->name_to_dispid);
|
||||||
|
|
||||||
|
if (disp->object)
|
||||||
|
zval_ptr_dtor(&disp->object);
|
||||||
|
|
||||||
|
CoTaskMemFree(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
PHPAPI IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *sinkid,
|
||||||
|
HashTable *id_to_name TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_dispatchex *disp = disp_constructor(val TSRMLS_CC);
|
||||||
|
HashPosition pos;
|
||||||
|
char *name = NULL;
|
||||||
|
zval *tmp, **ntmp;
|
||||||
|
int namelen;
|
||||||
|
int keytype;
|
||||||
|
ulong pid;
|
||||||
|
|
||||||
|
disp->dispid_to_name = id_to_name;
|
||||||
|
|
||||||
|
memcpy(&disp->sinkid, sinkid, sizeof(disp->sinkid));
|
||||||
|
|
||||||
|
/* build up the reverse mapping */
|
||||||
|
ALLOC_HASHTABLE(disp->name_to_dispid);
|
||||||
|
zend_hash_init(disp->name_to_dispid, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||||
|
|
||||||
|
zend_hash_internal_pointer_reset_ex(id_to_name, &pos);
|
||||||
|
while (HASH_KEY_NON_EXISTANT != (keytype =
|
||||||
|
zend_hash_get_current_key_ex(id_to_name, &name, &namelen, &pid, 0, &pos))) {
|
||||||
|
|
||||||
|
if (keytype == HASH_KEY_IS_LONG) {
|
||||||
|
|
||||||
|
zend_hash_get_current_data_ex(id_to_name, (void**)&ntmp, &pos);
|
||||||
|
|
||||||
|
MAKE_STD_ZVAL(tmp);
|
||||||
|
ZVAL_LONG(tmp, pid);
|
||||||
|
zend_hash_update(disp->name_to_dispid, Z_STRVAL_PP(ntmp),
|
||||||
|
Z_STRLEN_PP(ntmp)+1, (void*)&tmp, sizeof(zval *), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
zend_hash_move_forward_ex(id_to_name, &pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (IDispatch*)disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
PHPAPI IDispatch *php_com_wrapper_export(zval *val TSRMLS_DC)
|
||||||
|
{
|
||||||
|
php_dispatchex *disp = NULL;
|
||||||
|
|
||||||
|
if (Z_TYPE_P(val) != IS_OBJECT)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (php_com_is_valid_object(val TSRMLS_CC)) {
|
||||||
|
/* pass back its IDispatch directly */
|
||||||
|
php_com_dotnet_object *obj = CDNO_FETCH(val);
|
||||||
|
|
||||||
|
if (obj == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (V_VT(&obj->v) == VT_DISPATCH && V_DISPATCH(&obj->v)) {
|
||||||
|
IDispatch_AddRef(V_DISPATCH(&obj->v));
|
||||||
|
return V_DISPATCH(&obj->v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
disp = disp_constructor(val TSRMLS_CC);
|
||||||
|
generate_dispids(disp TSRMLS_CC);
|
||||||
|
|
||||||
|
return (IDispatch*)disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ if (PHP_COM_DOTNET == "yes") {
|
||||||
CHECK_LIB('oleaut32.lib', 'com_dotnet');
|
CHECK_LIB('oleaut32.lib', 'com_dotnet');
|
||||||
EXTENSION("com_dotnet", "com_com.c com_dotnet.c com_extension.c \
|
EXTENSION("com_dotnet", "com_com.c com_dotnet.c com_extension.c \
|
||||||
com_handlers.c com_iterator.c com_misc.c com_olechar.c \
|
com_handlers.c com_iterator.c com_misc.c com_olechar.c \
|
||||||
com_typeinfo.c com_variant.c");
|
com_typeinfo.c com_variant.c com_wrapper.c com_saproxy.c");
|
||||||
AC_DEFINE('HAVE_COM_DOTNET', 1, 'Have COM_DOTNET support');
|
AC_DEFINE('HAVE_COM_DOTNET', 1, 'Have COM_DOTNET support');
|
||||||
CHECK_HEADER_ADD_INCLUDE('mscoree.h', 'CFLAGS_COM_DOTNET');
|
CHECK_HEADER_ADD_INCLUDE('mscoree.h', 'CFLAGS_COM_DOTNET');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -40,14 +40,13 @@ PHP_RINIT_FUNCTION(com_dotnet);
|
||||||
PHP_RSHUTDOWN_FUNCTION(com_dotnet);
|
PHP_RSHUTDOWN_FUNCTION(com_dotnet);
|
||||||
PHP_MINFO_FUNCTION(com_dotnet);
|
PHP_MINFO_FUNCTION(com_dotnet);
|
||||||
|
|
||||||
PHP_FUNCTION(com_create_guid);
|
|
||||||
|
|
||||||
ZEND_BEGIN_MODULE_GLOBALS(com_dotnet)
|
ZEND_BEGIN_MODULE_GLOBALS(com_dotnet)
|
||||||
zend_bool allow_dcom;
|
zend_bool allow_dcom;
|
||||||
zend_bool autoreg_verbose;
|
zend_bool autoreg_verbose;
|
||||||
zend_bool autoreg_on;
|
zend_bool autoreg_on;
|
||||||
zend_bool autoreg_case_sensitive;
|
zend_bool autoreg_case_sensitive;
|
||||||
void *dotnet_runtime_stuff; /* opaque to avoid cluttering up other modules */
|
void *dotnet_runtime_stuff; /* opaque to avoid cluttering up other modules */
|
||||||
|
int code_page; /* default code_page if left unspecified */
|
||||||
ZEND_END_MODULE_GLOBALS(com_dotnet)
|
ZEND_END_MODULE_GLOBALS(com_dotnet)
|
||||||
|
|
||||||
#ifdef ZTS
|
#ifdef ZTS
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| PHP Version 4 |
|
| PHP Version 5 |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
| Copyright (c) 1997-2003 The PHP Group |
|
| Copyright (c) 1997-2003 The PHP Group |
|
||||||
+----------------------------------------------------------------------+
|
+----------------------------------------------------------------------+
|
||||||
|
@ -41,6 +41,11 @@ typedef struct _php_com_dotnet_object {
|
||||||
|
|
||||||
zend_class_entry *ce;
|
zend_class_entry *ce;
|
||||||
DISPID default_bind; /* default property for array accesses */
|
DISPID default_bind; /* default property for array accesses */
|
||||||
|
|
||||||
|
/* associated event sink */
|
||||||
|
IDispatch *sink_dispatch;
|
||||||
|
GUID sink_id;
|
||||||
|
DWORD sink_cookie;
|
||||||
} php_com_dotnet_object;
|
} php_com_dotnet_object;
|
||||||
|
|
||||||
static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
|
static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
|
||||||
|
@ -54,7 +59,7 @@ static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
|
||||||
#define CDNO_FETCH(zv) (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC)
|
#define CDNO_FETCH(zv) (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC)
|
||||||
#define CDNO_FETCH_VERIFY(obj, zv) do { \
|
#define CDNO_FETCH_VERIFY(obj, zv) do { \
|
||||||
if (!php_com_is_valid_object(zv TSRMLS_CC)) { \
|
if (!php_com_is_valid_object(zv TSRMLS_CC)) { \
|
||||||
php_com_throw_exception("expected a variant object" TSRMLS_CC); \
|
php_com_throw_exception(E_UNEXPECTED, "expected a variant object" TSRMLS_CC); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
obj = (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC); \
|
obj = (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC); \
|
||||||
|
@ -62,13 +67,18 @@ static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
|
||||||
|
|
||||||
/* com_extension.c */
|
/* com_extension.c */
|
||||||
TsHashTable php_com_typelibraries;
|
TsHashTable php_com_typelibraries;
|
||||||
zend_class_entry *php_com_variant_class_entry;
|
zend_class_entry *php_com_variant_class_entry, *php_com_exception_class_entry, *php_com_saproxy_class_entry;
|
||||||
|
|
||||||
/* com_handlers.c */
|
/* com_handlers.c */
|
||||||
zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC);
|
zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC);
|
||||||
void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC);
|
void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC);
|
||||||
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC);
|
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC);
|
||||||
zend_object_handlers php_com_object_handlers;
|
zend_object_handlers php_com_object_handlers;
|
||||||
|
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable TSRMLS_DC);
|
||||||
|
|
||||||
|
/* com_saproxy.c */
|
||||||
|
zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC);
|
||||||
|
int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC);
|
||||||
|
|
||||||
/* com_olechar.c */
|
/* com_olechar.c */
|
||||||
PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring,
|
PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring,
|
||||||
|
@ -79,6 +89,12 @@ PHPAPI OLECHAR *php_com_string_to_olestring(char *string,
|
||||||
|
|
||||||
/* com_com.c */
|
/* com_com.c */
|
||||||
PHP_FUNCTION(com_create_instance);
|
PHP_FUNCTION(com_create_instance);
|
||||||
|
PHP_FUNCTION(com_event_sink);
|
||||||
|
PHP_FUNCTION(com_create_guid);
|
||||||
|
PHP_FUNCTION(com_print_typeinfo);
|
||||||
|
PHP_FUNCTION(com_message_pump);
|
||||||
|
PHP_FUNCTION(com_load_typelib);
|
||||||
|
|
||||||
HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
|
HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
|
||||||
WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC);
|
WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC);
|
||||||
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
||||||
|
@ -88,6 +104,11 @@ int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
|
||||||
int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
|
int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
|
||||||
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC);
|
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC);
|
||||||
|
|
||||||
|
/* com_wrapper.c */
|
||||||
|
int php_com_wrapper_minit(INIT_FUNC_ARGS);
|
||||||
|
PHPAPI IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC);
|
||||||
|
PHPAPI IDispatch *php_com_wrapper_export(zval *val TSRMLS_DC);
|
||||||
|
|
||||||
/* com_variant.c */
|
/* com_variant.c */
|
||||||
PHP_FUNCTION(com_variant_create_instance);
|
PHP_FUNCTION(com_variant_create_instance);
|
||||||
PHP_FUNCTION(variant_set);
|
PHP_FUNCTION(variant_set);
|
||||||
|
@ -127,20 +148,22 @@ void php_com_dotnet_rshutdown(TSRMLS_D);
|
||||||
void php_com_dotnet_mshutdown(TSRMLS_D);
|
void php_com_dotnet_mshutdown(TSRMLS_D);
|
||||||
|
|
||||||
/* com_misc.c */
|
/* com_misc.c */
|
||||||
zval *php_com_throw_exception(char *message TSRMLS_DC);
|
void php_com_throw_exception(HRESULT code, char *message TSRMLS_DC);
|
||||||
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
|
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
|
||||||
int codepage TSRMLS_DC);
|
int codepage TSRMLS_DC);
|
||||||
PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
|
PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
|
||||||
int codepage TSRMLS_DC);
|
int codepage TSRMLS_DC);
|
||||||
|
PHPAPI int php_com_safearray_get_elem(VARIANT *array, VARIANT *dest, LONG dim1 TSRMLS_DC);
|
||||||
|
|
||||||
/* com_typeinfo.c */
|
/* com_typeinfo.c */
|
||||||
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||||
int mode, int codepage, int *cached TSRMLS_DC);
|
int codepage, int *cached TSRMLS_DC);
|
||||||
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
|
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int codepage TSRMLS_DC);
|
||||||
int codepage TSRMLS_DC);
|
|
||||||
PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode,
|
PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode,
|
||||||
int codepage TSRMLS_DC);
|
int codepage TSRMLS_DC);
|
||||||
void php_com_typelibrary_dtor(void *pDest);
|
void php_com_typelibrary_dtor(void *pDest);
|
||||||
|
ITypeInfo *php_com_locate_typeinfo(char *typelibname, php_com_dotnet_object *obj, char *dispname, int sink TSRMLS_DC);
|
||||||
|
int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid, int codepage TSRMLS_DC);
|
||||||
|
|
||||||
/* com_iterator.c */
|
/* com_iterator.c */
|
||||||
zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC);
|
zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue