Enhance com_print_typeinfo.

The main expected use is like this, for figuring out what methods
are allowed for a COM object:

$ie = new COM("InternetExplorer.Application");
// Prints class definition for IE object
com_print_typeinfo($ie, "InternetExplorer.Application", false);
// Prints class definition for default IE event handler
com_print_typeinfo($ie, "InternetExplorer.Application", true);
This commit is contained in:
Wez Furlong 2002-05-21 22:41:45 +00:00
parent 634746ece9
commit fbf920d9a3
2 changed files with 272 additions and 166 deletions

View file

@ -15,9 +15,10 @@
| Author: Zeev Suraski <zeev@zend.com> | | Author: Zeev Suraski <zeev@zend.com> |
| Harald Radi <h.radi@nme.at> | | Harald Radi <h.radi@nme.at> |
| Alan Brown <abrown@pobox.com> | | Alan Brown <abrown@pobox.com> |
| Wez Furlong <wez@thebrainroom.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
*/ */
/* $Id$ */
/* /*
* This module implements support for COM components that support the IDispatch * This module implements support for COM components that support the IDispatch
* interface. Both local (COM) and remote (DCOM) components can be accessed. * interface. Both local (COM) and remote (DCOM) components can be accessed.
@ -1090,6 +1091,7 @@ static const struct {
{ VT_BYREF, "VT_BYREF" }, { VT_BYREF, "VT_BYREF" },
{ VT_VOID, "VT_VOID" }, { VT_VOID, "VT_VOID" },
{ VT_PTR, "VT_PTR" }, { VT_PTR, "VT_PTR" },
{ VT_HRESULT, "VT_HRESULT" },
{ 0, NULL } { 0, NULL }
}; };
@ -1117,7 +1119,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
return 0; return 0;
/* verify that it is suitable */ /* verify that it is suitable */
if (attr->typekind == TKIND_DISPATCH) { if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) {
if (guid) if (guid)
memcpy(guid, &attr->guid, sizeof(GUID)); memcpy(guid, &attr->guid, sizeof(GUID));
@ -1142,10 +1144,18 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
/* So we've got the dispatch interface; lets list the event methods */ /* So we've got the dispatch interface; lets list the event methods */
for (i = 0; i < attr->cFuncs; i++) { for (i = 0; i < attr->cFuncs; i++) {
zval *tmp; zval *tmp;
DISPID lastid = 0; /* for props */
int isprop;
if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func))) if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func)))
break; break;
isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT);
if (!isprop || lastid != func->memid) {
lastid = func->memid;
typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL); typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL);
ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC);
SysFreeString(olename); SysFreeString(olename);
@ -1159,22 +1169,26 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR)); names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR));
typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames); typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames);
/* first element is the function name */ /* first element is the function name */
SysFreeString(names[0]); SysFreeString(names[0]);
php_printf("\t/* DISPID=%d */\n\t", func->memid); php_printf("\t/* DISPID=%d */\n", func->memid);
if (func->elemdescFunc.tdesc.vt != VT_VOID) { if (func->elemdescFunc.tdesc.vt != VT_VOID) {
php_printf(" /* %s [%d] */ ", php_printf("\t/* %s [%d] */\n",
vt_to_string(func->elemdescFunc.tdesc.vt), vt_to_string(func->elemdescFunc.tdesc.vt),
func->elemdescFunc.tdesc.vt func->elemdescFunc.tdesc.vt
); );
} }
/* TODO: handle prop put and get */ if (isprop) {
php_printf("function %s(\n", ansiname); php_printf("\tvar $%s;\n\n", ansiname);
} else {
/* a function */
php_printf("\tfunction %s(\n", ansiname);
for (j = 0; j < func->cParams; j++) { for (j = 0; j < func->cParams; j++) {
ELEMDESC *elem = &func->lprgelemdescParam[j]; ELEMDESC *elem = &func->lprgelemdescParam[j];
@ -1223,6 +1237,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
} }
php_printf("\t}\n"); php_printf("\t}\n");
}
efree(names); efree(names);
} }
@ -1233,7 +1248,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0); ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0);
zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL); zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL);
} }
}
typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func); typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func);
} }
@ -1243,7 +1258,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
ret = 1; ret = 1;
} else { } else {
zend_error(E_WARNING, "Thats not a dispatchable interface!!\n"); zend_error(E_WARNING, "Thats not a dispatchable interface!! type kind = %08x\n", attr->typekind);
} }
typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr); typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr);
@ -1272,17 +1287,16 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
/* TODO: write some code here */ /* TODO: write some code here */
pci->lpVtbl->Release(pci); pci->lpVtbl->Release(pci);
} }
} else if (dispname) { } else if (dispname && C_HASTLIB(obj)) {
unsigned int idx; unsigned int idx;
/* get the library from the object; the rest will be dealt with later */ /* get the library from the object; the rest will be dealt with later */
C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx); C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx);
} else if (typelibname == NULL) {
C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &typeinfo);
} }
} else if (typelibname) { } else if (typelibname) {
/* Fetch the typelibrary and use that to look things up */ /* Fetch the typelibrary and use that to look things up */
typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC); typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC);
} else if (dispname) {
/* TODO: assume that the name is actually a progid */
} }
if (!gotguid && dispname && typelib) { if (!gotguid && dispname && typelib) {
@ -1291,7 +1305,44 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC); OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC);
cfound = 1; cfound = 1;
typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound); if (FAILED(typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) {
CLSID coclass;
ITypeInfo *coinfo;
/* assume that it might be a progid instead */
if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) &&
SUCCEEDED(typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {
/* enumerate implemented interfaces and pick the one as indicated by sink */
TYPEATTR *attr;
int i;
coinfo->lpVtbl->GetTypeAttr(coinfo, &attr);
for (i = 0; i < attr->cImplTypes; i++) {
HREFTYPE rt;
int tf;
if (FAILED(coinfo->lpVtbl->GetImplTypeFlags(coinfo, i, &tf)))
continue;
if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) ||
(!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) {
/* flags match what we are looking for */
if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeOfImplType(coinfo, i, &rt)))
if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeInfo(coinfo, rt, &typeinfo)))
break;
}
}
coinfo->lpVtbl->ReleaseTypeAttr(coinfo, attr);
coinfo->lpVtbl->Release(coinfo);
}
}
efree(olename); efree(olename);
} else if (gotguid) { } else if (gotguid) {
@ -1309,14 +1360,14 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
PHP_FUNCTION(com_print_typeinfo) PHP_FUNCTION(com_print_typeinfo)
{ {
zval *arg1; zval *arg1;
char *ifacename; char *ifacename = NULL;
char *typelibname = NULL; char *typelibname = NULL;
int ifacelen; int ifacelen;
zend_bool wantsink; zend_bool wantsink = 0;
comval *obj = NULL; comval *obj = NULL;
ITypeInfo *typeinfo; ITypeInfo *typeinfo;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/sb", &arg1, &ifacename, if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/s!b", &arg1, &ifacename,
&ifacelen, &wantsink)) { &ifacelen, &wantsink)) {
RETURN_FALSE; RETURN_FALSE;
} }
@ -1337,6 +1388,8 @@ PHP_FUNCTION(com_print_typeinfo)
process_typeinfo(typeinfo, NULL, 1, NULL TSRMLS_CC); process_typeinfo(typeinfo, NULL, 1, NULL TSRMLS_CC);
typeinfo->lpVtbl->Release(typeinfo); typeinfo->lpVtbl->Release(typeinfo);
RETURN_TRUE; RETURN_TRUE;
} else {
zend_error(E_WARNING, "Unable to find typeinfo using the parameters supplied");
} }
RETURN_FALSE; RETURN_FALSE;
} }

View file

@ -15,9 +15,10 @@
| Author: Zeev Suraski <zeev@zend.com> | | Author: Zeev Suraski <zeev@zend.com> |
| Harald Radi <h.radi@nme.at> | | Harald Radi <h.radi@nme.at> |
| Alan Brown <abrown@pobox.com> | | Alan Brown <abrown@pobox.com> |
| Wez Furlong <wez@thebrainroom.com> |
+----------------------------------------------------------------------+ +----------------------------------------------------------------------+
*/ */
/* $Id$ */
/* /*
* This module implements support for COM components that support the IDispatch * This module implements support for COM components that support the IDispatch
* interface. Both local (COM) and remote (DCOM) components can be accessed. * interface. Both local (COM) and remote (DCOM) components can be accessed.
@ -1090,6 +1091,7 @@ static const struct {
{ VT_BYREF, "VT_BYREF" }, { VT_BYREF, "VT_BYREF" },
{ VT_VOID, "VT_VOID" }, { VT_VOID, "VT_VOID" },
{ VT_PTR, "VT_PTR" }, { VT_PTR, "VT_PTR" },
{ VT_HRESULT, "VT_HRESULT" },
{ 0, NULL } { 0, NULL }
}; };
@ -1117,7 +1119,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
return 0; return 0;
/* verify that it is suitable */ /* verify that it is suitable */
if (attr->typekind == TKIND_DISPATCH) { if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) {
if (guid) if (guid)
memcpy(guid, &attr->guid, sizeof(GUID)); memcpy(guid, &attr->guid, sizeof(GUID));
@ -1142,10 +1144,18 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
/* So we've got the dispatch interface; lets list the event methods */ /* So we've got the dispatch interface; lets list the event methods */
for (i = 0; i < attr->cFuncs; i++) { for (i = 0; i < attr->cFuncs; i++) {
zval *tmp; zval *tmp;
DISPID lastid = 0; /* for props */
int isprop;
if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func))) if (FAILED(typeinfo->lpVtbl->GetFuncDesc(typeinfo, i, &func)))
break; break;
isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT);
if (!isprop || lastid != func->memid) {
lastid = func->memid;
typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL); typeinfo->lpVtbl->GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL);
ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC); ansiname = php_OLECHAR_to_char(olename, &ansinamelen, codepage TSRMLS_CC);
SysFreeString(olename); SysFreeString(olename);
@ -1159,22 +1169,26 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR)); names = (BSTR*)emalloc((func->cParams + 1) * sizeof(BSTR));
typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames); typeinfo->lpVtbl->GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames);
/* first element is the function name */ /* first element is the function name */
SysFreeString(names[0]); SysFreeString(names[0]);
php_printf("\t/* DISPID=%d */\n\t", func->memid); php_printf("\t/* DISPID=%d */\n", func->memid);
if (func->elemdescFunc.tdesc.vt != VT_VOID) { if (func->elemdescFunc.tdesc.vt != VT_VOID) {
php_printf(" /* %s [%d] */ ", php_printf("\t/* %s [%d] */\n",
vt_to_string(func->elemdescFunc.tdesc.vt), vt_to_string(func->elemdescFunc.tdesc.vt),
func->elemdescFunc.tdesc.vt func->elemdescFunc.tdesc.vt
); );
} }
/* TODO: handle prop put and get */ if (isprop) {
php_printf("function %s(\n", ansiname); php_printf("\tvar $%s;\n\n", ansiname);
} else {
/* a function */
php_printf("\tfunction %s(\n", ansiname);
for (j = 0; j < func->cParams; j++) { for (j = 0; j < func->cParams; j++) {
ELEMDESC *elem = &func->lprgelemdescParam[j]; ELEMDESC *elem = &func->lprgelemdescParam[j];
@ -1223,6 +1237,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
} }
php_printf("\t}\n"); php_printf("\t}\n");
}
efree(names); efree(names);
} }
@ -1233,7 +1248,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0); ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0);
zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL); zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL);
} }
}
typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func); typeinfo->lpVtbl->ReleaseFuncDesc(typeinfo, func);
} }
@ -1243,7 +1258,7 @@ static int process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int prin
ret = 1; ret = 1;
} else { } else {
zend_error(E_WARNING, "Thats not a dispatchable interface!!\n"); zend_error(E_WARNING, "Thats not a dispatchable interface!! type kind = %08x\n", attr->typekind);
} }
typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr); typeinfo->lpVtbl->ReleaseTypeAttr(typeinfo, attr);
@ -1272,17 +1287,16 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
/* TODO: write some code here */ /* TODO: write some code here */
pci->lpVtbl->Release(pci); pci->lpVtbl->Release(pci);
} }
} else if (dispname) { } else if (dispname && C_HASTLIB(obj)) {
unsigned int idx; unsigned int idx;
/* get the library from the object; the rest will be dealt with later */ /* get the library from the object; the rest will be dealt with later */
C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx); C_TYPEINFO_VT(obj)->GetContainingTypeLib(C_TYPEINFO(obj), &typelib, &idx);
} else if (typelibname == NULL) {
C_DISPATCH_VT(obj)->GetTypeInfo(C_DISPATCH(obj), 0, LANG_NEUTRAL, &typeinfo);
} }
} else if (typelibname) { } else if (typelibname) {
/* Fetch the typelibrary and use that to look things up */ /* Fetch the typelibrary and use that to look things up */
typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC); typelib = php_COM_find_typelib(typelibname, CONST_CS TSRMLS_CC);
} else if (dispname) {
/* TODO: assume that the name is actually a progid */
} }
if (!gotguid && dispname && typelib) { if (!gotguid && dispname && typelib) {
@ -1291,7 +1305,44 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC); OLECHAR *olename = php_char_to_OLECHAR(dispname, strlen(dispname), CP_ACP TSRMLS_CC);
cfound = 1; cfound = 1;
typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound); if (FAILED(typelib->lpVtbl->FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) {
CLSID coclass;
ITypeInfo *coinfo;
/* assume that it might be a progid instead */
if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) &&
SUCCEEDED(typelib->lpVtbl->GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {
/* enumerate implemented interfaces and pick the one as indicated by sink */
TYPEATTR *attr;
int i;
coinfo->lpVtbl->GetTypeAttr(coinfo, &attr);
for (i = 0; i < attr->cImplTypes; i++) {
HREFTYPE rt;
int tf;
if (FAILED(coinfo->lpVtbl->GetImplTypeFlags(coinfo, i, &tf)))
continue;
if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) ||
(!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) {
/* flags match what we are looking for */
if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeOfImplType(coinfo, i, &rt)))
if (SUCCEEDED(coinfo->lpVtbl->GetRefTypeInfo(coinfo, rt, &typeinfo)))
break;
}
}
coinfo->lpVtbl->ReleaseTypeAttr(coinfo, attr);
coinfo->lpVtbl->Release(coinfo);
}
}
efree(olename); efree(olename);
} else if (gotguid) { } else if (gotguid) {
@ -1309,14 +1360,14 @@ static ITypeInfo *locate_typeinfo(char *typelibname, comval *obj, char *dispname
PHP_FUNCTION(com_print_typeinfo) PHP_FUNCTION(com_print_typeinfo)
{ {
zval *arg1; zval *arg1;
char *ifacename; char *ifacename = NULL;
char *typelibname = NULL; char *typelibname = NULL;
int ifacelen; int ifacelen;
zend_bool wantsink; zend_bool wantsink = 0;
comval *obj = NULL; comval *obj = NULL;
ITypeInfo *typeinfo; ITypeInfo *typeinfo;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/sb", &arg1, &ifacename, if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/s!b", &arg1, &ifacename,
&ifacelen, &wantsink)) { &ifacelen, &wantsink)) {
RETURN_FALSE; RETURN_FALSE;
} }
@ -1337,6 +1388,8 @@ PHP_FUNCTION(com_print_typeinfo)
process_typeinfo(typeinfo, NULL, 1, NULL TSRMLS_CC); process_typeinfo(typeinfo, NULL, 1, NULL TSRMLS_CC);
typeinfo->lpVtbl->Release(typeinfo); typeinfo->lpVtbl->Release(typeinfo);
RETURN_TRUE; RETURN_TRUE;
} else {
zend_error(E_WARNING, "Unable to find typeinfo using the parameters supplied");
} }
RETURN_FALSE; RETURN_FALSE;
} }