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