static void test_type_info(void) { LPVOID pvObj = NULL; HRESULT hres; IFontDisp* fontdisp = NULL; ITypeInfo* pTInfo; WCHAR name_Name[] = {'N','a','m','e',0}; BSTR names[3]; UINT n; LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US), SORT_DEFAULT); DISPPARAMS dispparams; VARIANT varresult; pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj); fontdisp = pvObj; hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo); ok(hres == S_OK, "GTI returned 0x%08x instead of S_OK.\n", hres); ok(pTInfo != NULL, "GTI returned NULL.\n"); hres = ITypeInfo_GetNames(pTInfo, DISPID_FONT_NAME, names, 3, &n); ok(hres == S_OK, "GetNames returned 0x%08x instead of S_OK.\n", hres); ok(n == 1, "GetNames returned %d names instead of 1.\n", n); ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n"); SysFreeString(names[0]); ITypeInfo_Release(pTInfo); dispparams.cNamedArgs = 0; dispparams.rgdispidNamedArgs = NULL; dispparams.cArgs = 0; dispparams.rgvarg = NULL; VariantInit(&varresult); hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL); ok(hres == S_OK, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres); VariantClear(&varresult); IFontDisp_Release(fontdisp); }
/* Given a type-library, merge it into the current engine state */ PHP_COM_DOTNET_API 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; int len; 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, &len, codepage TSRMLS_CC); c.name = STR_INIT(const_name, len, 1); // TODO: avoid reallocation??? efree(const_name); if(c.name == NULL) { ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); continue; } //??? c.name_len++; /* include NUL */ SysFreeString(bstr_ids); /* sanity check for the case where the constant is already defined */ if ((exists = zend_get_constant(c.name TSRMLS_CC)) != NULL) { 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); } STR_RELEASE(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_INT) { c.flags = mode; ZVAL_INT(&c.value, Z_IVAL(value)); c.module_number = 0; zend_register_constant(&c TSRMLS_CC); } ITypeInfo_ReleaseVarDesc(TypeInfo, pVarDesc); } ITypeInfo_Release(TypeInfo); } } return SUCCESS; }
static void test_dump_typelib(const char *name) { WCHAR wszString[260]; ITypeInfo *info; ITypeLib *lib; int count; int i; MultiByteToWideChar(CP_ACP, 0, name, -1, wszString, 260); OLE_CHECK(LoadTypeLib(wszString, &lib)); count = ITypeLib_GetTypeInfoCount(lib); printf("/* interfaces count: %d */\n", count); for (i = 0; i < count; i++) { TYPEATTR *attr; BSTR name; int f = 0; OLE_CHECK(ITypeLib_GetDocumentation(lib, i, &name, NULL, NULL, NULL)); printf("{\n" " %s,\n", dump_string(name)); SysFreeString(name); OLE_CHECK(ITypeLib_GetTypeInfo(lib, i, &info)); ITypeInfo_GetTypeAttr(info, &attr); printf(" /*kind*/ %s, /*flags*/ 0x%x, /*align*/ %d, /*size*/ %d,\n" " /*#vtbl*/ %d, /*#func*/ %d,\n" " {\n", map_value(attr->typekind, tkind_map), attr->wTypeFlags, attr->cbAlignment, attr->cbSizeInstance, attr->cbSizeVft, attr->cFuncs); ITypeInfo_ReleaseTypeAttr(info, attr); while (1) { FUNCDESC *desc; BSTR tab[256]; UINT cNames; int p; if (FAILED(ITypeInfo_GetFuncDesc(info, f, &desc))) break; printf(" {\n" " 0x%x, /*func*/ %s, /*inv*/ %s, /*call*/ 0x%x,\n", desc->memid, map_value(desc->funckind, funckind_map), map_value(desc->invkind, invkind_map), desc->callconv); printf(" /*#param*/ %d, /*#opt*/ %d, /*vtbl*/ %d, /*#scodes*/ %d, /*flags*/ 0x%x,\n", desc->cParams, desc->cParamsOpt, desc->oVft, desc->cScodes, desc->wFuncFlags); printf(" {%d, %x}, /* ret */\n", desc->elemdescFunc.tdesc.vt, desc->elemdescFunc.paramdesc.wParamFlags); printf(" { /* params */\n"); for (p = 0; p < desc->cParams; p++) { ELEMDESC e = desc->lprgelemdescParam[p]; printf(" {%d, %x},\n", e.tdesc.vt, e.paramdesc.wParamFlags); } printf(" {-1, -1}\n"); printf(" },\n"); printf(" { /* names */\n"); OLE_CHECK(ITypeInfo_GetNames(info, desc->memid, tab, 256, &cNames)); for (p = 0; p < cNames; p++) { printf(" %s,\n", dump_string(tab[p])); SysFreeString(tab[p]); } printf(" NULL,\n"); printf(" },\n"); printf(" },\n"); ITypeInfo_ReleaseFuncDesc(info, desc); f++; } printf(" }\n"); printf("},\n"); ITypeInfo_Release(info); } ITypeLib_Release(lib); }
static void test_dump_typelib(const char *name) { WCHAR wszName[MAX_PATH]; ITypeLib *typelib; int ifcount = sizeof(info)/sizeof(info[0]); int iface, func; MultiByteToWideChar(CP_UTF8, 0, name, -1, wszName, MAX_PATH); ole_check(LoadTypeLibEx(wszName, REGKIND_NONE, &typelib)); expect_eq(ITypeLib_GetTypeInfoCount(typelib), ifcount, UINT, "%d"); for (iface = 0; iface < ifcount; iface++) { const interface_info *if_info = &info[iface]; ITypeInfo *typeinfo; TYPEATTR *typeattr; BSTR bstrIfName; trace("Interface %s\n", if_info->name); ole_check(ITypeLib_GetTypeInfo(typelib, iface, &typeinfo)); ole_check(ITypeLib_GetDocumentation(typelib, iface, &bstrIfName, NULL, NULL, NULL)); expect_wstr_utf8val(bstrIfName, if_info->name); SysFreeString(bstrIfName); ole_check(ITypeInfo_GetTypeAttr(typeinfo, &typeattr)); expect_int(typeattr->typekind, if_info->type); expect_hex(typeattr->wTypeFlags, if_info->wTypeFlags); expect_int(typeattr->cbAlignment, if_info->cbAlignment); expect_int(typeattr->cbSizeInstance, if_info->cbSizeInstance); expect_int(typeattr->cbSizeVft, if_info->cbSizeVft); expect_int(typeattr->cFuncs, if_info->cFuncs); for (func = 0; func < typeattr->cFuncs; func++) { function_info *fn_info = (function_info *)&if_info->funcs[func]; FUNCDESC *desc; BSTR namesTab[256]; UINT cNames; int i; trace("Function %s\n", fn_info->names[0]); ole_check(ITypeInfo_GetFuncDesc(typeinfo, func, &desc)); expect_int(desc->memid, fn_info->memid); expect_int(desc->funckind, fn_info->funckind); expect_int(desc->invkind, fn_info->invkind); expect_int(desc->callconv, fn_info->callconv); expect_int(desc->cParams, fn_info->cParams); expect_int(desc->cParamsOpt, fn_info->cParamsOpt); expect_int(desc->oVft, fn_info->oVft); expect_int(desc->cScodes, fn_info->cScodes); expect_int(desc->wFuncFlags, fn_info->wFuncFlags); ole_check(ITypeInfo_GetNames(typeinfo, desc->memid, namesTab, 256, &cNames)); for (i = 0; i < cNames; i++) { expect_wstr_utf8val(namesTab[i], fn_info->names[i]); SysFreeString(namesTab[i]); } expect_null(fn_info->names[cNames]); check_type(&desc->elemdescFunc, &fn_info->ret_type); for (i = 0 ; i < desc->cParams; i++) { check_type(&desc->lprgelemdescParam[i], &fn_info->params[i]); } expect_int(fn_info->params[desc->cParams].vt, (VARTYPE)-1); ITypeInfo_ReleaseFuncDesc(typeinfo, desc); } ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr); ITypeInfo_Release(typeinfo); } ITypeLib_Release(typelib); }
int php_com_process_typeinfo(ITypeInfo *typeinfo, HashTable *id_to_name, int printdef, GUID *guid, int codepage) { TYPEATTR *attr; FUNCDESC *func; int i; OLECHAR *olename; char *ansiname = NULL; size_t 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); SysFreeString(olename); guidstring = php_com_string_from_clsid(&attr->guid, codepage); 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); SysFreeString(olename); if (printdef) { int j; char *funcdesc; size_t funcdesclen; unsigned int 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); 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); 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); 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); ZVAL_STRINGL(&tmp, ansiname, ansinamelen); zend_hash_index_update(id_to_name, func->memid, &tmp); // TODO: avoid reallocation??? efree(ansiname); } } 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; }