Skip to content

Commit e10c206

Browse files
committed
Port other major parts of PHP 4 COM extension into PHP 5 com_dotnet
extension. This enables: - iteration of SafeArray types via foreach() - proxying of multi-dimensional SafeArray types so that multi-dimension array accesses work (untested!) - Fix COM exceptions, and expose them as their own class of exception "com_exception" - auto typelib file import (com.typelib_file ini option) - event sinking - wrapper to map PHP objects to COM - fix mapping of variant values to PHP values # Could someone please add com_saproxy.c and com_wrapper.c to the .dsp # file?
1 parent 48b96c1 commit e10c206

14 files changed

+1957
-159
lines changed

ext/com_dotnet/com_com.c

+174-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
+----------------------------------------------------------------------+
3-
| PHP Version 4 |
3+
| PHP Version 5 |
44
+----------------------------------------------------------------------+
55
| Copyright (c) 1997-2003 The PHP Group |
66
+----------------------------------------------------------------------+
@@ -64,7 +64,7 @@ PHP_FUNCTION(com_create_instance)
6464
&module_name, &module_name_len, &server_params, &obj->code_page,
6565
&typelib_name, &typelib_name_len)) {
6666

67-
php_com_throw_exception("Could not create COM object - invalid arguments!" TSRMLS_CC);
67+
php_com_throw_exception(E_INVALIDARG, "Could not create COM object - invalid arguments!" TSRMLS_CC);
6868
ZVAL_NULL(object);
6969
return;
7070
}
@@ -113,7 +113,7 @@ PHP_FUNCTION(com_create_instance)
113113
}
114114

115115
if (server_name && !COMG(allow_dcom)) {
116-
php_com_throw_exception("DCOM has been disabled by your administrator [com.allow_dcom=0]" TSRMLS_CC);
116+
php_com_throw_exception(E_ERROR, "DCOM has been disabled by your administrator [com.allow_dcom=0]" TSRMLS_CC);
117117
return;
118118
}
119119

@@ -227,7 +227,7 @@ PHP_FUNCTION(com_create_instance)
227227
spprintf(&msg, 0, "Failed to create COM object `%s': %s", module_name, werr);
228228
LocalFree(werr);
229229

230-
php_com_throw_exception(msg TSRMLS_CC);
230+
php_com_throw_exception(res, msg TSRMLS_CC);
231231
efree(msg);
232232
ZVAL_NULL(object);
233233
return;
@@ -240,7 +240,7 @@ PHP_FUNCTION(com_create_instance)
240240
/* load up the library from the named file */
241241
int cached;
242242

243-
TL = php_com_load_typelib_via_cache(typelib_name, mode, obj->code_page, &cached TSRMLS_CC);
243+
TL = php_com_load_typelib_via_cache(typelib_name, obj->code_page, &cached TSRMLS_CC);
244244

245245
if (TL) {
246246
if (COMG(autoreg_on) && !cached) {
@@ -341,7 +341,7 @@ HRESULT php_com_invoke_helper(php_com_dotnet_object *obj, DISPID id_member,
341341
}
342342

343343
if (msg) {
344-
php_com_throw_exception(msg TSRMLS_CC);
344+
php_com_throw_exception(hr, msg TSRMLS_CC);
345345
efree(msg);
346346
}
347347
}
@@ -434,14 +434,16 @@ int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen,
434434
winerr = php_win_err(hr);
435435
spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr);
436436
LocalFree(winerr);
437-
php_com_throw_exception(msg TSRMLS_CC);
437+
php_com_throw_exception(hr, msg TSRMLS_CC);
438438
efree(msg);
439439
return FAILURE;
440440
}
441441

442442
return php_com_do_invoke_by_id(obj, dispid, flags, v, nargs, args TSRMLS_CC);
443443
}
444444

445+
/* {{{ proto string com_create_guid()
446+
Generate a globally unique identifier (GUID) */
445447
PHP_FUNCTION(com_create_guid)
446448
{
447449
GUID retval;
@@ -460,4 +462,169 @@ PHP_FUNCTION(com_create_guid)
460462
RETURN_FALSE;
461463
}
462464
}
465+
/* }}} */
466+
467+
/* {{{ proto bool com_event_sink(object comobject, object sinkobject [, mixed sinkinterface])
468+
Connect events from a COM object to a PHP object */
469+
PHP_FUNCTION(com_event_sink)
470+
{
471+
zval *object, *sinkobject, *sink=NULL;
472+
char *dispname = NULL, *typelibname = NULL;
473+
zend_bool gotguid = 0;
474+
php_com_dotnet_object *obj;
475+
ITypeInfo *typeinfo = NULL;
476+
477+
RETVAL_FALSE;
478+
479+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oo|z/",
480+
&object, php_com_variant_class_entry, &sinkobject, &sink)) {
481+
RETURN_FALSE;
482+
}
483+
484+
obj = CDNO_FETCH(object);
485+
486+
if (sink && Z_TYPE_P(sink) == IS_ARRAY) {
487+
/* 0 => typelibname, 1 => dispname */
488+
zval **tmp;
489+
490+
if (zend_hash_index_find(Z_ARRVAL_P(sink), 0, (void**)&tmp) == SUCCESS)
491+
typelibname = Z_STRVAL_PP(tmp);
492+
if (zend_hash_index_find(Z_ARRVAL_P(sink), 1, (void**)&tmp) == SUCCESS)
493+
dispname = Z_STRVAL_PP(tmp);
494+
} else if (sink != NULL) {
495+
convert_to_string(sink);
496+
dispname = Z_STRVAL_P(sink);
497+
}
498+
499+
typeinfo = php_com_locate_typeinfo(typelibname, obj, dispname, 1 TSRMLS_CC);
500+
501+
if (typeinfo) {
502+
HashTable *id_to_name;
503+
504+
ALLOC_HASHTABLE(id_to_name);
505+
506+
if (php_com_process_typeinfo(typeinfo, id_to_name, 0, &obj->sink_id, obj->code_page TSRMLS_CC)) {
507+
508+
/* Create the COM wrapper for this sink */
509+
obj->sink_dispatch = php_com_wrapper_export_as_sink(sinkobject, &obj->sink_id, id_to_name TSRMLS_CC);
510+
511+
/* Now hook it up to the source */
512+
php_com_object_enable_event_sink(obj, TRUE TSRMLS_CC);
513+
RETVAL_TRUE;
514+
515+
} else {
516+
FREE_HASHTABLE(id_to_name);
517+
}
518+
}
519+
520+
if (typeinfo) {
521+
ITypeInfo_Release(typeinfo);
522+
}
523+
524+
}
525+
/* }}} */
526+
527+
/* {{{ proto bool com_print_typeinfo(object comobject | string typelib, string dispinterface, bool wantsink)
528+
Print out a PHP class definition for a dispatchable interface */
529+
PHP_FUNCTION(com_print_typeinfo)
530+
{
531+
zval *arg1;
532+
char *ifacename = NULL;
533+
char *typelibname = NULL;
534+
int ifacelen;
535+
zend_bool wantsink = 0;
536+
php_com_dotnet_object *obj = NULL;
537+
ITypeInfo *typeinfo;
538+
539+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/|s!b", &arg1, &ifacename,
540+
&ifacelen, &wantsink)) {
541+
RETURN_FALSE;
542+
}
543+
544+
if (Z_TYPE_P(arg1) == IS_OBJECT) {
545+
CDNO_FETCH_VERIFY(obj, arg1);
546+
} else {
547+
convert_to_string(arg1);
548+
typelibname = Z_STRVAL_P(arg1);
549+
}
550+
551+
typeinfo = php_com_locate_typeinfo(typelibname, obj, ifacename, wantsink ? 1 : 0 TSRMLS_CC);
552+
if (typeinfo) {
553+
php_com_process_typeinfo(typeinfo, NULL, 1, NULL, obj ? obj->code_page : COMG(code_page) TSRMLS_CC);
554+
ITypeInfo_Release(typeinfo);
555+
RETURN_TRUE;
556+
} else {
557+
zend_error(E_WARNING, "Unable to find typeinfo using the parameters supplied");
558+
}
559+
RETURN_FALSE;
560+
}
561+
/* }}} */
562+
563+
/* {{{ proto bool com_message_pump([int timeoutms])
564+
Process COM messages, sleeping for up to timeoutms milliseconds */
565+
PHP_FUNCTION(com_message_pump)
566+
{
567+
long timeoutms = 0;
568+
MSG msg;
569+
DWORD result;
570+
571+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &timeoutms) == FAILURE)
572+
RETURN_FALSE;
573+
574+
result = MsgWaitForMultipleObjects(0, NULL, FALSE, timeoutms, QS_ALLINPUT);
575+
576+
if (result == WAIT_OBJECT_0) {
577+
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
578+
TranslateMessage(&msg);
579+
DispatchMessage(&msg);
580+
}
581+
/* we processed messages */
582+
RETVAL_TRUE;
583+
} else {
584+
/* we did not process messages (timed out) */
585+
RETVAL_FALSE;
586+
}
587+
}
588+
/* }}} */
463589

590+
/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitive])
591+
Loads a Typelibrary and registers its constants */
592+
PHP_FUNCTION(com_load_typelib)
593+
{
594+
char *name;
595+
long namelen;
596+
ITypeLib *pTL = NULL;
597+
zend_bool cs = TRUE;
598+
int codepage = COMG(code_page);
599+
int cached = 0;
600+
601+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &name, &namelen, &cs)) {
602+
return;
603+
}
604+
605+
RETVAL_FALSE;
606+
607+
pTL = php_com_load_typelib_via_cache(name, codepage, &cached TSRMLS_CC);
608+
if (pTL) {
609+
if (cached) {
610+
RETVAL_TRUE;
611+
} else if (php_com_import_typelib(pTL, cs ? CONST_CS : 0, codepage TSRMLS_CC) == SUCCESS) {
612+
RETVAL_TRUE;
613+
}
614+
615+
ITypeLib_Release(pTL);
616+
pTL = NULL;
617+
}
618+
}
619+
/* }}} */
620+
621+
622+
623+
/*
624+
* Local variables:
625+
* tab-width: 4
626+
* c-basic-offset: 4
627+
* End:
628+
* vim600: noet sw=4 ts=4 fdm=marker
629+
* vim<600: noet sw=4 ts=4
630+
*/

ext/com_dotnet/com_dotnet.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
+----------------------------------------------------------------------+
3-
| PHP Version 4 |
3+
| PHP Version 5 |
44
+----------------------------------------------------------------------+
55
| Copyright (c) 1997-2003 The PHP Group |
66
+----------------------------------------------------------------------+
@@ -109,7 +109,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
109109

110110
if (COMG(dotnet_runtime_stuff) == NULL) {
111111
if (FAILURE == dotnet_init(TSRMLS_C)) {
112-
php_com_throw_exception("Failed to initialize .Net runtime" TSRMLS_CC);
112+
php_com_throw_exception(E_ERROR, "Failed to initialize .Net runtime" TSRMLS_CC);
113113
ZVAL_NULL(object);
114114
return;
115115
}
@@ -123,7 +123,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
123123
&assembly_name, &assembly_name_len,
124124
&datatype_name, &datatype_name_len,
125125
&obj->code_page)) {
126-
php_com_throw_exception("Could not create .Net object - invalid arguments!" TSRMLS_CC);
126+
php_com_throw_exception(E_INVALIDARG, "Could not create .Net object - invalid arguments!" TSRMLS_CC);
127127
ZVAL_NULL(object);
128128
return;
129129
}
@@ -171,7 +171,7 @@ PHP_FUNCTION(com_dotnet_create_instance)
171171
VariantClear(&vargs[1]);
172172

173173
if (ret == FAILURE) {
174-
php_com_throw_exception("Failed to instantiate .Net object" TSRMLS_CC);
174+
php_com_throw_exception(hr, "Failed to instantiate .Net object" TSRMLS_CC);
175175
ZVAL_NULL(object);
176176
return;
177177
}

0 commit comments

Comments
 (0)