oleaut32: Fix several memory leaks in tests.
[wine] / dlls / oleaut32 / tests / olefont.c
1 /*
2  * OLEFONT test program
3  *
4  * Copyright 2003 Marcus Meissner
5  * Copyright 2006 (Google) Benjamin Arai
6  *
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <float.h>
27
28 #define COBJMACROS
29
30 #include <wine/test.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winuser.h>
34 #include <wingdi.h>
35 #include <winnls.h>
36 #include <winerror.h>
37 #include <winnt.h>
38 #include <initguid.h>
39 #include <wtypes.h>
40 #include <olectl.h>
41 #include <ocidl.h>
42
43 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
44
45 static WCHAR MSSansSerif_font[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
46 static WCHAR system_font[] = { 'S','y','s','t','e','m',0 };
47 static WCHAR arial_font[] = { 'A','r','i','a','l',0 };
48
49 static HMODULE hOleaut32;
50
51 static HRESULT (WINAPI *pOleCreateFontIndirect)(LPFONTDESC,REFIID,LPVOID*);
52
53 #define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08x\n", hr)
54
55 /* Create a font with cySize given by lo_size, hi_size,  */
56 /* SetRatio to ratio_logical, ratio_himetric,            */
57 /* check that resulting hfont has height hfont_height.   */
58 /* Various checks along the way.                         */
59
60 static void test_ifont_sizes(LONG lo_size, LONG hi_size,
61         LONG ratio_logical, LONG ratio_himetric,
62         LONG hfont_height, const char * test_name)
63 {
64         FONTDESC fd;
65         LPVOID pvObj = NULL;
66         IFont* ifnt = NULL;
67         HFONT hfont;
68         LOGFONT lf;
69         CY psize;
70         HRESULT hres;
71
72         fd.cbSizeofstruct = sizeof(FONTDESC);
73         fd.lpstrName      = system_font;
74         S(fd.cySize).Lo   = lo_size;
75         S(fd.cySize).Hi   = hi_size;
76         fd.sWeight        = 0;
77         fd.sCharset       = 0;
78         fd.fItalic        = 0;
79         fd.fUnderline     = 0;
80         fd.fStrikethrough = 0;
81
82         /* Create font, test that it worked. */
83         hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
84         ifnt = pvObj;
85         ok(hres == S_OK,"%s: OCFI returns 0x%08x instead of S_OK.\n",
86                 test_name, hres);
87         ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name);
88
89         /* Read back size.  Hi part was ignored. */
90         hres = IFont_get_Size(ifnt, &psize);
91         ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
92                 test_name, hres);
93         ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
94                 "%s: get_Size: Lo=%d, Hi=%d; expected Lo=%d, Hi=0.\n",
95                 test_name, S(psize).Lo, S(psize).Hi, lo_size);
96
97         /* Change ratio, check size unchanged.  Standard is 72, 2540. */
98         hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric);
99         ok(hres == S_OK,"%s: IFont_SR returns 0x%08x instead of S_OK.\n",
100                 test_name, hres);
101         hres = IFont_get_Size(ifnt, &psize);
102         ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
103                 test_name, hres);
104         ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
105                 "%s: gS after SR: Lo=%d, Hi=%d; expected Lo=%d, Hi=0.\n",
106                 test_name, S(psize).Lo, S(psize).Hi, lo_size);
107
108         /* Check hFont size with this ratio.  This tests an important   */
109         /* conversion for which MSDN is very wrong.                     */
110         hres = IFont_get_hFont (ifnt, &hfont);
111         ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n",
112                 test_name, hres);
113         hres = GetObject (hfont, sizeof(LOGFONT), &lf);
114         ok(lf.lfHeight == hfont_height,
115                 "%s: hFont has lf.lfHeight=%d, expected %d.\n",
116                 test_name, lf.lfHeight, hfont_height);
117
118         /* Free IFont. */
119         IFont_Release(ifnt);
120 }
121
122 static void test_QueryInterface(void)
123 {
124         LPVOID pvObj = NULL;
125         HRESULT hres;
126         IFont*  font = NULL;
127         LONG ret;
128
129         hres = pOleCreateFontIndirect(NULL, &IID_IFont, &pvObj);
130         font = pvObj;
131
132         ok(hres == S_OK,"OCFI (NULL,..) does not return 0, but 0x%08x\n",hres);
133         ok(font != NULL,"OCFI (NULL,..) returns NULL, instead of !NULL\n");
134
135         pvObj = NULL;
136         hres = IFont_QueryInterface( font, &IID_IFont, &pvObj);
137
138         /* Test if QueryInterface increments ref counter for IFONTs */
139         ret = IFont_AddRef(font);
140         ok(ret == 3 ||
141            broken(ret == 1), /* win95 */
142            "IFont_QI expected ref value 3 but instead got %d\n",ret);
143         IFont_Release(font);
144
145         ok(hres == S_OK,"IFont_QI does not return S_OK, but 0x%08x\n", hres);
146         ok(pvObj != NULL,"IFont_QI does return NULL, instead of a ptr\n");
147
148         /* Original ref and QueryInterface ref both have to be released */
149         IFont_Release(font);
150         IFont_Release(font);
151 }
152
153 static void test_type_info(void)
154 {
155         LPVOID pvObj = NULL;
156         HRESULT hres;
157         IFontDisp*  fontdisp = NULL;
158         ITypeInfo* pTInfo;
159         WCHAR name_Name[] = {'N','a','m','e',0};
160         BSTR names[3];
161         UINT n;
162         LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
163                 SORT_DEFAULT);
164         DISPPARAMS dispparams;
165         VARIANT varresult;
166
167         pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
168         fontdisp = pvObj;
169
170         hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo);
171         ok(hres == S_OK, "GTI returned 0x%08x instead of S_OK.\n", hres);
172         ok(pTInfo != NULL, "GTI returned NULL.\n");
173
174         hres = ITypeInfo_GetNames(pTInfo, DISPID_FONT_NAME, names, 3, &n);
175         ok(hres == S_OK, "GetNames returned 0x%08x instead of S_OK.\n", hres);
176         ok(n == 1, "GetNames returned %d names instead of 1.\n", n);
177         ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n");
178         SysFreeString(names[0]);
179
180         ITypeInfo_Release(pTInfo);
181
182         dispparams.cNamedArgs = 0;
183         dispparams.rgdispidNamedArgs = NULL;
184         dispparams.cArgs = 0;
185         dispparams.rgvarg = NULL;
186         VariantInit(&varresult);
187         hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL,
188             LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult,
189             NULL, NULL);
190         ok(hres == S_OK, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres);
191         VariantClear(&varresult);
192
193         IFontDisp_Release(fontdisp);
194 }
195
196 static HRESULT WINAPI FontEventsDisp_QueryInterface(
197         IFontEventsDisp *iface,
198     /* [in] */ REFIID riid,
199     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
200 {
201     if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
202     {
203         IUnknown_AddRef(iface);
204         *ppvObject = iface;
205         return S_OK;
206     }
207     else
208     {
209         *ppvObject = NULL;
210         return E_NOINTERFACE;
211     }
212 }
213
214 static ULONG WINAPI FontEventsDisp_AddRef(
215     IFontEventsDisp *iface)
216 {
217     return 2;
218 }
219
220 static ULONG WINAPI FontEventsDisp_Release(
221         IFontEventsDisp *iface)
222 {
223     return 1;
224 }
225
226 static int fonteventsdisp_invoke_called = 0;
227
228 static HRESULT WINAPI FontEventsDisp_Invoke(
229         IFontEventsDisp __RPC_FAR * iface,
230     /* [in] */ DISPID dispIdMember,
231     /* [in] */ REFIID riid,
232     /* [in] */ LCID lcid,
233     /* [in] */ WORD wFlags,
234     /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
235     /* [out] */ VARIANT __RPC_FAR *pVarResult,
236     /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
237     /* [out] */ UINT __RPC_FAR *puArgErr)
238 {
239     static const WCHAR wszBold[] = {'B','o','l','d',0};
240     ok(wFlags == INVOKE_FUNC, "invoke flags should have been INVOKE_FUNC instead of 0x%x\n", wFlags);
241     ok(dispIdMember == DISPID_FONT_CHANGED, "dispIdMember should have been DISPID_FONT_CHANGED instead of 0x%x\n", dispIdMember);
242     ok(pDispParams->cArgs == 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams->cArgs);
243     ok(V_VT(&pDispParams->rgvarg[0]) == VT_BSTR, "VT of first param should have been VT_BSTR instead of %d\n", V_VT(&pDispParams->rgvarg[0]));
244     ok(!lstrcmpW(V_BSTR(&pDispParams->rgvarg[0]), wszBold), "String in first param should have been \"Bold\"\n");
245
246     fonteventsdisp_invoke_called++;
247     return S_OK;
248 }
249
250 static IFontEventsDispVtbl FontEventsDisp_Vtbl =
251 {
252     FontEventsDisp_QueryInterface,
253     FontEventsDisp_AddRef,
254     FontEventsDisp_Release,
255     NULL,
256     NULL,
257     NULL,
258     FontEventsDisp_Invoke
259 };
260
261 static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl };
262
263 static void test_font_events_disp(void)
264 {
265     IFont *pFont;
266     IFont *pFont2;
267     IConnectionPointContainer *pCPC;
268     IConnectionPoint *pCP;
269     FONTDESC fontdesc;
270     HRESULT hr;
271     DWORD dwCookie;
272     IFontDisp *pFontDisp;
273     DISPPARAMS dispparams;
274     VARIANTARG vararg;
275
276     fontdesc.cbSizeofstruct = sizeof(fontdesc);
277     fontdesc.lpstrName = MSSansSerif_font;
278     fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */
279     fontdesc.sWeight = FW_NORMAL;
280     fontdesc.sCharset = 0;
281     fontdesc.fItalic = FALSE;
282     fontdesc.fUnderline = FALSE;
283     fontdesc.fStrikethrough = FALSE;
284
285     hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont);
286     ok_ole_success(hr, "OleCreateFontIndirect");
287
288     hr = IFont_QueryInterface(pFont, &IID_IConnectionPointContainer, (void **)&pCPC);
289     ok_ole_success(hr, "IFont_QueryInterface");
290
291     hr = IConnectionPointContainer_FindConnectionPoint(pCPC, &IID_IFontEventsDisp, &pCP);
292     ok_ole_success(hr, "IConnectionPointContainer_FindConnectionPoint");
293     IConnectionPointContainer_Release(pCPC);
294
295     hr = IConnectionPoint_Advise(pCP, (IUnknown *)&FontEventsDisp, &dwCookie);
296     ok_ole_success(hr, "IConnectionPoint_Advise");
297     IConnectionPoint_Release(pCP);
298
299     hr = IFont_put_Bold(pFont, TRUE);
300     ok_ole_success(hr, "IFont_put_Bold");
301
302     ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n");
303
304     hr = IFont_QueryInterface(pFont, &IID_IFontDisp, (void **)&pFontDisp);
305     ok_ole_success(hr, "IFont_QueryInterface");
306
307     V_VT(&vararg) = VT_BOOL;
308     V_BOOL(&vararg) = VARIANT_FALSE;
309     dispparams.cNamedArgs = 0;
310     dispparams.rgdispidNamedArgs = NULL;
311     dispparams.cArgs = 1;
312     dispparams.rgvarg = &vararg;
313     hr = IFontDisp_Invoke(pFontDisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
314
315     IFontDisp_Release(pFontDisp);
316
317     ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
318         fonteventsdisp_invoke_called);
319
320     hr = IFont_Clone(pFont, &pFont2);
321     ok_ole_success(hr, "IFont_Clone");
322     IFont_Release(pFont);
323
324     hr = IFont_put_Bold(pFont2, FALSE);
325     ok_ole_success(hr, "IFont_put_Bold");
326
327     /* this test shows that the notification routine isn't called again */
328     ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
329         fonteventsdisp_invoke_called);
330
331     IFont_Release(pFont2);
332 }
333
334 static void test_names_ids(WCHAR* w_name_1, const char* a_name_1,
335                     WCHAR* w_name_2, const char* a_name_2,
336                     LCID lcid, DISPID id_1, DISPID id_2,
337                     HRESULT hres_expect, int numnames)
338 {
339     LPVOID pvObj = NULL;
340     IFontDisp *fontdisp = NULL;
341     HRESULT hres;
342     DISPID rgDispId[2] = {0xdeadbeef, 0xdeadbeef};
343     LPOLESTR names[2] = {w_name_1, w_name_2};
344
345     pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
346     fontdisp = pvObj;
347
348     hres = IFontDisp_GetIDsOfNames(fontdisp, &IID_NULL, names, numnames,
349                                    lcid, rgDispId);
350
351     /* test hres */
352     ok(hres == hres_expect,
353         "GetIDsOfNames: \"%s\", \"%s\" returns 0x%08x, expected 0x%08x.\n",
354         a_name_1, a_name_2, hres, hres_expect);
355
356     /* test first DISPID */
357     ok(rgDispId[0]==id_1,
358         "GetIDsOfNames: \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
359         a_name_1, rgDispId[0], id_1);
360
361     /* test second DISPID is present */
362     if (numnames == 2)
363     {
364         ok(rgDispId[1]==id_2,
365             "GetIDsOfNames: ..., \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
366             a_name_2, rgDispId[1], id_2);
367     }
368
369    IFontDisp_Release(fontdisp);
370 }
371
372 static void test_GetIDsOfNames(void)
373 {
374     WCHAR name_Name[] = {'N','a','m','e',0};
375     WCHAR name_Italic[] = {'I','t','a','l','i','c',0};
376     WCHAR name_Size[] = {'S','i','z','e',0};
377     WCHAR name_Bold[] = {'B','o','l','d',0};
378     WCHAR name_Underline[] = {'U','n','d','e','r','l','i','n','e',0};
379     WCHAR name_Strikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
380     WCHAR name_Weight[] = {'W','e','i','g','h','t',0};
381     WCHAR name_Charset[] = {'C','h','a','r','s','e','t',0};
382     WCHAR name_Foo[] = {'F','o','o',0};
383     WCHAR name_nAmE[] = {'n','A','m','E',0};
384     WCHAR name_Nom[] = {'N','o','m',0};
385
386     LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
387                           SORT_DEFAULT);
388     LCID fr_fr = MAKELCID(MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH),
389                           SORT_DEFAULT);
390
391     /* Test DISPID_FONTs for the various properties. */
392     test_names_ids(name_Name, "Name", NULL, "", en_us,
393                    DISPID_FONT_NAME, 0, S_OK,1);
394     test_names_ids(name_Size, "Size", NULL, "", en_us,
395                    DISPID_FONT_SIZE, 0, S_OK,1);
396     test_names_ids(name_Bold, "Bold", NULL, "", en_us,
397                    DISPID_FONT_BOLD, 0, S_OK,1);
398     test_names_ids(name_Italic, "Italic", NULL, "", en_us,
399                    DISPID_FONT_ITALIC, 0, S_OK,1);
400     test_names_ids(name_Underline, "Underline", NULL, "", en_us,
401                    DISPID_FONT_UNDER, 0, S_OK,1);
402     test_names_ids(name_Strikethrough, "Strikethrough", NULL, "", en_us,
403                    DISPID_FONT_STRIKE, 0, S_OK,1);
404     test_names_ids(name_Weight, "Weight", NULL, "", en_us,
405                    DISPID_FONT_WEIGHT, 0, S_OK,1);
406     test_names_ids(name_Charset, "Charset", NULL, "", en_us,
407                    DISPID_FONT_CHARSET, 0, S_OK,1);
408
409     /* Capitalization doesn't matter. */
410     test_names_ids(name_nAmE, "nAmE", NULL, "", en_us,
411                    DISPID_FONT_NAME, 0, S_OK,1);
412
413     /* Unknown name. */
414     test_names_ids(name_Foo, "Foo", NULL, "", en_us,
415                    DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);
416
417     /* Pass several names: first is processed,                */
418     /* second gets DISPID_UNKNOWN and doesn't affect retval.  */
419     test_names_ids(name_Italic, "Italic", name_Name, "Name", en_us,
420                    DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);
421     test_names_ids(name_Italic, "Italic", name_Foo, "Foo", en_us,
422                    DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);
423
424     /* Locale ID has no effect. */
425     test_names_ids(name_Name, "Name", NULL, "", fr_fr,
426                    DISPID_FONT_NAME, 0, S_OK,1);
427     test_names_ids(name_Nom, "This is not a font", NULL, "", fr_fr,
428                    DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);
429
430     /* One of the arguments are invalid */
431     test_names_ids(name_Name, "Name", NULL, "", en_us,
432                    0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
433     test_names_ids(name_Italic, "Italic", NULL, "", en_us,
434                    0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
435     test_names_ids(name_Foo, "Foo", NULL, "", en_us,
436                    0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
437
438     /* Crazy locale ID? */
439     test_names_ids(name_Name, "Name", NULL, "", -1,
440                    DISPID_FONT_NAME, 0, S_OK,1);
441 }
442
443 static void test_Invoke(void)
444 {
445     IFontDisp *fontdisp;
446     HRESULT hr;
447     VARIANTARG vararg;
448     DISPPARAMS dispparams;
449     VARIANT varresult;
450
451     hr = pOleCreateFontIndirect(NULL, &IID_IFontDisp, (void **)&fontdisp);
452     ok_ole_success(hr, "OleCreateFontIndirect");
453
454     V_VT(&vararg) = VT_BOOL;
455     V_BOOL(&vararg) = VARIANT_FALSE;
456     dispparams.cNamedArgs = 0;
457     dispparams.rgdispidNamedArgs = NULL;
458     dispparams.cArgs = 1;
459     dispparams.rgvarg = &vararg;
460     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_IFontDisp, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
461     ok(hr == DISP_E_UNKNOWNINTERFACE, "IFontDisp_Invoke should have returned DISP_E_UNKNOWNINTERFACE instead of 0x%08x\n", hr);
462
463     dispparams.cArgs = 0;
464     dispparams.rgvarg = NULL;
465     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
466     ok(hr == DISP_E_BADPARAMCOUNT, "IFontDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
467
468     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, NULL, NULL, NULL);
469     ok(hr == DISP_E_PARAMNOTOPTIONAL, "IFontDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
470
471     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, NULL, NULL, NULL);
472     ok(hr == DISP_E_PARAMNOTOPTIONAL, "IFontDisp_Invoke should have returned DISP_E_PARAMNOTOPTIONAL instead of 0x%08x\n", hr);
473
474     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
475     ok_ole_success(hr, "IFontDisp_Invoke");
476
477     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_METHOD, NULL, &varresult, NULL, NULL);
478     ok(hr == DISP_E_MEMBERNOTFOUND, "IFontDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
479
480     hr = IFontDisp_Invoke(fontdisp, 0xdeadbeef, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
481     ok(hr == DISP_E_MEMBERNOTFOUND, "IFontDisp_Invoke should have returned DISP_E_MEMBERNOTFOUND instead of 0x%08x\n", hr);
482
483     dispparams.cArgs = 1;
484     dispparams.rgvarg = &vararg;
485     hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
486     ok_ole_success(hr, "IFontDisp_Invoke");
487
488     IFontDisp_Release(fontdisp);
489 }
490
491 static void test_IsEqual(void)
492 {
493     FONTDESC fd;
494     IFont* ifnt = NULL;
495     IFont* ifnt2 = NULL;
496     HRESULT hres;
497
498     /* Basic font description */
499     fd.cbSizeofstruct = sizeof(FONTDESC);
500     fd.lpstrName      = system_font;
501     S(fd.cySize).Lo   = 100;
502     S(fd.cySize).Hi   = 100;
503     fd.sWeight        = 0;
504     fd.sCharset       = 0;
505     fd.fItalic        = 0;
506     fd.fUnderline     = 0;
507     fd.fStrikethrough = 0;
508
509     /* Create font */
510     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt);
511
512     /* Test equal fonts */
513     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
514     hres = IFont_IsEqual(ifnt,ifnt2);
515     ok(hres == S_OK,
516         "IFont_IsEqual: (EQUAL) Expected S_OK but got 0x%08x\n",hres);
517     IFont_Release(ifnt2);
518
519     /* Check for bad pointer */
520     hres = IFont_IsEqual(ifnt,NULL);
521     ok(hres == E_POINTER,
522         "IFont_IsEqual: (NULL) Expected 0x80004003 but got 0x%08x\n",hres);
523
524     /* Test strName */
525     fd.lpstrName = arial_font;
526     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
527     hres = IFont_IsEqual(ifnt,ifnt2);
528     ok(hres == S_FALSE,
529         "IFont_IsEqual: (strName) Expected S_FALSE but got 0x%08x\n",hres);
530     fd.lpstrName = system_font;
531     IFont_Release(ifnt2);
532
533     /* Test lo font size */
534     S(fd.cySize).Lo = 10000;
535     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
536     hres = IFont_IsEqual(ifnt,ifnt2);
537     ok(hres == S_FALSE,
538         "IFont_IsEqual: (Lo font size) Expected S_FALSE but got 0x%08x\n",hres);
539     S(fd.cySize).Lo = 100;
540     IFont_Release(ifnt2);
541
542     /* Test hi font size */
543     S(fd.cySize).Hi = 10000;
544     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
545     hres = IFont_IsEqual(ifnt,ifnt2);
546     ok(hres == S_FALSE,
547         "IFont_IsEqual: (Hi font size) Expected S_FALSE but got 0x%08x\n",hres);
548     S(fd.cySize).Hi = 100;
549     IFont_Release(ifnt2);
550
551     /* Test font weight  */
552     fd.sWeight = 100;
553     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
554     hres = IFont_IsEqual(ifnt,ifnt2);
555     ok(hres == S_FALSE,
556         "IFont_IsEqual: (Weight) Expected S_FALSE but got 0x%08x\n",hres);
557     fd.sWeight = 0;
558     IFont_Release(ifnt2);
559
560     /* Test charset */
561     fd.sCharset = 1;
562     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
563     hres = IFont_IsEqual(ifnt,ifnt2);
564     ok(hres == S_FALSE,
565         "IFont_IsEqual: (Charset) Expected S_FALSE but got 0x%08x\n",hres);
566     fd.sCharset = 0;
567     IFont_Release(ifnt2);
568
569     /* Test italic setting */
570     fd.fItalic = 1;
571     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
572     hres = IFont_IsEqual(ifnt,ifnt2);
573     ok(hres == S_FALSE,
574         "IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres);
575     fd.fItalic = 0;
576     IFont_Release(ifnt2);
577
578     /* Test underline setting */
579     fd.fUnderline = 1;
580     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
581     hres = IFont_IsEqual(ifnt,ifnt2);
582     ok(hres == S_FALSE,
583         "IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres);
584     fd.fUnderline = 0;
585     IFont_Release(ifnt2);
586
587     /* Test strikethrough setting */
588     fd.fStrikethrough = 1;
589     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
590     hres = IFont_IsEqual(ifnt,ifnt2);
591     ok(hres == S_FALSE,
592         "IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres);
593     fd.fStrikethrough = 0;
594     IFont_Release(ifnt2);
595
596     /* Free IFont. */
597     IFont_Release(ifnt);
598 }
599
600 static void test_ReleaseHfont(void)
601 {
602     FONTDESC fd;
603     LPVOID pvObj1 = NULL;
604     LPVOID pvObj2 = NULL;
605     IFont* ifnt1 = NULL;
606     IFont* ifnt2 = NULL;
607     HFONT hfnt1 = 0;
608     HFONT hfnt2 = 0;
609     HRESULT hres;
610
611     /* Basic font description */
612     fd.cbSizeofstruct = sizeof(FONTDESC);
613     fd.lpstrName      = system_font;
614     S(fd.cySize).Lo   = 100;
615     S(fd.cySize).Hi   = 100;
616     fd.sWeight        = 0;
617     fd.sCharset       = 0;
618     fd.fItalic        = 0;
619     fd.fUnderline     = 0;
620     fd.fStrikethrough = 0;
621
622     /* Create HFONTs and IFONTs */
623     pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj1);
624     ifnt1 = pvObj1;
625     IFont_get_hFont(ifnt1,&hfnt1);
626     fd.lpstrName = arial_font;
627     pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
628     ifnt2 = pvObj2;
629     IFont_get_hFont(ifnt2,&hfnt2);
630
631     /* Try invalid HFONT */
632     hres = IFont_ReleaseHfont(ifnt1,NULL);
633     ok(hres == E_INVALIDARG,
634         "IFont_ReleaseHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
635         hres);
636
637     /* Try to add a bad HFONT */
638     hres = IFont_ReleaseHfont(ifnt1,(HFONT)32);
639     ok(hres == S_FALSE,
640         "IFont_ReleaseHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
641         hres);
642
643     /* Release all refs */
644     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
645     ok(hres == S_OK,
646         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
647         hres);
648
649     hres = IFont_ReleaseHfont(ifnt2,hfnt2);
650     ok(hres == S_OK,
651         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
652         hres);
653
654     /* Check that both lists are empty */
655     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
656     ok(hres == S_FALSE,
657         "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
658         hres);
659
660     /* The list should be empty */
661     hres = IFont_ReleaseHfont(ifnt2,hfnt2);
662     ok(hres == S_FALSE,
663         "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
664         hres);
665
666     IFont_Release(ifnt1);
667     IFont_Release(ifnt2);
668 }
669
670 static void test_AddRefHfont(void)
671 {
672     FONTDESC fd;
673     IFont* ifnt1 = NULL;
674     IFont* ifnt2 = NULL;
675     IFont* ifnt3 = NULL;
676     HFONT hfnt1 = 0;
677     HFONT hfnt2 = 0;
678     HFONT hfnt3 = 0;
679     HRESULT hres;
680
681     /* Basic font description */
682     fd.cbSizeofstruct = sizeof(FONTDESC);
683     fd.lpstrName      = system_font;
684     S(fd.cySize).Lo   = 100;
685     S(fd.cySize).Hi   = 100;
686     fd.sWeight        = 0;
687     fd.sCharset       = 0;
688     fd.fItalic        = 0;
689     fd.fUnderline     = 0;
690     fd.fStrikethrough = 0;
691
692     /* Create HFONTs and IFONTs */
693     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt1);
694     IFont_get_hFont(ifnt1,&hfnt1);
695     fd.lpstrName = arial_font;
696     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
697     IFont_get_hFont(ifnt2,&hfnt2);
698
699     /* Try invalid HFONT */
700     hres = IFont_AddRefHfont(ifnt1,NULL);
701     ok(hres == E_INVALIDARG,
702         "IFont_AddRefHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
703         hres);
704
705     /* Try to add a bad HFONT */
706     hres = IFont_AddRefHfont(ifnt1,(HFONT)32);
707     ok(hres == S_FALSE,
708         "IFont_AddRefHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
709         hres);
710
711     /* Add simple IFONT HFONT pair */
712     hres = IFont_AddRefHfont(ifnt1,hfnt1);
713     ok(hres == S_OK,
714         "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
715         hres);
716
717     /* IFONT and HFONT do not have to be the same (always looks at HFONT) */
718     hres = IFont_AddRefHfont(ifnt2,hfnt1);
719     ok(hres == S_OK,
720         "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
721         hres);
722
723     /* Release all hfnt1 refs */
724     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
725     ok(hres == S_OK,
726         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
727         hres);
728
729     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
730     ok(hres == S_OK,
731         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
732         hres);
733
734     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
735     ok(hres == S_OK,
736         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
737         hres);
738
739     /* Check if hfnt1 is empty */
740     hres = IFont_ReleaseHfont(ifnt1,hfnt1);
741     ok(hres == S_FALSE,
742         "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
743         hres);
744
745     /* Release all hfnt2 refs */
746     hres = IFont_ReleaseHfont(ifnt2,hfnt2);
747     ok(hres == S_OK,
748         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
749         hres);
750
751     /* Check if hfnt2 is empty */
752     hres = IFont_ReleaseHfont(ifnt2,hfnt2);
753     ok(hres == S_FALSE,
754         "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
755         hres);
756
757     /* Show that releasing an IFONT does not always release it from the HFONT cache. */
758
759     IFont_Release(ifnt1);
760
761     /* Add a reference for destroyed hfnt1 */
762     hres = IFont_AddRefHfont(ifnt2,hfnt1);
763     ok(hres == S_OK,
764         "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
765         hres);
766
767     /* Decrement reference for destroyed hfnt1 */
768     hres = IFont_ReleaseHfont(ifnt2,hfnt1);
769     ok(hres == S_OK ||
770        hres == S_FALSE, /* <= win2k */
771         "IFont_AddRefHfont: (Release ref) Expected S_OK or S_FALSE but got 0x%08x\n",
772         hres);
773
774     /* Shows that releasing all IFONT's does clear the HFONT cache. */
775
776     IFont_Release(ifnt2);
777
778     /* Need to make a new IFONT for testing */
779     fd.fUnderline = 1;
780     pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt3);
781     IFont_get_hFont(ifnt3,&hfnt3);
782
783     /* Add a reference for destroyed hfnt1 */
784     hres = IFont_AddRefHfont(ifnt3,hfnt1);
785     ok(hres == S_FALSE,
786         "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
787         hres);
788
789     /* Decrement reference for destroyed hfnt1 */
790     hres = IFont_ReleaseHfont(ifnt3,hfnt1);
791     ok(hres == S_FALSE,
792         "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
793         hres);
794
795     IFont_Release(ifnt3);
796 }
797
798 START_TEST(olefont)
799 {
800         hOleaut32 = GetModuleHandleA("oleaut32.dll");
801         pOleCreateFontIndirect = (void*)GetProcAddress(hOleaut32, "OleCreateFontIndirect");
802         if (!pOleCreateFontIndirect)
803         {
804             win_skip("OleCreateFontIndirect not available\n");
805             return;
806         }
807
808         test_QueryInterface();
809         test_type_info();
810
811         /* Test various size operations and conversions. */
812         /* Add more as needed. */
813         if (0) /* FIXME: failing tests */
814         {
815             test_ifont_sizes(180000, 0, 72, 2540, -18, "default");
816             test_ifont_sizes(180000, 0, 144, 2540, -36, "ratio1");              /* change ratio */
817             test_ifont_sizes(180000, 0, 72, 1270, -36, "ratio2");               /* 2nd part of ratio */
818
819             /* These depend on details of how IFont rounds sizes internally. */
820             test_ifont_sizes(0, 0, 72, 2540, 0, "zero size");          /* zero size */
821             test_ifont_sizes(186000, 0, 72, 2540, -19, "rounding");   /* test rounding */
822         }
823
824         test_font_events_disp();
825         test_GetIDsOfNames();
826         test_Invoke();
827         test_IsEqual();
828         test_ReleaseHfont();
829         test_AddRefHfont();
830 }