olefont.c 27.7 KB
Newer Older
1 2 3 4
/*
 * OLEFONT test program
 *
 * Copyright 2003 Marcus Meissner
5
 * Copyright 2006 (Google) Benjamin Arai
6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 25 26 27
#include <stdio.h>
#include <math.h>
#include <float.h>

28 29
#define COBJMACROS

30
#include <wine/test.h>
31
#include <windef.h>
32 33 34 35 36 37
#include <winbase.h>
#include <winuser.h>
#include <wingdi.h>
#include <winnls.h>
#include <winerror.h>
#include <winnt.h>
38
#include <initguid.h>
39 40
#include <wtypes.h>
#include <olectl.h>
41
#include <ocidl.h>
42

43 44
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);

45 46 47 48
static WCHAR MSSansSerif_font[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f',0};
static WCHAR system_font[] = { 'S','y','s','t','e','m',0 };
static WCHAR arial_font[] = { 'A','r','i','a','l',0 };

49 50 51
static HMODULE hOleaut32;

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 56 57 58 59 60 61 62
/* Create a font with cySize given by lo_size, hi_size,  */
/* SetRatio to ratio_logical, ratio_himetric,            */
/* check that resulting hfont has height hfont_height.   */
/* Various checks along the way.                         */

static void test_ifont_sizes(long lo_size, long hi_size, 
	long ratio_logical, long ratio_himetric,
	long hfont_height, const char * test_name)
63
{
64
	FONTDESC fd;
65
	LPVOID pvObj = NULL;
66 67 68 69
	IFont* ifnt = NULL;
	HFONT hfont;
	LOGFONT lf;
	CY psize;
70 71
	HRESULT hres;

72
	fd.cbSizeofstruct = sizeof(FONTDESC);
73
	fd.lpstrName      = system_font;
74 75 76 77 78 79 80 81 82 83 84
	S(fd.cySize).Lo   = lo_size;
	S(fd.cySize).Hi   = hi_size;
	fd.sWeight        = 0;
	fd.sCharset       = 0;
	fd.fItalic        = 0;
	fd.fUnderline     = 0;
	fd.fStrikethrough = 0;

	/* Create font, test that it worked. */
	hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
	ifnt = pvObj;
85
	ok(hres == S_OK,"%s: OCFI returns 0x%08x instead of S_OK.\n",
86 87 88 89 90
		test_name, hres);
	ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name);

	/* Read back size.  Hi part was ignored. */
	hres = IFont_get_Size(ifnt, &psize);
91
	ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
92 93
		test_name, hres);
	ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
94
		"%s: get_Size: Lo=%d, Hi=%d; expected Lo=%ld, Hi=%ld.\n",
95 96 97 98
		test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);

	/* Change ratio, check size unchanged.  Standard is 72, 2540. */
	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 101
		test_name, hres);
	hres = IFont_get_Size(ifnt, &psize);
102
	ok(hres == S_OK,"%s: IFont_get_size returns 0x%08x instead of S_OK.\n",
103 104
                test_name, hres);
	ok(S(psize).Lo == lo_size && S(psize).Hi == 0,
105
		"%s: gS after SR: Lo=%d, Hi=%d; expected Lo=%ld, Hi=%ld.\n",
106 107 108 109 110
		test_name, S(psize).Lo, S(psize).Hi, lo_size, 0L);

	/* Check hFont size with this ratio.  This tests an important 	*/
	/* conversion for which MSDN is very wrong.			*/
	hres = IFont_get_hFont (ifnt, &hfont);
111
	ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n",
112 113 114
		test_name, hres);
	hres = GetObject (hfont, sizeof(LOGFONT), &lf);
	ok(lf.lfHeight == hfont_height,
115
		"%s: hFont has lf.lfHeight=%d, expected %ld.\n",
116 117 118 119 120 121
		test_name, lf.lfHeight, hfont_height);

	/* Free IFont. */
	IFont_Release(ifnt);
}

122
static void test_QueryInterface(void)
123 124 125 126
{
        LPVOID pvObj = NULL;
        HRESULT hres;
        IFont*  font = NULL;
127
        LONG ret;
128 129 130 131

        hres = pOleCreateFontIndirect(NULL, &IID_IFont, &pvObj);
        font = pvObj;

132
        ok(hres == S_OK,"OCFI (NULL,..) does not return 0, but 0x%08x\n",hres);
133 134 135 136 137
        ok(font != NULL,"OCFI (NULL,..) returns NULL, instead of !NULL\n");

        pvObj = NULL;
        hres = IFont_QueryInterface( font, &IID_IFont, &pvObj);

138 139
        /* Test if QueryInterface increments ref counter for IFONTs */
        ret = IFont_AddRef(font);
140 141
        ok(ret == 3 ||
           broken(ret == 1), /* win95 */
142
           "IFont_QI expected ref value 3 but instead got %d\n",ret);
143 144
        IFont_Release(font);

145
        ok(hres == S_OK,"IFont_QI does not return S_OK, but 0x%08x\n", hres);
146 147
        ok(pvObj != NULL,"IFont_QI does return NULL, instead of a ptr\n");

148
        /* Original ref and QueryInterface ref both have to be released */
149 150
        IFont_Release(font);
        IFont_Release(font);
151 152
}

153
static void test_type_info(void)
154 155 156 157 158 159 160 161 162 163
{
        LPVOID pvObj = NULL;
        HRESULT hres;
        IFontDisp*  fontdisp = NULL;
	ITypeInfo* pTInfo;
	WCHAR name_Name[] = {'N','a','m','e',0};
	BSTR names[3];
	UINT n;
        LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
                SORT_DEFAULT);
164 165
        DISPPARAMS dispparams;
        VARIANT varresult;
166 167 168 169 170

        pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
        fontdisp = pvObj;

	hres = IFontDisp_GetTypeInfo(fontdisp, 0, en_us, &pTInfo);
171
	ok(hres == S_OK, "GTI returned 0x%08x instead of S_OK.\n", hres);
172 173 174
	ok(pTInfo != NULL, "GTI returned NULL.\n");

	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 177
	ok(n == 1, "GetNames returned %d names instead of 1.\n", n);
	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 183 184 185 186 187 188 189

        dispparams.cNamedArgs = 0;
        dispparams.rgdispidNamedArgs = NULL;
        dispparams.cArgs = 0;
        dispparams.rgvarg = NULL;
        VariantInit(&varresult);
        hres = IFontDisp_Invoke(fontdisp, DISPID_FONT_NAME, &IID_NULL,
            LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult,
            NULL, NULL);
190
        ok(hres == S_OK, "IFontDisp_Invoke return 0x%08x instead of S_OK.\n", hres);
191 192
        VariantClear(&varresult);

193 194 195
	IFontDisp_Release(fontdisp);
}

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
static HRESULT WINAPI FontEventsDisp_QueryInterface(
        IFontEventsDisp *iface,
    /* [in] */ REFIID riid,
    /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
{
    if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
    {
        IUnknown_AddRef(iface);
        *ppvObject = iface;
        return S_OK;
    }
    else
    {
        *ppvObject = NULL;
        return E_NOINTERFACE;
    }
}

static ULONG WINAPI FontEventsDisp_AddRef(
    IFontEventsDisp *iface)
{
    return 2;
}

static ULONG WINAPI FontEventsDisp_Release(
        IFontEventsDisp *iface)
{
    return 1;
}

226
static int fonteventsdisp_invoke_called = 0;
227 228 229 230 231 232 233 234 235 236 237 238 239 240

static HRESULT WINAPI FontEventsDisp_Invoke(
        IFontEventsDisp __RPC_FAR * iface,
    /* [in] */ DISPID dispIdMember,
    /* [in] */ REFIID riid,
    /* [in] */ LCID lcid,
    /* [in] */ WORD wFlags,
    /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
    /* [out] */ VARIANT __RPC_FAR *pVarResult,
    /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
    /* [out] */ UINT __RPC_FAR *puArgErr)
{
    static const WCHAR wszBold[] = {'B','o','l','d',0};
    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 243 244 245
    ok(pDispParams->cArgs == 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams->cArgs);
    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]));
    ok(!lstrcmpW(V_BSTR(&pDispParams->rgvarg[0]), wszBold), "String in first param should have been \"Bold\"\n");

246
    fonteventsdisp_invoke_called++;
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
    return S_OK;
}

static IFontEventsDispVtbl FontEventsDisp_Vtbl =
{
    FontEventsDisp_QueryInterface,
    FontEventsDisp_AddRef,
    FontEventsDisp_Release,
    NULL,
    NULL,
    NULL,
    FontEventsDisp_Invoke
};

static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl };

static void test_font_events_disp(void)
{
    IFont *pFont;
266
    IFont *pFont2;
267 268 269 270 271
    IConnectionPointContainer *pCPC;
    IConnectionPoint *pCP;
    FONTDESC fontdesc;
    HRESULT hr;
    DWORD dwCookie;
272 273 274
    IFontDisp *pFontDisp;
    DISPPARAMS dispparams;
    VARIANTARG vararg;
275 276

    fontdesc.cbSizeofstruct = sizeof(fontdesc);
277
    fontdesc.lpstrName = MSSansSerif_font;
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    fontdesc.cySize.int64 = 12 * 10000; /* 12 pt */
    fontdesc.sWeight = FW_NORMAL;
    fontdesc.sCharset = 0;
    fontdesc.fItalic = FALSE;
    fontdesc.fUnderline = FALSE;
    fontdesc.fStrikethrough = FALSE;

    hr = pOleCreateFontIndirect(&fontdesc, &IID_IFont, (void **)&pFont);
    ok_ole_success(hr, "OleCreateFontIndirect");

    hr = IFont_QueryInterface(pFont, &IID_IConnectionPointContainer, (void **)&pCPC);
    ok_ole_success(hr, "IFont_QueryInterface");

    hr = IConnectionPointContainer_FindConnectionPoint(pCPC, &IID_IFontEventsDisp, &pCP);
    ok_ole_success(hr, "IConnectionPointContainer_FindConnectionPoint");
    IConnectionPointContainer_Release(pCPC);

    hr = IConnectionPoint_Advise(pCP, (IUnknown *)&FontEventsDisp, &dwCookie);
    ok_ole_success(hr, "IConnectionPoint_Advise");
    IConnectionPoint_Release(pCP);

    hr = IFont_put_Bold(pFont, TRUE);
    ok_ole_success(hr, "IFont_put_Bold");

302
    ok(fonteventsdisp_invoke_called == 1, "IFontEventDisp::Invoke wasn't called once\n");
303

304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
    hr = IFont_QueryInterface(pFont, &IID_IFontDisp, (void **)&pFontDisp);
    ok_ole_success(hr, "IFont_QueryInterface");

    V_VT(&vararg) = VT_BOOL;
    V_BOOL(&vararg) = VARIANT_FALSE;
    dispparams.cNamedArgs = 0;
    dispparams.rgdispidNamedArgs = NULL;
    dispparams.cArgs = 1;
    dispparams.rgvarg = &vararg;
    hr = IFontDisp_Invoke(pFontDisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);

    IFontDisp_Release(pFontDisp);

    ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
        fonteventsdisp_invoke_called);

320 321
    hr = IFont_Clone(pFont, &pFont2);
    ok_ole_success(hr, "IFont_Clone");
322
    IFont_Release(pFont);
323

324
    hr = IFont_put_Bold(pFont2, FALSE);
325 326 327
    ok_ole_success(hr, "IFont_put_Bold");

    /* this test shows that the notification routine isn't called again */
328 329
    ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
        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 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
                    WCHAR* w_name_2, const char* a_name_2,
                    LCID lcid, DISPID id_1, DISPID id_2,
                    HRESULT hres_expect, int numnames)
{
    LPVOID pvObj = NULL;
    IFontDisp *fontdisp = NULL;
    HRESULT hres;
    DISPID rgDispId[2] = {0xdeadbeef, 0xdeadbeef};
    LPOLESTR names[2] = {w_name_1, w_name_2};

    pOleCreateFontIndirect(NULL, &IID_IFontDisp, &pvObj);
    fontdisp = pvObj;

    hres = IFontDisp_GetIDsOfNames(fontdisp, &IID_NULL, names, numnames,
                                   lcid, rgDispId);

    /* test hres */
    ok(hres == hres_expect,
353
        "GetIDsOfNames: \"%s\", \"%s\" returns 0x%08x, expected 0x%08x.\n",
354 355 356 357
        a_name_1, a_name_2, hres, hres_expect);

    /* test first DISPID */
    ok(rgDispId[0]==id_1,
358
        "GetIDsOfNames: \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
359 360 361 362 363 364
        a_name_1, rgDispId[0], id_1);

    /* test second DISPID is present */
    if (numnames == 2)
    {
        ok(rgDispId[1]==id_2,
365
            "GetIDsOfNames: ..., \"%s\" gets DISPID 0x%08x, expected 0x%08x.\n",
366 367 368 369 370 371
            a_name_2, rgDispId[1], id_2);
    }

   IFontDisp_Release(fontdisp);
}

372
static void test_GetIDsOfNames(void)
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
{
    WCHAR name_Name[] = {'N','a','m','e',0};
    WCHAR name_Italic[] = {'I','t','a','l','i','c',0};
    WCHAR name_Size[] = {'S','i','z','e',0};
    WCHAR name_Bold[] = {'B','o','l','d',0};
    WCHAR name_Underline[] = {'U','n','d','e','r','l','i','n','e',0};
    WCHAR name_Strikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
    WCHAR name_Weight[] = {'W','e','i','g','h','t',0};
    WCHAR name_Charset[] = {'C','h','a','r','s','e','t',0};
    WCHAR name_Foo[] = {'F','o','o',0};
    WCHAR name_nAmE[] = {'n','A','m','E',0};
    WCHAR name_Nom[] = {'N','o','m',0};

    LCID en_us = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
                          SORT_DEFAULT);
    LCID fr_fr = MAKELCID(MAKELANGID(LANG_FRENCH,SUBLANG_FRENCH),
                          SORT_DEFAULT);

    /* Test DISPID_FONTs for the various properties. */
    test_names_ids(name_Name, "Name", NULL, "", en_us,
                   DISPID_FONT_NAME, 0, S_OK,1);
    test_names_ids(name_Size, "Size", NULL, "", en_us,
                   DISPID_FONT_SIZE, 0, S_OK,1);
    test_names_ids(name_Bold, "Bold", NULL, "", en_us,
                   DISPID_FONT_BOLD, 0, S_OK,1);
    test_names_ids(name_Italic, "Italic", NULL, "", en_us,
                   DISPID_FONT_ITALIC, 0, S_OK,1);
    test_names_ids(name_Underline, "Underline", NULL, "", en_us,
                   DISPID_FONT_UNDER, 0, S_OK,1);
    test_names_ids(name_Strikethrough, "Strikethrough", NULL, "", en_us,
                   DISPID_FONT_STRIKE, 0, S_OK,1);
    test_names_ids(name_Weight, "Weight", NULL, "", en_us,
                   DISPID_FONT_WEIGHT, 0, S_OK,1);
    test_names_ids(name_Charset, "Charset", NULL, "", en_us,
                   DISPID_FONT_CHARSET, 0, S_OK,1);

    /* Capitalization doesn't matter. */
    test_names_ids(name_nAmE, "nAmE", NULL, "", en_us,
                   DISPID_FONT_NAME, 0, S_OK,1);

    /* Unknown name. */
    test_names_ids(name_Foo, "Foo", NULL, "", en_us,
                   DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);

    /* Pass several names: first is processed,                */
    /* second gets DISPID_UNKNOWN and doesn't affect retval.  */
    test_names_ids(name_Italic, "Italic", name_Name, "Name", en_us,
                   DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);
    test_names_ids(name_Italic, "Italic", name_Foo, "Foo", en_us,
                   DISPID_FONT_ITALIC, DISPID_UNKNOWN, S_OK,2);

    /* Locale ID has no effect. */
    test_names_ids(name_Name, "Name", NULL, "", fr_fr,
                   DISPID_FONT_NAME, 0, S_OK,1);
    test_names_ids(name_Nom, "This is not a font", NULL, "", fr_fr,
                   DISPID_UNKNOWN, 0, DISP_E_UNKNOWNNAME,1);

    /* One of the arguments are invalid */
    test_names_ids(name_Name, "Name", NULL, "", en_us,
                   0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
    test_names_ids(name_Italic, "Italic", NULL, "", en_us,
                   0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);
    test_names_ids(name_Foo, "Foo", NULL, "", en_us,
                   0xdeadbeef, 0xdeadbeef, E_INVALIDARG,0);

    /* Crazy locale ID? */
    test_names_ids(name_Name, "Name", NULL, "", -1,
                   DISPID_FONT_NAME, 0, S_OK,1);
}

443 444 445 446 447 448
static void test_Invoke(void)
{
    IFontDisp *fontdisp;
    HRESULT hr;
    VARIANTARG vararg;
    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 457 458 459 460
    dispparams.cNamedArgs = 0;
    dispparams.rgdispidNamedArgs = NULL;
    dispparams.cArgs = 1;
    dispparams.rgvarg = &vararg;
    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 464 465

    dispparams.cArgs = 0;
    dispparams.rgvarg = NULL;
    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 475 476
    hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, NULL, &varresult, NULL, NULL);
    ok_ole_success(hr, "IFontDisp_Invoke");

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 484 485 486 487
    dispparams.cArgs = 1;
    dispparams.rgvarg = &vararg;
    hr = IFontDisp_Invoke(fontdisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
    ok_ole_success(hr, "IFontDisp_Invoke");

488 489 490
    IFontDisp_Release(fontdisp);
}

491
static void test_IsEqual(void)
492 493 494 495 496 497 498 499 500 501
{
    FONTDESC fd;
    LPVOID pvObj = NULL;
    LPVOID pvObj2 = NULL;
    IFont* ifnt = NULL;
    IFont* ifnt2 = NULL;
    HRESULT hres;

    /* Basic font description */
    fd.cbSizeofstruct = sizeof(FONTDESC);
502
    fd.lpstrName      = system_font;
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
    S(fd.cySize).Lo   = 100;
    S(fd.cySize).Hi   = 100;
    fd.sWeight        = 0;
    fd.sCharset       = 0;
    fd.fItalic        = 0;
    fd.fUnderline     = 0;
    fd.fStrikethrough = 0;

    /* Create font */
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
    ifnt = pvObj;

    /* Test equal fonts */
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    ifnt2 = pvObj2;
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_OK,
520
        "IFont_IsEqual: (EQUAL) Expected S_OK but got 0x%08x\n",hres);
521 522 523 524 525
    IFont_Release(ifnt2);

    /* Check for bad pointer */
    hres = IFont_IsEqual(ifnt,NULL);
    ok(hres == E_POINTER,
526
        "IFont_IsEqual: (NULL) Expected 0x80004003 but got 0x%08x\n",hres);
527 528

    /* Test strName */
529
    fd.lpstrName = arial_font;
530 531 532
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
533
        "IFont_IsEqual: (strName) Expected S_FALSE but got 0x%08x\n",hres);
534
    fd.lpstrName = system_font;
535 536 537 538 539 540 541 542
    IFont_Release(ifnt2);

    /* Test lo font size */
    S(fd.cySize).Lo = 10000;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    ifnt2 = pvObj2;
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
543
        "IFont_IsEqual: (Lo font size) Expected S_FALSE but got 0x%08x\n",hres);
544 545 546 547 548 549 550 551 552
    S(fd.cySize).Lo = 100;
    IFont_Release(ifnt2);

    /* Test hi font size */
    S(fd.cySize).Hi = 10000;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    ifnt2 = pvObj2;
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
553
        "IFont_IsEqual: (Hi font size) Expected S_FALSE but got 0x%08x\n",hres);
554 555 556 557 558 559 560 561 562
    S(fd.cySize).Hi = 100;
    IFont_Release(ifnt2);

    /* Test font weight  */
    fd.sWeight = 100;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    ifnt2 = pvObj2;
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
563
        "IFont_IsEqual: (Weight) Expected S_FALSE but got 0x%08x\n",hres);
564 565 566 567 568 569 570 571
    fd.sWeight = 0;
    IFont_Release(ifnt2);

    /* Test charset */
    fd.sCharset = 1;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
572
        "IFont_IsEqual: (Charset) Expected S_FALSE but got 0x%08x\n",hres);
573 574 575 576 577 578 579 580
    fd.sCharset = 0;
    IFont_Release(ifnt2);

    /* Test italic setting */
    fd.fItalic = 1;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
581
        "IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres);
582 583 584 585 586 587 588 589
    fd.fItalic = 0;
    IFont_Release(ifnt2);

    /* Test underline setting */
    fd.fUnderline = 1;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
590
        "IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres);
591 592 593 594 595 596 597 598
    fd.fUnderline = 0;
    IFont_Release(ifnt2);

    /* Test strikethrough setting */
    fd.fStrikethrough = 1;
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    hres = IFont_IsEqual(ifnt,ifnt2);
    ok(hres == S_FALSE,
599
        "IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres);
600 601 602 603 604 605 606
    fd.fStrikethrough = 0;
    IFont_Release(ifnt2);

    /* Free IFont. */
    IFont_Release(ifnt);
}

607 608 609 610 611 612 613 614 615 616 617 618 619
static void test_ReleaseHfont(void)
{
    FONTDESC fd;
    LPVOID pvObj1 = NULL;
    LPVOID pvObj2 = NULL;
    IFont* ifnt1 = NULL;
    IFont* ifnt2 = NULL;
    HFONT hfnt1 = 0;
    HFONT hfnt2 = 0;
    HRESULT hres;

    /* Basic font description */
    fd.cbSizeofstruct = sizeof(FONTDESC);
620
    fd.lpstrName      = system_font;
621 622 623 624 625 626 627 628 629 630 631 632
    S(fd.cySize).Lo   = 100;
    S(fd.cySize).Hi   = 100;
    fd.sWeight        = 0;
    fd.sCharset       = 0;
    fd.fItalic        = 0;
    fd.fUnderline     = 0;
    fd.fStrikethrough = 0;

    /* Create HFONTs and IFONTs */
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj1);
    ifnt1 = pvObj1;
    IFont_get_hFont(ifnt1,&hfnt1);
633
    fd.lpstrName = arial_font;
634 635 636 637 638
    pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj2);
    ifnt2 = pvObj2;
    IFont_get_hFont(ifnt2,&hfnt2);

    /* Try invalid HFONT */
639
    hres = IFont_ReleaseHfont(ifnt1,NULL);
640
    ok(hres == E_INVALIDARG,
641
        "IFont_ReleaseHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
642 643 644 645
        hres);

    /* Try to add a bad HFONT */
    hres = IFont_ReleaseHfont(ifnt1,(HFONT)32);
646
    ok(hres == S_FALSE,
647
        "IFont_ReleaseHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
648
        hres);
649 650 651 652

    /* Release all refs */
    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
    ok(hres == S_OK,
653
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
654 655 656 657
        hres);

    hres = IFont_ReleaseHfont(ifnt2,hfnt2);
    ok(hres == S_OK,
658
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
659 660 661 662
        hres);

    /* Check that both lists are empty */
    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
663
    ok(hres == S_FALSE,
664
        "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
665
        hres);
666 667 668

    /* The list should be empty */
    hres = IFont_ReleaseHfont(ifnt2,hfnt2);
669
    ok(hres == S_FALSE,
670
        "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
671
        hres);
672 673 674 675 676

    IFont_Release(ifnt1);
    IFont_Release(ifnt2);
}

677 678 679 680 681 682 683 684 685 686 687 688 689
static void test_AddRefHfont(void)
{
    FONTDESC fd;
    IFont* ifnt1 = NULL;
    IFont* ifnt2 = NULL;
    IFont* ifnt3 = NULL;
    HFONT hfnt1 = 0;
    HFONT hfnt2 = 0;
    HFONT hfnt3 = 0;
    HRESULT hres;

    /* Basic font description */
    fd.cbSizeofstruct = sizeof(FONTDESC);
690
    fd.lpstrName      = system_font;
691 692 693 694 695 696 697 698 699
    S(fd.cySize).Lo   = 100;
    S(fd.cySize).Hi   = 100;
    fd.sWeight        = 0;
    fd.sCharset       = 0;
    fd.fItalic        = 0;
    fd.fUnderline     = 0;
    fd.fStrikethrough = 0;

    /* Create HFONTs and IFONTs */
700
    pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt1);
701
    IFont_get_hFont(ifnt1,&hfnt1);
702
    fd.lpstrName = arial_font;
703
    pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
704 705 706
    IFont_get_hFont(ifnt2,&hfnt2);

    /* Try invalid HFONT */
707
    hres = IFont_AddRefHfont(ifnt1,NULL);
708
    ok(hres == E_INVALIDARG,
709
        "IFont_AddRefHfont: (Bad HFONT) Expected E_INVALIDARG but got 0x%08x\n",
710 711 712 713
        hres);

    /* Try to add a bad HFONT */
    hres = IFont_AddRefHfont(ifnt1,(HFONT)32);
714
    ok(hres == S_FALSE,
715
        "IFont_AddRefHfont: (Bad HFONT) Expected S_FALSE but got 0x%08x\n",
716
        hres);
717 718 719 720

    /* Add simple IFONT HFONT pair */
    hres = IFont_AddRefHfont(ifnt1,hfnt1);
    ok(hres == S_OK,
721
        "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
722 723 724 725
        hres);

    /* IFONT and HFONT do not have to be the same (always looks at HFONT) */
    hres = IFont_AddRefHfont(ifnt2,hfnt1);
726
    ok(hres == S_OK,
727
        "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
728
        hres);
729 730 731 732

    /* Release all hfnt1 refs */
    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
    ok(hres == S_OK,
733
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
734 735 736
        hres);

    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
737
    ok(hres == S_OK,
738
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
739
        hres);
740 741

    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
742
    ok(hres == S_OK,
743
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
744
        hres);
745 746 747

    /* Check if hfnt1 is empty */
    hres = IFont_ReleaseHfont(ifnt1,hfnt1);
748
    ok(hres == S_FALSE,
749
        "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
750
        hres);
751 752 753 754

    /* Release all hfnt2 refs */
    hres = IFont_ReleaseHfont(ifnt2,hfnt2);
    ok(hres == S_OK,
755
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
756 757 758 759
        hres);

    /* Check if hfnt2 is empty */
    hres = IFont_ReleaseHfont(ifnt2,hfnt2);
760
    ok(hres == S_FALSE,
761
        "IFont_AddRefHfont: (Release ref) Expected S_FALSE but got 0x%08x\n",
762
        hres);
763 764 765 766 767 768 769

    /* Show that releasing an IFONT does not always release it from the HFONT cache. */

    IFont_Release(ifnt1);

    /* Add a reference for destroyed hfnt1 */
    hres = IFont_AddRefHfont(ifnt2,hfnt1);
770
    ok(hres == S_OK,
771
        "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
772
        hres);
773 774 775

    /* Decrement reference for destroyed hfnt1 */
    hres = IFont_ReleaseHfont(ifnt2,hfnt1);
776 777 778
    ok(hres == S_OK ||
       hres == S_FALSE, /* <= win2k */
        "IFont_AddRefHfont: (Release ref) Expected S_OK or S_FALSE but got 0x%08x\n",
779
        hres);
780 781 782 783 784 785 786

    /* Shows that releasing all IFONT's does clear the HFONT cache. */

    IFont_Release(ifnt2);

    /* Need to make a new IFONT for testing */
    fd.fUnderline = 1;
787
    pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt3);
788 789 790 791
    IFont_get_hFont(ifnt3,&hfnt3);

    /* Add a reference for destroyed hfnt1 */
    hres = IFont_AddRefHfont(ifnt3,hfnt1);
792
    ok(hres == S_FALSE,
793
        "IFont_AddRefHfont: (Add ref) Expected S_OK but got 0x%08x\n",
794
        hres);
795 796 797

    /* Decrement reference for destroyed hfnt1 */
    hres = IFont_ReleaseHfont(ifnt3,hfnt1);
798
    ok(hres == S_FALSE,
799
        "IFont_AddRefHfont: (Release ref) Expected S_OK but got 0x%08x\n",
800
        hres);
801

802
    IFont_Release(ifnt3);
803 804
}

805 806
START_TEST(olefont)
{
807
	hOleaut32 = GetModuleHandleA("oleaut32.dll");
808 809
	pOleCreateFontIndirect = (void*)GetProcAddress(hOleaut32, "OleCreateFontIndirect");
	if (!pOleCreateFontIndirect)
810 811
	{
	    skip("OleCreateFontIndirect not available\n");
812
	    return;
813
	}
814

815
	test_QueryInterface();
816
	test_type_info();
817

818 819
	/* Test various size operations and conversions. */
	/* Add more as needed. */
820 821 822 823 824
	if (0) /* FIXME: failing tests */
	{
	    test_ifont_sizes(180000, 0, 72, 2540, -18, "default");
	    test_ifont_sizes(180000, 0, 144, 2540, -36, "ratio1");		/* change ratio */
	    test_ifont_sizes(180000, 0, 72, 1270, -36, "ratio2");		/* 2nd part of ratio */
825

826 827 828 829
	    /* These depend on details of how IFont rounds sizes internally. */
	    test_ifont_sizes(0, 0, 72, 2540, 0, "zero size");          /* zero size */
	    test_ifont_sizes(186000, 0, 72, 2540, -19, "rounding");   /* test rounding */
	}
830

831
	test_font_events_disp();
832
	test_GetIDsOfNames();
833
	test_Invoke();
834
	test_IsEqual();
835
	test_ReleaseHfont();
836
	test_AddRefHfont();
837
}