Back to index

php5  5.3.10
com_typeinfo.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Wez Furlong <wez@thebrainroom.com>                           |
00016    |         Harald Radi <h.radi@nme.at>                                  |
00017    +----------------------------------------------------------------------+
00018  */
00019 
00020 /* $Id: com_typeinfo.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include "php.h"
00027 #include "php_ini.h"
00028 #include "ext/standard/info.h"
00029 #include "php_com_dotnet.h"
00030 #include "php_com_dotnet_internal.h"
00031 
00032 
00033 /* The search string can be either:
00034  * a) a file name
00035  * b) a CLSID, major, minor e.g. "{00000200-0000-0010-8000-00AA006D2EA4},2,0"
00036  * c) a Type Library name e.g. "Microsoft OLE DB ActiveX Data Objects 1.0 Library"
00037  */
00038 PHPAPI ITypeLib *php_com_load_typelib(char *search_string, int codepage TSRMLS_DC)
00039 {
00040        ITypeLib *TL = NULL;
00041        char *strtok_buf, *major, *minor;
00042        CLSID clsid;
00043        OLECHAR *p;
00044        HRESULT hr;
00045 
00046        search_string = php_strtok_r(search_string, ",", &strtok_buf);
00047 
00048        if (search_string == NULL) {
00049               return NULL;
00050        }
00051 
00052        major = php_strtok_r(NULL, ",", &strtok_buf);
00053        minor = php_strtok_r(NULL, ",", &strtok_buf);
00054 
00055        p = php_com_string_to_olestring(search_string, strlen(search_string), codepage TSRMLS_CC);
00056 
00057        if (SUCCEEDED(CLSIDFromString(p, &clsid))) {
00058               WORD major_i = 1, minor_i = 0;
00059 
00060               /* pick up the major/minor numbers; if none specified, default to 1,0 */
00061               if (major && minor) {
00062                      major_i = (WORD)atoi(major);
00063                      minor_i = (WORD)atoi(minor);
00064               }
00065 
00066               /* Load the TypeLib by GUID */
00067               hr = LoadRegTypeLib((REFGUID)&clsid, major_i, minor_i, LANG_NEUTRAL, &TL);
00068 
00069               /* if that failed, assumed that the GUID is actually a CLSID and
00070                * attemp to get the library via an instance of that class */
00071               if (FAILED(hr) && (major == NULL || minor == NULL)) {
00072                      IDispatch *disp = NULL;
00073                      ITypeInfo *info = NULL;
00074                      int idx;
00075 
00076                      if (SUCCEEDED(hr = CoCreateInstance(&clsid, NULL, CLSCTX_SERVER, &IID_IDispatch, (LPVOID*)&disp)) &&
00077                                    SUCCEEDED(hr = IDispatch_GetTypeInfo(disp, 0, LANG_NEUTRAL, &info))) {
00078                             hr = ITypeInfo_GetContainingTypeLib(info, &TL, &idx);
00079                      }
00080 
00081                      if (info) {
00082                             ITypeInfo_Release(info);
00083                      }
00084                      if (disp) {
00085                             IDispatch_Release(disp);
00086                      }
00087               }
00088        } else {
00089               /* Try to load it from a file; if it fails, do a really painful search of
00090                * the registry */
00091               if (FAILED(LoadTypeLib(p, &TL))) {
00092                      HKEY hkey, hsubkey;
00093                      DWORD SubKeys, MaxSubKeyLength;
00094                      char *keyname;
00095                      unsigned int i, j;
00096                      DWORD VersionCount;
00097                      char version[20];
00098                      char *libname;
00099                      DWORD libnamelen;
00100 
00101                      if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, "TypeLib", 0, KEY_READ, &hkey) &&
00102                                    ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, NULL, &SubKeys,
00103                                    &MaxSubKeyLength, NULL, NULL, NULL, NULL, NULL, NULL)) {
00104 
00105                             MaxSubKeyLength++; /* make room for NUL */
00106                             keyname = emalloc(MaxSubKeyLength);
00107                             libname = emalloc(strlen(search_string) + 1);
00108 
00109                             for (i = 0; i < SubKeys && TL == NULL; i++) {
00110                                    if (ERROR_SUCCESS == RegEnumKey(hkey, i, keyname, MaxSubKeyLength) &&
00111                                                  ERROR_SUCCESS == RegOpenKeyEx(hkey, keyname, 0, KEY_READ, &hsubkey)) {
00112                                           if (ERROR_SUCCESS == RegQueryInfoKey(hsubkey, NULL, NULL, NULL, &VersionCount,
00113                                                         NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
00114                                                  for (j = 0; j < VersionCount; j++) {
00115                                                         if (ERROR_SUCCESS != RegEnumKey(hsubkey, j, version, sizeof(version))) {
00116                                                                continue;
00117                                                         }
00118                                                         /* get the default value for this key and compare */
00119                                                         libnamelen = strlen(search_string)+1;
00120                                                         if (ERROR_SUCCESS == RegQueryValue(hsubkey, version, libname, &libnamelen)) {
00121                                                                if (0 == stricmp(libname, search_string)) {
00122                                                                       char *str = NULL;
00123                                                                       int major_tmp, minor_tmp;
00124 
00125                                                                       /* fetch the GUID and add the version numbers */
00126                                                                       if (2 != sscanf(version, "%d.%d", &major_tmp, &minor_tmp)) {
00127                                                                              major_tmp = 1;
00128                                                                              minor_tmp = 0;
00129                                                                       }
00130                                                                       spprintf(&str, 0, "%s,%d,%d", keyname, major_tmp, minor_tmp);
00131                                                                       /* recurse */
00132                                                                       TL = php_com_load_typelib(str, codepage TSRMLS_CC);
00133 
00134                                                                       efree(str);
00135                                                                       break;
00136                                                                }
00137                                                         }
00138                                                  }
00139                                           }
00140                                           RegCloseKey(hsubkey);
00141                                    }
00142                             }
00143                             RegCloseKey(hkey);
00144                             efree(keyname);
00145                             efree(libname);
00146                      }
00147               }
00148        }
00149        
00150        efree(p);
00151 
00152        return TL;
00153 }
00154 
00155 /* Given a type-library, merge it into the current engine state */
00156 PHPAPI int php_com_import_typelib(ITypeLib *TL, int mode, int codepage TSRMLS_DC)
00157 {
00158        int i, j, interfaces;
00159        TYPEKIND pTKind;
00160        ITypeInfo *TypeInfo;
00161        VARDESC *pVarDesc;
00162        UINT NameCount;
00163        BSTR bstr_ids;
00164        zend_constant c;
00165        zval exists, results, value;
00166        char *const_name;
00167 
00168        if (TL == NULL) {
00169               return FAILURE;
00170        }
00171 
00172        interfaces = ITypeLib_GetTypeInfoCount(TL);
00173        for (i = 0; i < interfaces; i++) {
00174               ITypeLib_GetTypeInfoType(TL, i, &pTKind);
00175               if (pTKind == TKIND_ENUM) {
00176                      ITypeLib_GetTypeInfo(TL, i, &TypeInfo);
00177                      for (j = 0; ; j++) {
00178                             if (FAILED(ITypeInfo_GetVarDesc(TypeInfo, j, &pVarDesc))) {
00179                                    break;
00180                             }
00181                             ITypeInfo_GetNames(TypeInfo, pVarDesc->memid, &bstr_ids, 1, &NameCount);
00182                             if (NameCount != 1) {
00183                                    ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
00184                                    continue;
00185                             }
00186 
00187                             const_name = php_com_olestring_to_string(bstr_ids, &c.name_len, codepage TSRMLS_CC);
00188                             c.name = zend_strndup(const_name, c.name_len);
00189                             efree(const_name);
00190                             c.name_len++; /* include NUL */
00191                             SysFreeString(bstr_ids);
00192 
00193                             /* sanity check for the case where the constant is already defined */
00194                             if (zend_get_constant(c.name, c.name_len - 1, &exists TSRMLS_CC)) {
00195                                    if (COMG(autoreg_verbose) && !compare_function(&results, &c.value, &exists TSRMLS_CC)) {
00196                                           php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type library constant %s is already defined", c.name);
00197                                    }
00198                                    free(c.name);
00199                                    ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
00200                                    continue;
00201                             }
00202 
00203                             /* register the constant */
00204                             php_com_zval_from_variant(&value, pVarDesc->lpvarValue, codepage TSRMLS_CC);
00205                             if (Z_TYPE(value) == IS_LONG) {
00206                                    c.flags = mode;
00207                                    c.value.type = IS_LONG;
00208                                    c.value.value.lval = Z_LVAL(value);
00209                                    c.module_number = 0;
00210                                    zend_register_constant(&c TSRMLS_CC);
00211                             }
00212                             ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc);
00213                      }
00214                      ITypeInfo_Release(TypeInfo);
00215               }
00216        }
00217        return SUCCESS;
00218 }
00219 
00220 /* Type-library stuff */
00221 void php_com_typelibrary_dtor(void *pDest)
00222 {
00223        ITypeLib **Lib = (ITypeLib**)pDest;
00224        ITypeLib_Release(*Lib);
00225 }
00226 
00227 PHPAPI ITypeLib *php_com_load_typelib_via_cache(char *search_string,
00228        int codepage, int *cached TSRMLS_DC)
00229 {
00230        ITypeLib **TLp;
00231        ITypeLib *TL;
00232        char *name_dup;
00233        int l;
00234 
00235        l = strlen(search_string);
00236 
00237        if (zend_ts_hash_find(&php_com_typelibraries, search_string, l+1,
00238                      (void**)&TLp) == SUCCESS) {
00239               *cached = 1;
00240               /* add a reference for the caller */
00241               ITypeLib_AddRef(*TLp);
00242               return *TLp;
00243        }
00244 
00245        *cached = 0;
00246        name_dup = estrndup(search_string, l);
00247        TL = php_com_load_typelib(name_dup, codepage TSRMLS_CC);
00248        efree(name_dup);
00249 
00250        if (TL) {
00251               if (SUCCESS == zend_ts_hash_update(&php_com_typelibraries,
00252                             search_string, l+1, (void*)&TL, sizeof(ITypeLib*), NULL)) {
00253                      /* add a reference for the hash table */
00254                      ITypeLib_AddRef(TL);
00255               }
00256        }
00257 
00258        return TL;
00259 }
00260 
00261 ITypeInfo *php_com_locate_typeinfo(char *typelibname, php_com_dotnet_object *obj, char *dispname, int sink TSRMLS_DC)
00262 {
00263        ITypeInfo *typeinfo = NULL;
00264        ITypeLib *typelib = NULL;
00265        int gotguid = 0;
00266        GUID iid;
00267        
00268        if (obj) {
00269               if (dispname == NULL && sink) {
00270                      IProvideClassInfo2 *pci2;
00271                      IProvideClassInfo *pci;
00272 
00273                      if (SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo2, (void**)&pci2))) {
00274                             gotguid = SUCCEEDED(IProvideClassInfo2_GetGUID(pci2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid));
00275                             IProvideClassInfo2_Release(pci2);
00276                      }
00277                      if (!gotguid && SUCCEEDED(IDispatch_QueryInterface(V_DISPATCH(&obj->v), &IID_IProvideClassInfo, (void**)&pci))) {
00278                             /* examine the available interfaces */
00279                             /* TODO: write some code here */
00280                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "IProvideClassInfo: this code not yet written!");
00281                             IProvideClassInfo_Release(pci);
00282                      }
00283               } else if (dispname == NULL) {
00284                      if (obj->typeinfo) {
00285                             ITypeInfo_AddRef(obj->typeinfo);
00286                             return obj->typeinfo;
00287                      } else {
00288                             IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
00289                             if (typeinfo) {
00290                                    return typeinfo;
00291                             }
00292                      }
00293               } else if (dispname && obj->typeinfo) {
00294                      unsigned int idx;
00295                      /* get the library from the object; the rest will be dealt with later */
00296                      ITypeInfo_GetContainingTypeLib(obj->typeinfo, &typelib, &idx);
00297               } else if (typelibname == NULL) {
00298                      IDispatch_GetTypeInfo(V_DISPATCH(&obj->v), 0, LANG_NEUTRAL, &typeinfo);
00299                      if (dispname) {
00300                             unsigned int idx;
00301                             /* get the library from the object; the rest will be dealt with later */
00302                             ITypeInfo_GetContainingTypeLib(typeinfo, &typelib, &idx);
00303 
00304                             if (typelib) {
00305                                    ITypeInfo_Release(typeinfo);
00306                                    typeinfo = NULL;
00307                             }
00308                      }
00309               }
00310        } else if (typelibname) {
00311               /* Fetch the typelibrary and use that to look things up */
00312               typelib = php_com_load_typelib(typelibname, CP_THREAD_ACP TSRMLS_CC);
00313        } 
00314 
00315        if (!gotguid && dispname && typelib) {
00316               unsigned short cfound;
00317               MEMBERID memid;
00318               OLECHAR *olename = php_com_string_to_olestring(dispname, strlen(dispname), CP_ACP TSRMLS_CC);
00319                      
00320               cfound = 1;
00321               if (FAILED(ITypeLib_FindName(typelib, olename, 0, &typeinfo, &memid, &cfound)) || cfound == 0) {
00322                      CLSID coclass;
00323                      ITypeInfo *coinfo;
00324        
00325                      /* assume that it might be a progid instead */
00326                      if (SUCCEEDED(CLSIDFromProgID(olename, &coclass)) &&
00327                                    SUCCEEDED(ITypeLib_GetTypeInfoOfGuid(typelib, &coclass, &coinfo))) {
00328 
00329                             /* enumerate implemented interfaces and pick the one as indicated by sink */
00330                             TYPEATTR *attr;
00331                             int i;
00332 
00333                             ITypeInfo_GetTypeAttr(coinfo, &attr);
00334 
00335                             for (i = 0; i < attr->cImplTypes; i++) {
00336                                    HREFTYPE rt;
00337                                    int tf;
00338 
00339                                    if (FAILED(ITypeInfo_GetImplTypeFlags(coinfo, i, &tf))) {
00340                                           continue;
00341                                    }
00342 
00343                                    if ((sink && tf == (IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT)) ||
00344                                           (!sink && (tf & IMPLTYPEFLAG_FSOURCE) == 0)) {
00345 
00346                                           /* flags match what we are looking for */
00347 
00348                                           if (SUCCEEDED(ITypeInfo_GetRefTypeOfImplType(coinfo, i, &rt)))
00349                                                  if (SUCCEEDED(ITypeInfo_GetRefTypeInfo(coinfo, rt, &typeinfo)))
00350                                                         break;
00351                                           
00352                                    }
00353                             }
00354                             
00355                             ITypeInfo_ReleaseTypeAttr(coinfo, attr);
00356                             ITypeInfo_Release(coinfo);
00357                      }
00358               }
00359 
00360               
00361               efree(olename);
00362        } else if (gotguid) {
00363               ITypeLib_GetTypeInfoOfGuid(typelib, &iid, &typeinfo);
00364        }
00365 
00366        if (typelib) {
00367               ITypeLib_Release(typelib);
00368        }
00369 
00370        return typeinfo;
00371 }
00372 
00373 static const struct {
00374        VARTYPE vt;
00375        const char *name;
00376 } vt_names[] = {
00377        { VT_NULL,           "VT_NULL" },
00378        { VT_EMPTY,          "VT_EMPTY" },
00379        { VT_UI1,            "VT_UI1" },
00380        { VT_I2,             "VT_I2" },
00381        { VT_I4,             "VT_I4" },
00382        { VT_R4,             "VT_R4" },
00383        { VT_R8,             "VT_R8" },
00384        { VT_BOOL,           "VT_BOOL" },
00385        { VT_ERROR,          "VT_ERROR" },
00386        { VT_CY,             "VT_CY" },
00387        { VT_DATE,           "VT_DATE" },
00388        { VT_BSTR,           "VT_BSTR" },
00389        { VT_DECIMAL, "VT_DECIMAL" },
00390        { VT_UNKNOWN, "VT_UNKNOWN" },
00391        { VT_DISPATCH,       "VT_DISPATCH" },
00392        { VT_VARIANT, "VT_VARIANT" },
00393        { VT_I1,             "VT_I1" },
00394        { VT_UI2,            "VT_UI2" },
00395        { VT_UI4,            "VT_UI4" },
00396        { VT_INT,            "VT_INT" },
00397        { VT_UINT,           "VT_UINT" },
00398        { VT_ARRAY,          "VT_ARRAY" },
00399        { VT_BYREF,          "VT_BYREF" },
00400        { VT_VOID,           "VT_VOID" },
00401        { VT_PTR,            "VT_PTR" },
00402        { VT_HRESULT, "VT_HRESULT" },
00403        { VT_SAFEARRAY, "VT_SAFEARRAY" },
00404        { 0, NULL }
00405 };
00406 
00407 static inline const char *vt_to_string(VARTYPE vt)
00408 {
00409        int i;
00410        for (i = 0; vt_names[i].name != NULL; i++) {
00411               if (vt_names[i].vt == vt)
00412                      return vt_names[i].name;
00413        }
00414        return "?";
00415 }
00416 
00417 static char *php_com_string_from_clsid(const CLSID *clsid, int codepage TSRMLS_DC)
00418 {
00419        LPOLESTR ole_clsid;
00420        char *clsid_str;
00421 
00422        StringFromCLSID(clsid, &ole_clsid);
00423        clsid_str = php_com_olestring_to_string(ole_clsid, NULL, codepage TSRMLS_CC);
00424        LocalFree(ole_clsid);
00425 
00426        return clsid_str;
00427 }
00428 
00429 
00430 int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid, int codepage TSRMLS_DC)
00431 {
00432        TYPEATTR *attr;
00433        FUNCDESC *func;
00434        int i;
00435        OLECHAR *olename;
00436        char *ansiname = NULL;
00437        unsigned int ansinamelen;
00438        int ret = 0;
00439 
00440        if (FAILED(ITypeInfo_GetTypeAttr(typeinfo, &attr))) {
00441               return 0;
00442        }
00443 
00444        /* verify that it is suitable */
00445        if (id_to_name == NULL || attr->typekind == TKIND_DISPATCH) {
00446 
00447               if (guid) {
00448                      memcpy(guid, &attr->guid, sizeof(GUID));
00449               }
00450               
00451               if (printdef) {
00452                      char *guidstring;
00453 
00454                      ITypeInfo_GetDocumentation(typeinfo, MEMBERID_NIL, &olename, NULL, NULL, NULL);
00455                      ansiname = php_com_olestring_to_string(olename, &ansinamelen, codepage TSRMLS_CC);
00456                      SysFreeString(olename);
00457 
00458                      guidstring = php_com_string_from_clsid(&attr->guid, codepage TSRMLS_CC);
00459                      php_printf("class %s { /* GUID=%s */\n", ansiname, guidstring);
00460                      efree(guidstring);
00461 
00462                      efree(ansiname);
00463               }
00464 
00465               if (id_to_name) {
00466                      zend_hash_init(id_to_name, 0, NULL, ZVAL_PTR_DTOR, 0);
00467               }
00468 
00469               /* So we've got the dispatch interface; lets list the event methods */
00470               for (i = 0; i < attr->cFuncs; i++) {
00471                      zval *tmp;
00472                      DISPID lastid = 0;   /* for props */
00473                      int isprop;
00474 
00475                      if (FAILED(ITypeInfo_GetFuncDesc(typeinfo, i, &func)))
00476                             break;
00477 
00478                      isprop = (func->invkind & DISPATCH_PROPERTYGET || func->invkind & DISPATCH_PROPERTYPUT);
00479 
00480                      if (!isprop || lastid != func->memid) {
00481 
00482                             lastid = func->memid;
00483                             
00484                             ITypeInfo_GetDocumentation(typeinfo, func->memid, &olename, NULL, NULL, NULL);
00485                             ansiname = php_com_olestring_to_string(olename, &ansinamelen, codepage TSRMLS_CC);
00486                             SysFreeString(olename);
00487 
00488                             if (printdef) {
00489                                    int j;
00490                                    char *funcdesc;
00491                                    unsigned int funcdesclen, cnames = 0;
00492                                    BSTR *names;
00493 
00494                                    names = (BSTR*)safe_emalloc((func->cParams + 1), sizeof(BSTR), 0);
00495 
00496                                    ITypeInfo_GetNames(typeinfo, func->memid, names, func->cParams + 1, &cnames);
00497                                    /* first element is the function name */
00498                                    SysFreeString(names[0]);
00499 
00500                                    php_printf("\t/* DISPID=%d */\n", func->memid);
00501 
00502                                    if (func->elemdescFunc.tdesc.vt != VT_VOID) {
00503                                           php_printf("\t/* %s [%d] */\n",
00504                                                         vt_to_string(func->elemdescFunc.tdesc.vt),
00505                                                         func->elemdescFunc.tdesc.vt
00506                                                         );
00507                                    }
00508 
00509                                    if (isprop) {
00510 
00511                                           ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
00512                                           if (olename) {
00513                                                  funcdesc = php_com_olestring_to_string(olename, &funcdesclen, codepage TSRMLS_CC);
00514                                                  SysFreeString(olename);
00515                                                  php_printf("\t/* %s */\n", funcdesc);
00516                                                  efree(funcdesc);
00517                                           }
00518 
00519                                           php_printf("\tvar $%s;\n\n", ansiname);
00520 
00521                                    } else {
00522                                           /* a function */
00523 
00524                                           php_printf("\tfunction %s(\n", ansiname);
00525 
00526                                           for (j = 0; j < func->cParams; j++) {
00527                                                  ELEMDESC *elem = &func->lprgelemdescParam[j];
00528 
00529                                                  php_printf("\t\t/* %s [%d] ", vt_to_string(elem->tdesc.vt), elem->tdesc.vt);
00530 
00531                                                  if (elem->paramdesc.wParamFlags & PARAMFLAG_FIN)
00532                                                         php_printf("[in]");
00533                                                  if (elem->paramdesc.wParamFlags & PARAMFLAG_FOUT)
00534                                                         php_printf("[out]");
00535 
00536                                                  if (elem->tdesc.vt == VT_PTR) {
00537                                                         /* what does it point to ? */
00538                                                         php_printf(" --> %s [%d] ",
00539                                                                       vt_to_string(elem->tdesc.lptdesc->vt),
00540                                                                       elem->tdesc.lptdesc->vt
00541                                                                       );
00542                                                  }
00543 
00544                                                  /* when we handle prop put and get, this will look nicer */
00545                                                  if (j+1 < (int)cnames) {
00546                                                         funcdesc = php_com_olestring_to_string(names[j+1], &funcdesclen, codepage TSRMLS_CC);
00547                                                         SysFreeString(names[j+1]);
00548                                                  } else {
00549                                                         funcdesc = "???";
00550                                                  }
00551 
00552                                                  php_printf(" */ %s%s%c\n",
00553                                                                elem->tdesc.vt == VT_PTR ? "&$" : "$",
00554                                                                funcdesc,
00555                                                                j == func->cParams - 1 ? ' ' : ','
00556                                                                );
00557 
00558                                                  if (j+1 < (int)cnames) {
00559                                                         efree(funcdesc);
00560                                                  }
00561                                           }
00562 
00563                                           php_printf("\t\t)\n\t{\n");
00564 
00565                                           ITypeInfo_GetDocumentation(typeinfo, func->memid, NULL, &olename, NULL, NULL);
00566                                           if (olename) {
00567                                                  funcdesc = php_com_olestring_to_string(olename, &funcdesclen, codepage TSRMLS_CC);
00568                                                  SysFreeString(olename);
00569                                                  php_printf("\t\t/* %s */\n", funcdesc);
00570                                                  efree(funcdesc);
00571                                           }
00572 
00573                                           php_printf("\t}\n");
00574                                    }
00575 
00576                                    efree(names);
00577                             }
00578 
00579                             if (id_to_name) {
00580                                    zend_str_tolower(ansiname, ansinamelen);
00581                                    MAKE_STD_ZVAL(tmp);
00582                                    ZVAL_STRINGL(tmp, ansiname, ansinamelen, 0);
00583                                    zend_hash_index_update(id_to_name, func->memid, (void*)&tmp, sizeof(zval *), NULL);
00584                             }
00585                      }
00586                      ITypeInfo_ReleaseFuncDesc(typeinfo, func);
00587               }
00588 
00589               if (printdef) {
00590                      php_printf("}\n");
00591               }
00592 
00593               ret = 1;
00594        } else {
00595               zend_error(E_WARNING, "That's not a dispatchable interface!! type kind = %08x", attr->typekind);
00596        }
00597 
00598        ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
00599 
00600        return ret;
00601 }
00602 
00603