wez Thu Aug 14 12:49:56 2003 EDT
Added files:
/php-src/ext/com_dotnet README com_com.c com_dotnet.c
com_extension.c com_handlers.c com_misc.c
com_olechar.c com_typeinfo.c com_variant.c
php_com_dotnet.h php_com_dotnet_internal.h
/php-src/ext/com_dotnet/tests variants.phpt
Modified files:
/php-src/main config.w32.h internal_functions_win32.c
Log:
Add new COM (and .Net) extension for php5.
Not yet complete, but should work for most people.
Index: php-src/main/config.w32.h
diff -u php-src/main/config.w32.h:1.75 php-src/main/config.w32.h:1.76
--- php-src/main/config.w32.h:1.75 Fri Jun 27 12:43:05 2003
+++ php-src/main/config.w32.h Thu Aug 14 12:49:56 2003
@@ -2,7 +2,7 @@
Build Configuration for Win32.
This has only been tested with MS VisualC++ 6 (and later).
- $Id: config.w32.h,v 1.75 2003/06/27 16:43:05 sebastian Exp $
+ $Id: config.w32.h,v 1.76 2003/08/14 16:49:56 wez Exp $
*/
/* Default PHP / PEAR directories */
@@ -46,6 +46,10 @@
/* #define HAVE_MBSTR_KR 0 */
/* #define HAVE_MBSTR_RU 0 */
/* #define HAVE_MBSTR_TW 0 */
+
+/* If you have the .Net SDK in your include path, define this
+ * to compile .Net support into your COM extension. */
+#define HAVE_MSCOREE_H 0
/* Enable / Disable ODBC extension (default: enabled) */
#define HAVE_UODBC 1
Index: php-src/main/internal_functions_win32.c
diff -u php-src/main/internal_functions_win32.c:1.78
php-src/main/internal_functions_win32.c:1.79
--- php-src/main/internal_functions_win32.c:1.78 Fri Jun 27 10:32:59 2003
+++ php-src/main/internal_functions_win32.c Thu Aug 14 12:49:56 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: internal_functions_win32.c,v 1.78 2003/06/27 14:32:59 edink Exp $ */
+/* $Id: internal_functions_win32.c,v 1.79 2003/08/14 16:49:56 wez Exp $ */
/* {{{ includes
*/
@@ -97,6 +97,7 @@
#ifdef HAVE_SQLITE
#include "ext/sqlite/php_sqlite.h"
#endif
+#include "ext/com_dotnet/php_com_dotnet.h"
/* }}} */
/* {{{ php_builtin_extensions[]
@@ -109,6 +110,7 @@
#if HAVE_CALENDAR
,phpext_calendar_ptr
#endif
+ ,phpext_com_dotnet_ptr
#if HAVE_CTYPE
,phpext_ctype_ptr
#endif
@@ -135,14 +137,14 @@
#endif
#if HAVE_LIBXML
#if HAVE_DOM
- ,phpext_dom_ptr
+ phpext_dom_ptr
#endif
#if HAVE_SIMPLEXML
- ,phpext_simplexml_ptr
+ phpext_simplexml_ptr
#endif
#endif
#if HAVE_XML
- ,phpext_xml_ptr
+ phpext_xml_ptr
#endif
#if HAVE_XML && HAVE_WDDX
,phpext_wddx_ptr
Index: php-src/ext/com_dotnet/com_com.c
+++ php-src/ext/com_dotnet/com_com.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_com.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
#include "Zend/zend_default_classes.h"
/* {{{ com_create_instance - ctor for COM class */
PHP_FUNCTION(com_create_instance)
{
zval *object = getThis();
zval *server_params = NULL;
php_com_dotnet_object *obj;
char *module_name, *typelib_name = NULL, *server_name = NULL;
char *user_name = NULL, *domain_name = NULL, *password = NULL;
long module_name_len, typelib_name_len, server_name_len,
user_name_len, domain_name_len, password_len;
OLECHAR *moniker;
CLSID clsid;
CLSCTX ctx = CLSCTX_SERVER;
HRESULT res = E_FAIL;
int mode = COMG(autoreg_case_sensitive) ? CONST_CS : 0;
ITypeLib *TL = NULL;
obj = CDNO_FETCH(object);
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "s|s!ls",
&module_name, &module_name_len, &server_name, &server_name_len,
&obj->code_page, &typelib_name, &typelib_name_len) &&
FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "sa|ls",
&module_name, &module_name_len, &server_params,
&obj->code_page,
&typelib_name, &typelib_name_len)) {
php_com_throw_exception("Could not create COM object - invalid
arguments!" TSRMLS_CC);
ZVAL_NULL(object);
return;
}
if (server_name) {
ctx = CLSCTX_REMOTE_SERVER;
} else if (server_params) {
zval **tmp;
/* decode the data from the array */
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
"Server", sizeof("Server"), (void**)&tmp)) {
convert_to_string_ex(tmp);
server_name = Z_STRVAL_PP(tmp);
server_name_len = Z_STRLEN_PP(tmp);
ctx = CLSCTX_REMOTE_SERVER;
}
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
"Username", sizeof("Username"), (void**)&tmp)) {
convert_to_string_ex(tmp);
user_name = Z_STRVAL_PP(tmp);
user_name_len = Z_STRLEN_PP(tmp);
}
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
"Password", sizeof("Password"), (void**)&tmp)) {
convert_to_string_ex(tmp);
password = Z_STRVAL_PP(tmp);
password_len = Z_STRLEN_PP(tmp);
}
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
"Domain", sizeof("Domain"), (void**)&tmp)) {
convert_to_string_ex(tmp);
domain_name = Z_STRVAL_PP(tmp);
domain_name_len = Z_STRLEN_PP(tmp);
}
if (SUCCESS == zend_hash_find(HASH_OF(server_params),
"Flags", sizeof("Flags"), (void**)&tmp)) {
convert_to_long_ex(tmp);
ctx = (CLSCTX)Z_LVAL_PP(tmp);
}
}
if (server_name && !COMG(allow_dcom)) {
php_com_throw_exception("DCOM has been disabled by your administrator
[com.allow_dcom=0]" TSRMLS_CC);
return;
}
moniker = php_com_string_to_olestring(module_name, module_name_len,
obj->code_page TSRMLS_CC);
if (FAILED(CLSIDFromString(moniker, &clsid))) {
/* try to use it as a moniker */
IBindCtx *pBindCtx = NULL;
IMoniker *pMoniker = NULL;
ULONG ulEaten;
if (server_name == NULL) {
res = MK_E_SYNTAX;
} else if (SUCCEEDED(res = CreateBindCtx(0, &pBindCtx)) &&
SUCCEEDED(res = MkParseDisplayName(pBindCtx, moniker,
&ulEaten, &pMoniker))) {
res = IMoniker_BindToObject(pMoniker, pBindCtx, NULL,
&IID_IDispatch, (LPVOID*)&V_DISPATCH(&obj->v));
if (SUCCEEDED(res)) {
V_VT(&obj->v) = VT_DISPATCH;
}
IMoniker_Release(pMoniker);
}
if (pBindCtx) {
IBindCtx_Release(pBindCtx);
}
} else if (server_name) {
COSERVERINFO info;
MULTI_QI qi;
COAUTHIDENTITY authid;
COAUTHINFO authinfo = {
RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
&authid, EOAC_NONE
};
info.dwReserved1 = 0;
info.dwReserved2 = 0;
info.pwszName = php_com_string_to_olestring(server_name,
server_name_len, obj->code_page TSRMLS_CC);
if (user_name) {
authid.User = php_com_string_to_olestring(user_name, -1,
obj->code_page TSRMLS_CC);
authid.UserLength = user_name_len;
if (password) {
authid.Password = (OLECHAR*)password;
authid.PasswordLength = password_len;
} else {
authid.Password = (OLECHAR*)"";
authid.PasswordLength = 0;
}
if (domain_name) {
authid.Domain = (OLECHAR*)domain_name;
authid.DomainLength = domain_name_len;
} else {
authid.Domain = (OLECHAR*)"";
authid.DomainLength = 0;
}
authid.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
info.pAuthInfo = &authinfo;
} else {
info.pAuthInfo = NULL;
}
qi.pIID = &IID_IDispatch;
qi.pItf = NULL;
qi.hr = S_OK;
res = CoCreateInstanceEx(&clsid, NULL, ctx, &info, 1, &qi);
efree(info.pwszName);
if (SUCCEEDED(res)) {
res = qi.hr;
V_DISPATCH(&obj->v) = (IDispatch*)qi.pItf;
V_VT(&obj->v) = VT_DISPATCH;
}
} else {
res = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch,
(LPVOID*)&V_DISPATCH(&obj->v));
if (SUCCEEDED(res)) {
V_VT(&obj->v) = VT_DISPATCH;
}
}
efree(moniker);
if (FAILED(res)) {
char *werr, *msg;
werr = php_win_err(res);
spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name,
werr);
LocalFree(werr);
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
ZVAL_NULL(object);
return;
}
/* we got the object and it lives ! */
/* see if it has TypeInfo available */
if (FAILED(IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL,
&obj->typeinfo)) && typelib_name) {
/* load up the library from the named file */
int cached;
TL = php_com_load_typelib_via_cache(typelib_name, mode,
obj->code_page, &cached TSRMLS_CC);
if (TL) {
if (COMG(autoreg_on) && !cached) {
php_com_import_typelib(TL, mode, obj->code_page
TSRMLS_CC);
}
/* cross your fingers... there is no guarantee that this
ITypeInfo
* instance has any relation to this IDispatch instance... */
ITypeLib_GetTypeInfo(TL, 0, &obj->typeinfo);
ITypeLib_Release(TL);
}
} else if (obj->typeinfo && COMG(autoreg_on)) {
int idx;
if (SUCCEEDED(ITypeInfo_GetContainingTypeLib(obj->typeinfo, &TL,
&idx))) {
/* check if the library is already in the cache by getting its
name */
BSTR name;
if (SUCCEEDED(ITypeLib_GetDocumentation(TL, -1, &name, NULL,
NULL, NULL))) {
typelib_name = php_com_olestring_to_string(name,
&typelib_name_len, obj->code_page TSRMLS_CC);
if (SUCCESS ==
zend_ts_hash_add(&php_com_typelibraries, typelib_name, typelib_name_len+1, (void*)&TL,
sizeof(ITypeLib*), NULL)) {
php_com_import_typelib(TL, mode,
obj->code_page TSRMLS_CC);
/* add a reference for the hash */
ITypeLib_AddRef(TL);
}
} else {
/* try it anyway */
php_com_import_typelib(TL, mode, obj->code_page
TSRMLS_CC);
}
ITypeLib_Release(TL);
}
}
}
/* }}} */
/* Performs an Invoke on the given com object.
* returns a failure code and creates an exception if there was an error */
HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC)
{
HRESULT hr;
unsigned int arg_err;
EXCEPINFO e;
if (obj->typeinfo) {
hr = ITypeInfo_Invoke(obj->typeinfo, V_DISPATCH(&obj->v), id_member,
flags, disp_params, v, &e, &arg_err);
if (FAILED(hr) && (hr != DISP_E_EXCEPTION)) {
hr = IDispatch_Invoke(V_DISPATCH(&obj->v), id_member,
&IID_NULL, LOCALE_SYSTEM_DEFAULT, flags, disp_params,
v, &e, &arg_err);
if (SUCCEEDED(hr)) {
/* fall back on using IDispatch directly */
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
}
} else {
hr = IDispatch_Invoke(V_DISPATCH(&obj->v), id_member,
&IID_NULL, LOCALE_SYSTEM_DEFAULT, flags, disp_params, v, &e,
&arg_err);
}
if (FAILED(hr)) {
char *source = NULL, *desc = NULL, *msg = NULL;
int source_len, desc_len;
switch (hr) {
case DISP_E_EXCEPTION:
if (e.bstrSource) {
source =
php_com_olestring_to_string(e.bstrSource, &source_len, obj->code_page TSRMLS_CC);
SysFreeString(e.bstrSource);
}
if (e.bstrDescription) {
desc =
php_com_olestring_to_string(e.bstrDescription, &desc_len, obj->code_page TSRMLS_CC);
SysFreeString(e.bstrDescription);
}
if (PG(html_errors)) {
spprintf(&msg, 0, "<b>Source:</b>
%s<br/><b>Description:</b> %s",
source ? source : "Unknown",
desc ? desc : "Unknown");
} else {
spprintf(&msg, 0, "Source: %s\nDescription:
%s",
source ? source : "Unknown",
desc ? desc : "Unknown");
}
if (desc) {
efree(desc);
}
if (source) {
efree(source);
}
if (e.bstrHelpFile) {
SysFreeString(e.bstrHelpFile);
}
break;
case DISP_E_PARAMNOTFOUND:
case DISP_E_TYPEMISMATCH:
desc = php_win_err(hr);
spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc);
LocalFree(desc);
break;
default:
desc = php_win_err(hr);
spprintf(&msg, 0, "Error %s", desc);
LocalFree(desc);
break;
}
if (msg) {
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
}
}
return hr;
}
/* map an ID to a name */
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
int namelen, DISPID *dispid TSRMLS_DC)
{
OLECHAR *olename;
HRESULT hr;
olename = php_com_string_to_olestring(name, namelen, obj->code_page TSRMLS_CC);
if (obj->typeinfo) {
hr = ITypeInfo_GetIDsOfNames(obj->typeinfo, &olename, 1, dispid);
if (FAILED(hr)) {
hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL,
&olename, 1, LOCALE_SYSTEM_DEFAULT, dispid);
if (SUCCEEDED(hr)) {
/* fall back on IDispatch direct */
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
}
} else {
hr = IDispatch_GetIDsOfNames(V_DISPATCH(&obj->v), &IID_NULL, &olename,
1, LOCALE_SYSTEM_DEFAULT, dispid);
}
efree(olename);
return hr;
}
/* the core of COM */
int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC)
{
DISPID altdispid;
DISPPARAMS disp_params;
HRESULT hr;
VARIANT *vargs = NULL;
int i;
if (nargs) {
vargs = (VARIANT*)emalloc(sizeof(VARIANT) * nargs);
}
/* Invoke'd args are in reverse order */
for (i = 0; i < nargs; i++) {
php_com_variant_from_zval(&vargs[i], args[nargs - i - 1],
obj->code_page TSRMLS_CC);
}
disp_params.cArgs = nargs;
disp_params.cNamedArgs = 0;
disp_params.rgvarg = vargs;
disp_params.rgdispidNamedArgs = NULL;
if (flags & DISPATCH_PROPERTYPUT) {
altdispid = DISPID_PROPERTYPUT;
disp_params.rgdispidNamedArgs = &altdispid;
disp_params.cNamedArgs = 1;
}
/* this will create an exception if needed */
hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v TSRMLS_CC);
/* release variants */
if (vargs) {
for (i = 0; i < nargs; i++) {
VariantClear(&vargs[i]);
}
efree(vargs);
}
return SUCCEEDED(hr) ? SUCCESS : FAILURE;
}
int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC)
{
DISPID dispid;
HRESULT hr;
char *winerr = NULL;
char *msg = NULL;
hr = php_com_get_id_of_name(obj, name, namelen, &dispid TSRMLS_CC);
if (FAILED(hr)) {
winerr = php_win_err(hr);
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
LocalFree(winerr);
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
return FAILURE;
}
return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args TSRMLS_CC);
}
Index: php-src/ext/com_dotnet/com_dotnet.c
+++ php-src/ext/com_dotnet/com_dotnet.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_dotnet.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#if HAVE_MSCOREE_H
# include "php_ini.h"
# include "ext/standard/info.h"
# include "php_com_dotnet.h"
# include "php_com_dotnet_internal.h"
# include "Zend/zend_default_classes.h"
# include <mscoree.h>
struct dotnet_runtime_stuff {
ICorRuntimeHost *dotnet_host;
IDispatch *dotnet_domain;
DISPID create_instance;
};
/* Since there is no official public mscorlib.h header file, and since
* generating your own version from the binary .tlb file results in a 3MB
* header file (!), we opt for the Dispatch-able approach. This is slightly
* slower for creating new objects, but not too bad */
static int dotnet_init(TSRMLS_D)
{
HRESULT hr;
struct dotnet_runtime_stuff *stuff;
IUnknown *unk = NULL;
OLECHAR *olename;
stuff = emalloc(sizeof(*stuff));
memset(stuff, 0, sizeof(*stuff));
if (SUCCEEDED(CoCreateInstance(&CLSID_CorRuntimeHost, NULL, CLSCTX_ALL,
&IID_ICorRuntimeHost, (LPVOID*)&stuff->dotnet_host))) {
/* fire up the host and get the domain object */
if (SUCCEEDED(ICorRuntimeHost_Start(stuff->dotnet_host)) &&
SUCCEEDED(ICorRuntimeHost_GetDefaultDomain(stuff->dotnet_host, &unk)) &&
SUCCEEDED(IUnknown_QueryInterface(unk, &IID_IDispatch,
(LPVOID*)&stuff->dotnet_domain))) {
/* locate the create-instance member */
olename = php_com_string_to_olestring("CreateInstance",
sizeof("CreateInstance")-1, CP_ACP TSRMLS_CC);
hr = IDispatch_GetIDsOfNames(stuff->dotnet_domain, &IID_NULL,
&olename, 1, LOCALE_SYSTEM_DEFAULT, &stuff->create_instance);
efree(olename);
if (SUCCEEDED(hr)) {
COMG(dotnet_runtime_stuff) = stuff;
}
}
if (unk) {
IUnknown_Release(unk);
}
}
if (COMG(dotnet_runtime_stuff) == NULL) {
/* clean up */
if (stuff->dotnet_domain) {
IDispatch_Release(stuff->dotnet_domain);
}
if (stuff->dotnet_host) {
ICorRuntimeHost_Stop(stuff->dotnet_host);
ICorRuntimeHost_Release(stuff->dotnet_host);
}
efree(stuff);
return FAILURE;
}
return SUCCESS;
}
/* {{{ com_dotnet_create_instance - ctor for DOTNET class */
PHP_FUNCTION(com_dotnet_create_instance)
{
zval *object = getThis();
php_com_dotnet_object *obj;
char *assembly_name, *datatype_name;
long assembly_name_len, datatype_name_len;
struct dotnet_runtime_stuff *stuff;
IObjectHandle *handle;
DISPPARAMS params;
VARIANT vargs[2];
VARIANT retval;
HRESULT hr;
int ret = FAILURE;
if (COMG(dotnet_runtime_stuff) == NULL) {
if (FAILURE == dotnet_init(TSRMLS_C)) {
com_throw_exception("Failed to initialize .Net runtime"
TSRMLS_CC);
ZVAL_NULL(object);
return;
}
}
stuff = (struct dotnet_runtime_stuff*)COMG(dotnet_runtime_stuff);
obj = CDNO_FETCH(object);
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l",
&assembly_name, &assembly_name_len,
&datatype_name, &datatype_name_len,
&obj->code_page)) {
com_throw_exception("Could not create .Net object - invalid
arguments!" TSRMLS_CC);
ZVAL_NULL(object);
return;
}
params.cArgs = 2;
params.cNamedArgs = 0;
params.rgdispidNamedArgs = NULL;
params.rgvarg = vargs;
VariantInit(&vargs[0]);
VariantInit(&vargs[1]);
VariantInit(&retval);
V_VT(&vargs[0]) = VT_BSTR;
V_BSTR(&vargs[0]) = php_com_string_to_olestring(datatype_name,
datatype_name_len, obj->code_page TSRMLS_CC);
V_VT(&vargs[1]) = VT_BSTR;
V_BSTR(&vargs[1]) = php_com_string_to_olestring(assembly_name,
assembly_name_len, obj->code_page TSRMLS_CC);
hr = IDispatch_Invoke(stuff->dotnet_domain, stuff->create_instance, &IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, ¶ms, &retval, NULL, NULL);
if (SUCCEEDED(hr)) {
/* retval should now be an IUnknown/IDispatch representation of an
IObjectHandle interface */
if ((V_VT(&retval) == VT_UNKNOWN || V_VT(&retval) == VT_DISPATCH) &&
SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(&retval),
&IID_IObjectHandle, &handle))) {
VARIANT unwrapped;
if (SUCCEEDED(IObjectHandle_Unwrap(handle, &unwrapped))) {
/* unwrapped is now the dispatch pointer we want */
V_DISPATCH(&obj->v) = V_DISPATCH(&unwrapped);
V_VT(&obj->v) = VT_DISPATCH;
/* get its type-info */
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0,
LANG_NEUTRAL, &obj->typeinfo);
ret = SUCCESS;
}
IObjectHandle_Release(handle);
}
VariantClear(&retval);
}
VariantClear(&vargs[0]);
VariantClear(&vargs[1]);
if (ret == FAILURE) {
com_throw_exception("Failed to instantiate .Net object" TSRMLS_CC);
ZVAL_NULL(object);
return;
}
}
/* }}} */
void php_com_dotnet_rshutdown(TSRMLS_D)
{
struct dotnet_runtime_stuff *stuff = COMG(dotnet_runtime_stuff);
IDispatch_Release(stuff->dotnet_domain);
ICorRuntimeHost_Stop(stuff->dotnet_host);
ICorRuntimeHost_Release(stuff->dotnet_host);
efree(stuff);
COMG(dotnet_runtime_stuff) = NULL;
}
#endif /* HAVE_MSCOREE_H */
Index: php-src/ext/com_dotnet/com_extension.c
+++ php-src/ext/com_dotnet/com_extension.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_extension.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
#include "Zend/zend_default_classes.h"
ZEND_DECLARE_MODULE_GLOBALS(com_dotnet)
TsHashTable php_com_typelibraries;
zend_class_entry *php_com_variant_class_entry;
function_entry com_dotnet_functions[] = {
PHP_FE(variant_set, NULL)
PHP_FE(variant_add, NULL)
PHP_FE(variant_cat, NULL)
PHP_FE(variant_sub, NULL)
PHP_FE(variant_mul, NULL)
PHP_FE(variant_and, NULL)
PHP_FE(variant_div, NULL)
PHP_FE(variant_eqv, NULL)
PHP_FE(variant_idiv, NULL)
PHP_FE(variant_imp, NULL)
PHP_FE(variant_mod, NULL)
PHP_FE(variant_or, NULL)
PHP_FE(variant_pow, NULL)
PHP_FE(variant_xor, NULL)
PHP_FE(variant_abs, NULL)
PHP_FE(variant_fix, NULL)
PHP_FE(variant_int, NULL)
PHP_FE(variant_neg, NULL)
PHP_FE(variant_not, NULL)
PHP_FE(variant_round, NULL)
PHP_FE(variant_cmp, NULL)
PHP_FE(variant_date_to_timestamp, NULL)
PHP_FE(variant_date_from_timestamp, NULL)
PHP_FE(variant_get_type, NULL)
PHP_FE(variant_set_type, NULL)
PHP_FE(variant_cast, NULL)
{ NULL, NULL, NULL }
};
/* {{{ com_dotnet_module_entry
*/
zend_module_entry com_dotnet_module_entry = {
STANDARD_MODULE_HEADER,
"com_dotnet",
com_dotnet_functions,
PHP_MINIT(com_dotnet),
PHP_MSHUTDOWN(com_dotnet),
PHP_RINIT(com_dotnet),
PHP_RSHUTDOWN(com_dotnet),
PHP_MINFO(com_dotnet),
"0.1",
STANDARD_MODULE_PROPERTIES
};
/* }}} */
#ifdef COMPILE_DL_COM_DOTNET
ZEND_GET_MODULE(com_dotnet)
#endif
/* {{{ PHP_INI
*/
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("com.allow_dcom", "0", PHP_INI_SYSTEM,
OnUpdateBool, allow_dcom, zend_com_dotnet_globals, com_dotnet_globals)
STD_PHP_INI_ENTRY("com.autoregister_verbose", "0", PHP_INI_ALL,
OnUpdateBool, autoreg_verbose, zend_com_dotnet_globals, com_dotnet_globals)
STD_PHP_INI_ENTRY("com.autoregister_typelib", "0", PHP_INI_ALL,
OnUpdateBool, autoreg_on, zend_com_dotnet_globals, com_dotnet_globals)
STD_PHP_INI_ENTRY("com.autoregister_casesensitive", "0", PHP_INI_ALL,
OnUpdateBool, autoreg_case_sensitive, zend_com_dotnet_globals, com_dotnet_globals)
PHP_INI_END()
/* }}} */
/* {{{ php_com_dotnet_init_globals
*/
static void php_com_dotnet_init_globals(zend_com_dotnet_globals *com_dotnet_globals)
{
memset(com_dotnet_globals, 0, sizeof(*com_dotnet_globals));
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(com_dotnet)
{
zend_class_entry ce;
ZEND_INIT_MODULE_GLOBALS(com_dotnet, php_com_dotnet_init_globals, NULL);
REGISTER_INI_ENTRIES();
INIT_CLASS_ENTRY(ce, "variant", NULL);
ce.create_object = php_com_object_new;
php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
INIT_CLASS_ENTRY(ce, "com", NULL);
ce.create_object = php_com_object_new;
zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant"
TSRMLS_CC);
zend_ts_hash_init(&php_com_typelibraries, 0, NULL, php_com_typelibrary_dtor,
0);
#if HAVE_MSCOREE_H
INIT_CLASS_ENTRY(ce, "dotnet", NULL);
ce.create_object = php_com_object_new;
zend_register_internal_class_ex(&ce, php_com_variant_class_entry, "variant"
TSRMLS_CC);
#endif
#define COM_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS|CONST_PERSISTENT)
COM_CONST(CLSCTX_INPROC_SERVER);
COM_CONST(CLSCTX_INPROC_HANDLER);
COM_CONST(CLSCTX_LOCAL_SERVER);
COM_CONST(CLSCTX_REMOTE_SERVER);
COM_CONST(CLSCTX_SERVER);
COM_CONST(CLSCTX_ALL);
COM_CONST(DISPATCH_METHOD);
COM_CONST(DISPATCH_PROPERTYGET);
COM_CONST(DISPATCH_PROPERTYPUT);
COM_CONST(VT_NULL);
COM_CONST(VT_EMPTY);
COM_CONST(VT_UI1);
COM_CONST(VT_I1);
COM_CONST(VT_UI2);
COM_CONST(VT_I2);
COM_CONST(VT_UI4);
COM_CONST(VT_I4);
COM_CONST(VT_R4);
COM_CONST(VT_R8);
COM_CONST(VT_BOOL);
COM_CONST(VT_ERROR);
COM_CONST(VT_CY);
COM_CONST(VT_DATE);
COM_CONST(VT_BSTR);
COM_CONST(VT_DECIMAL);
COM_CONST(VT_UNKNOWN);
COM_CONST(VT_DISPATCH);
COM_CONST(VT_VARIANT);
COM_CONST(VT_INT);
COM_CONST(VT_UINT);
COM_CONST(VT_ARRAY);
COM_CONST(VT_BYREF);
COM_CONST(CP_ACP);
COM_CONST(CP_MACCP);
COM_CONST(CP_OEMCP);
COM_CONST(CP_UTF7);
COM_CONST(CP_UTF8);
COM_CONST(CP_SYMBOL);
COM_CONST(CP_THREAD_ACP);
COM_CONST(VARCMP_LT);
COM_CONST(VARCMP_EQ);
COM_CONST(VARCMP_GT);
COM_CONST(VARCMP_NULL);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(com_dotnet)
{
UNREGISTER_INI_ENTRIES();
zend_ts_hash_destroy(&php_com_typelibraries);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(com_dotnet)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(com_dotnet)
{
#if HAVE_MSCOREE_H
if (COMG(dotnet_runtime_stuff)) {
php_com_dotnet_rshutdown(TSRMLS_C);
}
#endif
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(com_dotnet)
{
php_info_print_table_start();
php_info_print_table_header(2, "COM support", "enabled");
php_info_print_table_header(2, "DCOM support", COMG(allow_dcom) ? "enabled" :
"disabled");
#if HAVE_MSCOREE_H
php_info_print_table_header(2, ".Net support", "enabled");
#else
php_info_print_table_header(2, ".Net support", "not present in this build");
#endif
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
Index: php-src/ext/com_dotnet/com_handlers.c
+++ php-src/ext/com_dotnet/com_handlers.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_handlers.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
#include "Zend/zend_default_classes.h"
static zval *com_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC)
{
zval *return_value;
php_com_dotnet_object *obj;
VARIANT v;
MAKE_STD_ZVAL(return_value);
ZVAL_NULL(return_value);
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) == VT_DISPATCH) {
VariantInit(&v);
convert_to_string_ex(&member);
if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member),
Z_STRLEN_P(member),
DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) {
php_com_zval_from_variant(return_value, &v, obj->code_page
TSRMLS_CC);
VariantClear(&v);
}
} else {
if (!silent) {
php_com_throw_exception("this variant has no properties"
TSRMLS_CC);
}
}
return return_value;
}
static void com_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
{
php_com_dotnet_object *obj;
VARIANT v;
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) == VT_DISPATCH) {
VariantInit(&v);
convert_to_string_ex(&member);
if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member),
Z_STRLEN_P(member),
DISPATCH_PROPERTYPUT, &v, 1, &value TSRMLS_CC)) {
VariantClear(&v);
}
} else {
php_com_throw_exception("this variant has no properties" TSRMLS_CC);
}
}
static HRESULT com_get_default_binding(php_com_dotnet_object *obj TSRMLS_DC)
{
VARDESC *vardesc;
int i;
if (!obj->typeinfo) {
return FAILURE;
}
for (i = 0; !obj->have_default_bind; i++) {
if (FAILED(ITypeInfo_GetVarDesc(obj->typeinfo, i, &vardesc))) {
return FAILURE;
}
if (vardesc->wVarFlags & VARFLAG_FDEFAULTBIND) {
obj->default_bind = (DISPID)vardesc->memid;
obj->have_default_bind = 1;
}
ITypeInfo_ReleaseVarDesc(obj->typeinfo, vardesc);
}
return obj->have_default_bind ? SUCCESS : FAILURE;
}
static zval *com_read_dimension(zval *object, zval *offset TSRMLS_DC)
{
zval *return_value;
php_com_dotnet_object *obj;
VARIANT v;
MAKE_STD_ZVAL(return_value);
ZVAL_NULL(return_value);
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) == VT_DISPATCH) {
if (!obj->have_default_bind && !com_get_default_binding(obj
TSRMLS_CC)) {
php_com_throw_exception("this COM object has no default
property" TSRMLS_CC);
return return_value;
}
VariantInit(&v);
if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind,
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 1, &offset
TSRMLS_CC)) {
php_com_zval_from_variant(return_value, &v, obj->code_page
TSRMLS_CC);
VariantClear(&v);
}
} else if (V_ISARRAY(&obj->v)) {
SAFEARRAY *sa = V_ARRAY(&obj->v);
UINT dims;
VARTYPE vt;
LONG bound_low = 0, bound_high = 0;
LONG indices[1];
dims = SafeArrayGetDim(sa);
if (dims != 1) {
php_com_throw_exception("can only handle single dimension
arrays" TSRMLS_CC);
return return_value;
}
if (FAILED(SafeArrayGetVartype(sa, &vt)) || vt == VT_EMPTY) {
vt = V_VT(&obj->v) & ~VT_ARRAY;
}
SafeArrayGetUBound(sa, 1, &bound_high);
SafeArrayGetLBound(sa, 1, &bound_low);
convert_to_long(offset);
/* check bounds */
if (Z_LVAL_P(offset) < bound_low || Z_LVAL_P(offset) > bound_high) {
php_com_throw_exception("index out of bounds" TSRMLS_CC);
return return_value;
}
indices[0] = Z_LVAL_P(offset);
VariantInit(&v);
V_VT(&v) = vt;
/* store the value into "lVal" member of the variant.
* This works because it is a union; since we know the variant
* type, we end up with a working variant */
SafeArrayGetElement(sa, indices, &v.lVal);
/* now we can set the return value from that element */
php_com_wrap_variant(return_value, &v, obj->code_page TSRMLS_CC);
VariantClear(&v);
} else {
php_com_throw_exception("this variant is not an array type" TSRMLS_CC);
}
return return_value;
}
static void com_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
{
php_com_dotnet_object *obj;
zval *args[2];
VARIANT v;
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) == VT_DISPATCH) {
if (!obj->have_default_bind && !com_get_default_binding(obj
TSRMLS_CC)) {
php_com_throw_exception("this COM object has no default
property" TSRMLS_CC);
return;
}
args[0] = offset;
args[1] = value;
VariantInit(&v);
if (SUCCESS == php_com_do_invoke_by_id(obj, obj->default_bind,
DISPATCH_METHOD|DISPATCH_PROPERTYPUT, &v, 2, args
TSRMLS_CC)) {
VariantClear(&v);
}
} else {
/* TODO: check for safearray */
php_com_throw_exception("this variant is not an array type" TSRMLS_CC);
}
}
static zval **com_property_get_ptr(zval *object, zval *member TSRMLS_DC)
{
zval **prop_ptr;
prop_ptr = emalloc(sizeof(zval **));
*prop_ptr = com_property_read(object, member, 0 TSRMLS_CC);
return prop_ptr;
}
static void com_object_set(zval **property, zval *value TSRMLS_DC)
{
/* Not yet implemented in the engine */
}
static zval *com_object_get(zval *property TSRMLS_DC)
{
/* Not yet implemented in the engine */
return NULL;
}
static int com_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
{
DISPID dispid;
php_com_dotnet_object *obj;
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) == VT_DISPATCH) {
convert_to_string_ex(&member);
if (SUCCEEDED(php_com_get_id_of_name(obj, Z_STRVAL_P(member),
Z_STRLEN_P(member), &dispid TSRMLS_CC))) {
/* TODO: distinguish between property and method! */
return 1;
}
} else {
/* TODO: check for safearray */
}
return 0;
}
static void com_property_delete(zval *object, zval *member TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a
COM object");
}
static void com_dimension_delete(zval *object, zval *offset TSRMLS_DC)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot delete properties from a
COM object");
}
static HashTable *com_properties_get(zval *object TSRMLS_DC)
{
/* TODO: use type-info to get all the names and values ?
* DANGER: if we do that, there is a strong possibility for
* infinite recursion when the hash is displayed via var_dump().
* Perhaps it is best to leave it un-implemented.
*/
return NULL;
}
static union _zend_function *com_method_get(zval *object, char *name, int len
TSRMLS_DC)
{
zend_internal_function *f;
php_com_dotnet_object *obj;
/* TODO: cache this */
obj = CDNO_FETCH(object);
if (V_VT(&obj->v) != VT_DISPATCH) {
return NULL;
}
f = emalloc(sizeof(zend_internal_function));
f->type = ZEND_OVERLOADED_FUNCTION;
f->num_args = 0;
f->arg_info = NULL;
f->scope = obj->ce;
f->fn_flags = 0;
f->function_name = estrndup(name, len);
if (obj->typeinfo) {
/* look for byref params */
ITypeComp *comp;
ITypeInfo *TI = NULL;
DESCKIND kind;
BINDPTR bindptr;
OLECHAR *olename;
ULONG lhash;
int i;
if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) {
olename = php_com_string_to_olestring(name, len,
obj->code_page TSRMLS_CC);
lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT,
olename);
if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash,
INVOKE_FUNC, &TI, &kind, &bindptr))) {
switch (kind) {
case DESCKIND_FUNCDESC:
f->arg_info =
ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info));
for (i = 0; i <
bindptr.lpfuncdesc->cParams; i++) {
f->arg_info[i].allow_null = 1;
if
(bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) {
f->arg_info[i].pass_by_reference = 1;
}
}
f->num_args =
bindptr.lpfuncdesc->cParams;
ITypeInfo_ReleaseFuncDesc(TI,
bindptr.lpfuncdesc);
break;
/* these should not happen, but *might* happen
if the user
* screws up; lets avoid a leak in that case */
case DESCKIND_VARDESC:
ITypeInfo_ReleaseVarDesc(TI,
bindptr.lpvardesc);
break;
case DESCKIND_TYPECOMP:
ITypeComp_Release(bindptr.lptcomp);
break;
}
ITypeInfo_Release(TI);
}
ITypeComp_Release(comp);
efree(olename);
}
}
return (union _zend_function*)f;
}
static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS)
{
zval **args = NULL;
php_com_dotnet_object *obj;
int nargs;
VARIANT v;
int ret = FAILURE;
obj = CDNO_FETCH(getThis());
if (V_VT(&obj->v) != VT_DISPATCH) {
//php_com_throw_exception("call to member function of non-object");
return FAILURE;
}
nargs = ZEND_NUM_ARGS();
if (nargs) {
args = (zval **)emalloc(sizeof(zval *) * nargs);
zend_get_parameters_array(ht, nargs, args);
}
VariantInit(&v);
if (SUCCESS == php_com_do_invoke(obj, method, -1,
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) {
php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC);
ret = SUCCESS;
VariantClear(&v);
}
if (args) {
efree(args);
}
return ret;
}
static union _zend_function *com_constructor_get(zval *object TSRMLS_DC)
{
php_com_dotnet_object *obj;
zend_internal_function *f;
obj = CDNO_FETCH(object);
/* TODO: this leaks */
f = emalloc(sizeof(zend_internal_function));
f->type = ZEND_INTERNAL_FUNCTION;
f->function_name = obj->ce->name;
f->scope = obj->ce;
f->arg_info = NULL;
f->num_args = 0;
f->fn_flags = 0;
#if HAVE_MSCOREE_H
if (f->function_name[0] == 'd') { /* 'd'otnet */
f->handler = ZEND_FN(com_dotnet_create_instance);
} else
#endif
if (f->function_name[0] == 'c') { /* 'c'om */
f->handler = ZEND_FN(com_create_instance);
} else { /* 'v'ariant */
f->handler = ZEND_FN(com_variant_create_instance);
}
return (union _zend_function*)f;
}
static zend_class_entry *com_class_entry_get(zval *object TSRMLS_DC)
{
php_com_dotnet_object *obj;
obj = CDNO_FETCH(object);
return obj->ce;
}
static int com_class_name_get(zval *object, char **class_name, zend_uint
*class_name_len, int parent TSRMLS_DC)
{
php_com_dotnet_object *obj;
obj = CDNO_FETCH(object);
*class_name = estrndup(obj->ce->name, obj->ce->name_length);
*class_name_len = obj->ce->name_length;
return 0;
}
/* This compares two variants for equality */
static int com_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
{
php_com_dotnet_object *obja, *objb;
int ret;
/* strange header bug problem here... the headers define the proto without the
* flags parameter. However, the MSDN docs state that there is a flags
parameter,
* and my VC6 won't link unless the code uses the version with 4 parameters.
* So, we have this declaration here to fix it */
STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
obja = CDNO_FETCH(object1);
objb = CDNO_FETCH(object2);
switch (VarCmp(&obja->v, &objb->v, LOCALE_SYSTEM_DEFAULT, 0)) {
case VARCMP_LT:
ret = -1;
break;
case VARCMP_GT:
ret = 1;
break;
case VARCMP_EQ:
ret = 0;
break;
default:
/* either or both operands are NULL...
* not 100% sure how to handle this */
ret = -2;
}
return ret;
}
static void com_object_cast(zval *readobj, zval *writeobj, int type, int should_free
TSRMLS_DC)
{
php_com_dotnet_object *obj;
VARIANT v;
VARTYPE vt = VT_EMPTY;
if (should_free) {
zval_dtor(writeobj);
}
ZVAL_NULL(writeobj);
obj = CDNO_FETCH(readobj);
VariantInit(&v);
if (V_VT(&obj->v) == VT_DISPATCH) {
if (!obj->have_default_bind && !com_get_default_binding(obj
TSRMLS_CC)) {
return;
}
if (FAILURE == php_com_do_invoke_by_id(obj, obj->default_bind,
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, 0, NULL
TSRMLS_CC)) {
return;
}
} else {
VariantCopy(&v, &obj->v);
}
switch(type) {
case IS_LONG:
vt = VT_INT;
break;
case IS_DOUBLE:
vt = VT_R8;
break;
case IS_BOOL:
vt = VT_BOOL;
break;
case IS_STRING:
vt = VT_BSTR;
break;
}
if (vt != VT_EMPTY) {
VariantChangeType(&v, &v, 0, vt);
}
php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC);
VariantClear(&v);
}
zend_object_handlers php_com_object_handlers = {
ZEND_OBJECTS_STORE_HANDLERS,
com_property_read,
com_property_write,
com_read_dimension,
com_write_dimension,
com_property_get_ptr,
com_property_get_ptr,
com_object_get,
com_object_set,
com_property_exists,
com_property_delete,
com_dimension_delete,
com_properties_get,
com_method_get,
com_call_method,
com_constructor_get,
com_class_entry_get,
com_class_name_get,
com_objects_compare,
com_object_cast
};
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
{
php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
if (obj->typeinfo) {
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
VariantClear(&obj->v);
efree(obj);
}
void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC)
{
php_com_dotnet_object *cloneobj, *origobject;
origobject = (php_com_dotnet_object*)object;
cloneobj = (php_com_dotnet_object*)emalloc(sizeof(php_com_dotnet_object));
memcpy(cloneobj, origobject, sizeof(*cloneobj));
/* VariantCopy will perform VariantClear; we don't want to clobber
* the IDispatch that we memcpy'd, so we init a new variant in the
* clone structure */
VariantInit(&cloneobj->v);
/* We use the Indirection-following version of the API since we
* want to clone as much as possible */
VariantCopyInd(&cloneobj->v, &origobject->v);
if (cloneobj->typeinfo) {
ITypeInfo_AddRef(cloneobj->typeinfo);
}
*clone_ptr = cloneobj;
}
zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC)
{
php_com_dotnet_object *obj;
zend_object_value retval;
obj = emalloc(sizeof(*obj));
memset(obj, 0, sizeof(*obj));
VariantInit(&obj->v);
obj->code_page = CP_ACP;
obj->ce = ce;
retval.handle = zend_objects_store_put(obj, php_com_object_dtor,
php_com_object_clone TSRMLS_CC);
retval.handlers = &php_com_object_handlers;
return retval;
}
Index: php-src/ext/com_dotnet/com_misc.c
+++ php-src/ext/com_dotnet/com_misc.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_misc.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
#include "Zend/zend_default_classes.h"
zval *php_com_throw_exception(char *message TSRMLS_DC)
{
zval *e, *tmp;
ALLOC_ZVAL(e);
Z_TYPE_P(e) = IS_OBJECT;
object_init_ex(e, zend_exception_get_default());
e->refcount = 1;
e->is_ref = 1;
MAKE_STD_ZVAL(tmp);
ZVAL_STRING(tmp, message, 1);
zend_hash_update(Z_OBJPROP_P(e), "message", sizeof("message"), (void**)&tmp,
sizeof(zval*), NULL);
MAKE_STD_ZVAL(tmp);
ZVAL_STRING(tmp, zend_get_executed_filename(TSRMLS_C), 1);
zend_hash_update(Z_OBJPROP_P(e), "file", sizeof("file"), (void**)&tmp,
sizeof(zval*), NULL);
MAKE_STD_ZVAL(tmp);
ZVAL_LONG(tmp, zend_get_executed_lineno(TSRMLS_C));
zend_hash_update(Z_OBJPROP_P(e), "line", sizeof("line"), (void**)&tmp,
sizeof(zval*), NULL);
EG(exception) = e;
return e;
}
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
int codepage TSRMLS_DC)
{
php_com_dotnet_object *obj;
obj = emalloc(sizeof(*obj));
memset(obj, 0, sizeof(*obj));
obj->code_page = codepage;
obj->ce = php_com_variant_class_entry;
VariantInit(&obj->v);
V_VT(&obj->v) = VT_DISPATCH;
V_DISPATCH(&obj->v) = disp;
IDispatch_AddRef(V_DISPATCH(&obj->v));
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &obj->typeinfo);
Z_TYPE_P(z) = IS_OBJECT;
z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor,
php_com_object_clone TSRMLS_CC);
z->value.obj.handlers = &php_com_object_handlers;
}
PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
int codepage TSRMLS_DC)
{
php_com_dotnet_object *obj;
obj = emalloc(sizeof(*obj));
memset(obj, 0, sizeof(*obj));
obj->code_page = codepage;
obj->ce = php_com_variant_class_entry;
VariantInit(&obj->v);
VariantCopy(&obj->v, v);
if (V_VT(&obj->v) == VT_DISPATCH) {
IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL,
&obj->typeinfo);
}
Z_TYPE_P(z) = IS_OBJECT;
z->value.obj.handle = zend_objects_store_put(obj, php_com_object_dtor,
php_com_object_clone TSRMLS_CC);
z->value.obj.handlers = &php_com_object_handlers;
}
Index: php-src/ext/com_dotnet/com_olechar.c
+++ php-src/ext/com_dotnet/com_olechar.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
| Harald Radi <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_olechar.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
PHPAPI OLECHAR *php_com_string_to_olestring(char *string, uint string_len, int
codepage TSRMLS_DC)
{
OLECHAR *olestring = NULL;
DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
BOOL ok;
if (string_len == -1) {
/* determine required length for the buffer (includes NUL terminator)
*/
string_len = MultiByteToWideChar(codepage, flags, string, -1, NULL, 0);
} else {
/* allow room for NUL terminator */
string_len++;
}
if (strlen > 0) {
olestring = (OLECHAR*)emalloc(sizeof(OLECHAR) * string_len);
ok = MultiByteToWideChar(codepage, flags, string, string_len,
olestring, string_len);
} else {
ok = FALSE;
olestring = (OLECHAR*)emalloc(sizeof(OLECHAR));
*olestring = 0;
}
if (!ok) {
char *msg = php_win_err(GetLastError());
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not convert string to unicode: `%s'", msg);
LocalFree(msg);
}
return olestring;
}
PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring, uint *string_len, int
codepage TSRMLS_DC)
{
char *string;
uint length = 0;
BOOL ok;
LONG err;
length = WideCharToMultiByte(codepage, 0, olestring, -1, NULL, 0, NULL, NULL);
if (length) {
string = (char*)emalloc(sizeof(char) * length);
length = WideCharToMultiByte(codepage, 0, olestring, -1, string,
length, NULL, NULL);
ok = length > 0;
} else {
err = GetLastError();
string = (char*)emalloc(sizeof(char));
*string = '\0';
ok = FALSE;
length = 0;
}
if (!ok) {
char *msg = php_win_err(err);
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not convert string from unicode: `%s'", msg);
LocalFree(msg);
}
if (string_len) {
*string_len = length-1;
}
return string;
}
Index: php-src/ext/com_dotnet/com_typeinfo.c
+++ php-src/ext/com_dotnet/com_typeinfo.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
| Harald Radi <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_typeinfo.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
/* The search string can be either:
* a) a file name
* b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0"
* c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library"
*/
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
int codepage TSRMLS_DC)
{
ITypeLib *TL = NULL;
char *strtok_buf, *major, *minor;
CLSID clsid;
OLECHAR *p;
HRESULT hr;
search_string = php_strtok_r(search_string, ",", &strtok_buf);
if (search_string == NULL) {
return NULL;
}
major = php_strtok_r(NULL, ",", &strtok_buf);
minor = php_strtok_r(NULL, ",", &strtok_buf);
p = php_com_string_to_olestring(search_string, strlen(search_string), codepage
TSRMLS_CC);
if (SUCCEEDED(CLSIDFromString(p, &clsid))) {
WORD major_i = 1, minor_i = 0;
/* pick up the major/minor numbers; if none specified, default to 1,0
*/
if (major && minor) {
major_i = (WORD)atoi(major);
minor_i = (WORD)atoi(minor);
}
/* Load the TypeLib by GUID */
hr = LoadRegTypeLib((REFGUID)&clsid, major_i, minor_i, LANG_NEUTRAL,
&TL);
/* if that failed, assumed that the GUID is actually a CLSID and
* attemp to get the library via an instance of that class */
if (FAILED(hr) && (major == NULL || minor == NULL)) {
IDispatch *disp = NULL;
ITypeInfo *info = NULL;
int idx;
if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL,
CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&disp)) &&
SUCCEEDED(hr = IDispatch_GetTypeInfo(disp, 0,
LANG_NEUTRAL, &info))) {
hr = ITypeInfo_GetContainingTypeLib(info, &TL, &idx);
}
if (info) {
ITypeInfo_Release(info);
}
if (disp) {
IDispatch_Release(disp);
}
}
} else {
/* Try to load it from a file; if it fails, do a really painful search
of
* the registry */
if (FAILED(LoadTypeLib(p, &TL))) {
HKEY hkey, hsubkey;
DWORD SubKeys, MaxSubKeyLength;
char *keyname;
unsigned int i, j;
DWORD VersionCount;
char version[20];
char *libname;
DWORD libnamelen;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT,
"TypeLib", 0, KEY_READ, &hkey) &&
ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL,
NULL, NULL, &SubKeys,
&MaxSubKeyLength, NULL, NULL, NULL, NULL,
NULL, NULL)) {
MaxSubKeyLength++; /* make room for NUL */
keyname = emalloc(MaxSubKeyLength);
libname = emalloc(strlen(search_string) + 1);
for (i = 0; i < SubKeys && TL == NULL; i++) {
if (ERROR_SUCCESS == RegEnumKey(hkey, i,
keyname, MaxSubKeyLength) &&
ERROR_SUCCESS ==
RegOpenKeyEx(hkey, keyname, 0, KEY_READ, &hsubkey)) {
if (ERROR_SUCCESS ==
RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL)) {
for (j = 0; j < VersionCount;
j++) {
if (ERROR_SUCCESS !=
RegEnumKey(hsubkey, j, version, sizeof(version))) {
continue;
}
/* get the default
value for this key and compare */
libnamelen =
strlen(search_string)+1;
if (ERROR_SUCCESS ==
RegQueryValue(hsubkey, version, libname, &libnamelen)) {
if (0 ==
((mode & CONST_CS) ? strcmp(libname, search_string) : stricmp(libname,
search_string))) {
char
*str = NULL;
int
major, minor;
/*
fetch the GUID and add the version numbers */
if (2
!= sscanf(version, "%d.%d", &major, &minor)) {
major = 1;
minor = 0;
}
spprintf(&str, 0, "%s,%d,%d", keyname, major, minor);
/*
recurse */
TL =
php_com_load_typelib(str, mode, codepage TSRMLS_CC);
efree(str);
break;
}
}
}
}
RegCloseKey(hsubkey);
}
}
RegCloseKey(hkey);
efree(keyname);
efree(libname);
}
}
}
efree(p);
return TL;
}
/* Given a type-library, merge it into the current engine state */
PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC)
{
int i, j, interfaces;
TYPEKIND pTKind;
ITypeInfo *TypeInfo;
VARDESC *pVarDesc;
UINT NameCount;
BSTR bstr_ids;
zend_constant c;
zval exists, results, value;
char *const_name;
if (TL == NULL) {
return FAILURE;
}
interfaces = ITypeLib_GetTypeInfoCount(TL);
for (i = 0; i < interfaces; i++) {
ITypeLib_GetTypeInfoType(TL, i, &pTKind);
if (pTKind == TKIND_ENUM) {
ITypeLib_GetTypeInfo(TL, i, &TypeInfo);
for (j = 0; ; j++) {
if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j,
&pVarDesc))) {
break;
}
ITypeInfo_GetNames(TypeInfo, pVarDesc->memid,
&bstr_ids, 1, &NameCount);
if (NameCount != 1) {
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
continue;
}
const_name = php_com_olestring_to_string(bstr_ids,
&c.name_len, codepage TSRMLS_CC);
c.name = zend_strndup(const_name, c.name_len);
efree(const_name);
c.name_len++; /* include NUL */
SysFreeString(bstr_ids);
/* sanity check for the case where the constant is
already defined */
if (zend_get_constant(c.name, c.name_len - 1, &exists
TSRMLS_CC)) {
if (COMG(autoreg_verbose) &&
!compare_function(&results, &c.value, &exists TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC,
E_WARNING, "Type library constant %s is already defined", c.name);
}
free(c.name);
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
continue;
}
/* register the constant */
php_com_zval_from_variant(&value,
pVarDesc->lpvarValue, codepage TSRMLS_CC);
if (Z_TYPE(value) == IS_LONG) {
c.flags = mode;
c.value.type = IS_LONG;
c.value.value.lval = Z_LVAL(value);
c.module_number = 0;
zend_register_constant(&c TSRMLS_CC);
}
ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
}
ITypeInfo_Release(TypeInfo);
}
}
return SUCCESS;
}
/* Type-library stuff */
void php_com_typelibrary_dtor(void *pDest)
{
ITypeLib *Lib = *(ITypeLib**)pDest;
ITypeLib_Release(Lib);
}
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
int mode, int codepage, int *cached TSRMLS_DC)
{
ITypeLib **TL;
char *name_dup;
int l;
l = strlen(search_string);
if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1,
(void**)&TL) == SUCCESS) {
*cached = 1;
/* add a reference for the caller */
ITypeLib_AddRef(*TL);
return *TL;
}
*cached = 0;
name_dup = estrndup(search_string, l);
*TL = php_com_load_typelib(name_dup, mode, codepage TSRMLS_CC);
efree(name_dup);
if (*TL) {
if (SUCCESS == zend_ts_hash_update(&php_com_typelibraries,
search_string, l+1, (void*)*TL, sizeof(ITypeLib*),
NULL)) {
/* add a reference for the hash table */
ITypeLib_AddRef(*TL);
}
}
return *TL;
}
Index: php-src/ext/com_dotnet/com_variant.c
+++ php-src/ext/com_dotnet/com_variant.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: com_variant.c,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"
PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC)
{
OLECHAR *olestring;
php_com_dotnet_object *obj;
switch (Z_TYPE_P(z)) {
case IS_NULL:
V_VT(v) = VT_NULL;
break;
case IS_BOOL:
V_VT(v) = VT_BOOL;
V_BOOL(v) = Z_BVAL_P(z) ? VARIANT_TRUE : VARIANT_FALSE;
break;
case IS_OBJECT:
if (php_com_is_valid_object(z TSRMLS_CC)) {
obj = CDNO_FETCH(z);
if (V_VT(&obj->v) == VT_DISPATCH) {
/* pass the underlying object */
V_VT(v) = VT_DISPATCH;
if (V_DISPATCH(&obj->v)) {
IDispatch_AddRef(V_DISPATCH(&obj->v));
}
V_DISPATCH(v) = V_DISPATCH(&obj->v);
} else {
/* pass the variant by reference */
V_VT(v) = VT_VARIANT | VT_BYREF;
V_VARIANTREF(v) = &obj->v;
}
} else {
/* TODO: export the object using our COM wrapper */
V_VT(v) = VT_NULL;
}
break;
case IS_ARRAY:
V_VT(v) = VT_NULL;
/* TODO: map as safe array ? */
break;
case IS_LONG:
V_VT(v) = VT_I4;
V_I4(v) = Z_LVAL_P(z);
break;
case IS_DOUBLE:
V_VT(v) = VT_R8;
V_R8(v) = Z_DVAL_P(z);
break;
case IS_STRING:
V_VT(v) = VT_BSTR;
olestring = php_com_string_to_olestring(Z_STRVAL_P(z),
Z_STRLEN_P(z), codepage TSRMLS_CC);
V_BSTR(v) = SysAllocStringByteLen((char*)olestring,
Z_STRLEN_P(z) * sizeof(OLECHAR));
efree(olestring);
break;
case IS_RESOURCE:
case IS_CONSTANT:
case IS_CONSTANT_ARRAY:
default:
V_VT(v) = VT_NULL;
break;
}
}
PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC)
{
OLECHAR *olestring = NULL;
int ret = SUCCESS;
SYSTEMTIME systime;
struct tm tmv;
php_com_dotnet_object *obj;
switch (V_VT(v)) {
case VT_EMPTY:
case VT_NULL:
case VT_VOID:
ZVAL_NULL(z);
break;
case VT_UI1:
ZVAL_LONG(z, (long)V_UI1(v));
break;
case VT_I1:
ZVAL_LONG(z, (long)V_I1(v));
break;
case VT_UI2:
ZVAL_LONG(z, (long)V_UI2(v));
break;
case VT_I2:
ZVAL_LONG(z, (long)V_I2(v));
break;
case VT_UI4: /* TODO: promote to double if large? */
ZVAL_LONG(z, (long)V_UI4(v));
break;
case VT_I4:
ZVAL_LONG(z, (long)V_I4(v));
break;
case VT_INT:
ZVAL_LONG(z, V_INT(v));
break;
case VT_UINT: /* TODO: promote to double if large? */
ZVAL_LONG(z, (long)V_UINT(v));
break;
case VT_R4:
ZVAL_DOUBLE(z, (double)V_R4(v));
break;
case VT_R8:
ZVAL_DOUBLE(z, V_R8(v));
break;
case VT_BOOL:
ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0);
break;
case VT_BSTR:
olestring = V_BSTR(v);
if (olestring) {
Z_TYPE_P(z) = IS_STRING;
Z_STRVAL_P(z) = php_com_olestring_to_string(olestring,
&Z_STRLEN_P(z), codepage TSRMLS_CC);
olestring = NULL;
}
break;
case VT_UNKNOWN:
if (V_UNKNOWN(v) != NULL) {
IDispatch *disp;
if (SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(v),
&IID_IDispatch, &disp))) {
php_com_wrap_dispatch(z, disp, codepage
TSRMLS_CC);
IDispatch_Release(disp);
} else {
ret = FAILURE;
}
}
break;
case VT_DISPATCH:
if (V_DISPATCH(v) != NULL) {
php_com_wrap_dispatch(z, V_DISPATCH(v), codepage
TSRMLS_CC);
}
break;
case VT_VARIANT:
default:
php_com_wrap_variant(z, v, codepage TSRMLS_CC);
}
if (olestring) {
efree(olestring);
}
if (ret == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "variant->zval: conversion
from 0x%x ret=%d", V_VT(v), ret);
}
return ret;
}
/* {{{ com_variant_create_instance - ctor for new VARIANT() */
PHP_FUNCTION(com_variant_create_instance)
{
VARTYPE vt = VT_EMPTY;
long codepage = CP_ACP;
zval *object = getThis();
php_com_dotnet_object *obj;
zval *zvalue = NULL;
HRESULT res;
if (ZEND_NUM_ARGS() == 0) {
/* just leave things as-is - an empty variant */
return;
}
obj = CDNO_FETCH(object);
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z!|ll", &zvalue, &vt, &codepage)) {
php_com_throw_exception("Invalid arguments" TSRMLS_CC);
return;
}
if (ZEND_NUM_ARGS() == 3) {
obj->code_page = codepage;
}
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
if (ZEND_NUM_ARGS() >= 2) {
res = VariantChangeType(&obj->v, &obj->v, 0, vt);
if (FAILED(res)) {
char *werr, *msg;
werr = php_win_err(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
}
}
if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) {
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
}
/* }}} */
/* {{{ proto void variant_set(object variant, mixed value)
Assigns a new value for a variant object (like "set" in VB) */
PHP_FUNCTION(variant_set)
{
zval *zobj, *zvalue = NULL;
php_com_dotnet_object *obj;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"Oz!", &zobj, php_com_variant_class_entry, &zvalue)) {
return;
}
obj = CDNO_FETCH(zobj);
/* dtor the old value */
if (obj->typeinfo) {
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
VariantClear(&obj->v);
php_com_variant_from_zval(&obj->v, zvalue, obj->code_page TSRMLS_CC);
}
/* }}} */
enum variant_binary_opcode {
VOP_ADD, VOP_CAT, VOP_SUB, VOP_MUL, VOP_AND, VOP_DIV,
VOP_EQV, VOP_IDIV, VOP_IMP, VOP_MOD, VOP_OR, VOP_POW,
VOP_XOR
};
enum variant_unary_opcode {
VOP_ABS, VOP_FIX, VOP_INT, VOP_NEG, VOP_NOT
};
static void variant_binary_operation(enum variant_binary_opcode op,
INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
VARIANT vres;
VARIANT left_val, right_val;
VARIANT *vleft = NULL, *vright = NULL;
zval *zleft = NULL, *zright = NULL;
php_com_dotnet_object *obj;
HRESULT result;
int codepage = CP_ACP;
VariantInit(&left_val);
VariantInit(&right_val);
VariantInit(&vres);
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "OO", &zleft,
php_com_variant_class_entry,
&zright, php_com_variant_class_entry)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
obj = CDNO_FETCH(zright);
vright = &obj->v;
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "Oz!", &zleft,
php_com_variant_class_entry,
&zright)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
vright = &right_val;
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "z!O", &zleft, &zright,
php_com_variant_class_entry)) {
obj = CDNO_FETCH(zright);
vright = &obj->v;
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z!z!", &zleft, &zright)) {
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
vright = &right_val;
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
} else {
return;
}
switch (op) {
case VOP_ADD:
result = VarAdd(vleft, vright, &vres);
break;
case VOP_CAT:
result = VarCat(vleft, vright, &vres);
break;
case VOP_SUB:
result = VarSub(vleft, vright, &vres);
break;
case VOP_MUL:
result = VarMul(vleft, vright, &vres);
break;
case VOP_AND:
result = VarAnd(vleft, vright, &vres);
break;
case VOP_DIV:
result = VarDiv(vleft, vright, &vres);
break;
case VOP_EQV:
result = VarEqv(vleft, vright, &vres);
break;
case VOP_IDIV:
result = VarIdiv(vleft, vright, &vres);
break;
case VOP_IMP:
result = VarImp(vleft, vright, &vres);
break;
case VOP_MOD:
result = VarMod(vleft, vright, &vres);
break;
case VOP_OR:
result = VarOr(vleft, vright, &vres);
break;
case VOP_POW:
result = VarPow(vleft, vright, &vres);
break;
case VOP_XOR:
result = VarXor(vleft, vright, &vres);
break;
}
if (SUCCEEDED(result)) {
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
}
VariantClear(&vres);
VariantClear(&left_val);
VariantClear(&right_val);
}
/* }}} */
/* {{{ proto mixed variant_add(mixed left, mixed right)
"Adds" two variant values together and returns the result */
PHP_FUNCTION(variant_add)
{
variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_cat(mixed left, mixed right)
concatenates two variant values together and returns the result */
PHP_FUNCTION(variant_cat)
{
variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_sub(mixed left, mixed right)
subjects the value of the right variant from the left variant value and returns the
result */
PHP_FUNCTION(variant_sub)
{
variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_mul(mixed left, mixed right)
multiplies the values of the two variants and returns the result */
PHP_FUNCTION(variant_mul)
{
variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_and(mixed left, mixed right)
performs a bitwise AND operation between two variants and returns the result */
PHP_FUNCTION(variant_and)
{
variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_div(mixed left, mixed right)
Returns the result from dividing two variants */
PHP_FUNCTION(variant_div)
{
variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_eqv(mixed left, mixed right)
Performs a bitwise equivalence on two variants */
PHP_FUNCTION(variant_eqv)
{
variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_idiv(mixed left, mixed right)
Converts variants to operands and then returns the result from dividing them */
PHP_FUNCTION(variant_idiv)
{
variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_imp(mixed left, mixed right)
Performs a bitwise implication on two variants */
PHP_FUNCTION(variant_imp)
{
variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_mod(mixed left, mixed right)
Divides two variants and returns only the remainder */
PHP_FUNCTION(variant_mod)
{
variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_or(mixed left, mixed right)
Performs a logical disjunction on two variants */
PHP_FUNCTION(variant_or)
{
variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_pow(mixed left, mixed right)
Returns the result of performing the power function with two variants */
PHP_FUNCTION(variant_pow)
{
variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_xor(mixed left, mixed right)
Performs a logical exclusion on two variants */
PHP_FUNCTION(variant_xor)
{
variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
static void variant_unary_operation(enum variant_unary_opcode op,
INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
{
VARIANT vres;
VARIANT left_val;
VARIANT *vleft = NULL;
zval *zleft = NULL;
php_com_dotnet_object *obj;
HRESULT result;
int codepage = CP_ACP;
VariantInit(&left_val);
VariantInit(&vres);
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "O", &zleft,
php_com_variant_class_entry)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z!", &zleft)) {
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
} else {
return;
}
switch (op) {
case VOP_ABS:
result = VarAbs(vleft, &vres);
break;
case VOP_FIX:
result = VarFix(vleft, &vres);
break;
case VOP_INT:
result = VarInt(vleft, &vres);
break;
case VOP_NEG:
result = VarNeg(vleft, &vres);
break;
case VOP_NOT:
result = VarNot(vleft, &vres);
break;
}
if (SUCCEEDED(result)) {
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
}
VariantClear(&vres);
VariantClear(&left_val);
}
/* }}} */
/* {{{ proto mixed variant_abs(mixed left)
Returns the absolute value of a variant */
PHP_FUNCTION(variant_abs)
{
variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_fix(mixed left)
Returns the ? of a variant */
PHP_FUNCTION(variant_fix)
{
variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_int(mixed left)
Returns the integer portion of a variant */
PHP_FUNCTION(variant_int)
{
variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_neg(mixed left)
Performs logical negation on a variant */
PHP_FUNCTION(variant_neg)
{
variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_not(mixed left)
Performs bitwise not negation on a variant */
PHP_FUNCTION(variant_not)
{
variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
/* }}} */
/* {{{ proto mixed variant_round(mixed left, int decimals)
Rounds a variant to the specified number of decimal places */
PHP_FUNCTION(variant_round)
{
VARIANT vres;
VARIANT left_val;
VARIANT *vleft = NULL;
zval *zleft = NULL;
php_com_dotnet_object *obj;
HRESULT result;
int codepage = CP_ACP;
long decimals = 0;
VariantInit(&left_val);
VariantInit(&vres);
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "Ol", &zleft,
php_com_variant_class_entry, &decimals)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z!l", &zleft, &decimals)) {
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
} else {
return;
}
if (SUCCEEDED(VarRound(vleft, decimals, &vres))) {
php_com_wrap_variant(return_value, &vres, codepage TSRMLS_CC);
}
VariantClear(&vres);
VariantClear(&left_val);
}
/* }}} */
/* {{{ proto int variant_cmp(mixed left, mixed right [, int lcid [, int flags]])
Compares two variants */
PHP_FUNCTION(variant_cmp)
{
VARIANT left_val, right_val;
VARIANT *vleft = NULL, *vright = NULL;
zval *zleft = NULL, *zright = NULL;
php_com_dotnet_object *obj;
HRESULT result;
int codepage = CP_ACP;
long lcid = LOCALE_SYSTEM_DEFAULT;
long flags = 0;
/* it is safe to ignore the warning for this line; see the comments in
com_handlers.c */
STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
VariantInit(&left_val);
VariantInit(&right_val);
if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "OO|ll", &zleft,
php_com_variant_class_entry,
&zright, php_com_variant_class_entry, &lcid, &flags)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
obj = CDNO_FETCH(zright);
vright = &obj->v;
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "Oz!|ll", &zleft,
php_com_variant_class_entry,
&zright, &lcid, &flags)) {
obj = CDNO_FETCH(zleft);
vleft = &obj->v;
vright = &right_val;
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
} else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
ZEND_NUM_ARGS() TSRMLS_CC, "z!O|ll", &zleft, &zright,
php_com_variant_class_entry,
&lcid, &flags)) {
obj = CDNO_FETCH(zright);
vright = &obj->v;
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
} else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"z!z!|ll", &zleft, &zright, &lcid, &flags)) {
vleft = &left_val;
php_com_variant_from_zval(vleft, zleft, codepage TSRMLS_CC);
vright = &right_val;
php_com_variant_from_zval(vright, zright, codepage TSRMLS_CC);
} else {
return;
}
ZVAL_LONG(return_value, VarCmp(vleft, vright, lcid, flags));
VariantClear(&left_val);
VariantClear(&right_val);
}
/* }}} */
/* {{{ proto int variant_date_to_timestamp(object variant)
Converts a variant date/time value to unix timestamp */
PHP_FUNCTION(variant_date_to_timestamp)
{
VARIANT vres;
zval *zleft = NULL;
php_com_dotnet_object *obj;
VariantInit(&vres);
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"O", &zleft, php_com_variant_class_entry)) {
return;
}
obj = CDNO_FETCH(zleft);
if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) {
SYSTEMTIME systime;
struct tm tmv;
VariantTimeToSystemTime(V_DATE(&vres), &systime);
memset(&tmv, 0, sizeof(tmv));
tmv.tm_year = systime.wYear - 1900;
tmv.tm_mon = systime.wMonth - 1;
tmv.tm_mday = systime.wDay;
tmv.tm_hour = systime.wHour;
tmv.tm_min = systime.wMinute;
tmv.tm_sec = systime.wSecond;
tmv.tm_isdst = -1;
tzset();
RETVAL_LONG(mktime(&tmv));
}
VariantClear(&vres);
}
/* }}} */
/* {{{ proto object variant_date_from_timestamp(int timestamp)
Returns a variant date representation of a unix timestamp */
PHP_FUNCTION(variant_date_from_timestamp)
{
int timestamp;
SYSTEMTIME systime;
struct tm *tmv;
VARIANT res;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
×tamp)) {
return;
}
VariantInit(&res);
tmv = gmtime(×tamp);
memset(&systime, 0, sizeof(systime));
systime.wDay = tmv->tm_mday;
systime.wHour = tmv->tm_hour;
systime.wMinute = tmv->tm_min;
systime.wMonth = tmv->tm_mon + 1;
systime.wSecond = tmv->tm_sec;
systime.wYear = tmv->tm_year + 1900;
V_VT(&res) = VT_DATE;
SystemTimeToVariantTime(&systime, &V_DATE(&res));
php_com_wrap_variant(return_value, &res, CP_ACP TSRMLS_CC);
VariantClear(&res);
}
/* }}} */
/* {{{ proto int variant_get_type(object variant)
Returns the VT_XXX type code for a variant */
PHP_FUNCTION(variant_get_type)
{
zval *zobj;
php_com_dotnet_object *obj;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"O", &zobj, php_com_variant_class_entry)) {
return;
}
obj = CDNO_FETCH(zobj);
RETURN_LONG(V_VT(&obj->v));
}
/* }}} */
/* {{{ proto void variant_set_type(object variant, int type)
Convert a variant into another type. Variant is modified "in-place" */
PHP_FUNCTION(variant_set_type)
{
zval *zobj;
php_com_dotnet_object *obj;
VARTYPE vt;
HRESULT res;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"Ol", &zobj, php_com_variant_class_entry, &vt)) {
return;
}
obj = CDNO_FETCH(zobj);
res = VariantChangeType(&obj->v, &obj->v, 0, vt);
if (SUCCEEDED(res)) {
if (vt != VT_DISPATCH && obj->typeinfo) {
ITypeInfo_Release(obj->typeinfo);
obj->typeinfo = NULL;
}
} else {
char *werr, *msg;
werr = php_win_err(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
}
}
/* }}} */
/* {{{ proto object variant_cast(object variant, int type)
Convert a variant into a new variant object of another type */
PHP_FUNCTION(variant_cast)
{
zval *zobj;
php_com_dotnet_object *obj;
VARTYPE vt;
VARIANT vres;
HRESULT res;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"Ol", &zobj, php_com_variant_class_entry, &vt)) {
return;
}
obj = CDNO_FETCH(zobj);
VariantInit(&vres);
res = VariantChangeType(&vres, &obj->v, 0, vt);
if (SUCCEEDED(res)) {
php_com_wrap_variant(return_value, &vres, obj->code_page TSRMLS_CC);
} else {
char *werr, *msg;
werr = php_win_err(res);
spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
LocalFree(werr);
php_com_throw_exception(msg TSRMLS_CC);
efree(msg);
}
VariantClear(&vres);
}
/* }}} */
/* {{{ proto mixed variant_index_get(object variant, mixed index1 [, mixed index2 [,
...]])
Get the value of a multi dimensional array property */
PHP_FUNCTION(variant_index_get)
{
zval *zobj;
php_com_dotnet_object *obj;
VARIANT vres;
HRESULT res;
if (FAILURE == zend_parse_parameters(1 TSRMLS_CC,
"O", &zobj, php_com_variant_class_entry)) {
return;
}
obj = CDNO_FETCH(zobj);
/* TODO: finish... */
}
/* }}} */
Index: php-src/ext/com_dotnet/php_com_dotnet.h
+++ php-src/ext/com_dotnet/php_com_dotnet.h
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: php_com_dotnet.h,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifndef PHP_COM_DOTNET_H
#define PHP_COM_DOTNET_H
extern zend_module_entry com_dotnet_module_entry;
#define phpext_com_dotnet_ptr &com_dotnet_module_entry
#ifdef PHP_WIN32
# define PHP_COM_DOTNET_API __declspec(dllexport)
#else
# define PHP_COM_DOTNET_API
#endif
#ifdef ZTS
#include "TSRM.h"
#endif
PHP_MINIT_FUNCTION(com_dotnet);
PHP_MSHUTDOWN_FUNCTION(com_dotnet);
PHP_RINIT_FUNCTION(com_dotnet);
PHP_RSHUTDOWN_FUNCTION(com_dotnet);
PHP_MINFO_FUNCTION(com_dotnet);
PHP_FUNCTION(confirm_com_dotnet_compiled);
ZEND_BEGIN_MODULE_GLOBALS(com_dotnet)
zend_bool allow_dcom;
zend_bool autoreg_verbose;
zend_bool autoreg_on;
zend_bool autoreg_case_sensitive;
void *dotnet_runtime_stuff; /* opaque to avoid cluttering up other modules */
ZEND_END_MODULE_GLOBALS(com_dotnet)
#ifdef ZTS
# define COMG(v) TSRMG(com_dotnet_globals_id, zend_com_dotnet_globals *, v)
#else
# define COMG(v) (com_dotnet_globals.v)
#endif
extern ZEND_DECLARE_MODULE_GLOBALS(com_dotnet);
#endif /* PHP_COM_DOTNET_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h
+++ php-src/ext/com_dotnet/php_com_dotnet_internal.h
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2003 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Wez Furlong <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: php_com_dotnet_internal.h,v 1.1 2003/08/14 16:49:55 wez Exp $ */
#ifndef PHP_COM_DOTNET_INTERNAL_H
#define PHP_COM_DOTNET_INTERNAL_H
#define _WIN32_DCOM
#define COBJMACROS
#include <ocidl.h>
#include "oleauto.h"
#include "win32/winutil.h"
/* brain-death in winutil.h defines the macro to hide the useful function... */
#undef php_win_err
typedef struct _php_com_dotnet_object {
VARIANT v;
ITypeInfo *typeinfo;
int code_page;
unsigned int have_default_bind:1;
zend_class_entry *ce;
DISPID default_bind; /* default property for array accesses */
} php_com_dotnet_object;
static inline int php_com_is_valid_object(zval *zv TSRMLS_DC)
{
zend_class_entry *ce = Z_OBJCE_P(zv);
return strcmp("com", ce->name) == 0 ||
strcmp("dotnet", ce->name) == 0 ||
strcmp("variant", ce->name) == 0;
}
#define CDNO_FETCH(zv)
(php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC)
#define CDNO_FETCH_VERIFY(obj, zv) do { \
if (!php_com_is_valid_object(zv TSRMLS_CC)) { \
php_com_throw_exception("expected a variant object" TSRMLS_CC); \
return; \
} \
obj = (php_com_dotnet_object*)zend_object_store_get_object(zv TSRMLS_CC); \
} while(0)
/* com_extension.c */
TsHashTable php_com_typelibraries;
zend_class_entry *php_com_variant_class_entry;
/* com_handlers.c */
zend_object_value php_com_object_new(zend_class_entry *ce TSRMLS_DC);
void php_com_object_clone(void *object, void **clone_ptr TSRMLS_DC);
void php_com_object_dtor(void *object, zend_object_handle handle TSRMLS_DC);
zend_object_handlers php_com_object_handlers;
/* com_olechar.c */
PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring,
uint *string_len, int codepage TSRMLS_DC);
PHPAPI OLECHAR *php_com_string_to_olestring(char *string,
uint string_len, int codepage TSRMLS_DC);
/* com_com.c */
PHP_FUNCTION(com_create_instance);
HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
WORD flags, DISPPARAMS *disp_params, VARIANT *v TSRMLS_DC);
HRESULT php_com_get_id_of_name(php_com_dotnet_object *obj, char *name,
int namelen, DISPID *dispid TSRMLS_DC);
int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid,
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC);
int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC);
/* com_variant.c */
PHP_FUNCTION(com_variant_create_instance);
PHP_FUNCTION(variant_set);
PHP_FUNCTION(variant_add);
PHP_FUNCTION(variant_cat);
PHP_FUNCTION(variant_sub);
PHP_FUNCTION(variant_mul);
PHP_FUNCTION(variant_and);
PHP_FUNCTION(variant_div);
PHP_FUNCTION(variant_eqv);
PHP_FUNCTION(variant_idiv);
PHP_FUNCTION(variant_imp);
PHP_FUNCTION(variant_mod);
PHP_FUNCTION(variant_or);
PHP_FUNCTION(variant_pow);
PHP_FUNCTION(variant_xor);
PHP_FUNCTION(variant_abs);
PHP_FUNCTION(variant_fix);
PHP_FUNCTION(variant_int);
PHP_FUNCTION(variant_neg);
PHP_FUNCTION(variant_not);
PHP_FUNCTION(variant_round);
PHP_FUNCTION(variant_cmp);
PHP_FUNCTION(variant_date_to_timestamp);
PHP_FUNCTION(variant_date_from_timestamp);
PHP_FUNCTION(variant_get_type);
PHP_FUNCTION(variant_set_type);
PHP_FUNCTION(variant_cast);
PHPAPI void php_com_variant_from_zval_with_type(VARIANT *v, zval *z, VARTYPE type, int
codepage TSRMLS_DC);
PHPAPI void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage TSRMLS_DC);
PHPAPI int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage TSRMLS_DC);
/* com_dotnet.c */
PHP_FUNCTION(com_dotnet_create_instance);
void php_com_dotnet_rshutdown(TSRMLS_D);
/* com_misc.c */
zval *php_com_throw_exception(char *message TSRMLS_DC);
PHPAPI void php_com_wrap_dispatch(zval *z, IDispatch *disp,
int codepage TSRMLS_DC);
PHPAPI void php_com_wrap_variant(zval *z, VARIANT *v,
int codepage TSRMLS_DC);
/* com_typeinfo.c */
PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
int mode, int codepage, int *cached TSRMLS_DC);
PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int mode,
int codepage TSRMLS_DC);
PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode,
int codepage TSRMLS_DC);
void php_com_typelibrary_dtor(void *pDest);
#endif
Index: php-src/ext/com_dotnet/tests/variants.phpt
+++ php-src/ext/com_dotnet/tests/variants.phpt
--TEST--
COM: General variant tests
--SKIPIF--
<?php # vim:ft=php
if (!extension_loaded("com_dotnet")) print "skip"; ?>
--FILE--
<?php // $Id: variants.phpt,v 1.1 2003/08/14 16:49:56 wez Exp $
error_reporting(E_ALL);
$v = new VARIANT();
if (VT_EMPTY != variant_get_type($v)) {
echo "VT_EMPTY: bork\n";
}
$values = array(VT_I4 => 42, VT_R8 => 3.5, VT_BSTR => "hello", VT_BOOL => false);
$binary_ops = array('add', 'cat', 'sub', 'mul', 'and', 'div',
'eqv', 'idiv', 'imp', 'mod', 'or', 'pow', 'xor');
foreach ($values as $t => $val) {
$v = new VARIANT($val);
if ($t != variant_get_type($v)) {
printf("Bork: [%d] %d: %s\n", $t, variant_get_type($v), (string)$v);
}
$results = array();
foreach ($values as $op2) {
echo "--\n";
foreach ($binary_ops as $op) {
echo "$op: " . call_user_func('variant_' . $op, $v, $op2) .
"\n";
}
}
}
$a = new VARIANT('10.0', VT_DECIMAL);
var_dump($a);
echo "OK!";
?>
--EXPECT--
--
add: 84
cat: 4242
sub: 0
mul: 1764
and: 42
div: 1
eqv: -1
idiv: 1
imp: -1
mod: 0
or: 42
pow: 1.50130937545297E+68
xor: 0
--
add: 45.5
cat: 423.5
sub: 38.5
mul: 147
and: 0
div: 12
eqv: -47
idiv: 10
imp: -43
mod: 2
or: 46
pow: 480145.116863642
xor: 46
--
add:
cat: 42hello
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add: 42
cat: 42False
sub: 42
mul: 0
and: 0
div:
eqv: -43
idiv:
imp: -43
mod:
or: 42
pow: 1
xor: 42
--
add: 45.5
cat: 3.542
sub: -38.5
mul: 147
and: 0
div: 8.33333333333333E-02
eqv: -47
idiv: 0
imp: -5
mod: 4
or: 46
pow: 7.09345573078604E+22
xor: 46
--
add: 7
cat: 3.53.5
sub: 0
mul: 12.25
and: 4
div: 1
eqv: -1
idiv: 1
imp: -1
mod: 0
or: 4
pow: 80.2117802289664
xor: 0
--
add:
cat: 3.5hello
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add: 3.5
cat: 3.5False
sub: 3.5
mul: 0
and: 0
div:
eqv: -5
idiv:
imp: -5
mod:
or: 4
pow: 1
xor: 4
--
add:
cat: hello42
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add:
cat: hello3.5
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add: hellohello
cat: hellohello
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add:
cat: helloFalse
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add: 42
cat: False42
sub: -42
mul: 0
and: 0
div: 0
eqv: -43
idiv: 0
imp: -1
mod: 0
or: 42
pow: 0
xor: 42
--
add: 3.5
cat: False3.5
sub: -3.5
mul: 0
and: 0
div: 0
eqv: -5
idiv: 0
imp: -1
mod: 0
or: 4
pow: 0
xor: 4
--
add:
cat: Falsehello
sub:
mul:
and:
div:
eqv:
idiv:
imp:
mod:
or:
pow:
xor:
--
add: 0
cat: FalseFalse
sub: 0
mul: 0
and: 0
div:
eqv: -1
idiv:
imp: -1
mod:
or: 0
pow: 1
xor: 0
OK!
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php