mirror of
https://github.com/php/php-src.git
synced 2024-12-03 23:05:57 +08:00
Implemented ext/com_dotnet support for phpng
This commit is contained in:
parent
4c716e8b51
commit
8013a27ad9
@ -333,6 +333,39 @@ ZEND_API int zend_ts_hash_rehash(TsHashTable *ht)
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_read(ht);
|
||||
retval = zend_hash_str_find(TS_HASH(ht), key, len);
|
||||
end_read(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_str_update(TS_HASH(ht), key, len, pData);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC)
|
||||
{
|
||||
zval *retval;
|
||||
|
||||
begin_write(ht);
|
||||
retval = zend_hash_str_add(TS_HASH(ht), key, len, pData);
|
||||
end_write(ht);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
@ -102,6 +102,41 @@ void zend_ts_hash_display_pListTail(TsHashTable *ht);
|
||||
void zend_ts_hash_display(TsHashTable *ht);
|
||||
#endif
|
||||
|
||||
ZEND_API zval *zend_ts_hash_str_find(TsHashTable *ht, const char *key, int len);
|
||||
ZEND_API zval *_zend_ts_hash_str_update(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
ZEND_API zval *_zend_ts_hash_str_add(TsHashTable *ht, const char *key, int len, zval *pData ZEND_FILE_LINE_DC);
|
||||
|
||||
#define zend_ts_hash_str_update(ht, key, len, pData) \
|
||||
_zend_ts_hash_str_update(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
#define zend_ts_hash_str_add(ht, key, len, pData) \
|
||||
_zend_ts_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC)
|
||||
|
||||
static inline void *zend_ts_hash_str_find_ptr(TsHashTable *ht, const char *str, int len)
|
||||
{
|
||||
zval *zv;
|
||||
|
||||
zv = zend_ts_hash_str_find(ht, str, len);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_ts_hash_str_update_ptr(TsHashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_ts_hash_str_update(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
static inline void *zend_ts_hash_str_add_ptr(TsHashTable *ht, const char *str, int len, void *pData)
|
||||
{
|
||||
zval tmp, *zv;
|
||||
|
||||
ZVAL_PTR(&tmp, pData);
|
||||
zv = zend_ts_hash_str_add(ht, str, len, &tmp);
|
||||
return zv ? Z_PTR_P(zv) : NULL;
|
||||
}
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_TS_INIT_SYMTABLE(ht) \
|
||||
|
102
ext/com_dotnet/com_com.c
Normal file → Executable file
102
ext/com_dotnet/com_com.c
Normal file → Executable file
@ -66,50 +66,50 @@ PHP_FUNCTION(com_create_instance)
|
||||
&typelib_name, &typelib_name_len)) {
|
||||
|
||||
php_com_throw_exception(E_INVALIDARG, "Could not create COM object - invalid arguments!" TSRMLS_CC);
|
||||
ZVAL_NULL(object);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
if (server_name) {
|
||||
ctx = CLSCTX_REMOTE_SERVER;
|
||||
} else if (server_params) {
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
|
||||
/* decode the data from the array */
|
||||
|
||||
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
|
||||
"Server", sizeof("Server"), (void**)&tmp)) {
|
||||
if (NULL != (tmp = zend_hash_str_find(HASH_OF(server_params),
|
||||
"Server", sizeof("Server")-1))) {
|
||||
convert_to_string_ex(tmp);
|
||||
server_name = Z_STRVAL_PP(tmp);
|
||||
server_name_len = Z_STRLEN_PP(tmp);
|
||||
server_name = Z_STRVAL_P(tmp);
|
||||
server_name_len = Z_STRLEN_P(tmp);
|
||||
ctx = CLSCTX_REMOTE_SERVER;
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
|
||||
"Username", sizeof("Username"), (void**)&tmp)) {
|
||||
if (NULL != (tmp = zend_hash_str_find(HASH_OF(server_params),
|
||||
"Username", sizeof("Username")-1))) {
|
||||
convert_to_string_ex(tmp);
|
||||
user_name = Z_STRVAL_PP(tmp);
|
||||
user_name_len = Z_STRLEN_PP(tmp);
|
||||
user_name = Z_STRVAL_P(tmp);
|
||||
user_name_len = Z_STRLEN_P(tmp);
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
|
||||
"Password", sizeof("Password"), (void**)&tmp)) {
|
||||
if (NULL != (tmp = zend_hash_str_find(HASH_OF(server_params),
|
||||
"Password", sizeof("Password")-1))) {
|
||||
convert_to_string_ex(tmp);
|
||||
password = Z_STRVAL_PP(tmp);
|
||||
password_len = Z_STRLEN_PP(tmp);
|
||||
password = Z_STRVAL_P(tmp);
|
||||
password_len = Z_STRLEN_P(tmp);
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
|
||||
"Domain", sizeof("Domain"), (void**)&tmp)) {
|
||||
if (NULL != (tmp = zend_hash_str_find(HASH_OF(server_params),
|
||||
"Domain", sizeof("Domain")-1))) {
|
||||
convert_to_string_ex(tmp);
|
||||
domain_name = Z_STRVAL_PP(tmp);
|
||||
domain_name_len = Z_STRLEN_PP(tmp);
|
||||
domain_name = Z_STRVAL_P(tmp);
|
||||
domain_name_len = Z_STRLEN_P(tmp);
|
||||
}
|
||||
|
||||
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
|
||||
"Flags", sizeof("Flags"), (void**)&tmp)) {
|
||||
if (NULL != (tmp = zend_hash_str_find(HASH_OF(server_params),
|
||||
"Flags", sizeof("Flags")-1))) {
|
||||
convert_to_long_ex(tmp);
|
||||
ctx = (CLSCTX)Z_LVAL_PP(tmp);
|
||||
ctx = (CLSCTX)Z_LVAL_P(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,8 +215,8 @@ PHP_FUNCTION(com_create_instance)
|
||||
}
|
||||
|
||||
if (server_name) {
|
||||
STR_FREE((char*)info.pwszName);
|
||||
STR_FREE((char*)authid.User);
|
||||
if (info.pwszName) efree(info.pwszName);
|
||||
if (authid.User) efree(authid.User);
|
||||
}
|
||||
|
||||
efree(moniker);
|
||||
@ -230,7 +230,7 @@ PHP_FUNCTION(com_create_instance)
|
||||
|
||||
php_com_throw_exception(res, msg TSRMLS_CC);
|
||||
efree(msg);
|
||||
ZVAL_NULL(object);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -263,7 +263,7 @@ PHP_FUNCTION(com_create_instance)
|
||||
if (SUCCEEDED(ITypeLib_GetDocumentation(TL, -1, &name, NULL, NULL, NULL))) {
|
||||
typelib_name = php_com_olestring_to_string(name, &typelib_name_len, obj->code_page TSRMLS_CC);
|
||||
|
||||
if (SUCCESS == zend_ts_hash_add(&php_com_typelibraries, typelib_name, typelib_name_len+1, (void*)&TL, sizeof(ITypeLib*), NULL)) {
|
||||
if (NULL != zend_ts_hash_str_add_ptr(&php_com_typelibraries, typelib_name, typelib_name_len, TL)) {
|
||||
php_com_import_typelib(TL, mode, obj->code_page TSRMLS_CC);
|
||||
|
||||
/* add a reference for the hash */
|
||||
@ -420,14 +420,14 @@ HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
||||
{
|
||||
OLECHAR *olename;
|
||||
HRESULT hr;
|
||||
DISPID *dispid_ptr;
|
||||
zval *tmp;
|
||||
|
||||
if (namelen == -1) {
|
||||
namelen = strlen(name);
|
||||
}
|
||||
|
||||
if (obj->id_of_name_cache && SUCCESS == zend_hash_find(obj->id_of_name_cache, name, namelen, (void**)&dispid_ptr)) {
|
||||
*dispid = *dispid_ptr;
|
||||
if (obj->id_of_name_cache && NULL != (tmp = zend_hash_str_find(obj->id_of_name_cache, name, namelen))) {
|
||||
*dispid = Z_LVAL_P(tmp);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -449,12 +449,15 @@ HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
||||
efree(olename);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
zval tmp;
|
||||
|
||||
/* cache the mapping */
|
||||
if (!obj->id_of_name_cache) {
|
||||
ALLOC_HASHTABLE(obj->id_of_name_cache);
|
||||
zend_hash_init(obj->id_of_name_cache, 2, NULL, NULL, 0);
|
||||
}
|
||||
zend_hash_update(obj->id_of_name_cache, name, namelen, dispid, sizeof(*dispid), NULL);
|
||||
ZVAL_LONG(&tmp, *dispid);
|
||||
zend_hash_str_update(obj->id_of_name_cache, name, namelen, &tmp);
|
||||
}
|
||||
|
||||
return hr;
|
||||
@ -462,14 +465,14 @@ HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
||||
|
||||
/* the core of COM */
|
||||
int php_com_do_invoke_byref(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)
|
||||
{
|
||||
DISPID dispid, altdispid;
|
||||
DISPPARAMS disp_params;
|
||||
HRESULT hr;
|
||||
VARIANT *vargs = NULL, *byref_vals = NULL;
|
||||
int i, byref_count = 0, j;
|
||||
zend_internal_function *f = (zend_internal_function*)EG(current_execute_data)->function_state.function;
|
||||
zend_internal_function *f = (zend_internal_function*)EG(current_execute_data)->func;
|
||||
|
||||
/* assumption: that the active function (f) is the function we generated for the engine */
|
||||
if (!f || f->arg_info == NULL) {
|
||||
@ -507,7 +510,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
for (j = 0, i = 0; i < nargs; i++) {
|
||||
if (f->arg_info[nargs - i - 1].pass_by_reference) {
|
||||
/* put the value into byref_vals instead */
|
||||
php_com_variant_from_zval(&byref_vals[j], *args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
php_com_variant_from_zval(&byref_vals[j], &args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
|
||||
/* if it is already byref, "move" it into the vargs array, otherwise
|
||||
* make vargs a reference to this value */
|
||||
@ -522,14 +525,14 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
}
|
||||
j++;
|
||||
} else {
|
||||
php_com_variant_from_zval(&vargs[i], *args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Invoke'd args are in reverse order */
|
||||
for (i = 0; i < nargs; i++) {
|
||||
php_com_variant_from_zval(&vargs[i], *args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +555,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
for (i = 0, j = 0; i < nargs; i++) {
|
||||
/* if this was byref, update the zval */
|
||||
if (f && f->arg_info[nargs - i - 1].pass_by_reference) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(args[nargs - i - 1]);
|
||||
SEPARATE_ZVAL_IF_NOT_REF(&args[nargs - i - 1]);
|
||||
|
||||
/* if the variant is pointing at the byref_vals, we need to map
|
||||
* the pointee value as a zval; otherwise, the value is pointing
|
||||
@ -560,13 +563,13 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
if (V_VT(&vargs[i]) & VT_BYREF) {
|
||||
if (vargs[i].byref == &V_UINT(&byref_vals[j])) {
|
||||
/* copy that value */
|
||||
php_com_zval_from_variant(*args[nargs - i - 1], &byref_vals[j],
|
||||
php_com_zval_from_variant(&args[nargs - i - 1], &byref_vals[j],
|
||||
obj->code_page TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
/* not sure if this can ever happen; the variant we marked as BYREF
|
||||
* is no longer BYREF - copy its value */
|
||||
php_com_zval_from_variant(*args[nargs - i - 1], &vargs[i],
|
||||
php_com_zval_from_variant(&args[nargs - i - 1], &vargs[i],
|
||||
obj->code_page TSRMLS_CC);
|
||||
}
|
||||
VariantClear(&byref_vals[j]);
|
||||
@ -583,7 +586,7 @@ int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
|
||||
|
||||
int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
|
||||
WORD flags, VARIANT *v, int nargs, zval **args, int silent, int allow_noarg TSRMLS_DC)
|
||||
WORD flags, VARIANT *v, int nargs, zval *args, int silent, int allow_noarg TSRMLS_DC)
|
||||
{
|
||||
DISPID altdispid;
|
||||
DISPPARAMS disp_params;
|
||||
@ -597,7 +600,7 @@ int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
|
||||
|
||||
/* Invoke'd args are in reverse order */
|
||||
for (i = 0; i < nargs; i++) {
|
||||
php_com_variant_from_zval(&vargs[i], args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
php_com_variant_from_zval(&vargs[i], &args[nargs - i - 1], obj->code_page TSRMLS_CC);
|
||||
}
|
||||
|
||||
disp_params.cArgs = nargs;
|
||||
@ -630,7 +633,7 @@ 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,
|
||||
WORD flags, VARIANT *v, int nargs, zval **args, int allow_noarg TSRMLS_DC)
|
||||
WORD flags, VARIANT *v, int nargs, zval *args, int allow_noarg TSRMLS_DC)
|
||||
{
|
||||
DISPID dispid;
|
||||
HRESULT hr;
|
||||
@ -664,8 +667,13 @@ PHP_FUNCTION(com_create_guid)
|
||||
|
||||
php_com_initialize(TSRMLS_C);
|
||||
if (CoCreateGuid(&retval) == S_OK && StringFromCLSID(&retval, &guid_string) == S_OK) {
|
||||
Z_TYPE_P(return_value) = IS_STRING;
|
||||
Z_STRVAL_P(return_value) = php_com_olestring_to_string(guid_string, &Z_STRLEN_P(return_value), CP_ACP TSRMLS_CC);
|
||||
int len;
|
||||
char *str;
|
||||
|
||||
str = php_com_olestring_to_string(guid_string, &len, CP_ACP TSRMLS_CC);
|
||||
RETVAL_STRINGL(str, len);
|
||||
// TODO: avoid reallocation ???
|
||||
efree(str);
|
||||
|
||||
CoTaskMemFree(guid_string);
|
||||
} else {
|
||||
@ -696,12 +704,12 @@ PHP_FUNCTION(com_event_sink)
|
||||
|
||||
if (sink && Z_TYPE_P(sink) == IS_ARRAY) {
|
||||
/* 0 => typelibname, 1 => dispname */
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
|
||||
if (zend_hash_index_find(Z_ARRVAL_P(sink), 0, (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING)
|
||||
typelibname = Z_STRVAL_PP(tmp);
|
||||
if (zend_hash_index_find(Z_ARRVAL_P(sink), 1, (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING)
|
||||
dispname = Z_STRVAL_PP(tmp);
|
||||
if ((tmp = zend_hash_index_find(Z_ARRVAL_P(sink), 0)) != NULL && Z_TYPE_P(tmp) == IS_STRING)
|
||||
typelibname = Z_STRVAL_P(tmp);
|
||||
if ((tmp = zend_hash_index_find(Z_ARRVAL_P(sink), 1)) != NULL && Z_TYPE_P(tmp) == IS_STRING)
|
||||
dispname = Z_STRVAL_P(tmp);
|
||||
} else if (sink != NULL) {
|
||||
convert_to_string(sink);
|
||||
dispname = Z_STRVAL_P(sink);
|
||||
|
6
ext/com_dotnet/com_dotnet.c
Normal file → Executable file
6
ext/com_dotnet/com_dotnet.c
Normal file → Executable file
@ -207,7 +207,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||
if (err)
|
||||
LocalFree(err);
|
||||
php_com_throw_exception(hr, buf TSRMLS_CC);
|
||||
ZVAL_NULL(object);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -221,7 +221,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||
&datatype_name, &datatype_name_len,
|
||||
&obj->code_page)) {
|
||||
php_com_throw_exception(E_INVALIDARG, "Could not create .Net object - invalid arguments!" TSRMLS_CC);
|
||||
ZVAL_NULL(object);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
|
||||
LocalFree(err);
|
||||
}
|
||||
php_com_throw_exception(hr, buf TSRMLS_CC);
|
||||
ZVAL_NULL(object);
|
||||
ZEND_CTOR_MAKE_NULL();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
147
ext/com_dotnet/com_handlers.c
Normal file → Executable file
147
ext/com_dotnet/com_handlers.c
Normal file → Executable file
@ -29,42 +29,38 @@
|
||||
#include "php_com_dotnet_internal.h"
|
||||
#include "Zend/zend_exceptions.h"
|
||||
|
||||
static zval *com_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
|
||||
static zval *com_property_read(zval *object, zval *member, int type, void **cahce_slot, zval *rv TSRMLS_DC)
|
||||
{
|
||||
zval *return_value;
|
||||
php_com_dotnet_object *obj;
|
||||
VARIANT v;
|
||||
HRESULT res;
|
||||
|
||||
MAKE_STD_ZVAL(return_value);
|
||||
ZVAL_NULL(return_value);
|
||||
Z_SET_REFCOUNT_P(return_value, 0);
|
||||
Z_UNSET_ISREF_P(return_value);
|
||||
ZVAL_NULL(rv);
|
||||
|
||||
obj = CDNO_FETCH(object);
|
||||
|
||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||
VariantInit(&v);
|
||||
|
||||
convert_to_string_ex(&member);
|
||||
convert_to_string_ex(member);
|
||||
|
||||
res = php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
|
||||
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL, 1 TSRMLS_CC);
|
||||
|
||||
if (res == SUCCESS) {
|
||||
php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
||||
php_com_zval_from_variant(rv, &v, obj->code_page TSRMLS_CC);
|
||||
VariantClear(&v);
|
||||
} else if (res == DISP_E_BADPARAMCOUNT) {
|
||||
php_com_saproxy_create(object, return_value, member TSRMLS_CC);
|
||||
php_com_saproxy_create(object, rv, member TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
php_com_throw_exception(E_INVALIDARG, "this variant has no properties" TSRMLS_CC);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void com_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
|
||||
static void com_property_write(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
VARIANT v;
|
||||
@ -74,9 +70,9 @@ static void com_property_write(zval *object, zval *member, zval *value, const ze
|
||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||
VariantInit(&v);
|
||||
|
||||
convert_to_string_ex(&member);
|
||||
convert_to_string_ex(member);
|
||||
if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
|
||||
DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF, &v, 1, &value, 0 TSRMLS_CC)) {
|
||||
DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF, &v, 1, value, 0 TSRMLS_CC)) {
|
||||
VariantClear(&v);
|
||||
}
|
||||
} else {
|
||||
@ -84,16 +80,12 @@ static void com_property_write(zval *object, zval *member, zval *value, const ze
|
||||
}
|
||||
}
|
||||
|
||||
static zval *com_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
|
||||
static zval *com_read_dimension(zval *object, zval *offset, int type, zval *rv TSRMLS_DC)
|
||||
{
|
||||
zval *return_value;
|
||||
php_com_dotnet_object *obj;
|
||||
VARIANT v;
|
||||
|
||||
MAKE_STD_ZVAL(return_value);
|
||||
ZVAL_NULL(return_value);
|
||||
Z_SET_REFCOUNT_P(return_value, 0);
|
||||
Z_UNSET_ISREF_P(return_value);
|
||||
ZVAL_NULL(rv);
|
||||
|
||||
obj = CDNO_FETCH(object);
|
||||
|
||||
@ -101,8 +93,8 @@ static zval *com_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
|
||||
VariantInit(&v);
|
||||
|
||||
if (SUCCESS == php_com_do_invoke_by_id(obj, DISPID_VALUE,
|
||||
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, &offset, 0, 0 TSRMLS_CC)) {
|
||||
php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
||||
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, offset, 0, 0 TSRMLS_CC)) {
|
||||
php_com_zval_from_variant(rv, &v, obj->code_page TSRMLS_CC);
|
||||
VariantClear(&v);
|
||||
}
|
||||
} else if (V_ISARRAY(&obj->v)) {
|
||||
@ -110,32 +102,32 @@ static zval *com_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
|
||||
|
||||
if (SafeArrayGetDim(V_ARRAY(&obj->v)) == 1) {
|
||||
if (php_com_safearray_get_elem(&obj->v, &v, Z_LVAL_P(offset) TSRMLS_CC)) {
|
||||
php_com_wrap_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
||||
php_com_wrap_variant(rv, &v, obj->code_page TSRMLS_CC);
|
||||
VariantClear(&v);
|
||||
}
|
||||
} else {
|
||||
php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
|
||||
php_com_saproxy_create(object, rv, offset TSRMLS_CC);
|
||||
}
|
||||
|
||||
} else {
|
||||
php_com_throw_exception(E_INVALIDARG, "this variant is not an array type" TSRMLS_CC);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
zval *args[2];
|
||||
zval args[2];
|
||||
VARIANT v;
|
||||
HRESULT res;
|
||||
|
||||
obj = CDNO_FETCH(object);
|
||||
|
||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||
args[0] = offset;
|
||||
args[1] = value;
|
||||
ZVAL_COPY_VALUE(&args[0], offset);
|
||||
ZVAL_COPY_VALUE(&args[1], value);
|
||||
|
||||
VariantInit(&v);
|
||||
|
||||
@ -196,7 +188,7 @@ static zval *com_object_get(zval *property TSRMLS_DC)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int com_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
|
||||
static int com_property_exists(zval *object, zval *member, int check_empty, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
DISPID dispid;
|
||||
php_com_dotnet_object *obj;
|
||||
@ -204,7 +196,7 @@ static int com_property_exists(zval *object, zval *member, int check_empty, cons
|
||||
obj = CDNO_FETCH(object);
|
||||
|
||||
if (V_VT(&obj->v) == VT_DISPATCH) {
|
||||
convert_to_string_ex(&member);
|
||||
convert_to_string_ex(member);
|
||||
if (SUCCEEDED(php_com_get_id_of_name(obj, Z_STRVAL_P(member), Z_STRLEN_P(member), &dispid TSRMLS_CC))) {
|
||||
/* TODO: distinguish between property and method! */
|
||||
return 1;
|
||||
@ -222,7 +214,7 @@ static int com_dimension_exists(zval *object, zval *member, int check_empty TSRM
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void com_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
|
||||
static void com_property_delete(zval *object, zval *member, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
|
||||
}
|
||||
@ -242,49 +234,50 @@ static HashTable *com_properties_get(zval *object TSRMLS_DC)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void function_dtor(void *pDest)
|
||||
static void function_dtor(zval *zv)
|
||||
{
|
||||
zend_internal_function *f = (zend_internal_function*)pDest;
|
||||
zend_internal_function *f = (zend_internal_function*)Z_PTR_P(zv);
|
||||
|
||||
efree((char*)f->function_name);
|
||||
STR_RELEASE(f->function_name);
|
||||
if (f->arg_info) {
|
||||
efree(f->arg_info);
|
||||
}
|
||||
efree(f);
|
||||
}
|
||||
|
||||
static PHP_FUNCTION(com_method_handler)
|
||||
{
|
||||
Z_OBJ_HANDLER_P(getThis(), call_method)(
|
||||
((zend_internal_function*)EG(current_execute_data)->function_state.function)->function_name,
|
||||
zval *object = getThis();
|
||||
|
||||
Z_OBJ_HANDLER_P(object, call_method)(
|
||||
((zend_internal_function*)EG(current_execute_data)->func)->function_name,
|
||||
Z_OBJ_P(object),
|
||||
INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
}
|
||||
|
||||
static union _zend_function *com_method_get(zval **object_ptr, char *name, int len, const zend_literal *key TSRMLS_DC)
|
||||
static union _zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key TSRMLS_DC)
|
||||
{
|
||||
zend_internal_function f, *fptr = NULL;
|
||||
php_com_dotnet_object *obj;
|
||||
union _zend_function *func;
|
||||
DISPID dummy;
|
||||
zval *object = *object_ptr;
|
||||
|
||||
obj = CDNO_FETCH(object);
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object*)*object_ptr;
|
||||
|
||||
if (V_VT(&obj->v) != VT_DISPATCH) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (FAILED(php_com_get_id_of_name(obj, name, len, &dummy TSRMLS_CC))) {
|
||||
if (FAILED(php_com_get_id_of_name(obj, name->val, name->len, &dummy TSRMLS_CC))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check cache */
|
||||
if (obj->method_cache == NULL || FAILURE == zend_hash_find(obj->method_cache, name, len, (void**)&fptr)) {
|
||||
if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) {
|
||||
f.type = ZEND_OVERLOADED_FUNCTION;
|
||||
f.num_args = 0;
|
||||
f.arg_info = NULL;
|
||||
f.scope = obj->ce;
|
||||
f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
||||
f.function_name = estrndup(name, len);
|
||||
f.function_name = STR_COPY(name);
|
||||
f.handler = PHP_FN(com_method_handler);
|
||||
|
||||
fptr = &f;
|
||||
@ -300,7 +293,7 @@ static union _zend_function *com_method_get(zval **object_ptr, char *name, int l
|
||||
int i;
|
||||
|
||||
if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
|
||||
olename = php_com_string_to_olestring(name, len, obj->code_page TSRMLS_CC);
|
||||
olename = php_com_string_to_olestring(name->val, name->len, obj->code_page TSRMLS_CC);
|
||||
lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename);
|
||||
|
||||
if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) {
|
||||
@ -348,7 +341,7 @@ static union _zend_function *com_method_get(zval **object_ptr, char *name, int l
|
||||
zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0);
|
||||
}
|
||||
|
||||
zend_hash_update(obj->method_cache, name, len, &f, sizeof(f), (void**)&fptr);
|
||||
zend_hash_update_mem(obj->method_cache, name, &f, sizeof(f));
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,15 +357,13 @@ static union _zend_function *com_method_get(zval **object_ptr, char *name, int l
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int com_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||
static int com_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
|
||||
{
|
||||
zval ***args = NULL;
|
||||
php_com_dotnet_object *obj;
|
||||
zval *args = NULL;
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
|
||||
int nargs;
|
||||
VARIANT v;
|
||||
int ret = FAILURE;
|
||||
|
||||
obj = CDNO_FETCH(getThis());
|
||||
|
||||
if (V_VT(&obj->v) != VT_DISPATCH) {
|
||||
return FAILURE;
|
||||
@ -381,13 +372,13 @@ static int com_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||
nargs = ZEND_NUM_ARGS();
|
||||
|
||||
if (nargs) {
|
||||
args = (zval ***)safe_emalloc(sizeof(zval *), nargs, 0);
|
||||
args = (zval *)safe_emalloc(sizeof(zval), nargs, 0);
|
||||
zend_get_parameters_array_ex(nargs, args);
|
||||
}
|
||||
|
||||
VariantInit(&v);
|
||||
|
||||
if (SUCCESS == php_com_do_invoke_byref(obj, (char*)method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) {
|
||||
if (SUCCESS == php_com_do_invoke_byref(obj, method->val, method->len, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) {
|
||||
php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
|
||||
ret = SUCCESS;
|
||||
VariantClear(&v);
|
||||
@ -400,16 +391,14 @@ static int com_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
|
||||
static union _zend_function *com_constructor_get(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object *) object;
|
||||
static zend_internal_function c, d, v;
|
||||
|
||||
obj = CDNO_FETCH(object);
|
||||
|
||||
#define POPULATE_CTOR(f, fn) \
|
||||
f.type = ZEND_INTERNAL_FUNCTION; \
|
||||
f.function_name = (char *) obj->ce->name; \
|
||||
f.function_name = obj->ce->name; \
|
||||
f.scope = obj->ce; \
|
||||
f.arg_info = NULL; \
|
||||
f.num_args = 0; \
|
||||
@ -417,7 +406,7 @@ static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
|
||||
f.handler = ZEND_FN(fn); \
|
||||
return (union _zend_function*)&f;
|
||||
|
||||
switch (obj->ce->name[0]) {
|
||||
switch (obj->ce->name->val[0]) {
|
||||
#if HAVE_MSCOREE_H
|
||||
case 'd':
|
||||
POPULATE_CTOR(d, com_dotnet_create_instance);
|
||||
@ -434,23 +423,18 @@ static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
static zend_class_entry *com_class_entry_get(const zval *object TSRMLS_DC)
|
||||
static zend_class_entry *com_class_entry_get(const zend_object *object TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
obj = CDNO_FETCH(object);
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object *)object;
|
||||
|
||||
return obj->ce;
|
||||
}
|
||||
|
||||
static int com_class_name_get(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
|
||||
static zend_string* com_class_name_get(const zend_object *object, int parent TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
obj = CDNO_FETCH(object);
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object *)object;
|
||||
|
||||
*class_name = estrndup(obj->ce->name, obj->ce->name_length);
|
||||
*class_name_len = obj->ce->name_length;
|
||||
|
||||
return 0;
|
||||
return STR_COPY(obj->ce->name);
|
||||
}
|
||||
|
||||
/* This compares two variants for equality */
|
||||
@ -513,7 +497,8 @@ static int com_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
|
||||
case IS_DOUBLE:
|
||||
vt = VT_R8;
|
||||
break;
|
||||
case IS_BOOL:
|
||||
case IS_FALSE:
|
||||
case IS_TRUE:
|
||||
vt = VT_BOOL;
|
||||
break;
|
||||
case IS_STRING:
|
||||
@ -560,7 +545,10 @@ static int com_object_count(zval *object, long *count TSRMLS_DC)
|
||||
}
|
||||
|
||||
zend_object_handlers php_com_object_handlers = {
|
||||
ZEND_OBJECTS_STORE_HANDLERS,
|
||||
0,
|
||||
php_com_object_free_storage,
|
||||
zend_objects_destroy_object,
|
||||
php_com_object_clone,
|
||||
com_property_read,
|
||||
com_property_write,
|
||||
com_read_dimension,
|
||||
@ -610,7 +598,7 @@ void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable TSR
|
||||
}
|
||||
}
|
||||
|
||||
void php_com_object_free_storage(void *object TSRMLS_DC)
|
||||
void php_com_object_free_storage(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
|
||||
|
||||
@ -635,14 +623,13 @@ void php_com_object_free_storage(void *object TSRMLS_DC)
|
||||
zend_hash_destroy(obj->id_of_name_cache);
|
||||
FREE_HASHTABLE(obj->id_of_name_cache);
|
||||
}
|
||||
efree(obj);
|
||||
}
|
||||
|
||||
void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC)
|
||||
zend_object* php_com_object_clone(zval *object TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *cloneobj, *origobject;
|
||||
|
||||
origobject = (php_com_dotnet_object*)object;
|
||||
origobject = (php_com_dotnet_object*)Z_OBJ_P(object);
|
||||
cloneobj = (php_com_dotnet_object*)emalloc(sizeof(php_com_dotnet_object));
|
||||
|
||||
memcpy(cloneobj, origobject, sizeof(*cloneobj));
|
||||
@ -659,13 +646,12 @@ void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC)
|
||||
ITypeInfo_AddRef(cloneobj->typeinfo);
|
||||
}
|
||||
|
||||
*clone_ptr = cloneobj;
|
||||
return (zend_object*)cloneobj;
|
||||
}
|
||||
|
||||
zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC)
|
||||
zend_object* php_com_object_new(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
php_com_dotnet_object *obj;
|
||||
zend_object_value retval;
|
||||
|
||||
php_com_initialize(TSRMLS_C);
|
||||
obj = emalloc(sizeof(*obj));
|
||||
@ -674,10 +660,9 @@ zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC)
|
||||
VariantInit(&obj->v);
|
||||
obj->code_page = CP_ACP;
|
||||
obj->ce = ce;
|
||||
obj->zo.ce = ce;
|
||||
|
||||
retval.handle = zend_objects_store_put(obj, NULL, php_com_object_free_storage, php_com_object_clone TSRMLS_CC);
|
||||
retval.handlers = &php_com_object_handlers;
|
||||
zend_object_std_init(&obj->zo, ce TSRMLS_CC);
|
||||
obj->zo.handlers = &php_com_object_handlers;
|
||||
|
||||
return retval;
|
||||
return (zend_object*)obj;
|
||||
}
|
||||
|
56
ext/com_dotnet/com_iterator.c
Normal file → Executable file
56
ext/com_dotnet/com_iterator.c
Normal file → Executable file
@ -38,45 +38,42 @@ struct php_com_iterator {
|
||||
VARIANT safe_array;
|
||||
VARTYPE sa_type;
|
||||
LONG sa_max;
|
||||
zval *zdata;
|
||||
zval zdata;
|
||||
};
|
||||
|
||||
static void com_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
|
||||
|
||||
if (I->ev) {
|
||||
IEnumVARIANT_Release(I->ev);
|
||||
}
|
||||
VariantClear(&I->v);
|
||||
VariantClear(&I->safe_array);
|
||||
if (I->zdata) {
|
||||
zval_ptr_dtor((zval**)&I->zdata);
|
||||
}
|
||||
efree(I);
|
||||
zval_ptr_dtor(&I->zdata);
|
||||
}
|
||||
|
||||
static int com_iter_valid(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
|
||||
|
||||
if (I->zdata) {
|
||||
if (Z_TYPE(I->zdata) != IS_UNDEF) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void com_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
|
||||
static zval* com_iter_get_data(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
|
||||
|
||||
*data = &I->zdata;
|
||||
return &I->zdata;
|
||||
}
|
||||
|
||||
static void com_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
|
||||
{
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
|
||||
|
||||
if (I->key == (ulong)-1) {
|
||||
ZVAL_NULL(key);
|
||||
@ -87,16 +84,16 @@ static void com_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
|
||||
|
||||
static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)iter->data;
|
||||
struct php_com_iterator *I = (struct php_com_iterator*)Z_PTR(iter->data);
|
||||
unsigned long n_fetched;
|
||||
zval *ptr;
|
||||
zval ptr;
|
||||
|
||||
/* release current cached element */
|
||||
VariantClear(&I->v);
|
||||
|
||||
if (I->zdata) {
|
||||
zval_ptr_dtor((zval**)&I->zdata);
|
||||
I->zdata = NULL;
|
||||
if (Z_TYPE(I->zdata) != IS_UNDEF) {
|
||||
zval_ptr_dtor(&I->zdata);
|
||||
ZVAL_UNDEF(&I->zdata);
|
||||
}
|
||||
|
||||
if (I->ev) {
|
||||
@ -121,10 +118,10 @@ static int com_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
MAKE_STD_ZVAL(ptr);
|
||||
php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
|
||||
ZVAL_NULL(&ptr);
|
||||
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); */
|
||||
I->zdata = ptr;
|
||||
ZVAL_COPY_VALUE(&I->zdata, &ptr);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -146,7 +143,7 @@ zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int b
|
||||
DISPPARAMS dp;
|
||||
VARIANT v;
|
||||
unsigned long n_fetched;
|
||||
zval *ptr;
|
||||
zval ptr;
|
||||
|
||||
if (by_ref) {
|
||||
zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
|
||||
@ -163,10 +160,11 @@ zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int b
|
||||
VariantInit(&v);
|
||||
|
||||
I = (struct php_com_iterator*)ecalloc(1, sizeof(*I));
|
||||
zend_iterator_init(&I->iter TSRMLS_CC);
|
||||
I->iter.funcs = &com_iter_funcs;
|
||||
I->iter.data = I;
|
||||
Z_PTR(I->iter.data) = I;
|
||||
I->code_page = obj->code_page;
|
||||
I->zdata = NULL;
|
||||
ZVAL_UNDEF(&I->zdata);
|
||||
VariantInit(&I->safe_array);
|
||||
VariantInit(&I->v);
|
||||
|
||||
@ -193,9 +191,9 @@ zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int b
|
||||
/* pre-fetch the element */
|
||||
if (php_com_safearray_get_elem(&I->safe_array, &I->v, bound TSRMLS_CC)) {
|
||||
I->key = bound;
|
||||
MAKE_STD_ZVAL(ptr);
|
||||
php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
|
||||
I->zdata = ptr;
|
||||
ZVAL_NULL(&ptr);
|
||||
php_com_zval_from_variant(&ptr, &I->v, I->code_page TSRMLS_CC);
|
||||
ZVAL_COPY_VALUE(&I->zdata, &ptr);
|
||||
} else {
|
||||
I->key = (ulong)-1;
|
||||
}
|
||||
@ -227,9 +225,9 @@ zend_object_iterator *php_com_iter_get(zend_class_entry *ce, zval *object, int b
|
||||
if (SUCCEEDED(IEnumVARIANT_Next(I->ev, 1, &I->v, &n_fetched)) && n_fetched > 0) {
|
||||
/* indicate that we have element 0 */
|
||||
I->key = 0;
|
||||
MAKE_STD_ZVAL(ptr);
|
||||
php_com_zval_from_variant(ptr, &I->v, I->code_page TSRMLS_CC);
|
||||
I->zdata = ptr;
|
||||
ZVAL_NULL(&ptr);
|
||||
php_com_zval_from_variant(&ptr, &I->v, I->code_page TSRMLS_CC);
|
||||
ZVAL_COPY_VALUE(&I->zdata, &ptr);
|
||||
} else {
|
||||
/* indicate that there are no more items */
|
||||
I->key = (ulong)-1;
|
||||
|
13
ext/com_dotnet/com_misc.c
Normal file → Executable file
13
ext/com_dotnet/com_misc.c
Normal file → Executable file
@ -60,9 +60,9 @@ PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp,
|
||||
IDispatch_AddRef(V_DISPATCH(&obj->v));
|
||||
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
|
||||
|
||||
Z_TYPE_P(z) = IS_OBJECT;
|
||||
z->value.obj.handle = zend_objects_store_put(obj, NULL, php_com_object_free_storage, php_com_object_clone TSRMLS_CC);
|
||||
z->value.obj.handlers = &php_com_object_handlers;
|
||||
zend_object_std_init(&obj->zo, php_com_variant_class_entry TSRMLS_CC);
|
||||
obj->zo.handlers = &php_com_object_handlers;
|
||||
ZVAL_OBJ(z, &obj->zo);
|
||||
}
|
||||
|
||||
PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v,
|
||||
@ -84,10 +84,9 @@ PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v,
|
||||
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
|
||||
}
|
||||
|
||||
Z_TYPE_P(z) = IS_OBJECT;
|
||||
|
||||
z->value.obj.handle = zend_objects_store_put(obj, NULL, php_com_object_free_storage, php_com_object_clone TSRMLS_CC);
|
||||
z->value.obj.handlers = &php_com_object_handlers;
|
||||
zend_object_std_init(&obj->zo, php_com_variant_class_entry TSRMLS_CC);
|
||||
obj->zo.handlers = &php_com_object_handlers;
|
||||
ZVAL_OBJ(z, &obj->zo);
|
||||
}
|
||||
|
||||
/* this is a convenience function for fetching a particular
|
||||
|
60
ext/com_dotnet/com_persist.c
Normal file → Executable file
60
ext/com_dotnet/com_persist.c
Normal file → Executable file
@ -41,13 +41,13 @@ typedef struct {
|
||||
DWORD engine_thread;
|
||||
LONG refcount;
|
||||
php_stream *stream;
|
||||
int id;
|
||||
zend_resource *res;
|
||||
} php_istream;
|
||||
|
||||
static int le_istream;
|
||||
static void istream_destructor(php_istream *stm TSRMLS_DC);
|
||||
|
||||
static void istream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
static void istream_dtor(zend_resource *rsrc TSRMLS_DC)
|
||||
{
|
||||
php_istream *stm = (php_istream *)rsrc->ptr;
|
||||
istream_destructor(stm TSRMLS_CC);
|
||||
@ -97,8 +97,8 @@ static ULONG STDMETHODCALLTYPE stm_release(IStream *This)
|
||||
ret = InterlockedDecrement(&stm->refcount);
|
||||
if (ret == 0) {
|
||||
/* destroy it */
|
||||
if (stm->id)
|
||||
zend_list_delete(stm->id);
|
||||
if (stm->res)
|
||||
zend_list_delete(stm->res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -251,10 +251,10 @@ static struct IStreamVtbl php_istream_vtbl = {
|
||||
|
||||
static void istream_destructor(php_istream *stm TSRMLS_DC)
|
||||
{
|
||||
if (stm->id) {
|
||||
int id = stm->id;
|
||||
stm->id = 0;
|
||||
zend_list_delete(id);
|
||||
if (stm->res) {
|
||||
zend_resource *res = stm->res;
|
||||
stm->res = NULL;
|
||||
zend_list_delete(res);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ static void istream_destructor(php_istream *stm TSRMLS_DC)
|
||||
CoDisconnectObject((IUnknown*)stm, 0);
|
||||
}
|
||||
|
||||
zend_list_delete(stm->stream->rsrc_id);
|
||||
zend_list_delete(stm->stream->res);
|
||||
|
||||
CoTaskMemFree(stm);
|
||||
}
|
||||
@ -271,6 +271,7 @@ static void istream_destructor(php_istream *stm TSRMLS_DC)
|
||||
PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream TSRMLS_DC)
|
||||
{
|
||||
php_istream *stm = (php_istream*)CoTaskMemAlloc(sizeof(*stm));
|
||||
zval *tmp;
|
||||
|
||||
if (stm == NULL)
|
||||
return NULL;
|
||||
@ -281,8 +282,9 @@ PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream TSR
|
||||
stm->refcount = 1;
|
||||
stm->stream = stream;
|
||||
|
||||
zend_list_addref(stream->rsrc_id);
|
||||
stm->id = zend_list_insert(stm, le_istream TSRMLS_CC);
|
||||
GC_REFCOUNT(stream->res)++;
|
||||
tmp = zend_list_insert(stm, le_istream TSRMLS_CC);
|
||||
stm->res = Z_RES_P(tmp);
|
||||
|
||||
return (IStream*)stm;
|
||||
}
|
||||
@ -291,7 +293,7 @@ PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream TSR
|
||||
#define CPH_SME(fname, arginfo) PHP_ME(com_persist, fname, arginfo, ZEND_ACC_ALLOW_STATIC|ZEND_ACC_PUBLIC)
|
||||
#define CPH_METHOD(fname) static PHP_METHOD(com_persist, fname)
|
||||
|
||||
#define CPH_FETCH() php_com_persist_helper *helper = (php_com_persist_helper*)zend_object_store_get_object(getThis() TSRMLS_CC);
|
||||
#define CPH_FETCH() php_com_persist_helper *helper = (php_com_persist_helper*)Z_OBJ_P(getThis());
|
||||
|
||||
#define CPH_NO_OBJ() if (helper->unk == NULL) { php_com_throw_exception(E_INVALIDARG, "No COM object is associated with this helper instance" TSRMLS_CC); return; }
|
||||
|
||||
@ -347,9 +349,12 @@ CPH_METHOD(GetCurFileName)
|
||||
res = IPersistFile_GetCurFile(helper->ipf, &olename);
|
||||
|
||||
if (res == S_OK) {
|
||||
Z_TYPE_P(return_value) = IS_STRING;
|
||||
Z_STRVAL_P(return_value) = php_com_olestring_to_string(olename,
|
||||
&Z_STRLEN_P(return_value), helper->codepage TSRMLS_CC);
|
||||
int len;
|
||||
char *str = php_com_olestring_to_string(olename,
|
||||
&len, helper->codepage TSRMLS_CC);
|
||||
RETVAL_STRINGL(str, len);
|
||||
// TODO: avoid reallocarion???
|
||||
efree(str);
|
||||
CoTaskMemFree(olename);
|
||||
return;
|
||||
} else if (res == S_FALSE) {
|
||||
@ -545,7 +550,7 @@ CPH_METHOD(LoadFromStream)
|
||||
return;
|
||||
}
|
||||
|
||||
php_stream_from_zval_no_verify(stream, &zstm);
|
||||
php_stream_from_zval_no_verify(stream, zstm);
|
||||
|
||||
if (stream == NULL) {
|
||||
php_com_throw_exception(E_INVALIDARG, "expected a stream" TSRMLS_CC);
|
||||
@ -607,7 +612,7 @@ CPH_METHOD(SaveToStream)
|
||||
return;
|
||||
}
|
||||
|
||||
php_stream_from_zval_no_verify(stream, &zstm);
|
||||
php_stream_from_zval_no_verify(stream, zstm);
|
||||
|
||||
if (stream == NULL) {
|
||||
php_com_throw_exception(E_INVALIDARG, "expected a stream" TSRMLS_CC);
|
||||
@ -688,7 +693,7 @@ static const zend_function_entry com_persist_helper_methods[] = {
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
static void helper_free_storage(void *obj TSRMLS_DC)
|
||||
static void helper_free_storage(zend_object *obj TSRMLS_DC)
|
||||
{
|
||||
php_com_persist_helper *object = (php_com_persist_helper*)obj;
|
||||
|
||||
@ -705,17 +710,15 @@ static void helper_free_storage(void *obj TSRMLS_DC)
|
||||
IUnknown_Release(object->unk);
|
||||
}
|
||||
zend_object_std_dtor(&object->std TSRMLS_CC);
|
||||
efree(object);
|
||||
}
|
||||
|
||||
|
||||
static void helper_clone(void *obj, void **clone_ptr TSRMLS_DC)
|
||||
static zend_object* helper_clone(zval *obj TSRMLS_DC)
|
||||
{
|
||||
php_com_persist_helper *clone, *object = (php_com_persist_helper*)obj;
|
||||
php_com_persist_helper *clone, *object = (php_com_persist_helper*)Z_OBJ_P(obj);
|
||||
|
||||
clone = emalloc(sizeof(*object));
|
||||
memcpy(clone, object, sizeof(*object));
|
||||
*clone_ptr = clone;
|
||||
|
||||
zend_object_std_init(&clone->std, object->std.ce TSRMLS_CC);
|
||||
|
||||
@ -731,22 +734,20 @@ static void helper_clone(void *obj, void **clone_ptr TSRMLS_DC)
|
||||
if (clone->unk) {
|
||||
IUnknown_AddRef(clone->unk);
|
||||
}
|
||||
return (zend_object*)clone;
|
||||
}
|
||||
|
||||
static zend_object_value helper_new(zend_class_entry *ce TSRMLS_DC)
|
||||
static zend_object* helper_new(zend_class_entry *ce TSRMLS_DC)
|
||||
{
|
||||
php_com_persist_helper *helper;
|
||||
zend_object_value retval;
|
||||
|
||||
helper = emalloc(sizeof(*helper));
|
||||
memset(helper, 0, sizeof(*helper));
|
||||
|
||||
zend_object_std_init(&helper->std, helper_ce TSRMLS_CC);
|
||||
|
||||
retval.handle = zend_objects_store_put(helper, NULL, helper_free_storage, helper_clone TSRMLS_CC);
|
||||
retval.handlers = &helper_handlers;
|
||||
helper->std.handlers = &helper_handlers;
|
||||
|
||||
return retval;
|
||||
return &helper->std;
|
||||
}
|
||||
|
||||
int php_com_persist_minit(INIT_FUNC_ARGS)
|
||||
@ -754,7 +755,8 @@ int php_com_persist_minit(INIT_FUNC_ARGS)
|
||||
zend_class_entry ce;
|
||||
|
||||
memcpy(&helper_handlers, zend_get_std_object_handlers(), sizeof(helper_handlers));
|
||||
helper_handlers.clone_obj = NULL;
|
||||
helper_handlers.free_obj = helper_free_storage;
|
||||
helper_handlers.clone_obj = helper_clone;
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "COMPersistHelper", com_persist_helper_methods);
|
||||
ce.create_object = helper_new;
|
||||
|
205
ext/com_dotnet/com_saproxy.c
Normal file → Executable file
205
ext/com_dotnet/com_saproxy.c
Normal file → Executable file
@ -37,6 +37,7 @@
|
||||
#include "Zend/zend_exceptions.h"
|
||||
|
||||
typedef struct {
|
||||
zend_object std;
|
||||
/* the object we a proxying for; we hold a refcount to it */
|
||||
zval *zobj;
|
||||
php_com_dotnet_object *obj;
|
||||
@ -45,95 +46,89 @@ typedef struct {
|
||||
LONG dimensions;
|
||||
|
||||
/* this is an array whose size_is(dimensions) */
|
||||
zval **indices;
|
||||
zval *indices;
|
||||
|
||||
} php_com_saproxy;
|
||||
|
||||
typedef struct {
|
||||
zend_object_iterator iter;
|
||||
zval *proxy_obj;
|
||||
zval proxy_obj;
|
||||
zval data;
|
||||
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)
|
||||
#define SA_FETCH(zv) (php_com_saproxy*)Z_OBJ_P(zv)
|
||||
|
||||
static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int ndims)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ndims; i++) {
|
||||
MAKE_STD_ZVAL(dest->indices[i]);
|
||||
*dest->indices[i] = *src->indices[i];
|
||||
zval_copy_ctor(dest->indices[i]);
|
||||
ZVAL_DUP(&dest->indices[i], &src->indices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static zval *saproxy_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
|
||||
static zval *saproxy_property_read(zval *object, zval *member, int type, void **cahce_slot, zval *rv TSRMLS_DC)
|
||||
{
|
||||
zval *return_value;
|
||||
|
||||
MAKE_STD_ZVAL(return_value);
|
||||
ZVAL_NULL(return_value);
|
||||
ZVAL_NULL(rv);
|
||||
|
||||
php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
|
||||
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void saproxy_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
|
||||
static void saproxy_property_write(zval *object, zval *member, zval *value, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_com_throw_exception(E_INVALIDARG, "safearray has no properties" TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
|
||||
static zval *saproxy_read_dimension(zval *object, zval *offset, int type, zval *rv TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy *proxy = SA_FETCH(object);
|
||||
zval *return_value;
|
||||
UINT dims, i;
|
||||
SAFEARRAY *sa;
|
||||
LONG ubound, lbound;
|
||||
HRESULT res;
|
||||
|
||||
MAKE_STD_ZVAL(return_value);
|
||||
ZVAL_NULL(return_value);
|
||||
ZVAL_NULL(rv);
|
||||
|
||||
if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
|
||||
VARIANT v;
|
||||
zval **args;
|
||||
zval *args;
|
||||
|
||||
/* prop-get using first dimension as the property name,
|
||||
* all subsequent dimensions and the offset as parameters */
|
||||
|
||||
args = safe_emalloc(proxy->dimensions + 1, sizeof(zval *), 0);
|
||||
args = safe_emalloc(proxy->dimensions + 1, sizeof(zval), 0);
|
||||
|
||||
for (i = 1; i < (UINT) proxy->dimensions; i++) {
|
||||
args[i-1] = proxy->indices[i];
|
||||
}
|
||||
args[i-1] = offset;
|
||||
ZVAL_COPY_VALUE(&args[i-1], offset);
|
||||
|
||||
convert_to_string(proxy->indices[0]);
|
||||
convert_to_string(&proxy->indices[0]);
|
||||
VariantInit(&v);
|
||||
|
||||
res = php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
|
||||
Z_STRLEN_P(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
|
||||
res = php_com_do_invoke(proxy->obj, Z_STRVAL(proxy->indices[0]),
|
||||
Z_STRLEN(proxy->indices[0]), DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
|
||||
proxy->dimensions, args, 0 TSRMLS_CC);
|
||||
|
||||
if (res == SUCCESS) {
|
||||
php_com_zval_from_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
|
||||
php_com_zval_from_variant(rv, &v, proxy->obj->code_page TSRMLS_CC);
|
||||
VariantClear(&v);
|
||||
} else if (res == DISP_E_BADPARAMCOUNT) {
|
||||
/* return another proxy */
|
||||
php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
|
||||
php_com_saproxy_create(object, rv, offset TSRMLS_CC);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
return rv;
|
||||
|
||||
} else if (!V_ISARRAY(&proxy->obj->v)) {
|
||||
php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy object" TSRMLS_CC);
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* the SafeArray case */
|
||||
@ -147,7 +142,7 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
|
||||
if ((UINT) proxy->dimensions >= dims) {
|
||||
/* too many dimensions */
|
||||
php_com_throw_exception(E_INVALIDARG, "too many dimensions!" TSRMLS_CC);
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* bounds check */
|
||||
@ -156,7 +151,7 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
|
||||
|
||||
if (Z_LVAL_P(offset) < lbound || Z_LVAL_P(offset) > ubound) {
|
||||
php_com_throw_exception(DISP_E_BADINDEX, "index out of bounds" TSRMLS_CC);
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (dims - 1 == proxy->dimensions) {
|
||||
@ -171,8 +166,8 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
|
||||
|
||||
/* copy indices from proxy */
|
||||
for (i = 0; i < dims; i++) {
|
||||
convert_to_long(proxy->indices[i]);
|
||||
indices[i] = Z_LVAL_P(proxy->indices[i]);
|
||||
convert_to_long(&proxy->indices[i]);
|
||||
indices[i] = Z_LVAL(proxy->indices[i]);
|
||||
}
|
||||
|
||||
/* add user-supplied index */
|
||||
@ -193,7 +188,7 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
|
||||
efree(indices);
|
||||
|
||||
if (SUCCEEDED(res)) {
|
||||
php_com_wrap_variant(return_value, &v, proxy->obj->code_page TSRMLS_CC);
|
||||
php_com_wrap_variant(rv, &v, proxy->obj->code_page TSRMLS_CC);
|
||||
} else {
|
||||
php_com_throw_exception(res, NULL TSRMLS_CC);
|
||||
}
|
||||
@ -202,10 +197,10 @@ static zval *saproxy_read_dimension(zval *object, zval *offset, int type TSRMLS_
|
||||
|
||||
} else {
|
||||
/* return another proxy */
|
||||
php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
|
||||
php_com_saproxy_create(object, rv, offset TSRMLS_CC);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
|
||||
@ -219,18 +214,18 @@ static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRM
|
||||
/* We do a prop-set using the first dimension as the property name,
|
||||
* all subsequent dimensions and offset as parameters, with value as
|
||||
* the final value */
|
||||
zval **args = safe_emalloc(proxy->dimensions + 2, sizeof(zval *), 0);
|
||||
zval *args = safe_emalloc(proxy->dimensions + 2, sizeof(zval), 0);
|
||||
|
||||
for (i = 1; i < (UINT) proxy->dimensions; i++) {
|
||||
args[i-1] = proxy->indices[i];
|
||||
ZVAL_COPY_VALUE(&args[i-1], &proxy->indices[i]);
|
||||
}
|
||||
args[i-1] = offset;
|
||||
args[i] = value;
|
||||
ZVAL_COPY_VALUE(&args[i-1], offset);
|
||||
ZVAL_COPY_VALUE(&args[i], value);
|
||||
|
||||
convert_to_string(proxy->indices[0]);
|
||||
convert_to_string(&proxy->indices[0]);
|
||||
VariantInit(&v);
|
||||
if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
|
||||
Z_STRLEN_P(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
|
||||
if (SUCCESS == php_com_do_invoke(proxy->obj, Z_STRVAL(proxy->indices[0]),
|
||||
Z_STRLEN(proxy->indices[0]), DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
|
||||
args, 0 TSRMLS_CC)) {
|
||||
VariantClear(&v);
|
||||
}
|
||||
@ -245,8 +240,8 @@ static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRM
|
||||
indices = safe_emalloc(dims, sizeof(LONG), 0);
|
||||
/* copy indices from proxy */
|
||||
for (i = 0; i < dims; i++) {
|
||||
convert_to_long(proxy->indices[i]);
|
||||
indices[i] = Z_LVAL_P(proxy->indices[i]);
|
||||
convert_to_long(&proxy->indices[i]);
|
||||
indices[i] = Z_LVAL(proxy->indices[i]);
|
||||
}
|
||||
|
||||
/* add user-supplied index */
|
||||
@ -293,7 +288,7 @@ static zval *saproxy_object_get(zval *property TSRMLS_DC)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int saproxy_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
|
||||
static int saproxy_property_exists(zval *object, zval *member, int check_empty, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
/* no properties */
|
||||
return 0;
|
||||
@ -305,7 +300,7 @@ static int saproxy_dimension_exists(zval *object, zval *member, int check_empty
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void saproxy_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
|
||||
static void saproxy_property_delete(zval *object, zval *member, void **cache_slot TSRMLS_DC)
|
||||
{
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a COM object");
|
||||
}
|
||||
@ -321,33 +316,31 @@ static HashTable *saproxy_properties_get(zval *object TSRMLS_DC)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static union _zend_function *saproxy_method_get(zval **object, const char *name, int len, const zend_literal *key TSRMLS_DC)
|
||||
static union _zend_function *saproxy_method_get(zend_object **object, zend_string *name, const zval *key TSRMLS_DC)
|
||||
{
|
||||
/* no methods */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int saproxy_call_method(const char *method, INTERNAL_FUNCTION_PARAMETERS)
|
||||
static int saproxy_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS)
|
||||
{
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static union _zend_function *saproxy_constructor_get(zval *object TSRMLS_DC)
|
||||
static union _zend_function *saproxy_constructor_get(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
/* user cannot instantiate */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static zend_class_entry *saproxy_class_entry_get(const zval *object TSRMLS_DC)
|
||||
static zend_class_entry *saproxy_class_entry_get(const zend_object *object TSRMLS_DC)
|
||||
{
|
||||
return php_com_saproxy_class_entry;
|
||||
}
|
||||
|
||||
static int saproxy_class_name_get(const zval *object, const char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
|
||||
static zend_string* saproxy_class_name_get(const zend_object *object, 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;
|
||||
return STR_COPY(php_com_saproxy_class_entry->name);
|
||||
}
|
||||
|
||||
static int saproxy_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
|
||||
@ -377,8 +370,41 @@ static int saproxy_count_elements(zval *object, long *count TSRMLS_DC)
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void saproxy_free_storage(zend_object *object TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy *proxy = (php_com_saproxy *)object;
|
||||
//??? int i;
|
||||
//???
|
||||
//??? for (i = 0; i < proxy->dimensions; i++) {
|
||||
//??? if (proxy->indices) {
|
||||
//??? FREE_ZVAL(proxy->indices[i]);
|
||||
//??? }
|
||||
//??? }
|
||||
|
||||
zval_ptr_dtor(proxy->zobj);
|
||||
efree(proxy->indices);
|
||||
}
|
||||
|
||||
static zend_object* saproxy_clone(zval *object TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy *proxy = (php_com_saproxy *)Z_OBJ_P(object);
|
||||
php_com_saproxy *cloneproxy;
|
||||
|
||||
cloneproxy = emalloc(sizeof(*cloneproxy));
|
||||
memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
|
||||
|
||||
Z_ADDREF_P(cloneproxy->zobj);
|
||||
cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
|
||||
clone_indices(cloneproxy, proxy, proxy->dimensions);
|
||||
|
||||
return &cloneproxy->std;
|
||||
}
|
||||
|
||||
zend_object_handlers php_com_saproxy_handlers = {
|
||||
ZEND_OBJECTS_STORE_HANDLERS,
|
||||
0,
|
||||
saproxy_free_storage,
|
||||
zend_objects_destroy_object,
|
||||
saproxy_clone,
|
||||
saproxy_property_read,
|
||||
saproxy_property_write,
|
||||
saproxy_read_dimension,
|
||||
@ -401,37 +427,6 @@ zend_object_handlers php_com_saproxy_handlers = {
|
||||
saproxy_count_elements
|
||||
};
|
||||
|
||||
static void saproxy_free_storage(void *object TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy *proxy = (php_com_saproxy *)object;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < proxy->dimensions; i++) {
|
||||
if (proxy->indices) {
|
||||
FREE_ZVAL(proxy->indices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&proxy->zobj);
|
||||
efree(proxy->indices);
|
||||
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));
|
||||
|
||||
Z_ADDREF_P(cloneproxy->zobj);
|
||||
cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
|
||||
clone_indices(cloneproxy, proxy, proxy->dimensions);
|
||||
|
||||
*clone_ptr = cloneproxy;
|
||||
}
|
||||
|
||||
int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy *proxy, *rel = NULL;
|
||||
@ -456,13 +451,11 @@ int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS
|
||||
clone_indices(proxy, rel, rel->dimensions);
|
||||
}
|
||||
|
||||
MAKE_STD_ZVAL(proxy->indices[proxy->dimensions-1]);
|
||||
*proxy->indices[proxy->dimensions-1] = *index;
|
||||
zval_copy_ctor(proxy->indices[proxy->dimensions-1]);
|
||||
ZVAL_DUP(&proxy->indices[proxy->dimensions-1], index);
|
||||
|
||||
Z_TYPE_P(proxy_out) = IS_OBJECT;
|
||||
Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, NULL, saproxy_free_storage, saproxy_clone TSRMLS_CC);
|
||||
Z_OBJ_HT_P(proxy_out) = &php_com_saproxy_handlers;
|
||||
zend_object_std_init(&proxy->std, php_com_saproxy_class_entry TSRMLS_CC);
|
||||
proxy->std.handlers = &php_com_saproxy_handlers;
|
||||
ZVAL_OBJ(proxy_out, &proxy->std);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -471,7 +464,7 @@ int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS
|
||||
|
||||
static void saproxy_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data);
|
||||
|
||||
zval_ptr_dtor(&I->proxy_obj);
|
||||
|
||||
@ -481,17 +474,16 @@ static void saproxy_iter_dtor(zend_object_iterator *iter TSRMLS_DC)
|
||||
|
||||
static int saproxy_iter_valid(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data);
|
||||
|
||||
return (I->key < I->imax) ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
|
||||
static zval* saproxy_iter_get_data(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data);
|
||||
VARIANT v;
|
||||
VARTYPE vt;
|
||||
zval *return_value, **ptr_ptr;
|
||||
SAFEARRAY *sa;
|
||||
|
||||
I->indices[I->proxy->dimensions-1] = I->key;
|
||||
@ -510,18 +502,16 @@ static void saproxy_iter_get_data(zend_object_iterator *iter, zval ***data TSRML
|
||||
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);
|
||||
ZVAL_NULL(&I->data);
|
||||
php_com_wrap_variant(&I->data, &v, I->proxy->obj->code_page TSRMLS_CC);
|
||||
VariantClear(&v);
|
||||
|
||||
ptr_ptr = emalloc(sizeof(*ptr_ptr));
|
||||
*ptr_ptr = return_value;
|
||||
*data = ptr_ptr;
|
||||
return &I->data;
|
||||
}
|
||||
|
||||
static void saproxy_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data);
|
||||
|
||||
if (I->key == -1) {
|
||||
ZVAL_NULL(key);
|
||||
@ -532,7 +522,7 @@ static void saproxy_iter_get_key(zend_object_iterator *iter, zval *key TSRMLS_DC
|
||||
|
||||
static int saproxy_iter_move_forwards(zend_object_iterator *iter TSRMLS_DC)
|
||||
{
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)iter->data;
|
||||
php_com_saproxy_iter *I = (php_com_saproxy_iter*)Z_PTR(iter->data);
|
||||
|
||||
if (++I->key >= I->imax) {
|
||||
I->key = -1;
|
||||
@ -563,16 +553,15 @@ zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *objec
|
||||
|
||||
I = ecalloc(1, sizeof(*I));
|
||||
I->iter.funcs = &saproxy_iter_funcs;
|
||||
I->iter.data = I;
|
||||
Z_PTR(I->iter.data) = I;
|
||||
|
||||
I->proxy = proxy;
|
||||
I->proxy_obj = object;
|
||||
Z_ADDREF_P(I->proxy_obj);
|
||||
ZVAL_COPY(&I->proxy_obj, object);
|
||||
|
||||
I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
|
||||
for (i = 0; i < proxy->dimensions; i++) {
|
||||
convert_to_long(proxy->indices[i]);
|
||||
I->indices[i] = Z_LVAL_P(proxy->indices[i]);
|
||||
convert_to_long(&proxy->indices[i]);
|
||||
I->indices[i] = Z_LVAL(proxy->indices[i]);
|
||||
}
|
||||
|
||||
SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
|
||||
|
40
ext/com_dotnet/com_typeinfo.c
Normal file → Executable file
40
ext/com_dotnet/com_typeinfo.c
Normal file → Executable file
@ -162,8 +162,9 @@ PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepa
|
||||
UINT NameCount;
|
||||
BSTR bstr_ids;
|
||||
zend_constant c;
|
||||
zval exists, results, value;
|
||||
zval *exists, results, value;
|
||||
char *const_name;
|
||||
int len;
|
||||
|
||||
if (TL == NULL) {
|
||||
return FAILURE;
|
||||
@ -184,22 +185,23 @@ PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepa
|
||||
continue;
|
||||
}
|
||||
|
||||
const_name = php_com_olestring_to_string(bstr_ids, &c.name_len, codepage TSRMLS_CC);
|
||||
c.name = zend_strndup(const_name, c.name_len);
|
||||
const_name = php_com_olestring_to_string(bstr_ids, &len, codepage TSRMLS_CC);
|
||||
c.name = STR_INIT(const_name, len, 1);
|
||||
// TODO: avoid reallocation???
|
||||
efree(const_name);
|
||||
if(c.name == NULL) {
|
||||
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
|
||||
continue;
|
||||
}
|
||||
c.name_len++; /* include NUL */
|
||||
//??? c.name_len++; /* include NUL */
|
||||
SysFreeString(bstr_ids);
|
||||
|
||||
/* sanity check for the case where the constant is already defined */
|
||||
if (zend_get_constant(c.name, c.name_len - 1, &exists TSRMLS_CC)) {
|
||||
if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, &exists TSRMLS_CC)) {
|
||||
if ((exists = zend_get_constant(c.name TSRMLS_CC)) != NULL) {
|
||||
if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, exists TSRMLS_CC)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name);
|
||||
}
|
||||
free(c.name);
|
||||
STR_RELEASE(c.name);
|
||||
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
|
||||
continue;
|
||||
}
|
||||
@ -208,8 +210,7 @@ PHP_COM_DOTNET_API int php_com_import_typelib(ITypeLib *TL, int mode, int codepa
|
||||
php_com_zval_from_variant(&value, pVarDesc->lpvarValue, codepage TSRMLS_CC);
|
||||
if (Z_TYPE(value) == IS_LONG) {
|
||||
c.flags = mode;
|
||||
c.value.type = IS_LONG;
|
||||
c.value.value.lval = Z_LVAL(value);
|
||||
ZVAL_LONG(&c.value, Z_LVAL(value));
|
||||
c.module_number = 0;
|
||||
zend_register_constant(&c TSRMLS_CC);
|
||||
}
|
||||
@ -231,19 +232,17 @@ void php_com_typelibrary_dtor(void *pDest)
|
||||
PHP_COM_DOTNET_API ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||
int codepage, int *cached TSRMLS_DC)
|
||||
{
|
||||
ITypeLib **TLp;
|
||||
ITypeLib *TL;
|
||||
char *name_dup;
|
||||
int l;
|
||||
|
||||
l = strlen(search_string);
|
||||
|
||||
if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1,
|
||||
(void**)&TLp) == SUCCESS) {
|
||||
if ((TL = zend_ts_hash_str_find_ptr(&php_com_typelibraries, search_string, l)) != NULL) {
|
||||
*cached = 1;
|
||||
/* add a reference for the caller */
|
||||
ITypeLib_AddRef(*TLp);
|
||||
return *TLp;
|
||||
ITypeLib_AddRef(TL);
|
||||
return TL;
|
||||
}
|
||||
|
||||
*cached = 0;
|
||||
@ -252,8 +251,8 @@ PHP_COM_DOTNET_API ITypeLib *php_com_load_typelib_via_cache(char *search_string,
|
||||
efree(name_dup);
|
||||
|
||||
if (TL) {
|
||||
if (SUCCESS == zend_ts_hash_update(&php_com_typelibraries,
|
||||
search_string, l+1, (void*)&TL, sizeof(ITypeLib*), NULL)) {
|
||||
if (NULL != zend_ts_hash_str_update_ptr(&php_com_typelibraries,
|
||||
search_string, l, TL)) {
|
||||
/* add a reference for the hash table */
|
||||
ITypeLib_AddRef(TL);
|
||||
}
|
||||
@ -472,7 +471,7 @@ int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int pri
|
||||
|
||||
/* So we've got the dispatch interface; lets list the event methods */
|
||||
for (i = 0; i < attr->cFuncs; i++) {
|
||||
zval *tmp;
|
||||
zval tmp;
|
||||
DISPID lastid = 0; /* for props */
|
||||
int isprop;
|
||||
|
||||
@ -582,9 +581,10 @@ int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int pri
|
||||
|
||||
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);
|
||||
ZVAL_STRINGL(&tmp, ansiname, ansinamelen);
|
||||
zend_hash_index_update(id_to_name, func->memid, &tmp);
|
||||
// TODO: avoid reallocation???
|
||||
efree(ansiname);
|
||||
}
|
||||
}
|
||||
ITypeInfo_ReleaseFuncDesc(typeinfo, func);
|
||||
|
@ -38,18 +38,17 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
|
||||
SAFEARRAYBOUND bound;
|
||||
HashPosition pos;
|
||||
int keytype;
|
||||
char *strindex;
|
||||
int strindexlen;
|
||||
zend_string *strindex;
|
||||
long intindex = -1;
|
||||
long max_index = 0;
|
||||
VARIANT *va;
|
||||
zval **item;
|
||||
zval *item;
|
||||
|
||||
/* find the largest array index, and assert that all keys are integers */
|
||||
zend_hash_internal_pointer_reset_ex(HASH_OF(z), &pos);
|
||||
for (;; zend_hash_move_forward_ex(HASH_OF(z), &pos)) {
|
||||
|
||||
keytype = zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &strindexlen, &intindex, 0, &pos);
|
||||
keytype = zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &intindex, 0, &pos);
|
||||
|
||||
if (HASH_KEY_IS_STRING == keytype) {
|
||||
goto bogus;
|
||||
@ -73,11 +72,11 @@ static void safe_array_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
|
||||
/* now fill it in */
|
||||
zend_hash_internal_pointer_reset_ex(HASH_OF(z), &pos);
|
||||
for (;; zend_hash_move_forward_ex(HASH_OF(z), &pos)) {
|
||||
if (FAILURE == zend_hash_get_current_data_ex(HASH_OF(z), (void**)&item, &pos)) {
|
||||
if (NULL == (item = zend_hash_get_current_data_ex(HASH_OF(z), &pos))) {
|
||||
break;
|
||||
}
|
||||
zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &strindexlen, &intindex, 0, &pos);
|
||||
php_com_variant_from_zval(&va[intindex], *item, codepage TSRMLS_CC);
|
||||
zend_hash_get_current_key_ex(HASH_OF(z), &strindex, &intindex, 0, &pos);
|
||||
php_com_variant_from_zval(&va[intindex], item, codepage TSRMLS_CC);
|
||||
}
|
||||
|
||||
/* Unlock it and stuff it into our variant */
|
||||
@ -109,9 +108,14 @@ PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codep
|
||||
V_VT(v) = VT_NULL;
|
||||
break;
|
||||
|
||||
case IS_BOOL:
|
||||
case IS_FALSE:
|
||||
V_VT(v) = VT_BOOL;
|
||||
V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
V_BOOL(v) = VARIANT_FALSE;
|
||||
break;
|
||||
|
||||
case IS_TRUE:
|
||||
V_VT(v) = VT_BOOL;
|
||||
V_BOOL(v) = VARIANT_TRUE;
|
||||
break;
|
||||
|
||||
case IS_OBJECT:
|
||||
@ -218,9 +222,12 @@ PHP_COM_DOTNET_API int php_com_zval_from_variant(zval *z, VARIANT *v, int codepa
|
||||
case VT_BSTR:
|
||||
olestring = V_BSTR(v);
|
||||
if (olestring) {
|
||||
Z_TYPE_P(z) = IS_STRING;
|
||||
Z_STRVAL_P(z) = php_com_olestring_to_string(olestring,
|
||||
&Z_STRLEN_P(z), codepage TSRMLS_CC);
|
||||
int len;
|
||||
char *str = php_com_olestring_to_string(olestring,
|
||||
&len, codepage TSRMLS_CC);
|
||||
ZVAL_STRINGL(z, str, len);
|
||||
// TODO: avoid reallocation???
|
||||
efree(str);
|
||||
olestring = NULL;
|
||||
}
|
||||
break;
|
||||
|
165
ext/com_dotnet/com_wrapper.c
Normal file → Executable file
165
ext/com_dotnet/com_wrapper.c
Normal file → Executable file
@ -39,7 +39,7 @@ typedef struct {
|
||||
/* now the PHP stuff */
|
||||
|
||||
DWORD engine_thread; /* for sanity checking */
|
||||
zval *object; /* the object exported */
|
||||
zval object; /* the object exported */
|
||||
LONG refcount; /* COM reference count */
|
||||
|
||||
HashTable *dispid_to_name; /* keep track of dispid -> name mappings */
|
||||
@ -47,14 +47,14 @@ typedef struct {
|
||||
|
||||
GUID sinkid; /* iid that we "implement" for event sinking */
|
||||
|
||||
int id;
|
||||
zend_resource *res;
|
||||
} php_dispatchex;
|
||||
|
||||
static int le_dispatch;
|
||||
|
||||
static void disp_destructor(php_dispatchex *disp TSRMLS_DC);
|
||||
|
||||
static void dispatch_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
static void dispatch_dtor(zend_resource *rsrc TSRMLS_DC)
|
||||
{
|
||||
php_dispatchex *disp = (php_dispatchex *)rsrc->ptr;
|
||||
disp_destructor(disp TSRMLS_CC);
|
||||
@ -90,9 +90,9 @@ static inline void trace(char *fmt, ...)
|
||||
php_dispatchex *disp = (php_dispatchex*)This; \
|
||||
TSRMLS_FETCH(); \
|
||||
if (COMG(rshutdown_started)) { \
|
||||
trace(" PHP Object:%p (name:unknown) %s\n", disp->object, methname); \
|
||||
trace(" PHP Object:%p (name:unknown) %s\n", Z_OBJ(disp->object), methname); \
|
||||
} else { \
|
||||
trace(" PHP Object:%p (name:%s) %s\n", disp->object, Z_OBJCE_P(disp->object)->name, methname); \
|
||||
trace(" PHP Object:%p (name:%s) %s\n", Z_OBJ(disp->object), Z_OBJCE(disp->object)->name->val, methname); \
|
||||
} \
|
||||
if (GetCurrentThreadId() != disp->engine_thread) { \
|
||||
return RPC_E_WRONG_THREAD; \
|
||||
@ -134,8 +134,8 @@ static ULONG STDMETHODCALLTYPE disp_release(IDispatchEx *This)
|
||||
trace("-- refcount now %d\n", ret);
|
||||
if (ret == 0) {
|
||||
/* destroy it */
|
||||
if (disp->id)
|
||||
zend_list_delete(disp->id);
|
||||
if (disp->res)
|
||||
zend_list_delete(disp->res);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -177,16 +177,16 @@ static HRESULT STDMETHODCALLTYPE disp_getidsofnames(
|
||||
for (i = 0; i < cNames; i++) {
|
||||
char *name;
|
||||
unsigned int namelen;
|
||||
zval **tmp;
|
||||
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) {
|
||||
if ((tmp = zend_hash_str_find(disp->name_to_dispid, name, namelen)) == NULL) {
|
||||
ret = DISP_E_UNKNOWNNAME;
|
||||
rgDispId[i] = 0;
|
||||
} else {
|
||||
rgDispId[i] = Z_LVAL_PP(tmp);
|
||||
rgDispId[i] = Z_LVAL_P(tmp);
|
||||
}
|
||||
|
||||
efree(name);
|
||||
@ -221,7 +221,7 @@ static HRESULT STDMETHODCALLTYPE disp_getdispid(
|
||||
HRESULT ret = DISP_E_UNKNOWNNAME;
|
||||
char *name;
|
||||
unsigned int namelen;
|
||||
zval **tmp;
|
||||
zval *tmp;
|
||||
FETCH_DISP("GetDispID");
|
||||
|
||||
name = php_com_olestring_to_string(bstrName, &namelen, COMG(code_page) TSRMLS_CC);
|
||||
@ -229,9 +229,9 @@ static HRESULT STDMETHODCALLTYPE disp_getdispid(
|
||||
trace("Looking for %s, namelen=%d in %p\n", name, namelen, disp->name_to_dispid);
|
||||
|
||||
/* Lookup the name in the hash */
|
||||
if (zend_hash_find(disp->name_to_dispid, name, namelen+1, (void**)&tmp) == SUCCESS) {
|
||||
if ((tmp = zend_hash_str_find(disp->name_to_dispid, name, namelen)) != NULL) {
|
||||
trace("found it\n");
|
||||
*pid = Z_LVAL_PP(tmp);
|
||||
*pid = Z_LVAL_P(tmp);
|
||||
ret = S_OK;
|
||||
}
|
||||
|
||||
@ -250,34 +250,30 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
|
||||
/* [out] */ EXCEPINFO *pei,
|
||||
/* [unique][in] */ IServiceProvider *pspCaller)
|
||||
{
|
||||
zval **name;
|
||||
zval *name;
|
||||
UINT i;
|
||||
zval *retval = NULL;
|
||||
zval ***params = NULL;
|
||||
zval rv, *retval = NULL;
|
||||
zval *params = NULL;
|
||||
HRESULT ret = DISP_E_MEMBERNOTFOUND;
|
||||
FETCH_DISP("InvokeEx");
|
||||
|
||||
if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) {
|
||||
if (NULL != (name = zend_hash_index_find(disp->dispid_to_name, id))) {
|
||||
/* TODO: add support for overloaded objects */
|
||||
|
||||
trace("-- Invoke: %d %20s [%d] flags=%08x args=%d\n", id, Z_STRVAL_PP(name), Z_STRLEN_PP(name), wFlags, pdp->cArgs);
|
||||
trace("-- Invoke: %d %20s [%d] flags=%08x args=%d\n", id, Z_STRVAL_P(name), Z_STRLEN_P(name), wFlags, pdp->cArgs);
|
||||
|
||||
/* convert args into zvals.
|
||||
* Args are in reverse order */
|
||||
if (pdp->cArgs) {
|
||||
params = (zval ***)safe_emalloc(sizeof(zval **), pdp->cArgs, 0);
|
||||
params = (zval *)safe_emalloc(sizeof(zval), pdp->cArgs, 0);
|
||||
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] = (zval**)emalloc(sizeof(zval**));
|
||||
*params[i] = zarg;
|
||||
php_com_wrap_variant(¶ms[i], arg, COMG(code_page) TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,19 +283,20 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
|
||||
* 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);
|
||||
retval = zend_read_property(Z_OBJCE(disp->object), &disp->object, Z_STRVAL_P(name), Z_STRLEN_P(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);
|
||||
zend_update_property(Z_OBJCE(disp->object), &disp->object, Z_STRVAL_P(name), Z_STRLEN_P(name), ¶ms[0] TSRMLS_CC);
|
||||
} else if (wFlags & DISPATCH_METHOD) {
|
||||
zend_try {
|
||||
if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, *name,
|
||||
&retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) {
|
||||
retval = &rv;
|
||||
if (SUCCESS == call_user_function_ex(EG(function_table), &disp->object, name,
|
||||
retval, pdp->cArgs, params, 1, NULL TSRMLS_CC)) {
|
||||
ret = S_OK;
|
||||
trace("function called ok\n");
|
||||
|
||||
/* Copy any modified values to callers copy of variant*/
|
||||
for (i = 0; i < pdp->cArgs; i++) {
|
||||
php_com_dotnet_object *obj = CDNO_FETCH(*params[i]);
|
||||
php_com_dotnet_object *obj = CDNO_FETCH(¶ms[i]);
|
||||
VARIANT *srcvar = &obj->v;
|
||||
VARIANT *dstvar = &pdp->rgvarg[ pdp->cArgs - 1 - i];
|
||||
if ((V_VT(dstvar) & VT_BYREF) && obj->modified ) {
|
||||
@ -322,8 +319,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
|
||||
/* release arguments */
|
||||
if (params) {
|
||||
for (i = 0; i < pdp->cArgs; i++) {
|
||||
zval_ptr_dtor(params[i]);
|
||||
efree(params[i]);
|
||||
zval_ptr_dtor(¶ms[i]);
|
||||
}
|
||||
efree(params);
|
||||
}
|
||||
@ -334,7 +330,7 @@ static HRESULT STDMETHODCALLTYPE disp_invokeex(
|
||||
VariantInit(pvarRes);
|
||||
php_com_variant_from_zval(pvarRes, retval, COMG(code_page) TSRMLS_CC);
|
||||
}
|
||||
zval_ptr_dtor(&retval);
|
||||
zval_ptr_dtor(retval);
|
||||
} else if (pvarRes) {
|
||||
VariantInit(pvarRes);
|
||||
}
|
||||
@ -388,7 +384,7 @@ static HRESULT STDMETHODCALLTYPE disp_getmembername(
|
||||
zval *name;
|
||||
FETCH_DISP("GetMemberName");
|
||||
|
||||
if (SUCCESS == zend_hash_index_find(disp->dispid_to_name, id, (void**)&name)) {
|
||||
if (NULL != (name = zend_hash_index_find(disp->dispid_to_name, id))) {
|
||||
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);
|
||||
@ -451,9 +447,8 @@ static struct IDispatchExVtbl php_dispatch_vtbl = {
|
||||
static void generate_dispids(php_dispatchex *disp TSRMLS_DC)
|
||||
{
|
||||
HashPosition pos;
|
||||
char *name = NULL;
|
||||
zval *tmp;
|
||||
int namelen;
|
||||
zend_string *name = NULL;
|
||||
zval *tmp, tmp2;
|
||||
int keytype;
|
||||
ulong pid;
|
||||
|
||||
@ -465,65 +460,71 @@ static void generate_dispids(php_dispatchex *disp TSRMLS_DC)
|
||||
}
|
||||
|
||||
/* properties */
|
||||
if (Z_OBJPROP_P(disp->object)) {
|
||||
zend_hash_internal_pointer_reset_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||
if (Z_OBJPROP(disp->object)) {
|
||||
zend_hash_internal_pointer_reset_ex(Z_OBJPROP(disp->object), &pos);
|
||||
while (HASH_KEY_NON_EXISTENT != (keytype =
|
||||
zend_hash_get_current_key_ex(Z_OBJPROP_P(disp->object), &name,
|
||||
&namelen, &pid, 0, &pos))) {
|
||||
zend_hash_get_current_key_ex(Z_OBJPROP(disp->object), &name,
|
||||
&pid, 0, &pos))) {
|
||||
char namebuf[32];
|
||||
if (keytype == HASH_KEY_IS_LONG) {
|
||||
snprintf(namebuf, sizeof(namebuf), "%d", pid);
|
||||
name = namebuf;
|
||||
namelen = strlen(namebuf)+1;
|
||||
name = STR_INIT(namebuf, strlen(namebuf), 0);
|
||||
} else {
|
||||
STR_ADDREF(name);
|
||||
}
|
||||
|
||||
zend_hash_move_forward_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||
zend_hash_move_forward_ex(Z_OBJPROP(disp->object), &pos);
|
||||
|
||||
/* Find the existing id */
|
||||
if (zend_hash_find(disp->name_to_dispid, name, namelen, (void**)&tmp) == SUCCESS)
|
||||
if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) {
|
||||
STR_RELEASE(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* add the mappings */
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
ZVAL_STRINGL(tmp, name, namelen-1, 1);
|
||||
ZVAL_STR(&tmp2, STR_COPY(name));
|
||||
pid = zend_hash_next_free_element(disp->dispid_to_name);
|
||||
zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL);
|
||||
zend_hash_index_update(disp->dispid_to_name, pid, &tmp2);
|
||||
|
||||
ZVAL_LONG(&tmp2, pid);
|
||||
zend_hash_update(disp->name_to_dispid, name, &tmp2);
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
ZVAL_LONG(tmp, pid);
|
||||
zend_hash_update(disp->name_to_dispid, name, namelen, (void*)&tmp, sizeof(zval *), NULL);
|
||||
STR_RELEASE(name);
|
||||
}
|
||||
}
|
||||
|
||||
/* functions */
|
||||
if (Z_OBJCE_P(disp->object)) {
|
||||
zend_hash_internal_pointer_reset_ex(&Z_OBJCE_P(disp->object)->function_table, &pos);
|
||||
if (Z_OBJCE(disp->object)) {
|
||||
zend_hash_internal_pointer_reset_ex(&Z_OBJCE(disp->object)->function_table, &pos);
|
||||
while (HASH_KEY_NON_EXISTENT != (keytype =
|
||||
zend_hash_get_current_key_ex(&Z_OBJCE_P(disp->object)->function_table,
|
||||
&name, &namelen, &pid, 0, &pos))) {
|
||||
zend_hash_get_current_key_ex(&Z_OBJCE(disp->object)->function_table,
|
||||
&name, &pid, 0, &pos))) {
|
||||
|
||||
char namebuf[32];
|
||||
if (keytype == HASH_KEY_IS_LONG) {
|
||||
snprintf(namebuf, sizeof(namebuf), "%d", pid);
|
||||
name = namebuf;
|
||||
namelen = strlen(namebuf) + 1;
|
||||
name = STR_INIT(namebuf, strlen(namebuf), 0);
|
||||
} else {
|
||||
STR_ADDREF(name);
|
||||
}
|
||||
|
||||
zend_hash_move_forward_ex(Z_OBJPROP_P(disp->object), &pos);
|
||||
zend_hash_move_forward_ex(&Z_OBJCE(disp->object)->function_table, &pos);
|
||||
|
||||
/* Find the existing id */
|
||||
if (zend_hash_find(disp->name_to_dispid, name, namelen, (void**)&tmp) == SUCCESS)
|
||||
if ((tmp = zend_hash_find(disp->name_to_dispid, name)) != NULL) {
|
||||
STR_RELEASE(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* add the mappings */
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
ZVAL_STRINGL(tmp, name, namelen-1, 1);
|
||||
ZVAL_STR(&tmp2, STR_COPY(name));
|
||||
pid = zend_hash_next_free_element(disp->dispid_to_name);
|
||||
zend_hash_index_update(disp->dispid_to_name, pid, (void*)&tmp, sizeof(zval *), NULL);
|
||||
zend_hash_index_update(disp->dispid_to_name, pid, &tmp2);
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
ZVAL_LONG(tmp, pid);
|
||||
zend_hash_update(disp->name_to_dispid, name, namelen, (void*)&tmp, sizeof(zval *), NULL);
|
||||
ZVAL_LONG(&tmp2, pid);
|
||||
zend_hash_update(disp->name_to_dispid, name, &tmp2);
|
||||
|
||||
STR_RELEASE(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -531,6 +532,7 @@ static void generate_dispids(php_dispatchex *disp TSRMLS_DC)
|
||||
static php_dispatchex *disp_constructor(zval *object TSRMLS_DC)
|
||||
{
|
||||
php_dispatchex *disp = (php_dispatchex*)CoTaskMemAlloc(sizeof(php_dispatchex));
|
||||
zval *tmp;
|
||||
|
||||
trace("constructing a COM wrapper for PHP object %p (%s)\n", object, Z_OBJCE_P(object)->name);
|
||||
|
||||
@ -544,11 +546,14 @@ static php_dispatchex *disp_constructor(zval *object TSRMLS_DC)
|
||||
disp->refcount = 1;
|
||||
|
||||
|
||||
if (object)
|
||||
Z_ADDREF_P(object);
|
||||
disp->object = object;
|
||||
if (object) {
|
||||
ZVAL_COPY(&disp->object, object);
|
||||
} else {
|
||||
ZVAL_UNDEF(&disp->object);
|
||||
}
|
||||
|
||||
disp->id = zend_list_insert(disp, le_dispatch TSRMLS_CC);
|
||||
tmp = zend_list_insert(disp, le_dispatch TSRMLS_CC);
|
||||
disp->res = Z_RES_P(tmp);
|
||||
|
||||
return disp;
|
||||
}
|
||||
@ -557,12 +562,12 @@ static void disp_destructor(php_dispatchex *disp TSRMLS_DC)
|
||||
{
|
||||
/* Object store not available during request shutdown */
|
||||
if (COMG(rshutdown_started)) {
|
||||
trace("destroying COM wrapper for PHP object %p (name:unknown)\n", disp->object);
|
||||
trace("destroying COM wrapper for PHP object %p (name:unknown)\n", Z_OBJ(disp->object));
|
||||
} else {
|
||||
trace("destroying COM wrapper for PHP object %p (name:%s)\n", disp->object, Z_OBJCE_P(disp->object)->name);
|
||||
trace("destroying COM wrapper for PHP object %p (name:%s)\n", Z_OBJ(disp->object), Z_OBJCE(disp->object)->name->val);
|
||||
}
|
||||
|
||||
disp->id = 0;
|
||||
disp->res = NULL;
|
||||
|
||||
if (disp->refcount > 0)
|
||||
CoDisconnectObject((IUnknown*)disp, 0);
|
||||
@ -572,8 +577,7 @@ static void disp_destructor(php_dispatchex *disp TSRMLS_DC)
|
||||
FREE_HASHTABLE(disp->dispid_to_name);
|
||||
FREE_HASHTABLE(disp->name_to_dispid);
|
||||
|
||||
if (disp->object)
|
||||
zval_ptr_dtor(&disp->object);
|
||||
zval_ptr_dtor(&disp->object);
|
||||
|
||||
CoTaskMemFree(disp);
|
||||
}
|
||||
@ -583,9 +587,8 @@ PHP_COM_DOTNET_API IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *si
|
||||
{
|
||||
php_dispatchex *disp = disp_constructor(val TSRMLS_CC);
|
||||
HashPosition pos;
|
||||
char *name = NULL;
|
||||
zval *tmp, **ntmp;
|
||||
int namelen;
|
||||
zend_string *name = NULL;
|
||||
zval tmp, *ntmp;
|
||||
int keytype;
|
||||
ulong pid;
|
||||
|
||||
@ -599,16 +602,14 @@ PHP_COM_DOTNET_API IDispatch *php_com_wrapper_export_as_sink(zval *val, GUID *si
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(id_to_name, &pos);
|
||||
while (HASH_KEY_NON_EXISTENT != (keytype =
|
||||
zend_hash_get_current_key_ex(id_to_name, &name, &namelen, &pid, 0, &pos))) {
|
||||
zend_hash_get_current_key_ex(id_to_name, &name, &pid, 0, &pos))) {
|
||||
|
||||
if (keytype == HASH_KEY_IS_LONG) {
|
||||
|
||||
zend_hash_get_current_data_ex(id_to_name, (void**)&ntmp, &pos);
|
||||
ntmp = zend_hash_get_current_data_ex(id_to_name, &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);
|
||||
ZVAL_LONG(&tmp, pid);
|
||||
zend_hash_update(disp->name_to_dispid, Z_STR_P(ntmp), &tmp);
|
||||
}
|
||||
|
||||
zend_hash_move_forward_ex(id_to_name, &pos);
|
||||
|
24
ext/com_dotnet/php_com_dotnet_internal.h
Normal file → Executable file
24
ext/com_dotnet/php_com_dotnet_internal.h
Normal file → Executable file
@ -29,6 +29,8 @@
|
||||
#include <dispex.h>
|
||||
#include "win32/winutil.h"
|
||||
|
||||
#include "zend_ts_hash.h"
|
||||
|
||||
typedef struct _php_com_dotnet_object {
|
||||
zend_object zo;
|
||||
|
||||
@ -54,18 +56,18 @@ typedef struct _php_com_dotnet_object {
|
||||
static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(zv);
|
||||
return strcmp("com", ce->name) == 0 ||
|
||||
strcmp("dotnet", ce->name) == 0 ||
|
||||
strcmp("variant", ce->name) == 0;
|
||||
return strcmp("com", ce->name->val) == 0 ||
|
||||
strcmp("dotnet", ce->name->val) == 0 ||
|
||||
strcmp("variant", ce->name->val) == 0;
|
||||
}
|
||||
|
||||
#define CDNO_FETCH(zv) (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC)
|
||||
#define CDNO_FETCH(zv) (php_com_dotnet_object*)Z_OBJ_P(zv)
|
||||
#define CDNO_FETCH_VERIFY(obj, zv) do { \
|
||||
if (!php_com_is_valid_object(zv TSRMLS_CC)) { \
|
||||
php_com_throw_exception(E_UNEXPECTED, "expected a variant object" TSRMLS_CC); \
|
||||
return; \
|
||||
} \
|
||||
obj = (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC); \
|
||||
obj = (php_com_dotnet_object*)Z_OBJ_P(zv); \
|
||||
} while(0)
|
||||
|
||||
/* com_extension.c */
|
||||
@ -73,9 +75,9 @@ TsHashTable php_com_typelibraries;
|
||||
zend_class_entry *php_com_variant_class_entry, *php_com_exception_class_entry, *php_com_saproxy_class_entry;
|
||||
|
||||
/* com_handlers.c */
|
||||
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_free_storage(void *object TSRMLS_DC);
|
||||
zend_object* php_com_object_new(zend_class_entry *ce TSRMLS_DC);
|
||||
zend_object* php_com_object_clone(zval *object TSRMLS_DC);
|
||||
void php_com_object_free_storage(zend_object *object TSRMLS_DC);
|
||||
zend_object_handlers php_com_object_handlers;
|
||||
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, int enable TSRMLS_DC);
|
||||
|
||||
@ -104,11 +106,11 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
|
||||
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
|
||||
int namelen, DISPID *dispid TSRMLS_DC);
|
||||
int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
|
||||
WORD flags, VARIANT *v, int nargs, zval **args, int silent, int allow_noarg TSRMLS_DC);
|
||||
WORD flags, VARIANT *v, int nargs, zval *args, int silent, int allow_noarg TSRMLS_DC);
|
||||
int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
|
||||
WORD flags, VARIANT *v, int nargs, zval **args, int allow_noarg TSRMLS_DC);
|
||||
WORD flags, VARIANT *v, int nargs, zval *args, int allow_noarg TSRMLS_DC);
|
||||
int php_com_do_invoke_byref(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);
|
||||
|
Loading…
Reference in New Issue
Block a user