mshtml: Print wine_gecko version in load_wine_gecko.
[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 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25
26 #include <wine/test.h>
27 #include <stdarg.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "oleauto.h"
32 #include "ocidl.h"
33 #include "shlwapi.h"
34
35 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
36
37 static const WCHAR wszStdOle2[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
38
39 static void ref_count_test(LPCWSTR type_lib)
40 {
41     ITypeLib *iface;
42     ITypeInfo *iti1, *iti2;
43     HRESULT hRes;
44     int ref_count;
45
46     trace("Loading type library\n");
47     hRes = LoadTypeLib(type_lib, &iface);
48     ok(hRes == S_OK, "Could not load type library\n");
49     if(hRes != S_OK)
50         return;
51
52     hRes = ITypeLib_GetTypeInfo(iface, 1, &iti1);
53     ok(hRes == S_OK, "ITypeLib_GetTypeInfo failed on index = 1\n");
54     ok(ref_count=ITypeLib_Release(iface) > 0, "ITypeLib destroyed while ITypeInfo has back pointer\n");
55     if(!ref_count)
56         return;
57
58     hRes = ITypeLib_GetTypeInfo(iface, 1, &iti2);
59     ok(hRes == S_OK, "ITypeLib_GetTypeInfo failed on index = 1\n");
60     ok(iti1 == iti2, "ITypeLib_GetTypeInfo returned different pointers for same indexes\n");
61
62     ITypeLib_AddRef(iface);
63     ITypeInfo_Release(iti2);
64     ITypeInfo_Release(iti1);
65     ok(ITypeLib_Release(iface) == 0, "ITypeLib should be destroyed here.\n");
66 }
67
68 static void test_TypeComp(void)
69 {
70     ITypeLib *pTypeLib;
71     ITypeComp *pTypeComp;
72     HRESULT hr;
73     ULONG ulHash;
74     DESCKIND desckind;
75     BINDPTR bindptr;
76     ITypeInfo *pTypeInfo;
77     ITypeInfo *pFontTypeInfo;
78     static WCHAR wszStdFunctions[] = {'S','t','d','F','u','n','c','t','i','o','n','s',0};
79     static WCHAR wszSavePicture[] = {'S','a','v','e','P','i','c','t','u','r','e',0};
80     static WCHAR wszOLE_TRISTATE[] = {'O','L','E','_','T','R','I','S','T','A','T','E',0};
81     static WCHAR wszUnchecked[] = {'U','n','c','h','e','c','k','e','d',0};
82     static WCHAR wszIUnknown[] = {'I','U','n','k','n','o','w','n',0};
83     static WCHAR wszFont[] = {'F','o','n','t',0};
84     static WCHAR wszGUID[] = {'G','U','I','D',0};
85     static WCHAR wszStdPicture[] = {'S','t','d','P','i','c','t','u','r','e',0};
86     static WCHAR wszOLE_COLOR[] = {'O','L','E','_','C','O','L','O','R',0};
87     static WCHAR wszClone[] = {'C','l','o','n','e',0};
88     static WCHAR wszclone[] = {'c','l','o','n','e',0};
89
90     hr = LoadTypeLib(wszStdOle2, &pTypeLib);
91     ok_ole_success(hr, LoadTypeLib);
92
93     hr = ITypeLib_GetTypeComp(pTypeLib, &pTypeComp);
94     ok_ole_success(hr, ITypeLib_GetTypeComp);
95
96     /* test getting a TKIND_MODULE */
97     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions);
98     hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
99     ok_ole_success(hr, ITypeComp_Bind);
100
101     ok(desckind == DESCKIND_TYPECOMP,
102         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
103         desckind);
104     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
105
106     ITypeComp_Release(bindptr.lptcomp);
107
108     /* test getting a TKIND_MODULE with INVOKE_PROPERTYGET */
109     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdFunctions);
110     hr = ITypeComp_Bind(pTypeComp, wszStdFunctions, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
111     ok_ole_success(hr, ITypeComp_Bind);
112
113     ok(desckind == DESCKIND_TYPECOMP,
114         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
115         desckind);
116     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
117     ITypeComp_Release(bindptr.lptcomp);
118
119     /* test getting a function within a TKIND_MODULE */
120     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture);
121     hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
122     ok_ole_success(hr, ITypeComp_Bind);
123
124     ok(desckind == DESCKIND_FUNCDESC,
125         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
126         desckind);
127     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
128     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
129     ITypeInfo_Release(pTypeInfo);
130
131     /* test getting a function within a TKIND_MODULE with INVOKE_PROPERTYGET */
132     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszSavePicture);
133     hr = ITypeComp_Bind(pTypeComp, wszSavePicture, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
134     todo_wine ok(hr == TYPE_E_TYPEMISMATCH,
135         "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n",
136         hr);
137
138     ok(desckind == DESCKIND_NONE,
139         "desckind should have been DESCKIND_NONE instead of %d\n",
140         desckind);
141     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
142     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
143
144     /* test getting a TKIND_ENUM */
145     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_TRISTATE);
146     hr = ITypeComp_Bind(pTypeComp, wszOLE_TRISTATE, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
147     ok_ole_success(hr, ITypeComp_Bind);
148
149     ok(desckind == DESCKIND_TYPECOMP,
150         "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
151         desckind);
152     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
153
154     ITypeComp_Release(bindptr.lptcomp);
155
156     /* test getting a value within a TKIND_ENUM */
157     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszUnchecked);
158     hr = ITypeComp_Bind(pTypeComp, wszUnchecked, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
159     ok_ole_success(hr, ITypeComp_Bind);
160
161     ok(desckind == DESCKIND_VARDESC,
162         "desckind should have been DESCKIND_VARDESC instead of %d\n",
163         desckind);
164     ITypeInfo_ReleaseVarDesc(pTypeInfo, bindptr.lpvardesc);
165     ITypeInfo_Release(pTypeInfo);
166
167     /* test getting a TKIND_INTERFACE */
168     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszIUnknown);
169     hr = ITypeComp_Bind(pTypeComp, wszIUnknown, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
170     ok_ole_success(hr, ITypeComp_Bind);
171
172     ok(desckind == DESCKIND_NONE,
173         "desckind should have been DESCKIND_NONE instead of %d\n",
174         desckind);
175     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
176     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
177
178     /* test getting a TKIND_DISPATCH */
179     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszFont);
180     hr = ITypeComp_Bind(pTypeComp, wszFont, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
181     ok_ole_success(hr, ITypeComp_Bind);
182
183     ok(desckind == DESCKIND_NONE,
184         "desckind should have been DESCKIND_NONE instead of %d\n",
185         desckind);
186     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
187     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
188
189     /* test getting a TKIND_RECORD/TKIND_ALIAS */
190     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszGUID);
191     hr = ITypeComp_Bind(pTypeComp, wszGUID, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
192     ok_ole_success(hr, ITypeComp_Bind);
193
194     ok(desckind == DESCKIND_NONE,
195         "desckind should have been DESCKIND_NONE instead of %d\n",
196         desckind);
197     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
198     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
199
200     /* test getting a TKIND_ALIAS */
201     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszOLE_COLOR);
202     hr = ITypeComp_Bind(pTypeComp, wszOLE_COLOR, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
203     ok_ole_success(hr, ITypeComp_Bind);
204
205     ok(desckind == DESCKIND_NONE,
206         "desckind should have been DESCKIND_NONE instead of %d\n",
207         desckind);
208     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
209     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
210
211     /* test getting a TKIND_COCLASS */
212     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszStdPicture);
213     hr = ITypeComp_Bind(pTypeComp, wszStdPicture, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
214     ok_ole_success(hr, ITypeComp_Bind);
215
216     ok(desckind == DESCKIND_NONE,
217         "desckind should have been DESCKIND_NONE instead of %d\n",
218         desckind);
219     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
220     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
221
222     ITypeComp_Release(pTypeComp);
223
224     /* tests for ITypeComp on an interface */
225     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pFontTypeInfo);
226     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
227
228     hr = ITypeInfo_GetTypeComp(pFontTypeInfo, &pTypeComp);
229     ok_ole_success(hr, ITypeLib_GetTypeComp);
230
231     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone);
232     hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
233     ok_ole_success(hr, ITypeComp_Bind);
234
235     ok(desckind == DESCKIND_FUNCDESC,
236         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
237         desckind);
238     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
239     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
240     ITypeInfo_Release(pTypeInfo);
241
242     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszClone);
243     hr = ITypeComp_Bind(pTypeComp, wszClone, ulHash, INVOKE_PROPERTYGET, &pTypeInfo, &desckind, &bindptr);
244     ok(hr == TYPE_E_TYPEMISMATCH, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr);
245
246     ok(desckind == DESCKIND_NONE,
247         "desckind should have been DESCKIND_NONE instead of %d\n",
248         desckind);
249     ok(!pTypeInfo, "pTypeInfo should have been set to NULL\n");
250     ok(!bindptr.lptcomp, "bindptr should have been set to NULL\n");
251
252     /* tests that the compare is case-insensitive */
253     ulHash = LHashValOfNameSys(SYS_WIN32, LOCALE_NEUTRAL, wszclone);
254     hr = ITypeComp_Bind(pTypeComp, wszclone, ulHash, 0, &pTypeInfo, &desckind, &bindptr);
255     ok_ole_success(hr, ITypeComp_Bind);
256
257     ok(desckind == DESCKIND_FUNCDESC,
258         "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
259         desckind);
260     ok(bindptr.lpfuncdesc != NULL, "bindptr.lpfuncdesc should not have been set to NULL\n");
261     ITypeInfo_ReleaseFuncDesc(pTypeInfo, bindptr.lpfuncdesc);
262     ITypeInfo_Release(pTypeInfo);
263
264     ITypeComp_Release(pTypeComp);
265     ITypeInfo_Release(pFontTypeInfo);
266     ITypeLib_Release(pTypeLib);
267 }
268
269 static void test_CreateDispTypeInfo(void)
270 {
271     ITypeInfo *pTypeInfo, *pTI2;
272     HRESULT hr;
273     INTERFACEDATA ifdata;
274     METHODDATA methdata[4];
275     PARAMDATA parms1[2];
276     PARAMDATA parms3[1];
277     TYPEATTR *pTypeAttr;
278     HREFTYPE href;
279     FUNCDESC *pFuncDesc;
280     MEMBERID memid;
281
282     static const WCHAR func1[] = {'f','u','n','c','1',0};
283     static const WCHAR func2[] = {'f','u','n','c','2',0};
284     static const WCHAR func3[] = {'f','u','n','c','3',0};
285     static const WCHAR parm1[] = {'p','a','r','m','1',0};
286     static const WCHAR parm2[] = {'p','a','r','m','2',0};
287     OLECHAR *name = (OLECHAR *)func1;
288
289     ifdata.pmethdata = methdata;
290     ifdata.cMembers = sizeof(methdata) / sizeof(methdata[0]);
291
292     methdata[0].szName = SysAllocString(func1);
293     methdata[0].ppdata = parms1;
294     methdata[0].dispid = 0x123;
295     methdata[0].iMeth = 0;
296     methdata[0].cc = CC_STDCALL;
297     methdata[0].cArgs = 2;
298     methdata[0].wFlags = DISPATCH_METHOD;
299     methdata[0].vtReturn = VT_HRESULT;
300     parms1[0].szName = SysAllocString(parm1);
301     parms1[0].vt = VT_I4;
302     parms1[1].szName = SysAllocString(parm2);
303     parms1[1].vt = VT_BSTR;
304
305     methdata[1].szName = SysAllocString(func2);
306     methdata[1].ppdata = NULL;
307     methdata[1].dispid = 0x124;
308     methdata[1].iMeth = 1;
309     methdata[1].cc = CC_STDCALL;
310     methdata[1].cArgs = 0;
311     methdata[1].wFlags = DISPATCH_PROPERTYGET;
312     methdata[1].vtReturn = VT_I4;
313
314     methdata[2].szName = SysAllocString(func3);
315     methdata[2].ppdata = parms3;
316     methdata[2].dispid = 0x125;
317     methdata[2].iMeth = 3;
318     methdata[2].cc = CC_STDCALL;
319     methdata[2].cArgs = 1;
320     methdata[2].wFlags = DISPATCH_PROPERTYPUT;
321     methdata[2].vtReturn = VT_HRESULT;
322     parms3[0].szName = SysAllocString(parm1);
323     parms3[0].vt = VT_I4;
324
325     methdata[3].szName = SysAllocString(func3);
326     methdata[3].ppdata = NULL;
327     methdata[3].dispid = 0x125;
328     methdata[3].iMeth = 4;
329     methdata[3].cc = CC_STDCALL;
330     methdata[3].cArgs = 0;
331     methdata[3].wFlags = DISPATCH_PROPERTYGET;
332     methdata[3].vtReturn = VT_I4;
333
334     hr = CreateDispTypeInfo(&ifdata, LOCALE_NEUTRAL, &pTypeInfo);
335     ok(hr == S_OK, "hr %08x\n", hr);
336
337     hr = ITypeInfo_GetTypeAttr(pTypeInfo, &pTypeAttr);
338     ok(hr == S_OK, "hr %08x\n", hr);
339
340     ok(pTypeAttr->typekind == TKIND_COCLASS, "typekind %0x\n", pTypeAttr->typekind);
341     ok(pTypeAttr->cImplTypes == 1, "cImplTypes %d\n", pTypeAttr->cImplTypes);
342     ok(pTypeAttr->cFuncs == 0, "cFuncs %d\n", pTypeAttr->cFuncs);
343     ok(pTypeAttr->wTypeFlags == 0, "wTypeFlags %04x\n", pTypeAttr->cFuncs);
344     ITypeInfo_ReleaseTypeAttr(pTypeInfo, pTypeAttr);
345
346     hr = ITypeInfo_GetRefTypeOfImplType(pTypeInfo, 0, &href);
347     ok(hr == S_OK, "hr %08x\n", hr);
348     todo_wine {
349     ok(href == 0, "href = 0x%x\n", href);
350     }
351     hr = ITypeInfo_GetRefTypeInfo(pTypeInfo, href, &pTI2);
352     ok(hr == S_OK, "hr %08x\n", hr);
353     hr = ITypeInfo_GetTypeAttr(pTI2, &pTypeAttr);
354     ok(hr == S_OK, "hr %08x\n", hr);
355     ok(pTypeAttr->typekind == TKIND_INTERFACE, "typekind %0x\n", pTypeAttr->typekind);
356     ITypeInfo_ReleaseTypeAttr(pTI2, pTypeAttr);
357
358     hr = ITypeInfo_GetFuncDesc(pTI2, 0, &pFuncDesc);
359     ok(hr == S_OK, "hr %08x\n", hr);
360     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
361     ok(pFuncDesc->invkind == methdata[0].wFlags, "invkind %d\n", pFuncDesc->invkind);
362     ok(pFuncDesc->callconv == methdata[0].cc, "callconv %d\n", pFuncDesc->callconv);
363     ok(pFuncDesc->cParams == methdata[0].cArgs, "cParams %d\n", pFuncDesc->cParams);
364     ok(pFuncDesc->oVft == 0, "oVft %d\n", pFuncDesc->oVft);
365     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
366     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
367     ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt);
368     ok(pFuncDesc->lprgelemdescParam[0].u.paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", pFuncDesc->lprgelemdescParam[0].u.paramdesc.wParamFlags);
369
370     ok(pFuncDesc->lprgelemdescParam[1].tdesc.vt == VT_BSTR, "parm 1 vt %x\n", pFuncDesc->lprgelemdescParam[1].tdesc.vt);
371     ok(pFuncDesc->lprgelemdescParam[1].u.paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 1 flags %x\n", pFuncDesc->lprgelemdescParam[1].u.paramdesc.wParamFlags);
372     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
373
374     hr = ITypeInfo_GetFuncDesc(pTI2, 1, &pFuncDesc);
375     ok(hr == S_OK, "hr %08x\n", hr);
376     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
377     ok(pFuncDesc->invkind == methdata[1].wFlags, "invkind %d\n", pFuncDesc->invkind);
378     ok(pFuncDesc->callconv == methdata[1].cc, "callconv %d\n", pFuncDesc->callconv);
379     ok(pFuncDesc->cParams == methdata[1].cArgs, "cParams %d\n", pFuncDesc->cParams);
380     ok(pFuncDesc->oVft == 4, "oVft %d\n", pFuncDesc->oVft);
381     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
382     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
383     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
384
385     hr = ITypeInfo_GetFuncDesc(pTI2, 2, &pFuncDesc);
386     ok(hr == S_OK, "hr %08x\n", hr);
387     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
388     ok(pFuncDesc->invkind == methdata[2].wFlags, "invkind %d\n", pFuncDesc->invkind);
389     ok(pFuncDesc->callconv == methdata[2].cc, "callconv %d\n", pFuncDesc->callconv);
390     ok(pFuncDesc->cParams == methdata[2].cArgs, "cParams %d\n", pFuncDesc->cParams);
391     ok(pFuncDesc->oVft == 12, "oVft %d\n", pFuncDesc->oVft);
392     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
393     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_HRESULT, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
394     ok(pFuncDesc->lprgelemdescParam[0].tdesc.vt == VT_I4, "parm 0 vt %x\n", pFuncDesc->lprgelemdescParam[0].tdesc.vt);
395     ok(pFuncDesc->lprgelemdescParam[0].u.paramdesc.wParamFlags == PARAMFLAG_NONE, "parm 0 flags %x\n", pFuncDesc->lprgelemdescParam[0].u.paramdesc.wParamFlags);
396     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
397
398     hr = ITypeInfo_GetFuncDesc(pTI2, 3, &pFuncDesc);
399     ok(hr == S_OK, "hr %08x\n", hr);
400     ok(pFuncDesc->funckind == FUNC_VIRTUAL, "funckind %d\n", pFuncDesc->funckind);
401     ok(pFuncDesc->invkind == methdata[3].wFlags, "invkind %d\n", pFuncDesc->invkind);
402     ok(pFuncDesc->callconv == methdata[3].cc, "callconv %d\n", pFuncDesc->callconv);
403     ok(pFuncDesc->cParams == methdata[3].cArgs, "cParams %d\n", pFuncDesc->cParams);
404     ok(pFuncDesc->oVft == 16, "oVft %d\n", pFuncDesc->oVft);
405     ok(pFuncDesc->wFuncFlags == 0, "oVft %d\n", pFuncDesc->wFuncFlags);
406     ok(pFuncDesc->elemdescFunc.tdesc.vt == VT_I4, "ret vt %x\n", pFuncDesc->elemdescFunc.tdesc.vt);
407     ITypeInfo_ReleaseFuncDesc(pTI2, pFuncDesc);
408
409     /* test GetIDsOfNames on a coclass to see if it searches its interfaces */
410     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &name, 1, &memid);
411     ok(hr == S_OK, "hr 0x%08x\n", hr);
412     ok(memid == 0x123, "memid 0x%08x\n", memid);
413
414     ITypeInfo_Release(pTI2);
415     ITypeInfo_Release(pTypeInfo);
416
417     SysFreeString(parms1[0].szName);
418     SysFreeString(parms1[1].szName);
419     SysFreeString(parms3[0].szName);
420     SysFreeString(methdata[0].szName);
421     SysFreeString(methdata[1].szName);
422     SysFreeString(methdata[2].szName);
423     SysFreeString(methdata[3].szName);
424 }
425
426 static void test_TypeInfo(void)
427 {
428     ITypeLib *pTypeLib;
429     ITypeInfo *pTypeInfo;
430     HRESULT hr;
431     static WCHAR wszBogus[] = { 'b','o','g','u','s',0 };
432     static WCHAR wszGetTypeInfo[] = { 'G','e','t','T','y','p','e','I','n','f','o',0 };
433     static WCHAR wszClone[] = {'C','l','o','n','e',0};
434     OLECHAR* bogus = wszBogus;
435     OLECHAR* pwszGetTypeInfo = wszGetTypeInfo;
436     OLECHAR* pwszClone = wszClone;
437     DISPID dispidMember;
438     DISPPARAMS dispparams;
439
440     hr = LoadTypeLib(wszStdOle2, &pTypeLib);
441     ok_ole_success(hr, LoadTypeLib);
442
443     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IFont, &pTypeInfo);
444     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); 
445
446     /* test nonexistent method name */
447     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &bogus, 1, &dispidMember);
448     ok(hr == DISP_E_UNKNOWNNAME,
449        "ITypeInfo_GetIDsOfNames should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n",
450        hr);
451
452     /* test invalid memberid */
453     dispparams.cNamedArgs = 0;
454     dispparams.cArgs = 0;
455     dispparams.rgdispidNamedArgs = NULL;
456     dispparams.rgvarg = NULL;
457     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, 0xdeadbeef, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
458     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
459
460     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &pwszClone, 1, &dispidMember);
461     ok_ole_success(hr, ITypeInfo_GetIDsOfNames);
462
463     /* test correct memberid, but wrong flags */
464     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_PROPERTYGET, &dispparams, NULL, NULL, NULL);
465     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
466
467     /* test NULL dispparams */
468     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_METHOD, NULL, NULL, NULL, NULL);
469     ok(hr == E_INVALIDARG, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr);
470
471     /* test dispparams->cNamedArgs being bigger than dispparams->cArgs */
472     dispparams.cNamedArgs = 1;
473     hr = ITypeInfo_Invoke(pTypeInfo, (void *)0xdeadbeef, dispidMember, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
474     ok(hr == E_INVALIDARG, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr);
475
476     ITypeInfo_Release(pTypeInfo);
477
478     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IDispatch, &pTypeInfo);
479     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid); 
480
481     hr = ITypeInfo_GetIDsOfNames(pTypeInfo, &pwszGetTypeInfo, 1, &dispidMember);
482     ok_ole_success(hr, ITypeInfo_GetIDsOfNames);
483
484     /* test invoking a method with a [restricted] keyword */
485     hr = ITypeInfo_Invoke(pTypeInfo, NULL, dispidMember, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
486     todo_wine {
487     ok(hr == DISP_E_MEMBERNOTFOUND, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
488     }
489
490     ITypeInfo_Release(pTypeInfo);
491     ITypeLib_Release(pTypeLib);
492 }
493
494 static BOOL do_typelib_reg_key(GUID *uid, WORD maj, WORD min, LPCWSTR base, BOOL remove)
495 {
496     static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
497     static const WCHAR formatW[] = {'\\','%','u','.','%','u','\\','0','\\','w','i','n','3','2',0};
498     static const WCHAR format2W[] = {'%','s','_','%','u','_','%','u','.','d','l','l',0};
499     WCHAR buf[128];
500     HKEY hkey;
501     BOOL ret = TRUE;
502
503     memcpy(buf, typelibW, sizeof(typelibW));
504     StringFromGUID2(uid, buf + lstrlenW(buf), 40);
505
506     if (remove)
507     {
508 todo_wine {
509         ok(SHDeleteKeyW(HKEY_CLASSES_ROOT, buf) == ERROR_SUCCESS, "SHDeleteKey failed\n");
510 }
511         return TRUE;
512     }
513
514     wsprintfW(buf + lstrlenW(buf), formatW, maj, min );
515
516     if (RegCreateKeyExW(HKEY_CLASSES_ROOT, buf, 0, NULL, 0,
517                         KEY_WRITE, NULL, &hkey, NULL) != ERROR_SUCCESS)
518     {
519         trace("RegCreateKeyExW failed\n");
520         return FALSE;
521     }
522
523     wsprintfW(buf, format2W, base, maj, min);
524     if (RegSetValueExW(hkey, NULL, 0, REG_SZ,
525                        (BYTE *)buf, (lstrlenW(buf) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS)
526     {
527         trace("RegSetValueExW failed\n");
528         ret = FALSE;
529     }
530     RegCloseKey(hkey);
531     return ret;
532 }
533
534 static void test_QueryPathOfRegTypeLib(void)
535 {
536     static const struct test_data
537     {
538         WORD maj, min;
539         HRESULT ret;
540         const WCHAR path[16];
541     } td[] = {
542         { 1, 0, TYPE_E_LIBNOTREGISTERED, { 0 } },
543         { 3, 0, S_OK, {'f','a','k','e','_','3','_','0','.','d','l','l',0 } },
544         { 3, 1, S_OK, {'f','a','k','e','_','3','_','1','.','d','l','l',0 } },
545         { 3, 22, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
546         { 3, 37, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
547         { 3, 40, S_OK, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
548         { 4, 0, TYPE_E_LIBNOTREGISTERED, { 0 } }
549     };
550     static const WCHAR base[] = {'f','a','k','e',0};
551     UINT i;
552     RPC_STATUS status;
553     GUID uid;
554     WCHAR uid_str[40];
555     HRESULT ret;
556     BSTR path;
557
558     status = UuidCreate(&uid);
559     ok(!status, "UuidCreate error %08lx\n", status);
560
561     StringFromGUID2(&uid, uid_str, 40);
562     /*trace("GUID: %s\n", wine_dbgstr_w(uid_str));*/
563
564     if (!do_typelib_reg_key(&uid, 3, 0, base, 0)) return;
565     if (!do_typelib_reg_key(&uid, 3, 1, base, 0)) return;
566     if (!do_typelib_reg_key(&uid, 3, 37, base, 0)) return;
567
568     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
569     {
570         ret = QueryPathOfRegTypeLib(&uid, td[i].maj, td[i].min, 0, &path);
571         ok(ret == td[i].ret, "QueryPathOfRegTypeLib(%u.%u) returned %08x\n", td[i].maj, td[i].min, ret);
572         if (ret == S_OK)
573         {
574             ok(!lstrcmpW(td[i].path, path), "typelib %u.%u path doesn't match\n", td[i].maj, td[i].min);
575             SysFreeString(path);
576         }
577     }
578
579     do_typelib_reg_key(&uid, 0, 0, NULL, 1);
580 }
581
582 START_TEST(typelib)
583 {
584     ref_count_test(wszStdOle2);
585     test_TypeComp();
586     test_CreateDispTypeInfo();
587     test_TypeInfo();
588     test_QueryPathOfRegTypeLib();
589 }