mirror of
https://github.com/php/php-src.git
synced 2026-04-28 10:43:30 +02:00
ext/com is not compatible with ZE2, the ZE2 version is located in
ext/rpc/com
This commit is contained in:
-2474
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
Win32 COM
|
||||
Alan Brown, Wez Furlong, Harald Radi, Zeev Suraski
|
||||
@@ -1,28 +0,0 @@
|
||||
1) Multi-dimenstional array support
|
||||
4) Documentation (internal and user) and howtos
|
||||
5) IEnumVariant::All() which would be like IEnumVariant::Next(IDispatch::Count)
|
||||
7) Test component (goes with the docs)
|
||||
8) Test suite (Needs test component)
|
||||
10) lets try if we are able to call non IDispatch - only Typelib components
|
||||
|
||||
-- delayed till PHP5: 3) WithEvents
|
||||
-- delayed till PHP5: 9) reduce the need for VARIANT()
|
||||
|
||||
ad 6.) check vbsample.php (new VARIANT(*, *|VT_BYREF)) GPs
|
||||
|
||||
-- done 2) IErrorInfo
|
||||
-- done 6) Look for memory leaks and AdRef/Release problems - I KNOW there are some...
|
||||
-- done 11) IEnumVariant::Next() without parameter should only return an object, not an array with one element
|
||||
-- done 12) VARIANT->value as lvalue
|
||||
-- done 13) export VARIANT through the COM module
|
||||
-- done 14) trap exceptions and errors
|
||||
|
||||
-- donne ad 4.) faq (i've collected a few questions from various lists)
|
||||
variant attributes !!
|
||||
|
||||
to be discussed:
|
||||
|
||||
- mts support (getcontext)
|
||||
- adsi support (ads* functions)
|
||||
|
||||
-- delayed till PHP 5: try serialisation support (if component implements IPersist)
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 4 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2003 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.02 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at |
|
||||
| http://www.php.net/license/2_02.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Harald Radi <h.radi@nme.at> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This module maps the VARIANT datastructure into PHP so that it can be used to
|
||||
* pass values to COM and DOTNET Objects by reference and not only by value.
|
||||
*
|
||||
* harald
|
||||
*/
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
|
||||
#include "php.h"
|
||||
#include "php_ini.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "php_VARIANT.h"
|
||||
|
||||
#include <unknwn.h>
|
||||
|
||||
static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC);
|
||||
static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value);
|
||||
static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference);
|
||||
static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
|
||||
static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
|
||||
static void php_register_VARIANT_class(TSRMLS_D);
|
||||
|
||||
static int le_variant;
|
||||
static int codepage;
|
||||
static zend_class_entry VARIANT_class_entry;
|
||||
|
||||
|
||||
void php_VARIANT_init(int module_number TSRMLS_DC)
|
||||
{
|
||||
le_variant = zend_register_list_destructors_ex(php_VARIANT_destructor, NULL, "VARIANT", module_number);
|
||||
|
||||
/* variant datatypes */
|
||||
REGISTER_LONG_CONSTANT("VT_NULL", VT_NULL, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_EMPTY", VT_EMPTY, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_UI1", VT_UI1, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_I2", VT_I2, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_I4", VT_I4, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_R4", VT_R4, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_R8", VT_R8, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_BOOL", VT_BOOL, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_ERROR", VT_ERROR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_CY", VT_CY, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_DATE", VT_DATE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_BSTR", VT_BSTR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_DECIMAL", VT_DECIMAL, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_UNKNOWN", VT_UNKNOWN, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_DISPATCH", VT_DISPATCH, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_VARIANT", VT_VARIANT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_I1", VT_I1, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_UI2", VT_UI2, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_UI4", VT_UI4, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_INT", VT_INT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_UINT", VT_UINT, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_ARRAY", VT_ARRAY, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("VT_BYREF", VT_BYREF, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
/* codepages */
|
||||
REGISTER_LONG_CONSTANT("CP_ACP", CP_ACP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("CP_MACCP", CP_MACCP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("CP_OEMCP", CP_OEMCP, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("CP_UTF7", CP_UTF7, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("CP_UTF8", CP_UTF8, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
#ifdef CP_SYMBOL
|
||||
REGISTER_LONG_CONSTANT("CP_SYMBOL", CP_SYMBOL, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
# error "CP_SYMBOL undefined"
|
||||
#endif
|
||||
#ifdef CP_THREAD_ACP
|
||||
REGISTER_LONG_CONSTANT("CP_THREAD_ACP", CP_THREAD_ACP, CONST_CS | CONST_PERSISTENT);
|
||||
#else
|
||||
# error "CP_THREAD_ACP undefined"
|
||||
#endif
|
||||
|
||||
php_register_VARIANT_class(TSRMLS_C);
|
||||
}
|
||||
|
||||
|
||||
PHPAPI int php_VARIANT_get_le_variant()
|
||||
{
|
||||
return le_variant;
|
||||
}
|
||||
|
||||
|
||||
static void php_VARIANT_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
|
||||
{
|
||||
pval *object = property_reference->object;
|
||||
zend_overloaded_element *function_name = (zend_overloaded_element *) property_reference->elements_list->tail->data;
|
||||
VARIANT *pVar;
|
||||
|
||||
if ((zend_llist_count(property_reference->elements_list)==1) && !strcmp(Z_STRVAL(function_name->element), "variant")) {
|
||||
/* constructor */
|
||||
pval *object_handle, *data, *type, *code_page;
|
||||
|
||||
ALLOC_VARIANT(pVar);
|
||||
VariantInit(pVar);
|
||||
|
||||
switch (ZEND_NUM_ARGS()) {
|
||||
case 0:
|
||||
/* nothing to do */
|
||||
break;
|
||||
case 1:
|
||||
zend_get_parameters(ht, 1, &data);
|
||||
php_pval_to_variant(data, pVar, codepage TSRMLS_CC);
|
||||
codepage = CP_ACP;
|
||||
break;
|
||||
case 2:
|
||||
zend_get_parameters(ht, 2, &data, &type);
|
||||
php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
|
||||
codepage = CP_ACP;
|
||||
break;
|
||||
case 3:
|
||||
zend_get_parameters(ht, 3, &data, &type, &code_page);
|
||||
php_pval_to_variant_ex(data, pVar, type, codepage TSRMLS_CC);
|
||||
convert_to_long(code_page);
|
||||
codepage = Z_LVAL_P(code_page);
|
||||
break;
|
||||
default:
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
break;
|
||||
}
|
||||
|
||||
RETVAL_LONG(zend_list_insert(pVar, IS_VARIANT));
|
||||
|
||||
if (!zend_is_true(return_value)) {
|
||||
ZVAL_FALSE(object);
|
||||
return;
|
||||
}
|
||||
|
||||
ALLOC_ZVAL(object_handle);
|
||||
*object_handle = *return_value;
|
||||
zval_copy_ctor(object_handle);
|
||||
INIT_PZVAL(object_handle);
|
||||
zend_hash_index_update(Z_OBJPROP_P(object), 0, &object_handle, sizeof(pval *), NULL);
|
||||
zval_dtor(&function_name->element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static pval php_VARIANT_get_property_handler(zend_property_reference *property_reference)
|
||||
{
|
||||
zend_overloaded_element *overloaded_property;
|
||||
int type;
|
||||
pval result, **var_handle, *object = property_reference->object;
|
||||
VARIANT *var_arg;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
/* fetch the VARIANT structure */
|
||||
zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
|
||||
var_arg = zend_list_find(Z_LVAL_PP(var_handle), &type);
|
||||
|
||||
if (!var_arg || (type != IS_VARIANT)) {
|
||||
ZVAL_FALSE(&result);
|
||||
} else {
|
||||
overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data;
|
||||
switch (Z_TYPE_P(overloaded_property)) {
|
||||
case OE_IS_ARRAY:
|
||||
ZVAL_FALSE(&result);
|
||||
break;
|
||||
|
||||
case OE_IS_OBJECT:
|
||||
if (!strcmp(Z_STRVAL(overloaded_property->element), "value")) {
|
||||
// var_arg can't be an idispatch, so we don't care for the implicit AddRef() call here
|
||||
php_variant_to_pval(var_arg, &result, codepage TSRMLS_CC);
|
||||
} else if (!strcmp(Z_STRVAL(overloaded_property->element), "type")) {
|
||||
ZVAL_LONG(&result, V_VT(var_arg))
|
||||
} else {
|
||||
ZVAL_FALSE(&result);
|
||||
php_error(E_WARNING, "Unknown member.");
|
||||
}
|
||||
break;
|
||||
case OE_IS_METHOD:
|
||||
ZVAL_FALSE(&result);
|
||||
php_error(E_WARNING, "Unknown method.");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
zval_dtor(&overloaded_property->element);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int php_VARIANT_set_property_handler(zend_property_reference *property_reference, pval *value)
|
||||
{
|
||||
zend_overloaded_element *overloaded_property;
|
||||
int type;
|
||||
pval **var_handle, *object = property_reference->object;
|
||||
VARIANT *var_arg;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
|
||||
/* fetch the VARIANT structure */
|
||||
zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &var_handle);
|
||||
var_arg = zend_list_find(Z_LVAL_PP(var_handle), &type);
|
||||
|
||||
if (!var_arg || (type != IS_VARIANT)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
overloaded_property = (zend_overloaded_element *) property_reference->elements_list->head->data;
|
||||
do_VARIANT_propset(var_arg, &overloaded_property->element, value TSRMLS_CC);
|
||||
zval_dtor(&overloaded_property->element);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int do_VARIANT_propset(VARIANT *var_arg, pval *arg_property, pval *value TSRMLS_DC)
|
||||
{
|
||||
VARTYPE type;
|
||||
|
||||
if (!strcmp(Z_STRVAL_P(arg_property), "value")) {
|
||||
php_pval_to_variant(value, var_arg, codepage TSRMLS_CC);
|
||||
|
||||
return SUCCESS;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "bVal")) {
|
||||
type = VT_UI1;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "iVal")) {
|
||||
type = VT_I2;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "lVal")) {
|
||||
type = VT_I4;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "fltVal")) {
|
||||
type = VT_R4;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "dblVal")) {
|
||||
type = VT_R8;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "boolVal")) {
|
||||
type = VT_BOOL;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "scode")) {
|
||||
type = VT_ERROR;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "cyVal")) {
|
||||
type = VT_CY;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "date")) {
|
||||
type = VT_DATE;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "bstrVal")) {
|
||||
type = VT_BSTR;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pdecVal")) {
|
||||
type = VT_DECIMAL|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "punkVal")) {
|
||||
type = VT_UNKNOWN;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pdispVal")) {
|
||||
type = VT_DISPATCH;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "parray")) {
|
||||
type = VT_ARRAY;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pbVal")) {
|
||||
type = VT_UI1|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "piVal")) {
|
||||
type = VT_I2|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "plVal")) {
|
||||
type = VT_I4|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pfltVal")) {
|
||||
type = VT_R4|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pdblVal")) {
|
||||
type = VT_R8|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pboolVal")) {
|
||||
type = VT_BOOL|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pscode")) {
|
||||
type = VT_ERROR|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pcyVal")) {
|
||||
type = VT_CY|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pdate")) {
|
||||
type = VT_DATE|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pbstrVal")) {
|
||||
type = VT_BSTR|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "ppunkVal")) {
|
||||
type = VT_UNKNOWN|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "ppdispVal")) {
|
||||
type = VT_DISPATCH|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pparray")) {
|
||||
type = VT_ARRAY|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pvarVal")) {
|
||||
type = VT_VARIANT|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "byref")) {
|
||||
type = VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "cVal")) {
|
||||
type = VT_I1;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "uiVal")) {
|
||||
type = VT_UI2;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "ulVal")) {
|
||||
type = VT_UI4;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "intVal")) {
|
||||
type = VT_INT;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "uintVal")) {
|
||||
type = VT_UINT|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pcVal")) {
|
||||
type = VT_I1|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "puiVal")) {
|
||||
type = VT_UI2|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pulVal")) {
|
||||
type = VT_UI4|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "pintVal")) {
|
||||
type = VT_INT|VT_BYREF;
|
||||
} else if (!strcmp(Z_STRVAL_P(arg_property), "puintVal")) {
|
||||
type = VT_UINT|VT_BYREF;
|
||||
} else {
|
||||
php_error(E_WARNING, "Unknown member.");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
php_pval_to_variant_ex2(value, var_arg, type, codepage TSRMLS_CC);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void php_VARIANT_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
{
|
||||
FREE_VARIANT(rsrc->ptr);
|
||||
}
|
||||
|
||||
static void php_register_VARIANT_class(TSRMLS_D)
|
||||
{
|
||||
INIT_OVERLOADED_CLASS_ENTRY(VARIANT_class_entry, "VARIANT", NULL,
|
||||
php_VARIANT_call_function_handler,
|
||||
php_VARIANT_get_property_handler,
|
||||
php_VARIANT_set_property_handler);
|
||||
|
||||
zend_register_internal_class(&VARIANT_class_entry TSRMLS_CC);
|
||||
}
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
@@ -1,79 +0,0 @@
|
||||
#ifndef COM_H
|
||||
#define COM_H
|
||||
|
||||
#if PHP_WIN32
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
#include <oleauto.h>
|
||||
|
||||
typedef struct comval_ {
|
||||
#ifdef _DEBUG
|
||||
int resourceindex;
|
||||
#endif
|
||||
BOOL typelib;
|
||||
BOOL enumeration;
|
||||
int refcount;
|
||||
struct {
|
||||
IDispatch *dispatch;
|
||||
ITypeInfo *typeinfo;
|
||||
IEnumVARIANT *enumvariant;
|
||||
} i;
|
||||
IDispatch *sinkdispatch;
|
||||
GUID sinkid;
|
||||
DWORD sinkcookie;
|
||||
} comval;
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZVAL_COM(z,o) { \
|
||||
zval *handle = NULL; \
|
||||
ZVAL_COM_EX(z,o,handle) \
|
||||
}
|
||||
|
||||
#define ZVAL_COM_EX(z,o,handle) { \
|
||||
HashTable *properties; \
|
||||
\
|
||||
ALLOC_HASHTABLE(properties); \
|
||||
zend_hash_init(properties, 0, NULL, ZVAL_PTR_DTOR, 0); \
|
||||
\
|
||||
if (handle == NULL) { \
|
||||
MAKE_STD_ZVAL(handle); \
|
||||
} \
|
||||
ZVAL_RESOURCE(handle, zend_list_insert((o), IS_COM)); \
|
||||
\
|
||||
zval_copy_ctor(handle); \
|
||||
zend_hash_index_update(properties, 0, &handle, sizeof(zval *), NULL); \
|
||||
object_and_properties_init(z, &COM_class_entry, properties); \
|
||||
}
|
||||
|
||||
#define RETVAL_COM(o) ZVAL_COM(&return_value, o);
|
||||
#define RETURN_COM(o) RETVAL_COM(o) \
|
||||
return;
|
||||
|
||||
#define ALLOC_COM(z) (z) = (comval *) ecalloc(1, sizeof(comval)); \
|
||||
C_REFCOUNT(z) = 0;
|
||||
|
||||
#define FREE_COM(z) php_COM_destruct(z TSRMLS_CC);
|
||||
|
||||
#define IS_COM php_COM_get_le_comval()
|
||||
|
||||
#define C_HASTLIB(x) ((x)->typelib)
|
||||
#define C_HASENUM(x) ((x)->enumeration)
|
||||
#define C_REFCOUNT(x) ((x)->refcount)
|
||||
#define C_ISREFD(x) C_REFCOUNT(x)
|
||||
|
||||
#define C_ADDREF(x) (++((x)->refcount))
|
||||
#define C_RELEASE(x) (--((x)->refcount))
|
||||
|
||||
#define C_DISPATCH(x) ((x)->i.dispatch)
|
||||
#define C_TYPEINFO(x) ((x)->i.typeinfo)
|
||||
#define C_ENUMVARIANT(x) ((x)->i.enumvariant)
|
||||
|
||||
#define C_DISPATCH_VT(x) (C_DISPATCH(x)->lpVtbl)
|
||||
#define C_TYPEINFO_VT(x) (C_TYPEINFO(x)->lpVtbl)
|
||||
#define C_ENUMVARIANT_VT(x) (C_ENUMVARIANT(x)->lpVtbl)
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
|
||||
#endif /* COM_H */
|
||||
@@ -1,875 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 4 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2003 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.02 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at |
|
||||
| http://www.php.net/license/2_02.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Harald Radi <h.radi@nme.at> |
|
||||
| Alan Brown <abrown@pobox.com> |
|
||||
| Paul Shortis <pshortis@dataworx.com.au> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/*
|
||||
* 03.6.2001
|
||||
* Added SafeArray ==> Hash support
|
||||
*/
|
||||
|
||||
/*
|
||||
* Paul Shortis June 7, 2001 <pshortis@dataworx.com.au> - Added code to support SafeArray passing
|
||||
* to COM objects. Support includes passing arrays of variants as well
|
||||
* as typed arrays.
|
||||
*/
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
|
||||
#include "php.h"
|
||||
#include "php_COM.h"
|
||||
#include "php_VARIANT.h"
|
||||
|
||||
/* prototypes */
|
||||
|
||||
static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC);
|
||||
|
||||
/* implementations */
|
||||
PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC)
|
||||
{
|
||||
VARTYPE type = VT_EMPTY; /* default variant type */
|
||||
|
||||
switch (Z_TYPE_P(pval_arg)) {
|
||||
case IS_NULL:
|
||||
type = VT_NULL;
|
||||
break;
|
||||
|
||||
case IS_BOOL:
|
||||
type = VT_BOOL;
|
||||
break;
|
||||
|
||||
case IS_OBJECT:
|
||||
if (!strcmp(Z_OBJCE_P(pval_arg)->name, "VARIANT")) {
|
||||
type = VT_VARIANT|VT_BYREF;
|
||||
} else {
|
||||
type = VT_DISPATCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case IS_ARRAY:
|
||||
type = VT_ARRAY;
|
||||
break;
|
||||
|
||||
case IS_RESOURCE:
|
||||
case IS_CONSTANT:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
/* ?? */
|
||||
break;
|
||||
|
||||
case IS_LONG:
|
||||
type = VT_I4; /* assuming 32-bit platform */
|
||||
break;
|
||||
|
||||
case IS_DOUBLE:
|
||||
type = VT_R8; /* assuming 64-bit double precision */
|
||||
break;
|
||||
|
||||
case IS_STRING:
|
||||
type = VT_BSTR;
|
||||
break;
|
||||
}
|
||||
|
||||
php_pval_to_variant_ex2(pval_arg, var_arg, type, codepage TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC)
|
||||
{
|
||||
php_pval_to_variant_ex2(pval_arg, var_arg, (unsigned short) Z_LVAL_P(pval_type), codepage TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, VARTYPE type, int codepage TSRMLS_DC)
|
||||
{
|
||||
OLECHAR *unicode_str;
|
||||
|
||||
VariantInit(var_arg);
|
||||
V_VT(var_arg) = type;
|
||||
|
||||
if (V_VT(var_arg) & VT_ARRAY) {
|
||||
/* For now we'll just handle single dimension arrays, we'll use the data type of the first element for the
|
||||
output data type */
|
||||
HashTable *ht = Z_ARRVAL(*pval_arg);
|
||||
int numberOfElements = zend_hash_num_elements(ht);
|
||||
SAFEARRAY *safeArray;
|
||||
SAFEARRAYBOUND bounds[1];
|
||||
VARIANT *v, var;
|
||||
zval **entry; /* An entry in the input array */
|
||||
|
||||
type &= ~VT_ARRAY;
|
||||
|
||||
if (V_VT(var_arg) == (VT_ARRAY|VT_BYREF)) { /* == is intended, because VT_*|VT_BYREF|VT_ARRAY means something diffrent */
|
||||
type &= ~VT_BYREF;
|
||||
ALLOC_VARIANT(V_VARIANTREF(var_arg));
|
||||
var_arg = V_VARIANTREF(var_arg); /* put the array in that VARIANT */
|
||||
}
|
||||
if (!type) {
|
||||
// if no type is given we take the variant type
|
||||
type = VT_VARIANT;
|
||||
}
|
||||
|
||||
bounds[0].lLbound = 0;
|
||||
bounds[0].cElements = numberOfElements;
|
||||
safeArray = SafeArrayCreate(type, 1, bounds);
|
||||
|
||||
if (NULL == safeArray) {
|
||||
php_error( E_WARNING,"Unable to convert php array to VARIANT array - %s", numberOfElements ? "" : "(Empty input array)");
|
||||
ZVAL_FALSE(pval_arg);
|
||||
} else {
|
||||
V_ARRAY(var_arg) = safeArray;
|
||||
V_VT(var_arg) = VT_ARRAY|type; /* Now have a valid safe array allocated */
|
||||
if (SUCCEEDED(SafeArrayLock(safeArray))) {
|
||||
ulong i;
|
||||
UINT size = SafeArrayGetElemsize(safeArray);
|
||||
|
||||
zend_hash_internal_pointer_reset(ht);
|
||||
for (i = 0; i < (ulong)numberOfElements; ++i) {
|
||||
if ((zend_hash_get_current_data(ht, (void **)&entry) == SUCCESS) && (entry != NULL)) { /* Get a pointer to the php array element */
|
||||
/* Add another value to the safe array */
|
||||
if (SUCCEEDED(SafeArrayPtrOfIndex(safeArray, &i, &v))) { /* Pointer to output element entry retrieved successfully */
|
||||
if (type == VT_VARIANT) {
|
||||
php_pval_to_variant(*entry, v, codepage TSRMLS_CC); /* Do the required conversion */
|
||||
} else {
|
||||
php_pval_to_variant_ex2(*entry, &var, type, codepage TSRMLS_CC); /* Do the required conversion */
|
||||
memcpy(v, &(var.byref), size);
|
||||
}
|
||||
} else {
|
||||
php_error( E_WARNING,"phpArrayToSafeArray() - Unable to retrieve pointer to output element number (%d)", i);
|
||||
}
|
||||
}
|
||||
zend_hash_move_forward(ht);
|
||||
}
|
||||
SafeArrayUnlock( safeArray);
|
||||
} else {
|
||||
php_error( E_WARNING,"phpArrayToSafeArray() - Unable to lock safeArray");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (V_VT(var_arg)) {
|
||||
|
||||
case VT_NULL:
|
||||
case VT_VOID:
|
||||
ZVAL_NULL(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI1:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_UI1(var_arg) = (unsigned char) Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_I2:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_I2(var_arg) = (short) Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_I4:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_I4(var_arg) = Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_R4:
|
||||
convert_to_double_ex(&pval_arg);
|
||||
V_R4(var_arg) = (float) Z_DVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_R8:
|
||||
convert_to_double_ex(&pval_arg);
|
||||
V_R8(var_arg) = Z_DVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_BOOL:
|
||||
convert_to_boolean_ex(&pval_arg);
|
||||
if (Z_LVAL_P(pval_arg)) {
|
||||
V_BOOL(var_arg) = VT_TRUE;
|
||||
} else {
|
||||
V_BOOL(var_arg) = VT_FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_ERROR:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_ERROR(var_arg) = Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_CY:
|
||||
convert_to_double_ex(&pval_arg);
|
||||
VarCyFromR8(Z_DVAL_P(pval_arg), &V_CY(var_arg));
|
||||
break;
|
||||
|
||||
case VT_DATE: {
|
||||
SYSTEMTIME wintime;
|
||||
struct tm *phptime;
|
||||
|
||||
switch (Z_TYPE_P(pval_arg)) {
|
||||
case IS_DOUBLE:
|
||||
/* already a VariantTime value */
|
||||
V_DATE(var_arg) = Z_DVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
/** @todo
|
||||
case IS_STRING:
|
||||
*/
|
||||
/* string representation of a time value */
|
||||
|
||||
default:
|
||||
/* a PHP time value ? */
|
||||
convert_to_long_ex(&pval_arg);
|
||||
phptime = gmtime(&(Z_LVAL_P(pval_arg)));
|
||||
memset(&wintime, 0, sizeof(wintime));
|
||||
|
||||
wintime.wYear = phptime->tm_year + 1900;
|
||||
wintime.wMonth = phptime->tm_mon + 1;
|
||||
wintime.wDay = phptime->tm_mday;
|
||||
wintime.wHour = phptime->tm_hour;
|
||||
wintime.wMinute = phptime->tm_min;
|
||||
wintime.wSecond = phptime->tm_sec;
|
||||
|
||||
SystemTimeToVariantTime(&wintime, &V_DATE(var_arg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_BSTR:
|
||||
convert_to_string_ex(&pval_arg);
|
||||
unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
V_BSTR(var_arg) = SysAllocStringByteLen((char *) unicode_str, Z_STRLEN_P(pval_arg) * sizeof(OLECHAR));
|
||||
efree(unicode_str);
|
||||
break;
|
||||
|
||||
case VT_DECIMAL:
|
||||
convert_to_string_ex(&pval_arg);
|
||||
unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, &V_DECIMAL(var_arg));
|
||||
break;
|
||||
|
||||
case VT_DECIMAL|VT_BYREF:
|
||||
convert_to_string_ex(&pval_arg);
|
||||
unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
VarDecFromStr(unicode_str, LOCALE_SYSTEM_DEFAULT, 0, V_DECIMALREF(var_arg));
|
||||
break;
|
||||
|
||||
case VT_UNKNOWN:
|
||||
comval_to_variant(pval_arg, var_arg TSRMLS_CC);
|
||||
if (V_VT(var_arg) != VT_DISPATCH) {
|
||||
VariantInit(var_arg);
|
||||
} else {
|
||||
V_VT(var_arg) = VT_UNKNOWN;
|
||||
V_UNKNOWN(var_arg) = (IUnknown *) V_DISPATCH(var_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_DISPATCH:
|
||||
if (!strcmp(Z_OBJCE_P(pval_arg)->name, "COM")) {
|
||||
comval_to_variant(pval_arg, var_arg TSRMLS_CC);
|
||||
} else {
|
||||
V_DISPATCH(var_arg) = php_COM_export_object(pval_arg TSRMLS_CC);
|
||||
if (V_DISPATCH(var_arg)) {
|
||||
V_VT(var_arg) = VT_DISPATCH;
|
||||
}
|
||||
}
|
||||
if (V_VT(var_arg) != VT_DISPATCH) {
|
||||
VariantInit(var_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_UI1|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_UI1REF(var_arg) = (unsigned char FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_I2|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_I2REF(var_arg) = (short FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_I4|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_I4REF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_R4|VT_BYREF:
|
||||
convert_to_double(pval_arg);
|
||||
V_R4REF(var_arg) = (float FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_R8|VT_BYREF:
|
||||
convert_to_double(pval_arg);
|
||||
V_R8REF(var_arg) = (double FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_BOOL|VT_BYREF:
|
||||
convert_to_boolean(pval_arg);
|
||||
/* emalloc or malloc ? */
|
||||
V_BOOLREF(var_arg) = (short FAR*) pemalloc(sizeof(short), 1);
|
||||
if (Z_LVAL_P(pval_arg)) {
|
||||
*V_BOOLREF(var_arg) = VT_TRUE;
|
||||
} else {
|
||||
*V_BOOLREF(var_arg) = VT_TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_ERROR|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_ERRORREF(var_arg) = (long FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_CY|VT_BYREF:
|
||||
convert_to_double_ex(&pval_arg);
|
||||
VarCyFromR8(Z_DVAL_P(pval_arg), var_arg->pcyVal);
|
||||
break;
|
||||
|
||||
case VT_DATE|VT_BYREF: {
|
||||
SYSTEMTIME wintime;
|
||||
struct tm *phptime;
|
||||
|
||||
phptime = gmtime(&(Z_LVAL_P(pval_arg)));
|
||||
memset(&wintime, 0, sizeof(wintime));
|
||||
|
||||
wintime.wYear = phptime->tm_year + 1900;
|
||||
wintime.wMonth = phptime->tm_mon + 1;
|
||||
wintime.wDay = phptime->tm_mday;
|
||||
wintime.wHour = phptime->tm_hour;
|
||||
wintime.wMinute = phptime->tm_min;
|
||||
wintime.wSecond = phptime->tm_sec;
|
||||
|
||||
SystemTimeToVariantTime(&wintime, var_arg->pdate);
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_BSTR|VT_BYREF:
|
||||
convert_to_string(pval_arg);
|
||||
V_BSTRREF(var_arg) = (BSTR FAR*) emalloc(sizeof(BSTR FAR*));
|
||||
unicode_str = php_char_to_OLECHAR(Z_STRVAL_P(pval_arg), Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
*V_BSTRREF(var_arg) = SysAllocString(unicode_str);
|
||||
efree(unicode_str);
|
||||
break;
|
||||
|
||||
case VT_UNKNOWN|VT_BYREF:
|
||||
comval_to_variant(pval_arg, var_arg TSRMLS_CC);
|
||||
if (V_VT(var_arg) != VT_DISPATCH) {
|
||||
VariantInit(var_arg);
|
||||
} else {
|
||||
V_VT(var_arg) = VT_UNKNOWN|VT_BYREF;
|
||||
V_UNKNOWNREF(var_arg) = (IUnknown **) &V_DISPATCH(var_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_DISPATCH|VT_BYREF:
|
||||
comval_to_variant(pval_arg, var_arg TSRMLS_CC);
|
||||
if (V_VT(var_arg) != VT_DISPATCH) {
|
||||
VariantInit(var_arg);
|
||||
} else {
|
||||
V_VT(var_arg) = VT_DISPATCH|VT_BYREF;
|
||||
V_DISPATCHREF(var_arg) = &V_DISPATCH(var_arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_VARIANT:
|
||||
php_error(E_WARNING,"VT_VARIANT is invalid. Use VT_VARIANT|VT_BYREF instead.");
|
||||
/* break missing intentionally */
|
||||
case VT_VARIANT|VT_BYREF: {
|
||||
int tp;
|
||||
pval **var_handle;
|
||||
|
||||
/* fetch the VARIANT structure */
|
||||
zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &var_handle);
|
||||
|
||||
V_VT(var_arg) = VT_VARIANT|VT_BYREF;
|
||||
V_VARIANTREF(var_arg) = (VARIANT FAR*) zend_list_find(Z_LVAL_P(*var_handle), &tp);
|
||||
|
||||
if (!V_VARIANTREF(var_arg) && (tp != IS_VARIANT)) {
|
||||
VariantInit(var_arg);
|
||||
}
|
||||
}
|
||||
/*
|
||||
should be, but isn't :)
|
||||
|
||||
if (V_VT(var_arg) != (VT_VARIANT|VT_BYREF)) {
|
||||
VariantInit(var_arg);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
case VT_I1:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_I1(var_arg) = (char)Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI2:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_UI2(var_arg) = (unsigned short)Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI4:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_UI4(var_arg) = (unsigned long)Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_INT:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_INT(var_arg) = (int)Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UINT:
|
||||
convert_to_long_ex(&pval_arg);
|
||||
V_UINT(var_arg) = (unsigned int)Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_I1|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_I1REF(var_arg) = (char FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI2|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_UI2REF(var_arg) = (unsigned short FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI4|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_UI4REF(var_arg) = (unsigned long FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_INT|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_INTREF(var_arg) = (int FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UINT|VT_BYREF:
|
||||
convert_to_long(pval_arg);
|
||||
V_UINTREF(var_arg) = (unsigned int FAR*) &Z_LVAL_P(pval_arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TSRMLS_DC)
|
||||
{
|
||||
/* Changed the function to return a value for recursive error testing */
|
||||
/* Existing calls will be unaffected by the change - so it */
|
||||
/* seemed like the smallest impact on unfamiliar code */
|
||||
int ret = SUCCESS;
|
||||
|
||||
INIT_PZVAL(pval_arg);
|
||||
|
||||
/* Add SafeArray support */
|
||||
if (V_ISARRAY(var_arg)) {
|
||||
SAFEARRAY *array = V_ARRAY(var_arg);
|
||||
LONG indices[1];
|
||||
LONG lbound=0, ubound;
|
||||
VARTYPE vartype;
|
||||
register int ii;
|
||||
UINT Dims;
|
||||
VARIANT vv;
|
||||
pval *element;
|
||||
HRESULT hr;
|
||||
|
||||
/* TODO: Add support for multi-dimensional SafeArrays */
|
||||
/* For now just validate that the SafeArray has one dimension */
|
||||
if (1 != (Dims = SafeArrayGetDim(array))) {
|
||||
php_error(E_WARNING,"Unsupported: multi-dimensional (%d) SafeArrays", Dims);
|
||||
ZVAL_NULL(pval_arg);
|
||||
return FAILURE;
|
||||
}
|
||||
SafeArrayLock(array);
|
||||
|
||||
/* This call has failed for everything I have tried */
|
||||
/* But best leave it to be on the safe side */
|
||||
if (FAILED(SafeArrayGetVartype(array, &vartype)) || (vartype == VT_EMPTY)) {
|
||||
/* Fall back to what we do know */
|
||||
/* Mask off the array bit and assume */
|
||||
/* what is left is the type of the array */
|
||||
/* elements */
|
||||
vartype = V_VT(var_arg) & ~VT_ARRAY;
|
||||
}
|
||||
SafeArrayGetUBound(array, 1, &ubound);
|
||||
SafeArrayGetLBound(array, 1, &lbound);
|
||||
|
||||
/* Since COM returned an array we set up the php */
|
||||
/* return value to be an array */
|
||||
array_init(pval_arg);
|
||||
|
||||
/* Walk the safe array */
|
||||
for (ii=lbound;ii<=ubound;ii++) {
|
||||
indices[0] = ii;
|
||||
VariantInit(&vv); /* Docs say this just set the vt field, but you never know */
|
||||
/* Set up a variant to pass to a recursive call */
|
||||
/* So that we do not need to have two copies */
|
||||
/* of the code */
|
||||
if (VT_VARIANT == vartype) {
|
||||
hr = SafeArrayGetElement(array, indices, (VOID *) &(vv));
|
||||
} else {
|
||||
V_VT(&vv) = vartype;
|
||||
hr = SafeArrayGetElement(array, indices, (VOID *) &(vv.lVal));
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
/* Failure to retieve an element probably means the array is sparse */
|
||||
/* So leave the php array sparse too */
|
||||
continue;
|
||||
}
|
||||
/* Create an element to be added to the array */
|
||||
ALLOC_ZVAL(element);
|
||||
/* Call ourself again to handle the base type conversion */
|
||||
/* If SafeArrayGetElement proclaims to allocate */
|
||||
/* memory for a BSTR, so the recursive call frees */
|
||||
/* the string correctly */
|
||||
if (FAILURE == php_variant_to_pval(&vv, element, codepage TSRMLS_CC)) {
|
||||
/* Error occurred setting up array element */
|
||||
/* Error was displayed by the recursive call */
|
||||
FREE_ZVAL(element);
|
||||
/* TODO: Do we stop here, or go on and */
|
||||
/* try to make sense of the rest of the array */
|
||||
/* Going on leads to multiple errors displayed */
|
||||
/* for the same conversion. For large arrays that */
|
||||
/* could be very annoying */
|
||||
/* And if we don't go on - what to do about */
|
||||
/* the parts of the array that are OK? */
|
||||
/* break; */
|
||||
} else {
|
||||
/* Just insert the element into our return array */
|
||||
add_index_zval(pval_arg, ii, element);
|
||||
}
|
||||
}
|
||||
SafeArrayUnlock(array);
|
||||
} else switch (var_arg->vt & ~VT_BYREF) {
|
||||
case VT_EMPTY:
|
||||
ZVAL_NULL(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_UI1:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_UI1REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_UI1(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_I2:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long )*V_I2REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_I2(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_I4:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, *V_I4REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, V_I4(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_R4:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_DOUBLE(pval_arg, (double)*V_R4REF(var_arg));
|
||||
} else {
|
||||
ZVAL_DOUBLE(pval_arg, (double)V_R4(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_R8:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_DOUBLE(pval_arg, *V_R8REF(var_arg));
|
||||
} else {
|
||||
ZVAL_DOUBLE(pval_arg, V_R8(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
/* 96bit uint */
|
||||
case VT_DECIMAL: {
|
||||
OLECHAR *unicode_str;
|
||||
switch (VarBstrFromDec(&V_DECIMAL(var_arg), LOCALE_SYSTEM_DEFAULT, 0, &unicode_str)) {
|
||||
case S_OK:
|
||||
Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(unicode_str, &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
Z_TYPE_P(pval_arg) = IS_STRING;
|
||||
break;
|
||||
|
||||
default:
|
||||
ZVAL_NULL(pval_arg);
|
||||
ret = FAILURE;
|
||||
php_error(E_WARNING, "Error converting DECIMAL value to PHP string");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Currency */
|
||||
case VT_CY:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
VarR8FromCy(*V_CYREF(var_arg), &Z_DVAL_P(pval_arg));
|
||||
} else {
|
||||
VarR8FromCy(V_CY(var_arg), &Z_DVAL_P(pval_arg));
|
||||
}
|
||||
Z_TYPE_P(pval_arg) = IS_DOUBLE;
|
||||
break;
|
||||
|
||||
case VT_BOOL:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
if (*V_BOOLREF(var_arg)) {
|
||||
ZVAL_BOOL(pval_arg, Z_TRUE);
|
||||
} else {
|
||||
ZVAL_BOOL(pval_arg, Z_FALSE);
|
||||
}
|
||||
} else {
|
||||
if (V_BOOL(var_arg)) {
|
||||
ZVAL_BOOL(pval_arg, Z_TRUE);
|
||||
} else {
|
||||
ZVAL_BOOL(pval_arg, Z_FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_NULL:
|
||||
case VT_VOID:
|
||||
ZVAL_NULL(pval_arg);
|
||||
break;
|
||||
|
||||
case VT_VARIANT:
|
||||
php_variant_to_pval(V_VARIANTREF(var_arg), pval_arg, codepage TSRMLS_CC);
|
||||
break;
|
||||
|
||||
case VT_BSTR:
|
||||
Z_TYPE_P(pval_arg) = IS_STRING;
|
||||
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
if (*V_BSTR(var_arg)) {
|
||||
Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(*V_BSTRREF(var_arg), &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
} else {
|
||||
ZVAL_NULL(pval_arg);
|
||||
}
|
||||
efree(V_BSTRREF(var_arg));
|
||||
} else {
|
||||
if (V_BSTR(var_arg)) {
|
||||
Z_STRVAL_P(pval_arg) = php_OLECHAR_to_char(V_BSTR(var_arg), &Z_STRLEN_P(pval_arg), codepage TSRMLS_CC);
|
||||
} else {
|
||||
ZVAL_NULL(pval_arg);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case VT_DATE: {
|
||||
BOOL success;
|
||||
SYSTEMTIME wintime;
|
||||
struct tm phptime;
|
||||
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
success = VariantTimeToSystemTime(*V_DATEREF(var_arg), &wintime);
|
||||
} else {
|
||||
success = VariantTimeToSystemTime(V_DATE(var_arg), &wintime);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
memset(&phptime, 0, sizeof(phptime));
|
||||
|
||||
phptime.tm_year = wintime.wYear - 1900;
|
||||
phptime.tm_mon = wintime.wMonth - 1;
|
||||
phptime.tm_mday = wintime.wDay;
|
||||
phptime.tm_hour = wintime.wHour;
|
||||
phptime.tm_min = wintime.wMinute;
|
||||
phptime.tm_sec = wintime.wSecond;
|
||||
phptime.tm_isdst = -1;
|
||||
|
||||
tzset();
|
||||
ZVAL_LONG(pval_arg, mktime(&phptime));
|
||||
} else {
|
||||
ret = FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_UNKNOWN:
|
||||
if (V_UNKNOWN(var_arg) == NULL) {
|
||||
V_DISPATCH(var_arg) = NULL;
|
||||
} else {
|
||||
HRESULT hr;
|
||||
|
||||
hr = V_UNKNOWN(var_arg)->lpVtbl->QueryInterface(var_arg->punkVal, &IID_IDispatch, &V_DISPATCH(var_arg));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
char *error_message;
|
||||
|
||||
error_message = php_COM_error_message(hr TSRMLS_CC);
|
||||
php_error(E_WARNING,"Unable to obtain IDispatch interface: %s", error_message);
|
||||
LocalFree(error_message);
|
||||
|
||||
V_DISPATCH(var_arg) = NULL;
|
||||
}
|
||||
}
|
||||
/* break missing intentionaly */
|
||||
case VT_DISPATCH: {
|
||||
comval *obj;
|
||||
|
||||
if (V_DISPATCH(var_arg) == NULL) {
|
||||
ret = FAILURE;
|
||||
ZVAL_NULL(pval_arg);
|
||||
} else {
|
||||
ALLOC_COM(obj);
|
||||
php_COM_set(obj, &V_DISPATCH(var_arg), FALSE TSRMLS_CC);
|
||||
|
||||
ZVAL_COM(pval_arg, obj);
|
||||
VariantInit(var_arg); // to protect C_DISPATCH(obj) from being freed when var_result is destructed
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_I1:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_I1REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_I1(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_UI2:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_UI2REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_UI2(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_UI4:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_UI4REF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_UI4(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_INT:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_INTREF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_INT(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_UINT:
|
||||
if (V_ISBYREF(var_arg)) {
|
||||
ZVAL_LONG(pval_arg, (long)*V_UINTREF(var_arg));
|
||||
} else {
|
||||
ZVAL_LONG(pval_arg, (long)V_UINT(var_arg));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
php_error(E_WARNING,"Unsupported variant type: %d (0x%X)", V_VT(var_arg), V_VT(var_arg));
|
||||
ZVAL_NULL(pval_arg);
|
||||
ret = FAILURE;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC)
|
||||
{
|
||||
BOOL error = FALSE;
|
||||
OLECHAR *unicode_str;
|
||||
|
||||
if (strlen == -1) {
|
||||
/* request needed buffersize */
|
||||
strlen = MultiByteToWideChar(codepage, (codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS), C_str, -1, NULL, 0);
|
||||
} else {
|
||||
/* \0 terminator */
|
||||
strlen++;
|
||||
}
|
||||
|
||||
if (strlen >= 0) {
|
||||
unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR) * strlen);
|
||||
|
||||
/* convert string */
|
||||
error = !MultiByteToWideChar(codepage, (codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS), C_str, strlen, unicode_str, strlen);
|
||||
} else {
|
||||
/* return a zero-length string */
|
||||
unicode_str = (OLECHAR *) emalloc(sizeof(OLECHAR));
|
||||
*unicode_str = 0;
|
||||
|
||||
error = TRUE;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
switch (GetLastError()) {
|
||||
case ERROR_NO_UNICODE_TRANSLATION:
|
||||
php_error(E_WARNING, "No unicode translation available for the specified string");
|
||||
break;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
php_error(E_WARNING, "Internal Error: Insufficient Buffer");
|
||||
break;
|
||||
default:
|
||||
php_error(E_WARNING, "Unknown error in php_char_to_OLECHAR()");
|
||||
}
|
||||
}
|
||||
|
||||
return unicode_str;
|
||||
}
|
||||
|
||||
|
||||
PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage TSRMLS_DC)
|
||||
{
|
||||
char *C_str;
|
||||
uint length = 0;
|
||||
|
||||
/* request needed buffersize */
|
||||
uint reqSize = WideCharToMultiByte(codepage, codepage == CP_UTF8 ? 0 : WC_COMPOSITECHECK, unicode_str, -1, NULL, 0, NULL, NULL);
|
||||
|
||||
if (reqSize) {
|
||||
C_str = (char *) emalloc(sizeof(char) * reqSize);
|
||||
|
||||
/* convert string */
|
||||
length = WideCharToMultiByte(codepage, codepage == CP_UTF8 ? 0 : WC_COMPOSITECHECK, unicode_str, -1, C_str, reqSize, NULL, NULL) - 1;
|
||||
} else {
|
||||
C_str = (char *) emalloc(sizeof(char));
|
||||
*C_str = 0;
|
||||
|
||||
php_error(E_WARNING,"Error in php_OLECHAR_to_char()");
|
||||
}
|
||||
|
||||
if (out_length) {
|
||||
*out_length = length;
|
||||
}
|
||||
|
||||
return C_str;
|
||||
}
|
||||
|
||||
|
||||
static void comval_to_variant(pval *pval_arg, VARIANT *var_arg TSRMLS_DC)
|
||||
{
|
||||
pval **comval_handle;
|
||||
comval *obj;
|
||||
int type;
|
||||
|
||||
/* fetch the comval structure */
|
||||
zend_hash_index_find(Z_OBJPROP_P(pval_arg), 0, (void **) &comval_handle);
|
||||
obj = (comval *)zend_list_find(Z_LVAL_P(*comval_handle), &type);
|
||||
if (!obj || (type != IS_COM) || !C_ISREFD(obj)) {
|
||||
VariantInit(var_arg);
|
||||
} else {
|
||||
V_VT(var_arg) = VT_DISPATCH;
|
||||
V_DISPATCH(var_arg) = C_DISPATCH(obj);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef CONVERSION_H
|
||||
#define CONVERSION_H
|
||||
|
||||
/* isn't this defined somewhere else ? */
|
||||
|
||||
#define Z_TRUE 1
|
||||
#define Z_FALSE 0
|
||||
|
||||
#define VT_TRUE -1
|
||||
#define VT_FALSE 0
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
PHPAPI void php_pval_to_variant(pval *pval_arg, VARIANT *var_arg, int codepage TSRMLS_DC);
|
||||
PHPAPI void php_pval_to_variant_ex(pval *pval_arg, VARIANT *var_arg, pval *pval_type, int codepage TSRMLS_DC);
|
||||
PHPAPI void php_pval_to_variant_ex2(pval *pval_arg, VARIANT *var_arg, VARTYPE type, int codepage TSRMLS_DC);
|
||||
PHPAPI int php_variant_to_pval(VARIANT *var_arg, pval *pval_arg, int codepage TSRMLS_DC);
|
||||
PHPAPI OLECHAR *php_char_to_OLECHAR(char *C_str, uint strlen, int codepage TSRMLS_DC);
|
||||
PHPAPI char *php_OLECHAR_to_char(OLECHAR *unicode_str, uint *out_length, int codepage TSRMLS_DC);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif
|
||||
@@ -1,627 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 4 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2003 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 2.02 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available at through the world-wide-web at |
|
||||
| http://www.php.net/license/2_02.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Author: Wez Furlong <wez@thebrainroom.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This module is used to export PHP objects to COM and DOTNET by exposing
|
||||
* them as objects implementing IDispatch.
|
||||
* */
|
||||
|
||||
#include "php.h"
|
||||
#include "php_COM.h"
|
||||
#include "php_VARIANT.h"
|
||||
#include "conversion.h"
|
||||
#include "variant.h"
|
||||
|
||||
#define COBJMACROS
|
||||
#include <unknwn.h> /* IDispatch */
|
||||
#include <dispex.h> /* IDispatchEx */
|
||||
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
||||
static int le_dispatch;
|
||||
int php_COM_dispatch_init(int module_number TSRMLS_DC)
|
||||
{
|
||||
le_dispatch = zend_register_list_destructors_ex(dispatch_dtor, NULL, "COM:Dispatch", 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
FETCH_DISP("GetTypeInfoCount");
|
||||
|
||||
*pctinfo = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE disp_gettypeinfo(
|
||||
IDispatchEx *This,
|
||||
/* [in] */ UINT iTInfo,
|
||||
/* [in] */ LCID lcid,
|
||||
/* [out] */ ITypeInfo **ppTInfo)
|
||||
{
|
||||
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_OLECHAR_to_char(rgszNames[i], &namelen, CP_ACP 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_OLECHAR_to_char(bstrName, &namelen, CP_ACP 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;
|
||||
int codepage = CP_ACP;
|
||||
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);
|
||||
|
||||
if (V_VT(arg) == VT_DISPATCH) {
|
||||
trace("arg %d is dispatchable\n", i);
|
||||
if (NULL == php_COM_object_from_dispatch(V_DISPATCH(arg), zarg TSRMLS_CC)) {
|
||||
trace("failed to convert arg %d to zval\n", i);
|
||||
ZVAL_NULL(zarg);
|
||||
}
|
||||
} else {
|
||||
// arg can't be an idispatch, so we don't care for the implicit AddRef() call here
|
||||
if (FAILURE == php_variant_to_pval(arg, zarg, codepage TSRMLS_CC)) {
|
||||
trace("failed to convert arg %d to zval\n", i);
|
||||
ZVAL_NULL(zarg);
|
||||
}
|
||||
}
|
||||
|
||||
params[i] = &zarg;
|
||||
}
|
||||
|
||||
trace("arguments processed, prepare to do some work\n");
|
||||
|
||||
if (wFlags & DISPATCH_PROPERTYGET) {
|
||||
trace("trying to get a property\n");
|
||||
zend_hash_find(Z_OBJPROP_P(disp->object), Z_STRVAL_PP(name), Z_STRLEN_PP(name)+1, (void**)&retval);
|
||||
} else if (wFlags & DISPATCH_PROPERTYPUT) {
|
||||
trace("trying to set a property\n");
|
||||
add_property_zval(disp->object, Z_STRVAL_PP(name), *params[0]);
|
||||
} else if (wFlags & DISPATCH_METHOD) {
|
||||
trace("Trying to call user function\n");
|
||||
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_export_object(retval TSRMLS_CC);
|
||||
} else {
|
||||
php_pval_to_variant(retval, pvarRes, codepage 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)
|
||||
{
|
||||
FETCH_DISP("DeleteMemberByName");
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE disp_deletememberbydispid(
|
||||
IDispatchEx *This,
|
||||
/* [in] */ DISPID id)
|
||||
{
|
||||
FETCH_DISP("DeleteMemberByDispID");
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT STDMETHODCALLTYPE disp_getmemberproperties(
|
||||
IDispatchEx *This,
|
||||
/* [in] */ DISPID id,
|
||||
/* [in] */ DWORD grfdexFetch,
|
||||
/* [out] */ DWORD *pgrfdex)
|
||||
{
|
||||
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_char_to_OLECHAR(Z_STRVAL_P(name), Z_STRLEN_P(name), CP_ACP 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;
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
zend_hash_internal_pointer_reset_ex(Z_OBJPROP_PP(&disp->object), &pos);
|
||||
while (HASH_KEY_NON_EXISTANT != (keytype =
|
||||
zend_hash_get_current_key_ex(Z_OBJPROP_PP(&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_PP(&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 */
|
||||
zend_hash_internal_pointer_reset_ex(&Z_OBJCE_PP(&disp->object)->function_table, &pos);
|
||||
while (HASH_KEY_NON_EXISTANT != (keytype =
|
||||
zend_hash_get_current_key_ex(&Z_OBJCE_PP(&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_PP(&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_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_export_object(zval *val TSRMLS_DC)
|
||||
{
|
||||
php_dispatchex *disp = NULL;
|
||||
|
||||
if (Z_TYPE_P(val) != IS_OBJECT)
|
||||
return NULL;
|
||||
|
||||
if (Z_OBJCE_P(val) == &COM_class_entry || !strcmp(Z_OBJCE_P(val)->name, "COM")) {
|
||||
/* pass back it's IDispatch directly */
|
||||
zval **tmp;
|
||||
comval *obj;
|
||||
int type;
|
||||
|
||||
zend_hash_index_find(Z_OBJPROP_P(val), 0, (void**)&tmp);
|
||||
obj = (comval *)zend_list_find(Z_LVAL_PP(tmp), &type);
|
||||
if (type != IS_COM)
|
||||
return NULL;
|
||||
|
||||
C_DISPATCH(obj)->lpVtbl->AddRef(C_DISPATCH(obj));
|
||||
return C_DISPATCH(obj);
|
||||
}
|
||||
|
||||
disp = disp_constructor(val TSRMLS_CC);
|
||||
generate_dispids(disp TSRMLS_CC);
|
||||
|
||||
return (IDispatch*)disp;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
#ifndef PHP_COM_H
|
||||
#define PHP_COM_H
|
||||
|
||||
#if PHP_WIN32
|
||||
|
||||
#include "com.h"
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
PHP_MINIT_FUNCTION(COM);
|
||||
PHP_MSHUTDOWN_FUNCTION(COM);
|
||||
|
||||
PHP_FUNCTION(com_load);
|
||||
PHP_FUNCTION(com_invoke);
|
||||
PHP_FUNCTION(com_invoke_ex);
|
||||
PHP_FUNCTION(com_addref);
|
||||
PHP_FUNCTION(com_release);
|
||||
PHP_FUNCTION(com_propget);
|
||||
PHP_FUNCTION(com_propput);
|
||||
PHP_FUNCTION(com_load_typelib);
|
||||
PHP_FUNCTION(com_isenum);
|
||||
PHP_FUNCTION(com_event_sink);
|
||||
PHP_FUNCTION(com_message_pump);
|
||||
PHP_FUNCTION(com_print_typeinfo);
|
||||
|
||||
PHPAPI HRESULT php_COM_invoke(comval *obj, DISPID dispIdMember, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, char **ErrString TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_get_ids_of_names(comval *obj, OLECHAR FAR* FAR* rgszNames, DISPID FAR* rgDispId TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_release(comval *obj TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_addref(comval *obj TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_destruct(comval *obj TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_set(comval *obj, IDispatch FAR* FAR* pDisp, int cleanup TSRMLS_DC);
|
||||
PHPAPI HRESULT php_COM_clone(comval *obj, comval *clone, int cleanup TSRMLS_DC);
|
||||
PHPAPI char *php_COM_error_message(HRESULT hr TSRMLS_DC);
|
||||
PHPAPI int php_COM_get_le_comval();
|
||||
PHPAPI int php_COM_set_property_handler(zend_property_reference *property_reference, pval *value);
|
||||
PHPAPI pval php_COM_get_property_handler(zend_property_reference *property_reference);
|
||||
PHPAPI void php_COM_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
|
||||
PHPAPI zval *php_COM_object_from_dispatch(IDispatch *disp, zval *val TSRMLS_DC);
|
||||
PHPAPI int php_COM_load_typelib(ITypeLib *TypeLib, int mode TSRMLS_DC);
|
||||
|
||||
/* dispatch.c */
|
||||
PHPAPI IDispatch *php_COM_export_object(zval *val TSRMLS_DC);
|
||||
PHPAPI IDispatch *php_COM_export_as_sink(zval *val, GUID *sinkid, HashTable *id_to_name TSRMLS_DC);
|
||||
int php_COM_dispatch_init(int module_number TSRMLS_DC);
|
||||
|
||||
zend_module_entry COM_module_entry;
|
||||
zend_class_entry COM_class_entry;
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int resourcecounter;
|
||||
#endif
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#define phpext_com_ptr &COM_module_entry
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(com)
|
||||
int nothing;
|
||||
ZEND_END_MODULE_GLOBALS(com)
|
||||
|
||||
PHPAPI ZEND_EXTERN_MODULE_GLOBALS(com);
|
||||
|
||||
#ifdef ZTS
|
||||
#define COMG(v) TSRMG(com_globals_id, zend_com_globals *, v)
|
||||
#else
|
||||
#define COMG(v) (com_globals.v)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define phpext_com_ptr NULL
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
|
||||
#endif /* PHP_COM_H */
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef PHP_TYPEDEF_VARIANT_H
|
||||
#define PHP_TYPEDEF_VARIANT_H
|
||||
|
||||
#if PHP_WIN32
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
#include "conversion.h"
|
||||
#include "variant.h"
|
||||
|
||||
void php_VARIANT_init(int module_number TSRMLS_DC);
|
||||
|
||||
PHPAPI int php_VARIANT_get_le_variant();
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
|
||||
#endif /* PHP_TYPEDEF_VARIANT_H */
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef VARIANT_H
|
||||
#define VARIANT_H
|
||||
|
||||
#if PHP_WIN32
|
||||
|
||||
#define ALLOC_VARIANT(v) (v) = (VARIANT *) emalloc(sizeof(VARIANT)); \
|
||||
VariantInit(v);
|
||||
|
||||
#define FREE_VARIANT(v) VariantClear(v); \
|
||||
efree(v);
|
||||
|
||||
|
||||
#define IS_VARIANT php_VARIANT_get_le_variant()
|
||||
|
||||
#define ZVAL_VARIANT(z, v) if (V_VT(v) == VT_DISPATCH) { \
|
||||
comval *obj; \
|
||||
ALLOC_COM(obj); \
|
||||
php_COM_set(obj, &V_DISPATCH(v), TRUE TSRMLS_CC); \
|
||||
ZVAL_RESOURCE((z), zend_list_insert(obj, IS_COM)); \
|
||||
} else { \
|
||||
php_variant_to_pval((v), (z), codepage TSRMLS_CC); \
|
||||
FREE_VARIANT(v); \
|
||||
}
|
||||
|
||||
#define RETVAL_VARIANT(v) ZVAL_VARIANT(return_value, (v));
|
||||
#define RETURN_VARIANT(v) RETVAL_VARIANT(v) \
|
||||
return;
|
||||
|
||||
|
||||
#endif /* PHP_WIN32 */
|
||||
|
||||
#endif /* VARIANT_H */
|
||||
Reference in New Issue
Block a user