2 * ITypeLib and ITypeInfo test
4 * Copyright 2004 Jacek Caban
5 * Copyright 2006 Dmitry Timoshkov
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.
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.
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
24 #include <wine/test.h>
35 #define expect_eq(expr, value, type, format) { type _ret = (expr); ok((value) == _ret, #expr " expected " format " got " format "\n", value, _ret); }
36 #define expect_int(expr, value) expect_eq(expr, (int)(value), int, "%d")
37 #define expect_hex(expr, value) expect_eq(expr, (int)(value), int, "0x%x")
38 #define expect_null(expr) expect_eq(expr, NULL, const void *, "%p")
40 #define expect_wstr_acpval(expr, value) \
43 expect_eq(!WideCharToMultiByte(CP_ACP, 0, (expr), -1, buf, 260, NULL, NULL), 0, int, "%d"); \
44 ok(lstrcmp(value, buf) == 0, #expr " expected \"%s\" got \"%s\"\n", value, buf); \
47 #define ole_expect(expr, expect) { \
49 ok(r == (expect), #expr " returned %x, expected %s (%x)\n", r, #expect, expect); \
52 #define ole_check(expr) ole_expect(expr, S_OK);
54 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
56 static const WCHAR wszStdOle2
[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
58 static void ref_count_test(LPCWSTR type_lib
)
61 ITypeInfo
*iti1
, *iti2
;
65 trace("Loading type library\n");
66 hRes
= LoadTypeLib(type_lib
, &iface
);
67 ok(hRes
== S_OK
, "Could not load type library\n");
71 hRes
= ITypeLib_GetTypeInfo(iface
, 1, &iti1
);
72 ok(hRes
== S_OK
, "ITypeLib_GetTypeInfo failed on index = 1\n");
73 ok(ref_count
=ITypeLib_Release(iface
) > 0, "ITypeLib destroyed while ITypeInfo has back pointer\n");
77 hRes
= ITypeLib_GetTypeInfo(iface
, 1, &iti2
);
78 ok(hRes
== S_OK
, "ITypeLib_GetTypeInfo failed on index = 1\n");
79 ok(iti1
== iti2
, "ITypeLib_GetTypeInfo returned different pointers for same indexes\n");
81 ITypeLib_AddRef(iface
);
82 ITypeInfo_Release(iti2
);
83 ITypeInfo_Release(iti1
);
84 ok(ITypeLib_Release(iface
) == 0, "ITypeLib should be destroyed here.\n");
87 static void test_TypeComp(void)
96 ITypeInfo
*pFontTypeInfo
;
97 static WCHAR wszStdFunctions
[] = {'S','t','d','F','u','n','c','t','i','o','n','s',0};
98 static WCHAR wszSavePicture
[] = {'S','a','v','e','P','i','c','t','u','r','e',0};
99 static WCHAR wszOLE_TRISTATE
[] = {'O','L','E','_','T','R','I','S','T','A','T','E',0};
100 static WCHAR wszUnchecked
[] = {'U','n','c','h','e','c','k','e','d',0};
101 static WCHAR wszIUnknown
[] = {'I','U','n','k','n','o','w','n',0};
102 static WCHAR wszFont
[] = {'F','o','n','t',0};
103 static WCHAR wszGUID
[] = {'G','U','I','D',0};
104 static WCHAR wszStdPicture
[] = {'S','t','d','P','i','c','t','u','r','e',0};
105 static WCHAR wszOLE_COLOR
[] = {'O','L','E','_','C','O','L','O','R',0};
106 static WCHAR wszClone
[] = {'C','l','o','n','e',0};
107 static WCHAR wszclone
[] = {'c','l','o','n','e',0};
109 hr
= LoadTypeLib(wszStdOle2
, &pTypeLib
);
110 ok_ole_success(hr
, LoadTypeLib
);
112 hr
= ITypeLib_GetTypeComp(pTypeLib
, &pTypeComp
);
113 ok_ole_success(hr
, ITypeLib_GetTypeComp
);
115 /* test getting a TKIND_MODULE */
116 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszStdFunctions
);
117 hr
= ITypeComp_Bind(pTypeComp
, wszStdFunctions
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
118 ok_ole_success(hr
, ITypeComp_Bind
);
120 ok(desckind
== DESCKIND_TYPECOMP
,
121 "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
123 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
125 ITypeComp_Release(bindptr
.lptcomp
);
127 /* test getting a TKIND_MODULE with INVOKE_PROPERTYGET */
128 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszStdFunctions
);
129 hr
= ITypeComp_Bind(pTypeComp
, wszStdFunctions
, ulHash
, INVOKE_PROPERTYGET
, &pTypeInfo
, &desckind
, &bindptr
);
130 ok_ole_success(hr
, ITypeComp_Bind
);
132 ok(desckind
== DESCKIND_TYPECOMP
,
133 "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
135 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
136 ITypeComp_Release(bindptr
.lptcomp
);
138 /* test getting a function within a TKIND_MODULE */
139 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszSavePicture
);
140 hr
= ITypeComp_Bind(pTypeComp
, wszSavePicture
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
141 ok_ole_success(hr
, ITypeComp_Bind
);
143 ok(desckind
== DESCKIND_FUNCDESC
,
144 "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
146 ok(bindptr
.lpfuncdesc
!= NULL
, "bindptr.lpfuncdesc should not have been set to NULL\n");
147 ITypeInfo_ReleaseFuncDesc(pTypeInfo
, bindptr
.lpfuncdesc
);
148 ITypeInfo_Release(pTypeInfo
);
150 /* test getting a function within a TKIND_MODULE with INVOKE_PROPERTYGET */
151 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszSavePicture
);
152 hr
= ITypeComp_Bind(pTypeComp
, wszSavePicture
, ulHash
, INVOKE_PROPERTYGET
, &pTypeInfo
, &desckind
, &bindptr
);
153 todo_wine
ok(hr
== TYPE_E_TYPEMISMATCH
,
154 "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n",
157 ok(desckind
== DESCKIND_NONE
,
158 "desckind should have been DESCKIND_NONE instead of %d\n",
160 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
161 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
163 /* test getting a TKIND_ENUM */
164 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszOLE_TRISTATE
);
165 hr
= ITypeComp_Bind(pTypeComp
, wszOLE_TRISTATE
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
166 ok_ole_success(hr
, ITypeComp_Bind
);
168 ok(desckind
== DESCKIND_TYPECOMP
,
169 "desckind should have been DESCKIND_TYPECOMP instead of %d\n",
171 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
173 ITypeComp_Release(bindptr
.lptcomp
);
175 /* test getting a value within a TKIND_ENUM */
176 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszUnchecked
);
177 hr
= ITypeComp_Bind(pTypeComp
, wszUnchecked
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
178 ok_ole_success(hr
, ITypeComp_Bind
);
180 ok(desckind
== DESCKIND_VARDESC
,
181 "desckind should have been DESCKIND_VARDESC instead of %d\n",
183 ITypeInfo_ReleaseVarDesc(pTypeInfo
, bindptr
.lpvardesc
);
184 ITypeInfo_Release(pTypeInfo
);
186 /* test getting a TKIND_INTERFACE */
187 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszIUnknown
);
188 hr
= ITypeComp_Bind(pTypeComp
, wszIUnknown
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
189 ok_ole_success(hr
, ITypeComp_Bind
);
191 ok(desckind
== DESCKIND_NONE
,
192 "desckind should have been DESCKIND_NONE instead of %d\n",
194 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
195 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
197 /* test getting a TKIND_DISPATCH */
198 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszFont
);
199 hr
= ITypeComp_Bind(pTypeComp
, wszFont
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
200 ok_ole_success(hr
, ITypeComp_Bind
);
202 ok(desckind
== DESCKIND_NONE
,
203 "desckind should have been DESCKIND_NONE instead of %d\n",
205 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
206 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
208 /* test getting a TKIND_RECORD/TKIND_ALIAS */
209 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszGUID
);
210 hr
= ITypeComp_Bind(pTypeComp
, wszGUID
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
211 ok_ole_success(hr
, ITypeComp_Bind
);
213 ok(desckind
== DESCKIND_NONE
,
214 "desckind should have been DESCKIND_NONE instead of %d\n",
216 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
217 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
219 /* test getting a TKIND_ALIAS */
220 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszOLE_COLOR
);
221 hr
= ITypeComp_Bind(pTypeComp
, wszOLE_COLOR
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
222 ok_ole_success(hr
, ITypeComp_Bind
);
224 ok(desckind
== DESCKIND_NONE
,
225 "desckind should have been DESCKIND_NONE instead of %d\n",
227 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
228 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
230 /* test getting a TKIND_COCLASS */
231 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszStdPicture
);
232 hr
= ITypeComp_Bind(pTypeComp
, wszStdPicture
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
233 ok_ole_success(hr
, ITypeComp_Bind
);
235 ok(desckind
== DESCKIND_NONE
,
236 "desckind should have been DESCKIND_NONE instead of %d\n",
238 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
239 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
241 ITypeComp_Release(pTypeComp
);
243 /* tests for ITypeComp on an interface */
244 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, &IID_IFont
, &pFontTypeInfo
);
245 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
247 hr
= ITypeInfo_GetTypeComp(pFontTypeInfo
, &pTypeComp
);
248 ok_ole_success(hr
, ITypeLib_GetTypeComp
);
250 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszClone
);
251 hr
= ITypeComp_Bind(pTypeComp
, wszClone
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
252 ok_ole_success(hr
, ITypeComp_Bind
);
254 ok(desckind
== DESCKIND_FUNCDESC
,
255 "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
257 ok(bindptr
.lpfuncdesc
!= NULL
, "bindptr.lpfuncdesc should not have been set to NULL\n");
258 ITypeInfo_ReleaseFuncDesc(pTypeInfo
, bindptr
.lpfuncdesc
);
259 ITypeInfo_Release(pTypeInfo
);
261 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszClone
);
262 hr
= ITypeComp_Bind(pTypeComp
, wszClone
, ulHash
, INVOKE_PROPERTYGET
, &pTypeInfo
, &desckind
, &bindptr
);
263 ok(hr
== TYPE_E_TYPEMISMATCH
, "ITypeComp_Bind should have failed with TYPE_E_TYPEMISMATCH instead of 0x%08x\n", hr
);
265 ok(desckind
== DESCKIND_NONE
,
266 "desckind should have been DESCKIND_NONE instead of %d\n",
268 ok(!pTypeInfo
, "pTypeInfo should have been set to NULL\n");
269 ok(!bindptr
.lptcomp
, "bindptr should have been set to NULL\n");
271 /* tests that the compare is case-insensitive */
272 ulHash
= LHashValOfNameSys(SYS_WIN32
, LOCALE_NEUTRAL
, wszclone
);
273 hr
= ITypeComp_Bind(pTypeComp
, wszclone
, ulHash
, 0, &pTypeInfo
, &desckind
, &bindptr
);
274 ok_ole_success(hr
, ITypeComp_Bind
);
276 ok(desckind
== DESCKIND_FUNCDESC
,
277 "desckind should have been DESCKIND_FUNCDESC instead of %d\n",
279 ok(bindptr
.lpfuncdesc
!= NULL
, "bindptr.lpfuncdesc should not have been set to NULL\n");
280 ITypeInfo_ReleaseFuncDesc(pTypeInfo
, bindptr
.lpfuncdesc
);
281 ITypeInfo_Release(pTypeInfo
);
283 ITypeComp_Release(pTypeComp
);
284 ITypeInfo_Release(pFontTypeInfo
);
285 ITypeLib_Release(pTypeLib
);
288 static void test_CreateDispTypeInfo(void)
290 ITypeInfo
*pTypeInfo
, *pTI2
;
292 INTERFACEDATA ifdata
;
293 METHODDATA methdata
[4];
301 static WCHAR func1
[] = {'f','u','n','c','1',0};
302 static const WCHAR func2
[] = {'f','u','n','c','2',0};
303 static const WCHAR func3
[] = {'f','u','n','c','3',0};
304 static const WCHAR parm1
[] = {'p','a','r','m','1',0};
305 static const WCHAR parm2
[] = {'p','a','r','m','2',0};
306 OLECHAR
*name
= func1
;
308 ifdata
.pmethdata
= methdata
;
309 ifdata
.cMembers
= sizeof(methdata
) / sizeof(methdata
[0]);
311 methdata
[0].szName
= SysAllocString(func1
);
312 methdata
[0].ppdata
= parms1
;
313 methdata
[0].dispid
= 0x123;
314 methdata
[0].iMeth
= 0;
315 methdata
[0].cc
= CC_STDCALL
;
316 methdata
[0].cArgs
= 2;
317 methdata
[0].wFlags
= DISPATCH_METHOD
;
318 methdata
[0].vtReturn
= VT_HRESULT
;
319 parms1
[0].szName
= SysAllocString(parm1
);
320 parms1
[0].vt
= VT_I4
;
321 parms1
[1].szName
= SysAllocString(parm2
);
322 parms1
[1].vt
= VT_BSTR
;
324 methdata
[1].szName
= SysAllocString(func2
);
325 methdata
[1].ppdata
= NULL
;
326 methdata
[1].dispid
= 0x124;
327 methdata
[1].iMeth
= 1;
328 methdata
[1].cc
= CC_STDCALL
;
329 methdata
[1].cArgs
= 0;
330 methdata
[1].wFlags
= DISPATCH_PROPERTYGET
;
331 methdata
[1].vtReturn
= VT_I4
;
333 methdata
[2].szName
= SysAllocString(func3
);
334 methdata
[2].ppdata
= parms3
;
335 methdata
[2].dispid
= 0x125;
336 methdata
[2].iMeth
= 3;
337 methdata
[2].cc
= CC_STDCALL
;
338 methdata
[2].cArgs
= 1;
339 methdata
[2].wFlags
= DISPATCH_PROPERTYPUT
;
340 methdata
[2].vtReturn
= VT_HRESULT
;
341 parms3
[0].szName
= SysAllocString(parm1
);
342 parms3
[0].vt
= VT_I4
;
344 methdata
[3].szName
= SysAllocString(func3
);
345 methdata
[3].ppdata
= NULL
;
346 methdata
[3].dispid
= 0x125;
347 methdata
[3].iMeth
= 4;
348 methdata
[3].cc
= CC_STDCALL
;
349 methdata
[3].cArgs
= 0;
350 methdata
[3].wFlags
= DISPATCH_PROPERTYGET
;
351 methdata
[3].vtReturn
= VT_I4
;
353 hr
= CreateDispTypeInfo(&ifdata
, LOCALE_NEUTRAL
, &pTypeInfo
);
354 ok(hr
== S_OK
, "hr %08x\n", hr
);
356 hr
= ITypeInfo_GetTypeAttr(pTypeInfo
, &pTypeAttr
);
357 ok(hr
== S_OK
, "hr %08x\n", hr
);
359 ok(pTypeAttr
->typekind
== TKIND_COCLASS
, "typekind %0x\n", pTypeAttr
->typekind
);
360 ok(pTypeAttr
->cImplTypes
== 1, "cImplTypes %d\n", pTypeAttr
->cImplTypes
);
361 ok(pTypeAttr
->cFuncs
== 0, "cFuncs %d\n", pTypeAttr
->cFuncs
);
362 ok(pTypeAttr
->wTypeFlags
== 0, "wTypeFlags %04x\n", pTypeAttr
->cFuncs
);
363 ITypeInfo_ReleaseTypeAttr(pTypeInfo
, pTypeAttr
);
365 hr
= ITypeInfo_GetRefTypeOfImplType(pTypeInfo
, 0, &href
);
366 ok(hr
== S_OK
, "hr %08x\n", hr
);
367 ok(href
== 0, "href = 0x%x\n", href
);
368 hr
= ITypeInfo_GetRefTypeInfo(pTypeInfo
, href
, &pTI2
);
369 ok(hr
== S_OK
, "hr %08x\n", hr
);
370 hr
= ITypeInfo_GetTypeAttr(pTI2
, &pTypeAttr
);
371 ok(hr
== S_OK
, "hr %08x\n", hr
);
372 ok(pTypeAttr
->typekind
== TKIND_INTERFACE
, "typekind %0x\n", pTypeAttr
->typekind
);
373 ok(pTypeAttr
->cFuncs
== 4, "cFuncs %d\n", pTypeAttr
->cFuncs
);
374 ok(IsEqualGUID(&pTypeAttr
->guid
, &GUID_NULL
), "guid {%08x-...}\n", pTypeAttr
->guid
.Data1
);
375 ok(pTypeAttr
->wTypeFlags
== 0, "typeflags %08x\n", pTypeAttr
->wTypeFlags
);
377 ITypeInfo_ReleaseTypeAttr(pTI2
, pTypeAttr
);
379 hr
= ITypeInfo_GetFuncDesc(pTI2
, 0, &pFuncDesc
);
380 ok(hr
== S_OK
, "hr %08x\n", hr
);
381 ok(pFuncDesc
->memid
== 0x123, "memid %x\n", pFuncDesc
->memid
);
382 ok(pFuncDesc
->funckind
== FUNC_VIRTUAL
, "funckind %d\n", pFuncDesc
->funckind
);
383 ok(pFuncDesc
->invkind
== methdata
[0].wFlags
, "invkind %d\n", pFuncDesc
->invkind
);
384 ok(pFuncDesc
->callconv
== methdata
[0].cc
, "callconv %d\n", pFuncDesc
->callconv
);
385 ok(pFuncDesc
->cParams
== methdata
[0].cArgs
, "cParams %d\n", pFuncDesc
->cParams
);
386 ok(pFuncDesc
->oVft
== 0, "oVft %d\n", pFuncDesc
->oVft
);
387 ok(pFuncDesc
->wFuncFlags
== 0, "oVft %d\n", pFuncDesc
->wFuncFlags
);
388 ok(pFuncDesc
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
, "ret vt %x\n", pFuncDesc
->elemdescFunc
.tdesc
.vt
);
389 ok(pFuncDesc
->lprgelemdescParam
[0].tdesc
.vt
== VT_I4
, "parm 0 vt %x\n", pFuncDesc
->lprgelemdescParam
[0].tdesc
.vt
);
390 ok(U(pFuncDesc
->lprgelemdescParam
[0]).paramdesc
.wParamFlags
== PARAMFLAG_NONE
, "parm 0 flags %x\n", U(pFuncDesc
->lprgelemdescParam
[0]).paramdesc
.wParamFlags
);
392 ok(pFuncDesc
->lprgelemdescParam
[1].tdesc
.vt
== VT_BSTR
, "parm 1 vt %x\n", pFuncDesc
->lprgelemdescParam
[1].tdesc
.vt
);
393 ok(U(pFuncDesc
->lprgelemdescParam
[1]).paramdesc
.wParamFlags
== PARAMFLAG_NONE
, "parm 1 flags %x\n", U(pFuncDesc
->lprgelemdescParam
[1]).paramdesc
.wParamFlags
);
394 ITypeInfo_ReleaseFuncDesc(pTI2
, pFuncDesc
);
396 hr
= ITypeInfo_GetFuncDesc(pTI2
, 1, &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
[1].wFlags
, "invkind %d\n", pFuncDesc
->invkind
);
400 ok(pFuncDesc
->callconv
== methdata
[1].cc
, "callconv %d\n", pFuncDesc
->callconv
);
401 ok(pFuncDesc
->cParams
== methdata
[1].cArgs
, "cParams %d\n", pFuncDesc
->cParams
);
402 ok(pFuncDesc
->oVft
== sizeof(void *), "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
);
407 hr
= ITypeInfo_GetFuncDesc(pTI2
, 2, &pFuncDesc
);
408 ok(hr
== S_OK
, "hr %08x\n", hr
);
409 ok(pFuncDesc
->funckind
== FUNC_VIRTUAL
, "funckind %d\n", pFuncDesc
->funckind
);
410 ok(pFuncDesc
->invkind
== methdata
[2].wFlags
, "invkind %d\n", pFuncDesc
->invkind
);
411 ok(pFuncDesc
->callconv
== methdata
[2].cc
, "callconv %d\n", pFuncDesc
->callconv
);
412 ok(pFuncDesc
->cParams
== methdata
[2].cArgs
, "cParams %d\n", pFuncDesc
->cParams
);
413 ok(pFuncDesc
->oVft
== 3 * sizeof(void *), "oVft %d\n", pFuncDesc
->oVft
);
414 ok(pFuncDesc
->wFuncFlags
== 0, "oVft %d\n", pFuncDesc
->wFuncFlags
);
415 ok(pFuncDesc
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
, "ret vt %x\n", pFuncDesc
->elemdescFunc
.tdesc
.vt
);
416 ok(pFuncDesc
->lprgelemdescParam
[0].tdesc
.vt
== VT_I4
, "parm 0 vt %x\n", pFuncDesc
->lprgelemdescParam
[0].tdesc
.vt
);
417 ok(U(pFuncDesc
->lprgelemdescParam
[0]).paramdesc
.wParamFlags
== PARAMFLAG_NONE
, "parm 0 flags %x\n", U(pFuncDesc
->lprgelemdescParam
[0]).paramdesc
.wParamFlags
);
418 ITypeInfo_ReleaseFuncDesc(pTI2
, pFuncDesc
);
420 hr
= ITypeInfo_GetFuncDesc(pTI2
, 3, &pFuncDesc
);
421 ok(hr
== S_OK
, "hr %08x\n", hr
);
422 ok(pFuncDesc
->funckind
== FUNC_VIRTUAL
, "funckind %d\n", pFuncDesc
->funckind
);
423 ok(pFuncDesc
->invkind
== methdata
[3].wFlags
, "invkind %d\n", pFuncDesc
->invkind
);
424 ok(pFuncDesc
->callconv
== methdata
[3].cc
, "callconv %d\n", pFuncDesc
->callconv
);
425 ok(pFuncDesc
->cParams
== methdata
[3].cArgs
, "cParams %d\n", pFuncDesc
->cParams
);
426 ok(pFuncDesc
->oVft
== 4 * sizeof(void *), "oVft %d\n", pFuncDesc
->oVft
);
427 ok(pFuncDesc
->wFuncFlags
== 0, "oVft %d\n", pFuncDesc
->wFuncFlags
);
428 ok(pFuncDesc
->elemdescFunc
.tdesc
.vt
== VT_I4
, "ret vt %x\n", pFuncDesc
->elemdescFunc
.tdesc
.vt
);
429 ITypeInfo_ReleaseFuncDesc(pTI2
, pFuncDesc
);
431 /* test GetIDsOfNames on a coclass to see if it searches its interfaces */
432 hr
= ITypeInfo_GetIDsOfNames(pTypeInfo
, &name
, 1, &memid
);
433 ok(hr
== S_OK
, "hr 0x%08x\n", hr
);
434 ok(memid
== 0x123, "memid 0x%08x\n", memid
);
436 ITypeInfo_Release(pTI2
);
437 ITypeInfo_Release(pTypeInfo
);
439 SysFreeString(parms1
[0].szName
);
440 SysFreeString(parms1
[1].szName
);
441 SysFreeString(parms3
[0].szName
);
442 SysFreeString(methdata
[0].szName
);
443 SysFreeString(methdata
[1].szName
);
444 SysFreeString(methdata
[2].szName
);
445 SysFreeString(methdata
[3].szName
);
448 static void test_TypeInfo(void)
451 ITypeInfo
*pTypeInfo
;
453 static WCHAR wszBogus
[] = { 'b','o','g','u','s',0 };
454 static WCHAR wszGetTypeInfo
[] = { 'G','e','t','T','y','p','e','I','n','f','o',0 };
455 static WCHAR wszClone
[] = {'C','l','o','n','e',0};
456 OLECHAR
* bogus
= wszBogus
;
457 OLECHAR
* pwszGetTypeInfo
= wszGetTypeInfo
;
458 OLECHAR
* pwszClone
= wszClone
;
460 DISPPARAMS dispparams
;
462 hr
= LoadTypeLib(wszStdOle2
, &pTypeLib
);
463 ok_ole_success(hr
, LoadTypeLib
);
465 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, &IID_IFont
, &pTypeInfo
);
466 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
468 /* test nonexistent method name */
469 hr
= ITypeInfo_GetIDsOfNames(pTypeInfo
, &bogus
, 1, &dispidMember
);
470 ok(hr
== DISP_E_UNKNOWNNAME
,
471 "ITypeInfo_GetIDsOfNames should have returned DISP_E_UNKNOWNNAME instead of 0x%08x\n",
474 /* test invalid memberid */
475 dispparams
.cNamedArgs
= 0;
476 dispparams
.cArgs
= 0;
477 dispparams
.rgdispidNamedArgs
= NULL
;
478 dispparams
.rgvarg
= NULL
;
479 hr
= ITypeInfo_Invoke(pTypeInfo
, (void *)0xdeadbeef, 0xdeadbeef, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
480 ok(hr
== DISP_E_MEMBERNOTFOUND
, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
482 hr
= ITypeInfo_GetIDsOfNames(pTypeInfo
, &pwszClone
, 1, &dispidMember
);
483 ok_ole_success(hr
, ITypeInfo_GetIDsOfNames
);
485 /* test correct memberid, but wrong flags */
486 hr
= ITypeInfo_Invoke(pTypeInfo
, (void *)0xdeadbeef, dispidMember
, DISPATCH_PROPERTYGET
, &dispparams
, NULL
, NULL
, NULL
);
487 ok(hr
== DISP_E_MEMBERNOTFOUND
, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
489 /* test NULL dispparams */
490 hr
= ITypeInfo_Invoke(pTypeInfo
, (void *)0xdeadbeef, dispidMember
, DISPATCH_METHOD
, NULL
, NULL
, NULL
, NULL
);
491 ok(hr
== E_INVALIDARG
, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
493 /* test dispparams->cNamedArgs being bigger than dispparams->cArgs */
494 dispparams
.cNamedArgs
= 1;
495 hr
= ITypeInfo_Invoke(pTypeInfo
, (void *)0xdeadbeef, dispidMember
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
496 ok(hr
== E_INVALIDARG
, "ITypeInfo_Invoke should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
498 ITypeInfo_Release(pTypeInfo
);
500 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, &IID_IDispatch
, &pTypeInfo
);
501 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
503 hr
= ITypeInfo_GetIDsOfNames(pTypeInfo
, &pwszGetTypeInfo
, 1, &dispidMember
);
504 ok_ole_success(hr
, ITypeInfo_GetIDsOfNames
);
506 /* test invoking a method with a [restricted] keyword */
507 hr
= ITypeInfo_Invoke(pTypeInfo
, NULL
, dispidMember
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
509 ok(hr
== DISP_E_MEMBERNOTFOUND
, "ITypeInfo_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr
);
512 ITypeInfo_Release(pTypeInfo
);
513 ITypeLib_Release(pTypeLib
);
516 /* RegDeleteTreeW from dlls/advapi32/registry.c */
517 static LSTATUS
myRegDeleteTreeW(HKEY hKey
, LPCWSTR lpszSubKey
)
520 DWORD dwMaxSubkeyLen
, dwMaxValueLen
;
521 DWORD dwMaxLen
, dwSize
;
522 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
527 ret
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
531 ret
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
532 &dwMaxSubkeyLen
, NULL
, NULL
, &dwMaxValueLen
, NULL
, NULL
, NULL
);
533 if (ret
) goto cleanup
;
537 dwMaxLen
= max(dwMaxSubkeyLen
, dwMaxValueLen
);
538 if (dwMaxLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
540 /* Name too big: alloc a buffer for it */
541 if (!(lpszName
= HeapAlloc( GetProcessHeap(), 0, dwMaxLen
*sizeof(WCHAR
))))
543 ret
= ERROR_NOT_ENOUGH_MEMORY
;
548 /* Recursively delete all the subkeys */
552 if (RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
,
553 NULL
, NULL
, NULL
)) break;
555 ret
= myRegDeleteTreeW(hSubKey
, lpszName
);
556 if (ret
) goto cleanup
;
560 ret
= RegDeleteKeyW(hKey
, lpszSubKey
);
565 if (RegEnumValueW(hKey
, 0, lpszName
, &dwSize
,
566 NULL
, NULL
, NULL
, NULL
)) break;
568 ret
= RegDeleteValueW(hKey
, lpszName
);
569 if (ret
) goto cleanup
;
573 if (lpszName
!= szNameBuf
)
574 HeapFree(GetProcessHeap(), 0, lpszName
);
576 RegCloseKey(hSubKey
);
580 static BOOL
do_typelib_reg_key(GUID
*uid
, WORD maj
, WORD min
, LPCWSTR base
, BOOL remove
)
582 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
583 static const WCHAR formatW
[] = {'\\','%','u','.','%','u','\\','0','\\','w','i','n','3','2',0};
584 static const WCHAR format2W
[] = {'%','s','_','%','u','_','%','u','.','d','l','l',0};
590 memcpy(buf
, typelibW
, sizeof(typelibW
));
591 StringFromGUID2(uid
, buf
+ lstrlenW(buf
), 40);
595 ok(myRegDeleteTreeW(HKEY_CLASSES_ROOT
, buf
) == ERROR_SUCCESS
, "SHDeleteKey failed\n");
599 wsprintfW(buf
+ lstrlenW(buf
), formatW
, maj
, min
);
601 SetLastError(0xdeadbeef);
602 res
= RegCreateKeyExW(HKEY_CLASSES_ROOT
, buf
, 0, NULL
, 0,
603 KEY_WRITE
, NULL
, &hkey
, NULL
);
604 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
606 win_skip("W-calls are not implemented\n");
610 if (res
!= ERROR_SUCCESS
)
612 trace("RegCreateKeyExW failed\n");
616 wsprintfW(buf
, format2W
, base
, maj
, min
);
617 if (RegSetValueExW(hkey
, NULL
, 0, REG_SZ
,
618 (BYTE
*)buf
, (lstrlenW(buf
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
620 trace("RegSetValueExW failed\n");
627 static void test_QueryPathOfRegTypeLib(void)
629 static const struct test_data
633 const WCHAR path
[16];
635 { 1, 0, TYPE_E_LIBNOTREGISTERED
, { 0 } },
636 { 3, 0, S_OK
, {'f','a','k','e','_','3','_','0','.','d','l','l',0 } },
637 { 3, 1, S_OK
, {'f','a','k','e','_','3','_','1','.','d','l','l',0 } },
638 { 3, 22, S_OK
, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
639 { 3, 37, S_OK
, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
640 { 3, 40, S_OK
, {'f','a','k','e','_','3','_','3','7','.','d','l','l',0 } },
641 { 0xffff, 0xffff, S_OK
, {'f','a','k','e','_','5','_','3','7','.','d','l','l',0 } },
642 { 0xffff, 0, TYPE_E_LIBNOTREGISTERED
, { 0 } },
643 { 3, 0xffff, TYPE_E_LIBNOTREGISTERED
, { 0 } },
644 { 5, 0xffff, TYPE_E_LIBNOTREGISTERED
, { 0 } },
645 { 4, 0, TYPE_E_LIBNOTREGISTERED
, { 0 } }
647 static const WCHAR base
[] = {'f','a','k','e',0};
655 status
= UuidCreate(&uid
);
656 ok(!status
|| status
== RPC_S_UUID_LOCAL_ONLY
, "UuidCreate error %08x\n", status
);
658 StringFromGUID2(&uid
, uid_str
, 40);
659 /*trace("GUID: %s\n", wine_dbgstr_w(uid_str));*/
661 if (!do_typelib_reg_key(&uid
, 3, 0, base
, 0)) return;
662 if (!do_typelib_reg_key(&uid
, 3, 1, base
, 0)) return;
663 if (!do_typelib_reg_key(&uid
, 3, 37, base
, 0)) return;
664 if (!do_typelib_reg_key(&uid
, 5, 37, base
, 0)) return;
666 for (i
= 0; i
< sizeof(td
)/sizeof(td
[0]); i
++)
668 ret
= QueryPathOfRegTypeLib(&uid
, td
[i
].maj
, td
[i
].min
, 0, &path
);
669 ok(ret
== td
[i
].ret
, "QueryPathOfRegTypeLib(%u.%u) returned %08x\n", td
[i
].maj
, td
[i
].min
, ret
);
672 ok(!lstrcmpW(td
[i
].path
, path
), "typelib %u.%u path doesn't match\n", td
[i
].maj
, td
[i
].min
);
677 do_typelib_reg_key(&uid
, 0, 0, NULL
, 1);
680 static void test_inheritance(void)
684 ITypeInfo
*pTI
, *pTI_p
;
688 WCHAR path
[MAX_PATH
];
689 CHAR pathA
[MAX_PATH
];
690 static const WCHAR tl_path
[] = {'.','\\','m','i','d','l','_','t','m','a','r','s','h','a','l','.','t','l','b',0};
692 BOOL use_midl_tlb
= 0;
694 GetModuleFileNameA(NULL
, pathA
, MAX_PATH
);
695 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
698 memcpy(path
, tl_path
, sizeof(tl_path
));
700 hr
= LoadTypeLib(path
, &pTL
);
701 if(FAILED(hr
)) return;
704 /* ItestIF3 is a syntax 2 dispinterface */
705 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &DIID_ItestIF3
, &pTI
);
706 ok(hr
== S_OK
, "hr %08x\n", hr
);
708 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
709 ok(hr
== S_OK
, "hr %08x\n", hr
);
710 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
711 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
712 ok(pTA
->wTypeFlags
== TYPEFLAG_FDISPATCHABLE
, "typeflags %x\n", pTA
->wTypeFlags
);
714 ok(pTA
->cFuncs
== 6, "cfuncs %d\n", pTA
->cFuncs
);
715 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
716 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
718 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
719 ok(hr
== S_OK
, "hr %08x\n", hr
);
720 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
721 ok(hr
== S_OK
, "hr %08x\n", hr
);
722 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
723 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
724 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
725 ITypeInfo_Release(pTI_p
);
727 /* Should have six methods */
728 hr
= ITypeInfo_GetFuncDesc(pTI
, 6, &pFD
);
729 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
730 hr
= ITypeInfo_GetFuncDesc(pTI
, 5, &pFD
);
731 ok(hr
== S_OK
, "hr %08x\n", hr
);
732 ok(pFD
->memid
== 0x60020000, "memid %08x\n", pFD
->memid
);
733 ok(pFD
->oVft
== 5 * sizeof(void *), "oVft %d\n", pFD
->oVft
);
734 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
736 ITypeInfo_Release(pTI
);
739 /* ItestIF4 is a syntax 1 dispinterface */
740 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &DIID_ItestIF4
, &pTI
);
741 ok(hr
== S_OK
, "hr %08x\n", hr
);
743 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
744 ok(hr
== S_OK
, "hr %08x\n", hr
);
745 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
746 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
747 ok(pTA
->wTypeFlags
== TYPEFLAG_FDISPATCHABLE
, "typeflags %x\n", pTA
->wTypeFlags
);
748 ok(pTA
->cFuncs
== 1, "cfuncs %d\n", pTA
->cFuncs
);
749 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
750 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
752 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
753 ok(hr
== S_OK
, "hr %08x\n", hr
);
754 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
755 ok(hr
== S_OK
, "hr %08x\n", hr
);
756 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
757 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
758 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
759 ITypeInfo_Release(pTI_p
);
760 hr
= ITypeInfo_GetFuncDesc(pTI
, 1, &pFD
);
761 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
762 hr
= ITypeInfo_GetFuncDesc(pTI
, 0, &pFD
);
763 ok(hr
== S_OK
, "hr %08x\n", hr
);
764 ok(pFD
->memid
== 0x1c, "memid %08x\n", pFD
->memid
);
765 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
766 ITypeInfo_Release(pTI
);
769 /* ItestIF5 is dual with inherited ifaces which derive from IUnknown but not IDispatch */
770 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &IID_ItestIF5
, &pTI
);
771 ok(hr
== S_OK
, "hr %08x\n", hr
);
773 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
774 ok(hr
== S_OK
, "hr %08x\n", hr
);
777 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
778 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
780 ok(pTA
->wTypeFlags
== TYPEFLAG_FDUAL
, "typeflags %x\n", pTA
->wTypeFlags
);
782 ok(pTA
->cFuncs
== 8, "cfuncs %d\n", pTA
->cFuncs
);
783 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
784 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
786 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
787 ok(hr
== S_OK
, "hr %08x\n", hr
);
788 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
789 ok(hr
== S_OK
, "hr %08x\n", hr
);
790 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
791 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
792 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
793 ITypeInfo_Release(pTI_p
);
795 hr
= ITypeInfo_GetFuncDesc(pTI
, 6, &pFD
);
796 ok(hr
== S_OK
, "hr %08x\n", hr
);
797 ok(pFD
->memid
== 0x1234, "memid %08x\n", pFD
->memid
);
798 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
800 ITypeInfo_Release(pTI
);
802 /* ItestIF7 is dual with inherited ifaces which derive from Dispatch */
803 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &IID_ItestIF7
, &pTI
);
804 ok(hr
== S_OK
, "hr %08x\n", hr
);
806 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
807 ok(hr
== S_OK
, "hr %08x\n", hr
);
808 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
809 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
810 ok(pTA
->wTypeFlags
== (TYPEFLAG_FDISPATCHABLE
|TYPEFLAG_FDUAL
), "typeflags %x\n", pTA
->wTypeFlags
);
811 ok(pTA
->cFuncs
== 10, "cfuncs %d\n", pTA
->cFuncs
);
812 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
813 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
815 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
816 ok(hr
== S_OK
, "hr %08x\n", hr
);
817 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
818 ok(hr
== S_OK
, "hr %08x\n", hr
);
819 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
820 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
821 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
822 ITypeInfo_Release(pTI_p
);
824 hr
= ITypeInfo_GetFuncDesc(pTI
, 9, &pFD
);
825 ok(hr
== S_OK
, "hr %08x\n", hr
);
826 ok(pFD
->memid
== 0x1236, "memid %08x\n", pFD
->memid
);
827 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
828 ITypeInfo_Release(pTI
);
830 /* ItestIF10 is a syntax 2 dispinterface which doesn't derive from IUnknown */
831 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &DIID_ItestIF10
, &pTI
);
832 ok(hr
== S_OK
, "hr %08x\n", hr
);
834 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
835 ok(hr
== S_OK
, "hr %08x\n", hr
);
836 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
837 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
838 ok(pTA
->wTypeFlags
== TYPEFLAG_FDISPATCHABLE
, "typeflags %x\n", pTA
->wTypeFlags
);
840 ok(pTA
->cFuncs
== 3, "cfuncs %d\n", pTA
->cFuncs
);
841 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
842 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
844 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, -1, &href
);
845 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
846 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
847 ok(hr
== S_OK
, "hr %08x\n", hr
);
848 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
849 ok(hr
== S_OK
, "hr %08x\n", hr
);
850 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
851 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
852 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
853 ITypeInfo_Release(pTI_p
);
855 /* Should have three methods */
856 hr
= ITypeInfo_GetFuncDesc(pTI
, 3, &pFD
);
857 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
858 hr
= ITypeInfo_GetFuncDesc(pTI
, 2, &pFD
);
859 ok(hr
== S_OK
, "hr %08x\n", hr
);
860 ok(pFD
->memid
== 0x60010000, "memid %08x\n", pFD
->memid
);
861 ok(pFD
->oVft
== 2 * sizeof(void *), "oVft %d\n", pFD
->oVft
);
862 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
864 ITypeInfo_Release(pTI
);
866 /* ItestIF11 is a syntax 2 dispinterface which derives from IDispatch */
867 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &DIID_ItestIF11
, &pTI
);
868 ok(hr
== S_OK
, "hr %08x\n", hr
);
870 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
871 ok(hr
== S_OK
, "hr %08x\n", hr
);
872 ok(pTA
->typekind
== TKIND_DISPATCH
, "kind %04x\n", pTA
->typekind
);
873 ok(pTA
->cbSizeVft
== 7 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
874 ok(pTA
->wTypeFlags
== TYPEFLAG_FDISPATCHABLE
, "typeflags %x\n", pTA
->wTypeFlags
);
876 ok(pTA
->cFuncs
== 10, "cfuncs %d\n", pTA
->cFuncs
);
877 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
878 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
880 hr
= ITypeInfo_GetRefTypeOfImplType(pTI
, 0, &href
);
881 ok(hr
== S_OK
, "hr %08x\n", hr
);
882 hr
= ITypeInfo_GetRefTypeInfo(pTI
, href
, &pTI_p
);
883 ok(hr
== S_OK
, "hr %08x\n", hr
);
884 hr
= ITypeInfo_GetTypeAttr(pTI_p
, &pTA
);
885 ok(IsEqualGUID(&pTA
->guid
, &IID_IDispatch
), "guid {%08x-....\n", pTA
->guid
.Data1
);
886 ITypeInfo_ReleaseTypeAttr(pTI_p
, pTA
);
887 ITypeInfo_Release(pTI_p
);
889 /* Should have ten methods */
890 hr
= ITypeInfo_GetFuncDesc(pTI
, 10, &pFD
);
891 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
892 hr
= ITypeInfo_GetFuncDesc(pTI
, 9, &pFD
);
893 ok(hr
== S_OK
, "hr %08x\n", hr
);
894 ok(pFD
->memid
== 0x1236, "memid %08x\n", pFD
->memid
);
895 ok(pFD
->oVft
== 9 * sizeof(void *), "oVft %d\n", pFD
->oVft
);
896 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
898 ITypeInfo_Release(pTI
);
901 /* ItestIF2 is an interface which derives from IUnknown */
902 hr
= ITypeLib_GetTypeInfoOfGuid(pTL
, &IID_ItestIF2
, &pTI
);
903 ok(hr
== S_OK
, "hr %08x\n", hr
);
905 hr
= ITypeInfo_GetTypeAttr(pTI
, &pTA
);
906 ok(hr
== S_OK
, "hr %08x\n", hr
);
907 ok(pTA
->typekind
== TKIND_INTERFACE
, "kind %04x\n", pTA
->typekind
);
908 ok(pTA
->cbSizeVft
== 6 * sizeof(void *), "sizevft %d\n", pTA
->cbSizeVft
);
909 ok(pTA
->wTypeFlags
== 0, "typeflags %x\n", pTA
->wTypeFlags
);
911 ok(pTA
->cFuncs
== 1, "cfuncs %d\n", pTA
->cFuncs
);
912 ok(pTA
->cImplTypes
== 1, "cimpltypes %d\n", pTA
->cImplTypes
);
913 ITypeInfo_ReleaseTypeAttr(pTI
, pTA
);
915 /* Should have one method */
916 hr
= ITypeInfo_GetFuncDesc(pTI
, 1, &pFD
);
917 ok(hr
== TYPE_E_ELEMENTNOTFOUND
, "hr %08x\n", hr
);
918 hr
= ITypeInfo_GetFuncDesc(pTI
, 0, &pFD
);
919 ok(hr
== S_OK
, "hr %08x\n", hr
);
920 ok(pFD
->memid
== 0x60020000, "memid %08x\n", pFD
->memid
);
921 ok(pFD
->oVft
== 5 * sizeof(void *), "oVft %d\n", pFD
->oVft
);
922 ITypeInfo_ReleaseFuncDesc(pTI
, pFD
);
924 ITypeInfo_Release(pTI
);
926 ITypeLib_Release(pTL
);
931 #if 0 /* use this to generate more tests */
933 #define OLE_CHECK(x) { HRESULT hr = x; if (FAILED(hr)) { printf(#x "failed - %x\n", hr); return; } }
935 static char *dump_string(LPWSTR wstr
)
937 int size
= lstrlenW(wstr
)+3;
938 char *out
= CoTaskMemAlloc(size
);
939 WideCharToMultiByte(20127, 0, wstr
, -1, out
+1, size
, NULL
, NULL
);
951 #define MAP_ENTRY(x) { x, #x }
952 static const struct map_entry tkind_map
[] = {
953 MAP_ENTRY(TKIND_ENUM
),
954 MAP_ENTRY(TKIND_RECORD
),
955 MAP_ENTRY(TKIND_MODULE
),
956 MAP_ENTRY(TKIND_INTERFACE
),
957 MAP_ENTRY(TKIND_DISPATCH
),
958 MAP_ENTRY(TKIND_COCLASS
),
959 MAP_ENTRY(TKIND_ALIAS
),
960 MAP_ENTRY(TKIND_UNION
),
961 MAP_ENTRY(TKIND_MAX
),
965 static const struct map_entry funckind_map
[] = {
966 MAP_ENTRY(FUNC_VIRTUAL
),
967 MAP_ENTRY(FUNC_PUREVIRTUAL
),
968 MAP_ENTRY(FUNC_NONVIRTUAL
),
969 MAP_ENTRY(FUNC_STATIC
),
970 MAP_ENTRY(FUNC_DISPATCH
),
974 static const struct map_entry invkind_map
[] = {
975 MAP_ENTRY(INVOKE_FUNC
),
976 MAP_ENTRY(INVOKE_PROPERTYGET
),
977 MAP_ENTRY(INVOKE_PROPERTYPUT
),
978 MAP_ENTRY(INVOKE_PROPERTYPUTREF
),
984 static const char *map_value(DWORD val
, const struct map_entry
*map
)
987 static char bufs
[16][256];
992 if (map
->value
== val
)
997 buf
= bufs
[(map_id
++)%16];
998 sprintf(buf
, "0x%x", val
);
1002 static void test_dump_typelib(const char *name
)
1004 WCHAR wszString
[260];
1010 MultiByteToWideChar(CP_ACP
, 0, name
, -1, wszString
, 260);
1011 OLE_CHECK(LoadTypeLib(wszString
, &lib
));
1012 count
= ITypeLib_GetTypeInfoCount(lib
);
1013 printf("/* interfaces count: %d */\n", count
);
1014 for (i
= 0; i
< count
; i
++)
1020 OLE_CHECK(ITypeLib_GetDocumentation(lib
, i
, &name
, NULL
, NULL
, NULL
));
1022 " %s,\n", dump_string(name
));
1023 SysFreeString(name
);
1025 OLE_CHECK(ITypeLib_GetTypeInfo(lib
, i
, &info
));
1026 ITypeInfo_GetTypeAttr(info
, &attr
);
1027 printf(" /*kind*/ %s, /*flags*/ 0x%x, /*align*/ %d, /*size*/ %d,\n"
1028 " /*#vtbl*/ %d, /*#func*/ %d,\n"
1030 map_value(attr
->typekind
, tkind_map
), attr
->wTypeFlags
, attr
->cbAlignment
, attr
->cbSizeInstance
, attr
->cbSizeVft
,
1032 ITypeInfo_ReleaseTypeAttr(info
, attr
);
1040 if (FAILED(ITypeInfo_GetFuncDesc(info
, f
, &desc
)))
1043 " 0x%x, /*func*/ %s, /*inv*/ %s, /*call*/ 0x%x,\n",
1044 desc
->memid
, map_value(desc
->funckind
, funckind_map
), map_value(desc
->invkind
, invkind_map
),
1046 printf(" /*#param*/ %d, /*#opt*/ %d, /*vtbl*/ %d, /*#scodes*/ %d, /*flags*/ 0x%x,\n",
1047 desc
->cParams
, desc
->cParamsOpt
, desc
->oVft
, desc
->cScodes
, desc
->wFuncFlags
);
1048 printf(" {%d, %x}, /* ret */\n", desc
->elemdescFunc
.tdesc
.vt
, desc
->elemdescFunc
.paramdesc
.wParamFlags
);
1049 printf(" { /* params */\n");
1050 for (p
= 0; p
< desc
->cParams
; p
++)
1052 ELEMDESC e
= desc
->lprgelemdescParam
[p
];
1053 printf(" {%d, %x},\n", e
.tdesc
.vt
, e
.paramdesc
.wParamFlags
);
1055 printf(" {-1, -1}\n");
1057 printf(" { /* names */\n");
1058 OLE_CHECK(ITypeInfo_GetNames(info
, desc
->memid
, tab
, 256, &cNames
));
1059 for (p
= 0; p
< cNames
; p
++)
1061 printf(" %s,\n", dump_string(tab
[p
]));
1062 SysFreeString(tab
[p
]);
1067 ITypeInfo_ReleaseFuncDesc(info
, desc
);
1072 ITypeInfo_Release(info
);
1074 ITypeLib_Release(lib
);
1079 typedef struct _element_info
1085 typedef struct _function_info
1096 element_info ret_type
;
1097 element_info params
[15];
1101 typedef struct _interface_info
1107 USHORT cbSizeInstance
;
1110 function_info funcs
[20];
1113 static const interface_info info
[] = {
1114 /* interfaces count: 2 */
1117 /*kind*/ TKIND_DISPATCH
, /*flags*/ 0x1040, /*align*/ 4, /*size*/ 4,
1118 /*#vtbl*/ 7, /*#func*/ 8,
1121 0x60000000, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1122 /*#param*/ 2, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0x1,
1137 0x60000001, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1138 /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 1, /*#scodes*/ 0, /*flags*/ 0x1,
1149 0x60000002, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1150 /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 2, /*#scodes*/ 0, /*flags*/ 0x1,
1161 0x60010000, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1162 /*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 3, /*#scodes*/ 0, /*flags*/ 0x1,
1175 0x60010001, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1176 /*#param*/ 3, /*#opt*/ 0, /*vtbl*/ 4, /*#scodes*/ 0, /*flags*/ 0x1,
1193 0x60010002, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1194 /*#param*/ 5, /*#opt*/ 0, /*vtbl*/ 5, /*#scodes*/ 0, /*flags*/ 0x1,
1215 0x60010003, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1216 /*#param*/ 8, /*#opt*/ 0, /*vtbl*/ 6, /*#scodes*/ 0, /*flags*/ 0x1,
1243 0x60020000, /*func*/ FUNC_DISPATCH
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1244 /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0x0,
1258 /*kind*/ TKIND_INTERFACE
, /*flags*/ 0x1000, /*align*/ 4, /*size*/ 4,
1259 /*#vtbl*/ 8, /*#func*/ 1,
1262 0x60020000, /*func*/ FUNC_PUREVIRTUAL
, /*inv*/ INVOKE_FUNC
, /*call*/ 0x4,
1263 /*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0x0,
1277 #define check_type(elem, info) { \
1278 expect_int((elem)->tdesc.vt, (info)->vt); \
1279 expect_hex(U(*(elem)).paramdesc.wParamFlags, (info)->wParamFlags); \
1282 static void test_dump_typelib(const char *name
)
1284 WCHAR wszName
[MAX_PATH
];
1286 int ifcount
= sizeof(info
)/sizeof(info
[0]);
1289 MultiByteToWideChar(CP_ACP
, 0, name
, -1, wszName
, MAX_PATH
);
1290 ole_check(LoadTypeLibEx(wszName
, REGKIND_NONE
, &typelib
));
1291 expect_eq(ITypeLib_GetTypeInfoCount(typelib
), ifcount
, UINT
, "%d");
1292 for (iface
= 0; iface
< ifcount
; iface
++)
1294 const interface_info
*if_info
= &info
[iface
];
1295 ITypeInfo
*typeinfo
;
1299 trace("Interface %s\n", if_info
->name
);
1300 ole_check(ITypeLib_GetTypeInfo(typelib
, iface
, &typeinfo
));
1301 ole_check(ITypeLib_GetDocumentation(typelib
, iface
, &bstrIfName
, NULL
, NULL
, NULL
));
1302 expect_wstr_acpval(bstrIfName
, if_info
->name
);
1303 SysFreeString(bstrIfName
);
1305 ole_check(ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
));
1306 expect_int(typeattr
->typekind
, if_info
->type
);
1307 expect_hex(typeattr
->wTypeFlags
, if_info
->wTypeFlags
);
1308 expect_int(typeattr
->cbAlignment
, if_info
->cbAlignment
);
1309 expect_int(typeattr
->cbSizeInstance
, if_info
->cbSizeInstance
);
1310 expect_int(typeattr
->cbSizeVft
, if_info
->cbSizeVft
* sizeof(void*));
1311 expect_int(typeattr
->cFuncs
, if_info
->cFuncs
);
1313 for (func
= 0; func
< typeattr
->cFuncs
; func
++)
1315 function_info
*fn_info
= (function_info
*)&if_info
->funcs
[func
];
1321 trace("Function %s\n", fn_info
->names
[0]);
1322 ole_check(ITypeInfo_GetFuncDesc(typeinfo
, func
, &desc
));
1323 expect_int(desc
->memid
, fn_info
->memid
);
1324 expect_int(desc
->funckind
, fn_info
->funckind
);
1325 expect_int(desc
->invkind
, fn_info
->invkind
);
1326 expect_int(desc
->callconv
, fn_info
->callconv
);
1327 expect_int(desc
->cParams
, fn_info
->cParams
);
1328 expect_int(desc
->cParamsOpt
, fn_info
->cParamsOpt
);
1329 ok( desc
->oVft
== fn_info
->vtbl_index
* sizeof(void*) ||
1330 broken(desc
->oVft
== fn_info
->vtbl_index
* 4), /* xp64 */
1331 "desc->oVft got %u\n", desc
->oVft
);
1332 expect_int(desc
->cScodes
, fn_info
->cScodes
);
1333 expect_int(desc
->wFuncFlags
, fn_info
->wFuncFlags
);
1334 ole_check(ITypeInfo_GetNames(typeinfo
, desc
->memid
, namesTab
, 256, &cNames
));
1335 for (i
= 0; i
< cNames
; i
++)
1337 expect_wstr_acpval(namesTab
[i
], fn_info
->names
[i
]);
1338 SysFreeString(namesTab
[i
]);
1340 expect_null(fn_info
->names
[cNames
]);
1342 check_type(&desc
->elemdescFunc
, &fn_info
->ret_type
);
1343 for (i
= 0 ; i
< desc
->cParams
; i
++)
1345 check_type(&desc
->lprgelemdescParam
[i
], &fn_info
->params
[i
]);
1347 expect_int(fn_info
->params
[desc
->cParams
].vt
, (VARTYPE
)-1);
1349 ITypeInfo_ReleaseFuncDesc(typeinfo
, desc
);
1352 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
1353 ITypeInfo_Release(typeinfo
);
1355 ITypeLib_Release(typelib
);
1360 static const char *create_test_typelib(void)
1362 static char filename
[MAX_PATH
];
1368 GetTempFileNameA( ".", "tlb", 0, filename
);
1369 file
= CreateFile( filename
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0 );
1370 ok( file
!= INVALID_HANDLE_VALUE
, "file creation failed\n" );
1371 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
1372 res
= FindResource( GetModuleHandle(0), MAKEINTRESOURCE(2), "TYPELIB" );
1373 ok( res
!= 0, "couldn't find resource\n" );
1374 ptr
= LockResource( LoadResource( GetModuleHandle(0), res
));
1375 WriteFile( file
, ptr
, SizeofResource( GetModuleHandle(0), res
), &written
, NULL
);
1376 ok( written
== SizeofResource( GetModuleHandle(0), res
), "couldn't write resource\n" );
1377 CloseHandle( file
);
1381 static void test_create_typelib_lcid(LCID lcid
)
1383 char filename
[MAX_PATH
];
1384 WCHAR name
[MAX_PATH
];
1386 ICreateTypeLib2
*tl
;
1388 DWORD msft_header
[5]; /* five is enough for now */
1391 GetTempFileNameA( ".", "tlb", 0, filename
);
1392 MultiByteToWideChar(CP_ACP
, 0, filename
, -1, name
, MAX_PATH
);
1394 hr
= CreateTypeLib2(SYS_WIN32
, name
, &tl
);
1395 ok(hr
== S_OK
, "got %08x\n", hr
);
1397 hr
= ICreateTypeLib2_SetLcid(tl
, lcid
);
1398 ok(hr
== S_OK
, "got %08x\n", hr
);
1400 hr
= ICreateTypeLib2_SaveAllChanges(tl
);
1401 ICreateTypeLib2_Release(tl
);
1403 file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
1404 ok( file
!= INVALID_HANDLE_VALUE
, "file creation failed\n" );
1406 ReadFile( file
, msft_header
, sizeof(msft_header
), &read
, NULL
);
1407 ok(read
== sizeof(msft_header
), "read %d\n", read
);
1408 CloseHandle( file
);
1410 ok(msft_header
[0] == 0x5446534d, "got %08x\n", msft_header
[0]);
1411 ok(msft_header
[1] == 0x00010002, "got %08x\n", msft_header
[1]);
1412 ok(msft_header
[2] == 0xffffffff, "got %08x\n", msft_header
[2]);
1413 ok(msft_header
[3] == (lcid
? lcid
: 0x409), "got %08x (lcid %08x)\n", msft_header
[3], lcid
);
1414 ok(msft_header
[4] == lcid
, "got %08x (lcid %08x)\n", msft_header
[4], lcid
);
1416 DeleteFileA(filename
);
1419 static void test_create_typelibs(void)
1421 test_create_typelib_lcid(LOCALE_SYSTEM_DEFAULT
);
1422 test_create_typelib_lcid(LOCALE_USER_DEFAULT
);
1423 test_create_typelib_lcid(LOCALE_NEUTRAL
);
1425 test_create_typelib_lcid(0x009);
1426 test_create_typelib_lcid(0x409);
1427 test_create_typelib_lcid(0x809);
1429 test_create_typelib_lcid(0x007);
1430 test_create_typelib_lcid(0x407);
1435 const char *filename
;
1437 ref_count_test(wszStdOle2
);
1439 test_CreateDispTypeInfo();
1441 test_QueryPathOfRegTypeLib();
1444 if ((filename
= create_test_typelib()))
1446 test_dump_typelib( filename
);
1447 DeleteFile( filename
);
1450 test_create_typelibs();