oleaut32: Test for interface that derives from IUnknown.
[wine] / dlls / oleaut32 / tests / typelib.c
1 /*
2  * ITypeLib and ITypeInfo test
3  *
4  * Copyright 2004 Jacek Caban
5  * Copyright 2006 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23
24 #include <wine/test.h>
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "oleauto.h"
30 #include "ocidl.h"
31 #include "shlwapi.h"
32 #include "tmarshal.h"
33
34 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
35
36 static const WCHAR wszStdOle2[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
37
38 static void ref_count_test(LPCWSTR type_lib)
39 {
40     ITypeLib *iface;
41     ITypeInfo *iti1, *iti2;
42     HRESULT hRes;
43     int ref_count;
44
45     trace("Loading type library\n");
46     hRes = LoadTypeLib(type_lib, &iface);
47     ok(hRes == S_OK, "Could not load type library\n");
48     if(hRes != S_OK)
49         return;
50
51     hRes = ITypeLib_GetTypeInfo(iface, 1, &iti1);
52     ok(hRes == S_OK, "ITypeLib_GetTypeInfo failed on index = 1\n");
53     ok(ref_count=ITypeLib_Release(iface) > 0, "ITypeLib destroyed while ITypeInfo has back pointer\n");
54     if(!ref_count)
55         return;
56
57     hRes = ITypeLib_GetTypeInfo(iface, 1, &iti2);
58     ok(hRes == S_OK, "ITypeLib_GetTypeInfo failed on index = 1\n");
59     ok(iti1 == iti2, "ITypeLib_GetTypeInfo returned different pointers for same indexes\n");
60
61     ITypeLib_AddRef(iface);
62     ITypeInfo_Release(iti2);
63     ITypeInfo_Release(iti1);
64     ok(ITypeLib_Release(iface) == 0, "ITypeLib should be destroyed here.\n");
65 }
66
67 static void test_TypeComp(void)
68 {
69     ITypeLib *pTypeLib;
70     ITypeComp *pTypeComp;
71     HRESULT hr;
72     ULONG ulHash;
73     DESCKIND desckind;
74     BINDPTR bindptr;
75     ITypeInfo *pTypeInfo;
76     ITypeInfo *pFontTypeInfo;
77     static WCHAR wszStdFunctions[] = {'S','t','d','F','u','n','c','t','i','o','n','s',0};
78     static WCHAR wszSavePicture[] = {'S','a','v','e','P','i','c','t','u','r','e',0};
79     static WCHAR wszOLE_TRISTATE[] = {'O','L','E','_','T','R','I','S','T','A','T','E',0};
80     static WCHAR wszUnchecked[] = {'U','n','c','h','e','c','k','e','d',0};
81     static WCHAR wszIUnknown[] = {'I','U','n','k','n','o','w','n',0};
82     static WCHAR wszFont[] = {'F','o','n','t',0};
83     static WCHAR wszGUID[] = {'G','U','I','D',0};
84     static WCHAR wszStdPicture[] = {'S','t','d','P','i','c','t','u','r','e',0};
85     static WCHAR wszOLE_COLOR[] = {'O','L','E','_','C','O','L','O','R',0};
86     static WCHAR wszClone[] = {'C','l','o','n','e',0};
87     static WCHAR wszclone[] = {'c','l','o','n','e',0};
88
89     hr = LoadTypeLib(wszStdOle2, &pTypeLib);
90     ok_ole_success(hr, LoadTypeLib);
91
92     hr = ITypeLib_GetTypeComp(pTypeLib, &pTypeComp);
93     ok_ole_success(hr, ITypeLib_GetTypeComp);
94
95     /* test getting a TKIND_MODULE */
96     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions);
97     hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
98     ok_ole_success(hr, ITypeComp_Bind);
99
100     ok(desckind == DESCKIND_TYPECOMP,
101         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
102         desckind);
103     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
104
105     ITypeComp_Release(bindptr.lptcomp);
106
107     /* test getting a TKIND_MODULE with INVOKE_PROPERTYGET */
108     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions);
109     hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
110     ok_ole_success(hr, ITypeComp_Bind);
111
112     ok(desckind == DESCKIND_TYPECOMP,
113         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
114         desckind);
115     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
116     ITypeComp_Release(bindptr.lptcomp);
117
118     /* test getting a function within a TKIND_MODULE */
119     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture);
120     hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
121     ok_ole_success(hr, ITypeComp_Bind);
122
123     ok(desckind == DESCKIND_FUNCDESC,
124         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
125         desckind);
126     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
127     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
128     ITypeInfo_Release(pTypeInfo);
129
130     /* test getting a function within a TKIND_MODULE with INVOKE_PROPERTYGET */
131     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture);
132     hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
133     todo_wine ok(hr == TYPE_E_TYPEMISMATCH,
134         "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n",
135         hr);
136
137     ok(desckind == DESCKIND_NONE,
138         "desckind should have been DESCKIND_NONE instead of %d\n",
139         desckind);
140     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
141     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
142
143     /* test getting a TKIND_ENUM */
144     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_TRISTATE);
145     hr = ITypeComp_Bind(pTypeComp, wszOLE_TRISTATE, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
146     ok_ole_success(hr, ITypeComp_Bind);
147
148     ok(desckind == DESCKIND_TYPECOMP,
149         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
150         desckind);
151     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
152
153     ITypeComp_Release(bindptr.lptcomp);
154
155     /* test getting a value within a TKIND_ENUM */
156     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszUnchecked);
157     hr = ITypeComp_Bind(pTypeComp, wszUnchecked, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
158     ok_ole_success(hr, ITypeComp_Bind);
159
160     ok(desckind == DESCKIND_VARDESC,
161         "desckind should have been DESCKIND_VARDESC instead of %d\n",
162         desckind);
163     ITypeInfo_ReleaseVarDesc(pTypeInfo, bindptr.lpvardesc);
164     ITypeInfo_Release(pTypeInfo);
165
166     /* test getting a TKIND_INTERFACE */
167     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszIUnknown);
168     hr = ITypeComp_Bind(pTypeComp, wszIUnknown, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
169     ok_ole_success(hr, ITypeComp_Bind);
170
171     ok(desckind == DESCKIND_NONE,
172         "desckind should have been DESCKIND_NONE instead of %d\n",
173         desckind);
174     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
175     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
176
177     /* test getting a TKIND_DISPATCH */
178     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszFont);
179     hr = ITypeComp_Bind(pTypeComp, wszFont, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
180     ok_ole_success(hr, ITypeComp_Bind);
181
182     ok(desckind == DESCKIND_NONE,
183         "desckind should have been DESCKIND_NONE instead of %d\n",
184         desckind);
185     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
186     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
187
188     /* test getting a TKIND_RECORD/TKIND_ALIAS */
189     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszGUID);
190     hr = ITypeComp_Bind(pTypeComp, wszGUID, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
191     ok_ole_success(hr, ITypeComp_Bind);
192
193     ok(desckind == DESCKIND_NONE,
194         "desckind should have been DESCKIND_NONE instead of %d\n",
195         desckind);
196     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
197     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
198
199     /* test getting a TKIND_ALIAS */
200     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_COLOR);
201     hr = ITypeComp_Bind(pTypeComp, wszOLE_COLOR, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
202     ok_ole_success(hr, ITypeComp_Bind);
203
204     ok(desckind == DESCKIND_NONE,
205         "desckind should have been DESCKIND_NONE instead of %d\n",
206         desckind);
207     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
208     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
209
210     /* test getting a TKIND_COCLASS */
211     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdPicture);
212     hr = ITypeComp_Bind(pTypeComp, wszStdPicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
213     ok_ole_success(hr, ITypeComp_Bind);
214
215     ok(desckind == DESCKIND_NONE,
216         "desckind should have been DESCKIND_NONE instead of %d\n",
217         desckind);
218     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
219     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
220
221     ITypeComp_Release(pTypeComp);
222
223     /* tests for ITypeComp on an interface */
224     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pFontTypeInfo);
225     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
226
227     hr = ITypeInfo_GetTypeComp(pFontTypeInfo, &pTypeComp);
228     ok_ole_success(hr, ITypeLib_GetTypeComp);
229
230     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone);
231     hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
232     ok_ole_success(hr, ITypeComp_Bind);
233
234     ok(desckind == DESCKIND_FUNCDESC,
235         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
236         desckind);
237     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
238     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
239     ITypeInfo_Release(pTypeInfo);
240
241     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone);
242     hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
243     ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr);
244
245     ok(desckind == DESCKIND_NONE,
246         "desckind should have been DESCKIND_NONE instead of %d\n",
247         desckind);
248     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
249     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
250
251     /* tests that the compare is case-insensitive */
252     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszclone);
253     hr = ITypeComp_Bind(pTypeComp, wszclone, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
254     ok_ole_success(hr, ITypeComp_Bind);
255
256     ok(desckind == DESCKIND_FUNCDESC,
257         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
258         desckind);
259     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
260     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
261     ITypeInfo_Release(pTypeInfo);
262
263     ITypeComp_Release(pTypeComp);
264     ITypeInfo_Release(pFontTypeInfo);
265     ITypeLib_Release(pTypeLib);
266 }
267
268 static void test_CreateDispTypeInfo(void)
269 {
270     ITypeInfo *pTypeInfo, *pTI2;
271     HRESULT hr;
272     INTERFACEDATA ifdata;
273     METHODDATA methdata[4];
274     PARAMDATA parms1[2];
275     PARAMDATA parms3[1];
276     TYPEATTR *pTypeAttr;
277     HREFTYPE href;
278     FUNCDESC *pFuncDesc;
279     MEMBERID memid;
280
281     static WCHAR func1[] = {'f','u','n','c','1',0};
282     static const WCHAR func2[] = {'f','u','n','c','2',0};
283     static const WCHAR func3[] = {'f','u','n','c','3',0};
284     static const WCHAR parm1[] = {'p','a','r','m','1',0};
285     static const WCHAR parm2[] = {'p','a','r','m','2',0};
286     OLECHAR *name = func1;
287
288     ifdata.pmethdata = methdata;
289     ifdata.cMembers = sizeof(methdata) / sizeof(methdata[0]);
290
291     methdata[0].szName = SysAllocString(func1);
292     methdata[0].ppdata = parms1;
293     methdata[0].dispid = 0x123;
294     methdata[0].iMeth = 0;
295     methdata[0].cc = CC_STDCALL;
296     methdata[0].cArgs = 2;
297     methdata[0].wFlags = DISPATCH_METHOD;
298     methdata[0].vtReturn = VT_HRESULT;
299     parms1[0].szName = SysAllocString(parm1);
300     parms1[0].vt = VT_I4;
301     parms1[1].szName = SysAllocString(parm2);
302     parms1[1].vt = VT_BSTR;
303
304     methdata[1].szName = SysAllocString(func2);
305     methdata[1].ppdata = NULL;
306     methdata[1].dispid = 0x124;
307     methdata[1].iMeth = 1;
308     methdata[1].cc = CC_STDCALL;
309     methdata[1].cArgs = 0;
310     methdata[1].wFlags = DISPATCH_PROPERTYGET;
311     methdata[1].vtReturn = VT_I4;
312
313     methdata[2].szName = SysAllocString(func3);
314     methdata[2].ppdata = parms3;
315     methdata[2].dispid = 0x125;
316     methdata[2].iMeth = 3;
317     methdata[2].cc = CC_STDCALL;
318     methdata[2].cArgs = 1;
319     methdata[2].wFlags = DISPATCH_PROPERTYPUT;
320     methdata[2].vtReturn = VT_HRESULT;
321     parms3[0].szName = SysAllocString(parm1);
322     parms3[0].vt = VT_I4;
323
324     methdata[3].szName = SysAllocString(func3);
325     methdata[3].ppdata = NULL;
326     methdata[3].dispid = 0x125;
327     methdata[3].iMeth = 4;
328     methdata[3].cc = CC_STDCALL;
329     methdata[3].cArgs = 0;
330     methdata[3].wFlags = DISPATCH_PROPERTYGET;
331     methdata[3].vtReturn = VT_I4;
332
333     hr = CreateDispTypeInfo(&ifdata, LOCALE_NEUTRAL, &pTypeInfo);
334     ok(hr == S_OK, "hr %08x\n", hr);
335
336     hr = ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
337     ok(hr == S_OK, "hr %08x\n", hr);
338
339     ok(pTypeAttr->typekind == TKIND_COCLASS, "typekind %0x\n", pTypeAttr->typekind);
340     ok(pTypeAttr->cImplTypes == 1, "cImplTypes %d\n", pTypeAttr->cImplTypes);
341     ok(pTypeAttr->cFuncs == 0, "cFuncs %d\n", pTypeAttr->cFuncs);
342     ok(pTypeAttr->wTypeFlags == 0, "wTypeFlags %04x\n", pTypeAttr->cFuncs);
343     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
344
345     hr = ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &href);
346     ok(hr == S_OK, "hr %08x\n", hr);
347     ok(href == 0, "href = 0x%x\n", href);
348     hr = ITypeInfo_GetRefTypeInfo(pTypeInfo, href, &pTI2);
349     ok(hr == S_OK, "hr %08x\n", hr);
350     hr = ITypeInfo_GetTypeAttr(pTI2, &pTypeAttr);
351     ok(hr == S_OK, "hr %08x\n", hr);
352     ok(pTypeAttr->typekind == TKIND_INTERFACE, "typekind %0x\n", pTypeAttr->typekind);
353     ITypeInfo_ReleaseTypeAttr(pTI2, pTypeAttr);
354
355     hr = ITypeInfo_GetFuncDesc(pTI2, 0, &pFuncDesc);
356     ok(hr == S_OK, "hr %08x\n", hr);
357     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
358     ok(pFuncDesc->invkind == methdata[0].wFlags, "invkind %d\n", pFuncDesc->invkind);
359     ok(pFuncDesc->callconv == methdata[0].cc, "callconv %d\n", pFuncDesc->callconv);
360     ok(pFuncDesc->cParams == methdata[0].cArgs, "cParams %d\n", pFuncDesc->cParams);
361     ok(pFuncDesc->oVft == 0, "oVft %d\n", pFuncDesc->oVft);
362     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
363     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
364     ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt);
365     ok(U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags);
366
367     ok(pFuncDesc->lprgelemdescParam[1].tdesc.vt == VT_BSTR, "parm 1 vt %x\n", pFuncDesc->lprgelemdescParam[1].tdesc.vt);
368     ok(U(pFuncDesc->lprgelemdescParam[1]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 1 flags %x\n", U(pFuncDesc->lprgelemdescParam[1]).paramdesc.wParamFlags);
369     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
370
371     hr = ITypeInfo_GetFuncDesc(pTI2, 1, &pFuncDesc);
372     ok(hr == S_OK, "hr %08x\n", hr);
373     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
374     ok(pFuncDesc->invkind == methdata[1].wFlags, "invkind %d\n", pFuncDesc->invkind);
375     ok(pFuncDesc->callconv == methdata[1].cc, "callconv %d\n", pFuncDesc->callconv);
376     ok(pFuncDesc->cParams == methdata[1].cArgs, "cParams %d\n", pFuncDesc->cParams);
377     ok(pFuncDesc->oVft == 4, "oVft %d\n", pFuncDesc->oVft);
378     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
379     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
380     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
381
382     hr = ITypeInfo_GetFuncDesc(pTI2, 2, &pFuncDesc);
383     ok(hr == S_OK, "hr %08x\n", hr);
384     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
385     ok(pFuncDesc->invkind == methdata[2].wFlags, "invkind %d\n", pFuncDesc->invkind);
386     ok(pFuncDesc->callconv == methdata[2].cc, "callconv %d\n", pFuncDesc->callconv);
387     ok(pFuncDesc->cParams == methdata[2].cArgs, "cParams %d\n", pFuncDesc->cParams);
388     ok(pFuncDesc->oVft == 12, "oVft %d\n", pFuncDesc->oVft);
389     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
390     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
391     ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt);
392     ok(U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", U(pFuncDesc->lprgelemdescParam[0]).paramdesc.wParamFlags);
393     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
394
395     hr = ITypeInfo_GetFuncDesc(pTI2, 3, &pFuncDesc);
396     ok(hr == S_OK, "hr %08x\n", hr);
397     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
398     ok(pFuncDesc->invkind == methdata[3].wFlags, "invkind %d\n", pFuncDesc->invkind);
399     ok(pFuncDesc->callconv == methdata[3].cc, "callconv %d\n", pFuncDesc->callconv);
400     ok(pFuncDesc->cParams == methdata[3].cArgs, "cParams %d\n", pFuncDesc->cParams);
401     ok(pFuncDesc->oVft == 16, "oVft %d\n", pFuncDesc->oVft);
402     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
403     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
404     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
405
406     /* test GetIDsOfNames on a coclass to see if it searches its interfaces */
407     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &name, 1, &memid);
408     ok(hr == S_OK, "hr 0x%08x\n", hr);
409     ok(memid == 0x123, "memid 0x%08x\n", memid);
410
411     ITypeInfo_Release(pTI2);
412     ITypeInfo_Release(pTypeInfo);
413
414     SysFreeString(parms1[0].szName);
415     SysFreeString(parms1[1].szName);
416     SysFreeString(parms3[0].szName);
417     SysFreeString(methdata[0].szName);
418     SysFreeString(methdata[1].szName);
419     SysFreeString(methdata[2].szName);
420     SysFreeString(methdata[3].szName);
421 }
422
423 static void test_TypeInfo(void)
424 {
425     ITypeLib *pTypeLib;
426     ITypeInfo *pTypeInfo;
427     HRESULT hr;
428     static WCHAR wszBogus[] = { 'b','o','g','u','s',0 };
429     static WCHAR wszGetTypeInfo[] = { 'G','e','t','T','y','p','e','I','n','f','o',0 };
430     static WCHAR wszClone[] = {'C','l','o','n','e',0};
431     OLECHAR* bogus = wszBogus;
432     OLECHAR* pwszGetTypeInfo = wszGetTypeInfo;
433     OLECHAR* pwszClone = wszClone;
434     DISPID dispidMember;
435     DISPPARAMS dispparams;
436
437     hr = LoadTypeLib(wszStdOle2, &pTypeLib);
438     ok_ole_success(hr, LoadTypeLib);
439
440     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pTypeInfo);
441     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); 
442
443     /* test nonexistent method name */
444     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &bogus, 1, &dispidMember);
445     ok(hr == DISP_E_UNKNOWNNAME,
446        "ITypeInfo_GetIDsOfNames should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n",
447        hr);
448
449     /* test invalid memberid */
450     dispparams.cNamedArgs = 0;
451     dispparams.cArgs = 0;
452     dispparams.rgdispidNamedArgs = NULL;
453     dispparams.rgvarg = NULL;
454     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, 0xdeadbeef, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
455     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
456
457     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &pwszClone, 1, &dispidMember);
458     ok_ole_success(hr, ITypeInfo_GetIDsOfNames);
459
460     /* test correct memberid, but wrong flags */
461     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_PROPERTYGET, &dispparams, NULL, NULL, NULL);
462     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
463
464     /* test NULL dispparams */
465     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_METHOD, NULL, NULL, NULL, NULL);
466     ok(hr == E_INVALIDARG, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr);
467
468     /* test dispparams->cNamedArgs being bigger than dispparams->cArgs */
469     dispparams.cNamedArgs = 1;
470     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
471     ok(hr == E_INVALIDARG, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr);
472
473     ITypeInfo_Release(pTypeInfo);
474
475     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IDispatch, &pTypeInfo);
476     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); 
477
478     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &pwszGetTypeInfo, 1, &dispidMember);
479     ok_ole_success(hr, ITypeInfo_GetIDsOfNames);
480
481     /* test invoking a method with a [restricted] keyword */
482     hr = ITypeInfo_Invoke(pTypeInfo, NULL, dispidMember, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
483     todo_wine {
484     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
485     }
486
487     ITypeInfo_Release(pTypeInfo);
488     ITypeLib_Release(pTypeLib);
489 }
490
491 static BOOL do_typelib_reg_key(GUID *uid, WORD maj, WORD min, LPCWSTR base, BOOL remove)
492 {
493     static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
494     static const WCHAR formatW[] = {'\\','%','u','.','%','u','\\','0','\\','w','i','n','3','2',0};
495     static const WCHAR format2W[] = {'%','s','_','%','u','_','%','u','.','d','l','l',0};
496     WCHAR buf[128];
497     HKEY hkey;
498     BOOL ret = TRUE;
499
500     memcpy(buf, typelibW, sizeof(typelibW));
501     StringFromGUID2(uid, buf + lstrlenW(buf), 40);
502
503     if (remove)
504     {
505         ok(SHDeleteKeyW(HKEY_CLASSES_ROOT, buf) == ERROR_SUCCESS, "SHDeleteKey failed\n");
506         return TRUE;
507     }
508
509     wsprintfW(buf + lstrlenW(buf), formatW, maj, min );
510
511     if (RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
512                         KEY_WRITE, NULL, &hkey, NULL) != ERROR_SUCCESS)
513     {
514         trace("RegCreateKeyExW failed\n");
515         return FALSE;
516     }
517
518     wsprintfW(buf, format2W, base, maj, min);
519     if (RegSetValueExW(hkey, NULL, 0, REG_SZ,
520                        (BYTE *)buf, (lstrlenW(buf) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS)
521     {
522         trace("RegSetValueExW failed\n");
523         ret = FALSE;
524     }
525     RegCloseKey(hkey);
526     return ret;
527 }
528
529 static void test_QueryPathOfRegTypeLib(void)
530 {
531     static const struct test_data
532     {
533         WORD maj, min;
534         HRESULT ret;
535         const WCHAR path[16];
536     } td[] = {
537         { 1, 0, TYPE_E_LIBNOTREGISTERED, { 0 } },
538         { 3, 0, S_OK, {'f','a','k','e','_','3','_','0','.','d','l','l',0 } },
539         { 3, 1, S_OK, {'f','a','k','e','_','3','_','1','.','d','l','l',0 } },
540         { 3, 22, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
541         { 3, 37, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
542         { 3, 40, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
543         { 4, 0, TYPE_E_LIBNOTREGISTERED, { 0 } }
544     };
545     static const WCHAR base[] = {'f','a','k','e',0};
546     UINT i;
547     RPC_STATUS status;
548     GUID uid;
549     WCHAR uid_str[40];
550     HRESULT ret;
551     BSTR path;
552
553     status = UuidCreate(&uid);
554     ok(!status, "UuidCreate error %08lx\n", status);
555
556     StringFromGUID2(&uid, uid_str, 40);
557     /*trace("GUID: %s\n", wine_dbgstr_w(uid_str));*/
558
559     if (!do_typelib_reg_key(&uid, 3, 0, base, 0)) return;
560     if (!do_typelib_reg_key(&uid, 3, 1, base, 0)) return;
561     if (!do_typelib_reg_key(&uid, 3, 37, base, 0)) return;
562
563     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
564     {
565         ret = QueryPathOfRegTypeLib(&uid, td[i].maj, td[i].min, 0, &path);
566         ok(ret == td[i].ret, "QueryPathOfRegTypeLib(%u.%u) returned %08x\n", td[i].maj, td[i].min, ret);
567         if (ret == S_OK)
568         {
569             ok(!lstrcmpW(td[i].path, path), "typelib %u.%u path doesn't match\n", td[i].maj, td[i].min);
570             SysFreeString(path);
571         }
572     }
573
574     do_typelib_reg_key(&uid, 0, 0, NULL, 1);
575 }
576
577 static void test_inheritance(void)
578 {
579     HRESULT hr;
580     ITypeLib *pTL;
581     ITypeInfo *pTI, *pTI_p;
582     TYPEATTR *pTA;
583     HREFTYPE href;
584     FUNCDESC *pFD;
585     WCHAR path[MAX_PATH];
586     static const WCHAR tl_path[] = {'.','\\','m','i','d','l','_','t','m','a','r','s','h','a','l','.','t','l','b',0};
587
588     BOOL use_midl_tlb = 0;
589
590     GetModuleFileNameW(NULL, path, MAX_PATH);
591
592     if(use_midl_tlb)
593         memcpy(path, tl_path, sizeof(tl_path));
594
595     hr = LoadTypeLib(path, &pTL);
596     if(FAILED(hr)) return;
597
598
599     /* ItestIF3 is a syntax 2 dispinterface */
600     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF3, &pTI);
601     ok(hr == S_OK, "hr %08x\n", hr);
602
603     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
604     ok(hr == S_OK, "hr %08x\n", hr);
605     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
606     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
607     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
608 if(use_midl_tlb) {
609     ok(pTA->cFuncs == 6, "cfuncs %d\n", pTA->cFuncs);
610     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
611     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
612
613     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
614     ok(hr == S_OK, "hr %08x\n", hr);
615     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
616     ok(hr == S_OK, "hr %08x\n", hr);
617     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
618     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
619     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
620     ITypeInfo_Release(pTI_p);
621
622     /* Should have six methods */
623     hr = ITypeInfo_GetFuncDesc(pTI, 6, &pFD);
624     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
625     hr = ITypeInfo_GetFuncDesc(pTI, 5, &pFD);
626     ok(hr == S_OK, "hr %08x\n", hr);
627     ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid);
628     ok(pFD->oVft == 20, "oVft %d\n", pFD->oVft);
629     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
630 }
631     ITypeInfo_Release(pTI);
632
633
634     /* ItestIF4 is a syntax 1 dispinterface */
635     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF4, &pTI);
636     ok(hr == S_OK, "hr %08x\n", hr);
637
638     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
639     ok(hr == S_OK, "hr %08x\n", hr);
640     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
641     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
642     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
643     ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs);
644     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
645     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
646
647     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
648     ok(hr == S_OK, "hr %08x\n", hr);
649     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
650     ok(hr == S_OK, "hr %08x\n", hr);
651     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
652     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
653     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
654     ITypeInfo_Release(pTI_p);
655     hr = ITypeInfo_GetFuncDesc(pTI, 1, &pFD);
656     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
657     hr = ITypeInfo_GetFuncDesc(pTI, 0, &pFD);
658     ok(hr == S_OK, "hr %08x\n", hr);
659     ok(pFD->memid == 0x1c, "memid %08x\n", pFD->memid);
660     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
661     ITypeInfo_Release(pTI);
662
663
664     /* ItestIF5 is dual with inherited ifaces which derive from IUnknown but not IDispatch */
665     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF5, &pTI);
666     ok(hr == S_OK, "hr %08x\n", hr);
667
668     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
669     ok(hr == S_OK, "hr %08x\n", hr);
670     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
671     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
672 if(use_midl_tlb) {
673     ok(pTA->wTypeFlags == TYPEFLAG_FDUAL, "typeflags %x\n", pTA->wTypeFlags);
674  }
675     ok(pTA->cFuncs == 8, "cfuncs %d\n", pTA->cFuncs);
676     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
677     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
678
679     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
680     ok(hr == S_OK, "hr %08x\n", hr);
681     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
682     ok(hr == S_OK, "hr %08x\n", hr);
683     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
684     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
685     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
686     ITypeInfo_Release(pTI_p);
687 if(use_midl_tlb) {
688     hr = ITypeInfo_GetFuncDesc(pTI, 6, &pFD);
689     ok(hr == S_OK, "hr %08x\n", hr);
690     ok(pFD->memid == 0x1234, "memid %08x\n", pFD->memid);
691     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
692 }
693     ITypeInfo_Release(pTI);
694
695     /* ItestIF7 is dual with inherited ifaces which derive from Dispatch */
696     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF7, &pTI);
697     ok(hr == S_OK, "hr %08x\n", hr);
698
699     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
700     ok(hr == S_OK, "hr %08x\n", hr);
701     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
702     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
703     ok(pTA->wTypeFlags == (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL), "typeflags %x\n", pTA->wTypeFlags);
704     ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs);
705     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
706     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
707
708     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
709     ok(hr == S_OK, "hr %08x\n", hr);
710     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
711     ok(hr == S_OK, "hr %08x\n", hr);
712     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
713     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
714     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
715     ITypeInfo_Release(pTI_p);
716
717     hr = ITypeInfo_GetFuncDesc(pTI, 9, &pFD);
718     ok(hr == S_OK, "hr %08x\n", hr);
719     ok(pFD->memid == 0x1236, "memid %08x\n", pFD->memid);
720     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
721     ITypeInfo_Release(pTI);
722
723     /* ItestIF10 is a syntax 2 dispinterface which doesn't derive from IUnknown */
724     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF10, &pTI);
725     ok(hr == S_OK, "hr %08x\n", hr);
726
727     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
728     ok(hr == S_OK, "hr %08x\n", hr);
729     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
730     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
731     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
732 if(use_midl_tlb) {
733     ok(pTA->cFuncs == 3, "cfuncs %d\n", pTA->cFuncs);
734     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
735     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
736
737     hr = ITypeInfo_GetRefTypeOfImplType(pTI, -1, &href);
738     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
739     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
740     ok(hr == S_OK, "hr %08x\n", hr);
741     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
742     ok(hr == S_OK, "hr %08x\n", hr);
743     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
744     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
745     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
746     ITypeInfo_Release(pTI_p);
747
748     /* Should have three methods */
749     hr = ITypeInfo_GetFuncDesc(pTI, 3, &pFD);
750     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
751     hr = ITypeInfo_GetFuncDesc(pTI, 2, &pFD);
752     ok(hr == S_OK, "hr %08x\n", hr);
753     ok(pFD->memid == 0x60010000, "memid %08x\n", pFD->memid);
754     ok(pFD->oVft == 8, "oVft %d\n", pFD->oVft);
755     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
756 }
757     ITypeInfo_Release(pTI);
758
759     /* ItestIF11 is a syntax 2 dispinterface which derives from IDispatch */
760     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &DIID_ItestIF11, &pTI);
761     ok(hr == S_OK, "hr %08x\n", hr);
762
763     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
764     ok(hr == S_OK, "hr %08x\n", hr);
765     ok(pTA->typekind == TKIND_DISPATCH, "kind %04x\n", pTA->typekind);
766     ok(pTA->cbSizeVft == 28, "sizevft %d\n", pTA->cbSizeVft);
767     ok(pTA->wTypeFlags == TYPEFLAG_FDISPATCHABLE, "typeflags %x\n", pTA->wTypeFlags);
768 if(use_midl_tlb) {
769     ok(pTA->cFuncs == 10, "cfuncs %d\n", pTA->cFuncs);
770     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
771     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
772
773     hr = ITypeInfo_GetRefTypeOfImplType(pTI, 0, &href);
774     ok(hr == S_OK, "hr %08x\n", hr);
775     hr = ITypeInfo_GetRefTypeInfo(pTI, href, &pTI_p);
776     ok(hr == S_OK, "hr %08x\n", hr);
777     hr = ITypeInfo_GetTypeAttr(pTI_p, &pTA);
778     ok(IsEqualGUID(&pTA->guid, &IID_IDispatch), "guid {%08x-....\n", pTA->guid.Data1);
779     ITypeInfo_ReleaseTypeAttr(pTI_p, pTA);
780     ITypeInfo_Release(pTI_p);
781
782     /* Should have ten methods */
783     hr = ITypeInfo_GetFuncDesc(pTI, 10, &pFD);
784     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
785     hr = ITypeInfo_GetFuncDesc(pTI, 9, &pFD);
786     ok(hr == S_OK, "hr %08x\n", hr);
787     ok(pFD->memid == 0x1236, "memid %08x\n", pFD->memid);
788     ok(pFD->oVft == 36, "oVft %d\n", pFD->oVft);
789     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
790 }
791     ITypeInfo_Release(pTI);
792
793
794     /* ItestIF2 is an interface which derives from IUnknown */
795     hr = ITypeLib_GetTypeInfoOfGuid(pTL, &IID_ItestIF2, &pTI);
796     ok(hr == S_OK, "hr %08x\n", hr);
797
798     hr = ITypeInfo_GetTypeAttr(pTI, &pTA);
799     ok(hr == S_OK, "hr %08x\n", hr);
800     ok(pTA->typekind == TKIND_INTERFACE, "kind %04x\n", pTA->typekind);
801     ok(pTA->cbSizeVft == 24, "sizevft %d\n", pTA->cbSizeVft);
802     ok(pTA->wTypeFlags == 0, "typeflags %x\n", pTA->wTypeFlags);
803 if(use_midl_tlb) {
804     ok(pTA->cFuncs == 1, "cfuncs %d\n", pTA->cFuncs);
805     ok(pTA->cImplTypes == 1, "cimpltypes %d\n", pTA->cImplTypes);
806     ITypeInfo_ReleaseTypeAttr(pTI, pTA);
807
808     /* Should have one method */
809     hr = ITypeInfo_GetFuncDesc(pTI, 1, &pFD);
810     ok(hr == TYPE_E_ELEMENTNOTFOUND, "hr %08x\n", hr);
811     hr = ITypeInfo_GetFuncDesc(pTI, 0, &pFD);
812     ok(hr == S_OK, "hr %08x\n", hr);
813     ok(pFD->memid == 0x60020000, "memid %08x\n", pFD->memid);
814     ok(pFD->oVft == 20, "oVft %d\n", pFD->oVft);
815     ITypeInfo_ReleaseFuncDesc(pTI, pFD);
816 }
817     ITypeInfo_Release(pTI);
818
819     ITypeLib_Release(pTL);
820
821     return;
822 }
823
824 START_TEST(typelib)
825 {
826     ref_count_test(wszStdOle2);
827     test_TypeComp();
828     test_CreateDispTypeInfo();
829     test_TypeInfo();
830     test_QueryPathOfRegTypeLib();
831     test_inheritance();
832 }