static dispex_data_t *preprocess_dispex_data(DispatchEx *This) { const tid_t *tid = This->data->iface_tids; FUNCDESC *funcdesc; dispex_data_t *data; DWORD size = 16, i; ITypeInfo *ti, *dti; HRESULT hres; TRACE("(%p)\n", This); hres = get_typeinfo(This->data->disp_tid, &dti); if(FAILED(hres)) { ERR("Could not get disp type info: %08x\n", hres); return NULL; } data = heap_alloc(sizeof(dispex_data_t)); data->func_cnt = 0; data->funcs = heap_alloc(size*sizeof(func_info_t)); list_add_tail(&dispex_data_list, &data->entry); while(*tid) { hres = get_typeinfo(*tid, &ti); if(FAILED(hres)) break; i=7; while(1) { hres = ITypeInfo_GetFuncDesc(ti, i++, &funcdesc); if(FAILED(hres)) break; add_func_info(data, &size, *tid, funcdesc->memid, dti); ITypeInfo_ReleaseFuncDesc(ti, funcdesc); } tid++; } if(!data->func_cnt) { heap_free(data->funcs); data->funcs = NULL; }else if(data->func_cnt != size) { data->funcs = heap_realloc(data->funcs, data->func_cnt * sizeof(func_info_t)); } qsort(data->funcs, data->func_cnt, sizeof(func_info_t), dispid_cmp); if(data->funcs) { data->name_table = heap_alloc(data->func_cnt * sizeof(func_info_t*)); for(i=0; i < data->func_cnt; i++) data->name_table[i] = data->funcs+i; qsort(data->name_table, data->func_cnt, sizeof(func_info_t*), func_name_cmp); }else { data->name_table = NULL; } return data; }
HRESULT get_dispids(tid_t tid, DWORD *ret_size, DISPID **ret) { unsigned i, func_cnt; FUNCDESC *funcdesc; ITypeInfo *ti; TYPEATTR *attr; DISPID *ids; HRESULT hres; hres = get_typeinfo(tid, &ti); if(FAILED(hres)) return hres; hres = ITypeInfo_GetTypeAttr(ti, &attr); if(FAILED(hres)) { ITypeInfo_Release(ti); return hres; } func_cnt = attr->cFuncs; ITypeInfo_ReleaseTypeAttr(ti, attr); ids = heap_alloc(func_cnt*sizeof(DISPID)); if(!ids) { ITypeInfo_Release(ti); return E_OUTOFMEMORY; } for(i=0; i < func_cnt; i++) { hres = ITypeInfo_GetFuncDesc(ti, i, &funcdesc); if(FAILED(hres)) break; ids[i] = funcdesc->memid; ITypeInfo_ReleaseFuncDesc(ti, funcdesc); } ITypeInfo_Release(ti); if(FAILED(hres)) { heap_free(ids); return hres; } qsort(ids, func_cnt, sizeof(DISPID), id_cmp); *ret_size = func_cnt; *ret = ids; return S_OK; }
HRESULT __RPC_STUB ITypeInfo_GetFuncDesc_Stub( ITypeInfo* This, UINT index, LPFUNCDESC* ppFuncDesc, CLEANLOCALSTORAGE* pDummy) { HRESULT hr; TRACE("(%p, %d, %p)\n", This, index, ppFuncDesc); hr = ITypeInfo_GetFuncDesc(This, index, ppFuncDesc); if(hr != S_OK) return hr; pDummy->flags = CLS_FUNCDESC; ITypeInfo_AddRef(This); pDummy->pInterface = (IUnknown*)This; pDummy->pStorage = ppFuncDesc; return hr; }
static HRESULT process_interface(dispex_data_t *data, tid_t tid, ITypeInfo *disp_typeinfo, DWORD *size) { unsigned i = 7; /* skip IDispatch functions */ ITypeInfo *typeinfo; FUNCDESC *funcdesc; HRESULT hres; hres = get_typeinfo(tid, &typeinfo); if(FAILED(hres)) return hres; while(1) { hres = ITypeInfo_GetFuncDesc(typeinfo, i++, &funcdesc); if(FAILED(hres)) break; TRACE("adding...\n"); add_func_info(data, size, tid, funcdesc, disp_typeinfo ? disp_typeinfo : typeinfo); ITypeInfo_ReleaseFuncDesc(typeinfo, funcdesc); } return S_OK; }
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_inheritance(void) { HRESULT hr; ITypeLib *pTL; ITypeInfo *pTI, *pTI_p; TYPEATTR *pTA; HREFTYPE href; FUNCDESC *pFD; WCHAR path[MAX_PATH]; static const WCHAR tl_path[] = {'.','\\','m','i','d','l','_','t','m','a','r','s','h','a','l','.','t','l','b',0}; BOOL use_midl_tlb = 0; GetModuleFileNameW(NULL, path, MAX_PATH); if(use_midl_tlb) memcpy(path, tl_path, sizeof(tl_path)); hr = LoadTypeLib(path, &pTL); if(FAILED(hr)) return; /* ItestIF3 is a syntax 2 dispinterface */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF3, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags); if(use_midl_tlb) { ok(pTA->cFuncs == 6, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); /* Should have six methods */ hr = ITypeInfo_GetFuncDesc(pTI, 6, &pFD); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetFuncDesc(pTI, 5, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid); ok(pFD->oVft == 20, "oVft %d\n", pFD->oVft); ITypeInfo_ReleaseFuncDesc(pTI, pFD); } ITypeInfo_Release(pTI); /* ItestIF4 is a syntax 1 dispinterface */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF4, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags); ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); hr = ITypeInfo_GetFuncDesc(pTI, 1, &pFD); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetFuncDesc(pTI, 0, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x1c, "memid %08x\n", pFD->memid); ITypeInfo_ReleaseFuncDesc(pTI, pFD); ITypeInfo_Release(pTI); /* ItestIF5 is dual with inherited ifaces which derive from IUnknown but not IDispatch */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF5, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); if(use_midl_tlb) { ok(pTA->wTypeFlags == TYPEFLAG_FDUAL, "typeflags %x\n", pTA->wTypeFlags); } ok(pTA->cFuncs == 8, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); if(use_midl_tlb) { hr = ITypeInfo_GetFuncDesc(pTI, 6, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x1234, "memid %08x\n", pFD->memid); ITypeInfo_ReleaseFuncDesc(pTI, pFD); } ITypeInfo_Release(pTI); /* ItestIF7 is dual with inherited ifaces which derive from Dispatch */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF7, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL), "typeflags %x\n", pTA->wTypeFlags); ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); hr = ITypeInfo_GetFuncDesc(pTI, 9, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x1236, "memid %08x\n", pFD->memid); ITypeInfo_ReleaseFuncDesc(pTI, pFD); ITypeInfo_Release(pTI); /* ItestIF10 is a syntax 2 dispinterface which doesn't derive from IUnknown */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF10, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags); if(use_midl_tlb) { ok(pTA->cFuncs == 3, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, -1, &href); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); /* Should have three methods */ hr = ITypeInfo_GetFuncDesc(pTI, 3, &pFD); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetFuncDesc(pTI, 2, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x60010000, "memid %08x\n", pFD->memid); ok(pFD->oVft == 8, "oVft %d\n", pFD->oVft); ITypeInfo_ReleaseFuncDesc(pTI, pFD); } ITypeInfo_Release(pTI); /* ItestIF11 is a syntax 2 dispinterface which derives from IDispatch */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF11, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags); if(use_midl_tlb) { ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA); ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1); ITypeInfo_ReleaseTypeAttr(pTI_p, pTA); ITypeInfo_Release(pTI_p); /* Should have ten methods */ hr = ITypeInfo_GetFuncDesc(pTI, 10, &pFD); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetFuncDesc(pTI, 9, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x1236, "memid %08x\n", pFD->memid); ok(pFD->oVft == 36, "oVft %d\n", pFD->oVft); ITypeInfo_ReleaseFuncDesc(pTI, pFD); } ITypeInfo_Release(pTI); /* ItestIF2 is an interface which derives from IUnknown */ hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF2, &pTI); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI, &pTA); ok(hr == S_OK, "hr %08x\n", hr); ok(pTA->typekind == TKIND_INTERFACE, "kind %04x\n", pTA->typekind); ok(pTA->cbSizeVft == 24, "sizevft %d\n", pTA->cbSizeVft); ok(pTA->wTypeFlags == 0, "typeflags %x\n", pTA->wTypeFlags); if(use_midl_tlb) { ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs); ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes); ITypeInfo_ReleaseTypeAttr(pTI, pTA); /* Should have one method */ hr = ITypeInfo_GetFuncDesc(pTI, 1, &pFD); ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr); hr = ITypeInfo_GetFuncDesc(pTI, 0, &pFD); ok(hr == S_OK, "hr %08x\n", hr); ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid); ok(pFD->oVft == 20, "oVft %d\n", pFD->oVft); ITypeInfo_ReleaseFuncDesc(pTI, pFD); } ITypeInfo_Release(pTI); ITypeLib_Release(pTL); return; }
static void test_CreateDispTypeInfo(void) { ITypeInfo *pTypeInfo, *pTI2; HRESULT hr; INTERFACEDATA ifdata; METHODDATA methdata[4]; PARAMDATA parms1[2]; PARAMDATA parms3[1]; TYPEATTR *pTypeAttr; HREFTYPE href; FUNCDESC *pFuncDesc; MEMBERID memid; static WCHAR func1[] = {'f','u','n','c','1',0}; static const WCHAR func2[] = {'f','u','n','c','2',0}; static const WCHAR func3[] = {'f','u','n','c','3',0}; static const WCHAR parm1[] = {'p','a','r','m','1',0}; static const WCHAR parm2[] = {'p','a','r','m','2',0}; OLECHAR *name = func1; ifdata.pmethdata = methdata; ifdata.cMembers = sizeof(methdata) / sizeof(methdata[0]); methdata[0].szName = SysAllocString(func1); methdata[0].ppdata = parms1; methdata[0].dispid = 0x123; methdata[0].iMeth = 0; methdata[0].cc = CC_STDCALL; methdata[0].cArgs = 2; methdata[0].wFlags = DISPATCH_METHOD; methdata[0].vtReturn = VT_HRESULT; parms1[0].szName = SysAllocString(parm1); parms1[0].vt = VT_I4; parms1[1].szName = SysAllocString(parm2); parms1[1].vt = VT_BSTR; methdata[1].szName = SysAllocString(func2); methdata[1].ppdata = NULL; methdata[1].dispid = 0x124; methdata[1].iMeth = 1; methdata[1].cc = CC_STDCALL; methdata[1].cArgs = 0; methdata[1].wFlags = DISPATCH_PROPERTYGET; methdata[1].vtReturn = VT_I4; methdata[2].szName = SysAllocString(func3); methdata[2].ppdata = parms3; methdata[2].dispid = 0x125; methdata[2].iMeth = 3; methdata[2].cc = CC_STDCALL; methdata[2].cArgs = 1; methdata[2].wFlags = DISPATCH_PROPERTYPUT; methdata[2].vtReturn = VT_HRESULT; parms3[0].szName = SysAllocString(parm1); parms3[0].vt = VT_I4; methdata[3].szName = SysAllocString(func3); methdata[3].ppdata = NULL; methdata[3].dispid = 0x125; methdata[3].iMeth = 4; methdata[3].cc = CC_STDCALL; methdata[3].cArgs = 0; methdata[3].wFlags = DISPATCH_PROPERTYGET; methdata[3].vtReturn = VT_I4; hr = CreateDispTypeInfo(&ifdata, LOCALE_NEUTRAL, &pTypeInfo); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr); ok(hr == S_OK, "hr %08x\n", hr); ok(pTypeAttr->typekind == TKIND_COCLASS, "typekind %0x\n", pTypeAttr->typekind); ok(pTypeAttr->cImplTypes == 1, "cImplTypes %d\n", pTypeAttr->cImplTypes); ok(pTypeAttr->cFuncs == 0, "cFuncs %d\n", pTypeAttr->cFuncs); ok(pTypeAttr->wTypeFlags == 0, "wTypeFlags %04x\n", pTypeAttr->cFuncs); ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr); hr = ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &href); ok(hr == S_OK, "hr %08x\n", hr); ok(href == 0, "href = 0x%x\n", href); hr = ITypeInfo_GetRefTypeInfo(pTypeInfo, href, &pTI2); ok(hr == S_OK, "hr %08x\n", hr); hr = ITypeInfo_GetTypeAttr(pTI2, &pTypeAttr); ok(hr == S_OK, "hr %08x\n", hr); ok(pTypeAttr->typekind == TKIND_INTERFACE, "typekind %0x\n", pTypeAttr->typekind); ok(pTypeAttr->cFuncs == 4, "cFuncs %d\n", pTypeAttr->cFuncs); ok(IsEqualGUID(&pTypeAttr->guid, &GUID_NULL), "guid {%08x-...}\n", pTypeAttr->guid.Data1); ok(pTypeAttr->wTypeFlags == 0, "typeflags %08x\n", pTypeAttr->wTypeFlags); ITypeInfo_ReleaseTypeAttr(pTI2, pTypeAttr); hr = ITypeInfo_GetFuncDesc(pTI2, 0, &pFuncDesc); ok(hr == S_OK, "hr %08x\n", hr); ok(pFuncDesc->memid == 0x123, "memid %x\n", pFuncDesc->memid); ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind); ok(pFuncDesc->invkind == methdata[0].wFlags, "invkind %d\n", pFuncDesc->invkind); ok(pFuncDesc->callconv == methdata[0].cc, "callconv %d\n", pFuncDesc->callconv); ok(pFuncDesc->cParams == methdata[0].cArgs, "cParams %d\n", pFuncDesc->cParams); ok(pFuncDesc->oVft == 0, "oVft %d\n", pFuncDesc->oVft); ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags); ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt); ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt); ok(U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags); ok(pFuncDesc->lprgelemdescParam[1].tdesc.vt == VT_BSTR, "parm 1 vt %x\n", pFuncDesc->lprgelemdescParam[1].tdesc.vt); ok(U(pFuncDesc->lprgelemdescParam[1]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 1 flags %x\n", U(pFuncDesc->lprgelemdescParam[1]).paramdesc.wParamFlags); ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc); hr = ITypeInfo_GetFuncDesc(pTI2, 1, &pFuncDesc); ok(hr == S_OK, "hr %08x\n", hr); ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind); ok(pFuncDesc->invkind == methdata[1].wFlags, "invkind %d\n", pFuncDesc->invkind); ok(pFuncDesc->callconv == methdata[1].cc, "callconv %d\n", pFuncDesc->callconv); ok(pFuncDesc->cParams == methdata[1].cArgs, "cParams %d\n", pFuncDesc->cParams); ok(pFuncDesc->oVft == 4, "oVft %d\n", pFuncDesc->oVft); ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags); ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt); ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc); hr = ITypeInfo_GetFuncDesc(pTI2, 2, &pFuncDesc); ok(hr == S_OK, "hr %08x\n", hr); ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind); ok(pFuncDesc->invkind == methdata[2].wFlags, "invkind %d\n", pFuncDesc->invkind); ok(pFuncDesc->callconv == methdata[2].cc, "callconv %d\n", pFuncDesc->callconv); ok(pFuncDesc->cParams == methdata[2].cArgs, "cParams %d\n", pFuncDesc->cParams); ok(pFuncDesc->oVft == 12, "oVft %d\n", pFuncDesc->oVft); ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags); ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt); ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt); ok(U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags); ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc); hr = ITypeInfo_GetFuncDesc(pTI2, 3, &pFuncDesc); ok(hr == S_OK, "hr %08x\n", hr); ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind); ok(pFuncDesc->invkind == methdata[3].wFlags, "invkind %d\n", pFuncDesc->invkind); ok(pFuncDesc->callconv == methdata[3].cc, "callconv %d\n", pFuncDesc->callconv); ok(pFuncDesc->cParams == methdata[3].cArgs, "cParams %d\n", pFuncDesc->cParams); ok(pFuncDesc->oVft == 16, "oVft %d\n", pFuncDesc->oVft); ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags); ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt); ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc); /* test GetIDsOfNames on a coclass to see if it searches its interfaces */ hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &name, 1, &memid); ok(hr == S_OK, "hr 0x%08x\n", hr); ok(memid == 0x123, "memid 0x%08x\n", memid); ITypeInfo_Release(pTI2); ITypeInfo_Release(pTypeInfo); SysFreeString(parms1[0].szName); SysFreeString(parms1[1].szName); SysFreeString(parms3[0].szName); SysFreeString(methdata[0].szName); SysFreeString(methdata[1].szName); SysFreeString(methdata[2].szName); SysFreeString(methdata[3].szName); }
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; }