1
0
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:
Harald Radi
2003-01-10 23:39:09 +00:00
parent c3867a7c8e
commit fff34aa3be
11 changed files with 0 additions and 4577 deletions
-2474
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -1,2 +0,0 @@
Win32 COM
Alan Brown, Wez Furlong, Harald Radi, Zeev Suraski
-28
View File
@@ -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)
-343
View File
@@ -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 */
-79
View File
@@ -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 */
-875
View File
@@ -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 */
-23
View File
@@ -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
-627
View File
@@ -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;
}
-75
View File
@@ -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 */
-19
View File
@@ -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 */
-32
View File
@@ -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 */