Back to index

php5  5.3.10
Functions | Variables
com_typeinfo.c File Reference
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_com_dotnet.h"
#include "php_com_dotnet_internal.h"

Go to the source code of this file.

Functions

PHPAPI ITypeLib * php_com_load_typelib (char *search_string, 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)
PHPAPI ITypeLib * php_com_load_typelib_via_cache (char *search_string, int codepage, int *cached TSRMLS_DC)
ITypeInfo * php_com_locate_typeinfo (char *typelibname, php_com_dotnet_object *obj, char *dispname, int sink TSRMLS_DC)
static const char * vt_to_string (VARTYPE vt)
static char * php_com_string_from_clsid (const CLSID *clsid, int codepage TSRMLS_DC)
int php_com_process_typeinfo (ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid, int codepage TSRMLS_DC)

Variables

struct {
VARTYPE vt
const char * name
vt_names []

Function Documentation

PHPAPI int php_com_import_typelib ( ITypeLib *  TL,
int  mode,
int codepage  TSRMLS_DC 
)

Definition at line 156 of file com_typeinfo.c.

{
       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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI ITypeLib* php_com_load_typelib ( char *  search_string,
int codepage  TSRMLS_DC 
)

Definition at line 38 of file com_typeinfo.c.

{
       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 == stricmp(libname, search_string)) {
                                                                      char *str = NULL;
                                                                      int major_tmp, minor_tmp;

                                                                      /* fetch the GUID and add the version numbers */
                                                                      if (2 != sscanf(version, "%d.%d", &major_tmp, &minor_tmp)) {
                                                                             major_tmp = 1;
                                                                             minor_tmp = 0;
                                                                      }
                                                                      spprintf(&str, 0, "%s,%d,%d", keyname, major_tmp, minor_tmp);
                                                                      /* recurse */
                                                                      TL = php_com_load_typelib(str, codepage TSRMLS_CC);

                                                                      efree(str);
                                                                      break;
                                                               }
                                                        }
                                                 }
                                          }
                                          RegCloseKey(hsubkey);
                                   }
                            }
                            RegCloseKey(hkey);
                            efree(keyname);
                            efree(libname);
                     }
              }
       }
       
       efree(p);

       return TL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PHPAPI ITypeLib* php_com_load_typelib_via_cache ( char *  search_string,
int  codepage,
int *cached  TSRMLS_DC 
)

Definition at line 227 of file com_typeinfo.c.

{
       ITypeLib **TLp;
       ITypeLib *TL;
       char *name_dup;
       int l;

       l = strlen(search_string);

       if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1,
                     (void**)&TLp) == SUCCESS) {
              *cached = 1;
              /* add a reference for the caller */
              ITypeLib_AddRef(*TLp);
              return *TLp;
       }

       *cached = 0;
       name_dup = estrndup(search_string, l);
       TL = php_com_load_typelib(name_dup, 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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

ITypeInfo* php_com_locate_typeinfo ( char *  typelibname,
php_com_dotnet_object obj,
char *  dispname,
int sink  TSRMLS_DC 
)

Definition at line 261 of file com_typeinfo.c.

{
       ITypeInfo *typeinfo = NULL;
       ITypeLib *typelib = NULL;
       int gotguid = 0;
       GUID iid;
       
       if (obj) {
              if (dispname == NULL && sink) {
                     IProvideClassInfo2 *pci2;
                     IProvideClassInfo *pci;

                     if (SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo2, (void**)&pci2))) {
                            gotguid = SUCCEEDED(IProvideClassInfo2_GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid));
                            IProvideClassInfo2_Release(pci2);
                     }
                     if (!gotguid && SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo, (void**)&pci))) {
                            /* examine the available interfaces */
                            /* TODO: write some code here */
                            php_error_docref(NULL TSRMLS_CC, E_WARNING, "IProvideClassInfo: this code not yet written!");
                            IProvideClassInfo_Release(pci);
                     }
              } else if (dispname == NULL) {
                     if (obj->typeinfo) {
                            ITypeInfo_AddRef(obj->typeinfo);
                            return obj->typeinfo;
                     } else {
                            IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
                            if (typeinfo) {
                                   return typeinfo;
                            }
                     }
              } else if (dispname && obj->typeinfo) {
                     unsigned int idx;
                     /* get the library from the object; the rest will be dealt with later */
                     ITypeInfo_GetContainingTypeLib(obj->typeinfo, &typelib, &idx);
              } else if (typelibname == NULL) {
                     IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
                     if (dispname) {
                            unsigned int idx;
                            /* get the library from the object; the rest will be dealt with later */
                            ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, &idx);

                            if (typelib) {
                                   ITypeInfo_Release(typeinfo);
                                   typeinfo = NULL;
                            }
                     }
              }
       } else if (typelibname) {
              /* Fetch the typelibrary and use that to look things up */
              typelib = php_com_load_typelib(typelibname, CP_THREAD_ACP TSRMLS_CC);
       } 

       if (!gotguid && dispname && typelib) {
              unsigned short cfound;
              MEMBERID memid;
              OLECHAR *olename = php_com_string_to_olestring(dispname, strlen(dispname), CP_ACP TSRMLS_CC);
                     
              cfound = 1;
              if (FAILED(ITypeLib_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(ITypeLib_GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {

                            /* enumerate implemented interfaces and pick the one as indicated by sink */
                            TYPEATTR *attr;
                            int i;

                            ITypeInfo_GetTypeAttr(coinfo, &attr);

                            for (i = 0; i < attr->cImplTypes; i++) {
                                   HREFTYPE rt;
                                   int tf;

                                   if (FAILED(ITypeInfo_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(ITypeInfo_GetRefTypeOfImplType(coinfo, i, &rt)))
                                                 if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(coinfo, rt, &typeinfo)))
                                                        break;
                                          
                                   }
                            }
                            
                            ITypeInfo_ReleaseTypeAttr(coinfo, attr);
                            ITypeInfo_Release(coinfo);
                     }
              }

              
              efree(olename);
       } else if (gotguid) {
              ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &typeinfo);
       }

       if (typelib) {
              ITypeLib_Release(typelib);
       }

       return typeinfo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int php_com_process_typeinfo ( ITypeInfo *  typeinfo,
HashTable id_to_name,
int  printdef,
GUID *  guid,
int codepage  TSRMLS_DC 
)

Definition at line 430 of file com_typeinfo.c.

{
       TYPEATTR *attr;
       FUNCDESC *func;
       int i;
       OLECHAR *olename;
       char *ansiname = NULL;
       unsigned int ansinamelen;
       int ret = 0;

       if (FAILED(ITypeInfo_GetTypeAttr(typeinfo, &attr))) {
              return 0;
       }

       /* verify that it is suitable */
       if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) {

              if (guid) {
                     memcpy(guid, &attr->guid, sizeof(GUID));
              }
              
              if (printdef) {
                     char *guidstring;

                     ITypeInfo_GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL);
                     ansiname = php_com_olestring_to_string(olename, &ansinamelen, codepage TSRMLS_CC);
                     SysFreeString(olename);

                     guidstring = php_com_string_from_clsid(&attr->guid, codepage TSRMLS_CC);
                     php_printf("class %s { /* GUID=%s */\n", ansiname, guidstring);
                     efree(guidstring);

                     efree(ansiname);
              }

              if (id_to_name) {
                     zend_hash_init(id_to_name, 0, NULL, ZVAL_PTR_DTOR, 0);
              }

              /* So we've got the dispatch interface; lets list the event methods */
              for (i = 0; i < attr->cFuncs; i++) {
                     zval *tmp;
                     DISPID lastid = 0;   /* for props */
                     int isprop;

                     if (FAILED(ITypeInfo_GetFuncDesc(typeinfo, i, &func)))
                            break;

                     isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT);

                     if (!isprop || lastid != func->memid) {

                            lastid = func->memid;
                            
                            ITypeInfo_GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL);
                            ansiname = php_com_olestring_to_string(olename, &ansinamelen, codepage TSRMLS_CC);
                            SysFreeString(olename);

                            if (printdef) {
                                   int j;
                                   char *funcdesc;
                                   unsigned int funcdesclen, cnames = 0;
                                   BSTR *names;

                                   names = (BSTR*)safe_emalloc((func->cParams + 1), sizeof(BSTR), 0);

                                   ITypeInfo_GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames);
                                   /* first element is the function name */
                                   SysFreeString(names[0]);

                                   php_printf("\t/* DISPID=%d */\n", func->memid);

                                   if (func->elemdescFunc.tdesc.vt != VT_VOID) {
                                          php_printf("\t/* %s [%d] */\n",
                                                        vt_to_string(func->elemdescFunc.tdesc.vt),
                                                        func->elemdescFunc.tdesc.vt
                                                        );
                                   }

                                   if (isprop) {

                                          ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
                                          if (olename) {
                                                 funcdesc = php_com_olestring_to_string(olename, &funcdesclen, codepage TSRMLS_CC);
                                                 SysFreeString(olename);
                                                 php_printf("\t/* %s */\n", funcdesc);
                                                 efree(funcdesc);
                                          }

                                          php_printf("\tvar $%s;\n\n", ansiname);

                                   } else {
                                          /* a function */

                                          php_printf("\tfunction %s(\n", ansiname);

                                          for (j = 0; j < func->cParams; j++) {
                                                 ELEMDESC *elem = &func->lprgelemdescParam[j];

                                                 php_printf("\t\t/* %s [%d] ", vt_to_string(elem->tdesc.vt), elem->tdesc.vt);

                                                 if (elem->paramdesc.wParamFlags & PARAMFLAG_FIN)
                                                        php_printf("[in]");
                                                 if (elem->paramdesc.wParamFlags & PARAMFLAG_FOUT)
                                                        php_printf("[out]");

                                                 if (elem->tdesc.vt == VT_PTR) {
                                                        /* what does it point to ? */
                                                        php_printf(" --> %s [%d] ",
                                                                      vt_to_string(elem->tdesc.lptdesc->vt),
                                                                      elem->tdesc.lptdesc->vt
                                                                      );
                                                 }

                                                 /* when we handle prop put and get, this will look nicer */
                                                 if (j+1 < (int)cnames) {
                                                        funcdesc = php_com_olestring_to_string(names[j+1], &funcdesclen, codepage TSRMLS_CC);
                                                        SysFreeString(names[j+1]);
                                                 } else {
                                                        funcdesc = "???";
                                                 }

                                                 php_printf(" */ %s%s%c\n",
                                                               elem->tdesc.vt == VT_PTR ? "&$" : "$",
                                                               funcdesc,
                                                               j == func->cParams - 1 ? ' ' : ','
                                                               );

                                                 if (j+1 < (int)cnames) {
                                                        efree(funcdesc);
                                                 }
                                          }

                                          php_printf("\t\t)\n\t{\n");

                                          ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
                                          if (olename) {
                                                 funcdesc = php_com_olestring_to_string(olename, &funcdesclen, codepage TSRMLS_CC);
                                                 SysFreeString(olename);
                                                 php_printf("\t\t/* %s */\n", funcdesc);
                                                 efree(funcdesc);
                                          }

                                          php_printf("\t}\n");
                                   }

                                   efree(names);
                            }

                            if (id_to_name) {
                                   zend_str_tolower(ansiname, ansinamelen);
                                   MAKE_STD_ZVAL(tmp);
                                   ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0);
                                   zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL);
                            }
                     }
                     ITypeInfo_ReleaseFuncDesc(typeinfo, func);
              }

              if (printdef) {
                     php_printf("}\n");
              }

              ret = 1;
       } else {
              zend_error(E_WARNING, "That's not a dispatchable interface!! type kind = %08x", attr->typekind);
       }

       ITypeInfo_ReleaseTypeAttr(typeinfo, attr);

       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char* php_com_string_from_clsid ( const CLSID *  clsid,
int codepage  TSRMLS_DC 
) [static]

Definition at line 417 of file com_typeinfo.c.

{
       LPOLESTR ole_clsid;
       char *clsid_str;

       StringFromCLSID(clsid, &ole_clsid);
       clsid_str = php_com_olestring_to_string(ole_clsid, NULL, codepage TSRMLS_CC);
       LocalFree(ole_clsid);

       return clsid_str;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void php_com_typelibrary_dtor ( void *  pDest)

Definition at line 221 of file com_typeinfo.c.

{
       ITypeLib **Lib = (ITypeLib**)pDest;
       ITypeLib_Release(*Lib);
}

Here is the caller graph for this function:

static const char* vt_to_string ( VARTYPE  vt) [inline, static]

Definition at line 407 of file com_typeinfo.c.

{
       int i;
       for (i = 0; vt_names[i].name != NULL; i++) {
              if (vt_names[i].vt == vt)
                     return vt_names[i].name;
       }
       return "?";
}

Here is the caller graph for this function:


Variable Documentation

struct { ... } vt_names[] [static]