unsigned char * WINAPI CLEANLOCALSTORAGE_UserMarshal(unsigned long *pFlags, unsigned char *Buffer, CLEANLOCALSTORAGE *pstg) { ALIGN_POINTER(Buffer, 3); *(DWORD*)Buffer = pstg->flags; switch(pstg->flags) { case CLS_LIBATTR: ITypeLib_ReleaseTLibAttr((ITypeLib*)pstg->pInterface, *(TLIBATTR**)pstg->pStorage); break; case CLS_TYPEATTR: ITypeInfo_ReleaseTypeAttr((ITypeInfo*)pstg->pInterface, *(TYPEATTR**)pstg->pStorage); break; case CLS_FUNCDESC: ITypeInfo_ReleaseFuncDesc((ITypeInfo*)pstg->pInterface, *(FUNCDESC**)pstg->pStorage); break; case CLS_VARDESC: ITypeInfo_ReleaseVarDesc((ITypeInfo*)pstg->pInterface, *(VARDESC**)pstg->pStorage); break; default: ERR("Unknown type %lx\n", pstg->flags); } *(VOID**)pstg->pStorage = NULL; IUnknown_Release(pstg->pInterface); pstg->pInterface = NULL; return Buffer + sizeof(DWORD); }
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; }
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_TypeComp(void) { ITypeLib *pTypeLib; ITypeComp *pTypeComp; HRESULT hr; ULONG ulHash; DESCKIND desckind; BINDPTR bindptr; ITypeInfo *pTypeInfo; ITypeInfo *pFontTypeInfo; static WCHAR wszStdFunctions[] = {'S','t','d','F','u','n','c','t','i','o','n','s',0}; static WCHAR wszSavePicture[] = {'S','a','v','e','P','i','c','t','u','r','e',0}; static WCHAR wszOLE_TRISTATE[] = {'O','L','E','_','T','R','I','S','T','A','T','E',0}; static WCHAR wszUnchecked[] = {'U','n','c','h','e','c','k','e','d',0}; static WCHAR wszIUnknown[] = {'I','U','n','k','n','o','w','n',0}; static WCHAR wszFont[] = {'F','o','n','t',0}; static WCHAR wszGUID[] = {'G','U','I','D',0}; static WCHAR wszStdPicture[] = {'S','t','d','P','i','c','t','u','r','e',0}; static WCHAR wszOLE_COLOR[] = {'O','L','E','_','C','O','L','O','R',0}; static WCHAR wszClone[] = {'C','l','o','n','e',0}; static WCHAR wszclone[] = {'c','l','o','n','e',0}; hr = LoadTypeLib(wszStdOle2, &pTypeLib); ok_ole_success(hr, LoadTypeLib); hr = ITypeLib_GetTypeComp(pTypeLib, &pTypeComp); ok_ole_success(hr, ITypeLib_GetTypeComp); /* test getting a TKIND_MODULE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions); hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a TKIND_MODULE with INVOKE_PROPERTYGET */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions); hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a function within a TKIND_MODULE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture); hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); /* test getting a function within a TKIND_MODULE with INVOKE_PROPERTYGET */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture); hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); todo_wine ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_ENUM */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_TRISTATE); hr = ITypeComp_Bind(pTypeComp, wszOLE_TRISTATE, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_TYPECOMP, "desckind should have been DESCKIND_TYPECOMP instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ITypeComp_Release(bindptr.lptcomp); /* test getting a value within a TKIND_ENUM */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszUnchecked); hr = ITypeComp_Bind(pTypeComp, wszUnchecked, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_VARDESC, "desckind should have been DESCKIND_VARDESC instead of %d\n", desckind); ITypeInfo_ReleaseVarDesc(pTypeInfo, bindptr.lpvardesc); ITypeInfo_Release(pTypeInfo); /* test getting a TKIND_INTERFACE */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszIUnknown); hr = ITypeComp_Bind(pTypeComp, wszIUnknown, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_DISPATCH */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszFont); hr = ITypeComp_Bind(pTypeComp, wszFont, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_RECORD/TKIND_ALIAS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszGUID); hr = ITypeComp_Bind(pTypeComp, wszGUID, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_ALIAS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_COLOR); hr = ITypeComp_Bind(pTypeComp, wszOLE_COLOR, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* test getting a TKIND_COCLASS */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdPicture); hr = ITypeComp_Bind(pTypeComp, wszStdPicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); ITypeComp_Release(pTypeComp); /* tests for ITypeComp on an interface */ hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pFontTypeInfo); ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); hr = ITypeInfo_GetTypeComp(pFontTypeInfo, &pTypeComp); ok_ole_success(hr, ITypeLib_GetTypeComp); ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone); hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone); hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr); ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr); ok(desckind == DESCKIND_NONE, "desckind should have been DESCKIND_NONE instead of %d\n", desckind); ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n"); ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n"); /* tests that the compare is case-insensitive */ ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszclone); hr = ITypeComp_Bind(pTypeComp, wszclone, ulHash, 0, &pTypeInfo, &desckind, &bindptr); ok_ole_success(hr, ITypeComp_Bind); ok(desckind == DESCKIND_FUNCDESC, "desckind should have been DESCKIND_FUNCDESC instead of %d\n", desckind); ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n"); ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc); ITypeInfo_Release(pTypeInfo); ITypeComp_Release(pTypeComp); ITypeInfo_Release(pFontTypeInfo); ITypeLib_Release(pTypeLib); }
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; }
static union _zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key) { zend_internal_function f, *fptr = NULL; union _zend_function *func; DISPID dummy; php_com_dotnet_object *obj = (php_com_dotnet_object*)*object_ptr; if (V_VT(&obj->v) != VT_DISPATCH) { return NULL; } if (FAILED(php_com_get_id_of_name(obj, name->val, name->len, &dummy))) { return NULL; } /* check cache */ if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) { f.type = ZEND_OVERLOADED_FUNCTION; f.num_args = 0; f.arg_info = NULL; f.scope = obj->ce; f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER; f.function_name = zend_string_copy(name); f.handler = PHP_FN(com_method_handler); fptr = &f; if (obj->typeinfo) { /* look for byref params */ ITypeComp *comp; ITypeInfo *TI = NULL; DESCKIND kind; BINDPTR bindptr; OLECHAR *olename; ULONG lhash; int i; if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) { olename = php_com_string_to_olestring(name->val, name->len, obj->code_page); lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename); if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) { switch (kind) { case DESCKIND_FUNCDESC: f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info)); for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) { f.arg_info[i].allow_null = 1; if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) { f.arg_info[i].pass_by_reference = ZEND_SEND_BY_REF; } } f.num_args = bindptr.lpfuncdesc->cParams; ITypeInfo_ReleaseFuncDesc(TI, bindptr.lpfuncdesc); break; /* these should not happen, but *might* happen if the user * screws up; lets avoid a leak in that case */ case DESCKIND_VARDESC: ITypeInfo_ReleaseVarDesc(TI, bindptr.lpvardesc); break; case DESCKIND_TYPECOMP: ITypeComp_Release(bindptr.lptcomp); break; case DESCKIND_NONE: break; } if (TI) { ITypeInfo_Release(TI); } } ITypeComp_Release(comp); efree(olename); } } zend_set_function_arg_flags((zend_function*)&f); /* save this method in the cache */ if (!obj->method_cache) { ALLOC_HASHTABLE(obj->method_cache); zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0); } zend_hash_update_mem(obj->method_cache, name, &f, sizeof(f)); } if (fptr) { /* duplicate this into a new chunk of emalloc'd memory, * since the engine will efree it */ func = emalloc(sizeof(*fptr)); memcpy(func, fptr, sizeof(*fptr)); return func; } return NULL; }