1 /* 2 * OLE Font encapsulation implementation 3 * 4 * This file contains an implementation of the IFont 5 * interface and the OleCreateFontIndirect API call. 6 * 7 * Copyright 1999 Francis Beaudet 8 * Copyright 2006 (Google) Benjamin Arai 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 #include <assert.h> 25 #include <stdarg.h> 26 #include <string.h> 27 28 #define COBJMACROS 29 #define NONAMELESSUNION 30 #define NONAMELESSSTRUCT 31 32 #include "winerror.h" 33 #include "windef.h" 34 #include "winbase.h" 35 #include "wingdi.h" 36 #include "winuser.h" 37 #include "wine/list.h" 38 #include "wine/unicode.h" 39 #include "objbase.h" 40 #include "oleauto.h" /* for SysAllocString(....) */ 41 #include "ole2.h" 42 #include "olectl.h" 43 #include "wine/debug.h" 44 #include "connpt.h" /* for CreateConnectionPoint */ 45 #include "oaidl.h" 46 47 WINE_DEFAULT_DEBUG_CHANNEL(ole); 48 49 /*********************************************************************** 50 * Declaration of constants used when serializing the font object. 51 */ 52 #define FONTPERSIST_ITALIC 0x02 53 #define FONTPERSIST_UNDERLINE 0x04 54 #define FONTPERSIST_STRIKETHROUGH 0x08 55 56 static HDC olefont_hdc; 57 58 /*********************************************************************** 59 * List of the HFONTs it has given out, with each one having a separate 60 * ref count. 61 */ 62 typedef struct _HFONTItem 63 { 64 struct list entry; 65 66 /* Reference count of any IFont objects that own this hfont */ 67 LONG int_refs; 68 69 /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */ 70 LONG total_refs; 71 72 /* The font associated with this object. */ 73 HFONT gdiFont; 74 75 } HFONTItem, *PHFONTItem; 76 77 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList); 78 79 /* Counts how many fonts contain at least one lock */ 80 static LONG ifont_cnt = 0; 81 82 /*********************************************************************** 83 * Critical section for OLEFontImpl_hFontList 84 */ 85 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST; 86 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug = 87 { 88 0, 0, &OLEFontImpl_csHFONTLIST, 89 { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList, 90 &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList }, 91 0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") } 92 }; 93 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 }; 94 95 static HDC get_dc(void) 96 { 97 HDC hdc; 98 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 99 if(!olefont_hdc) 100 olefont_hdc = CreateCompatibleDC(NULL); 101 hdc = olefont_hdc; 102 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 103 return hdc; 104 } 105 106 static void delete_dc(void) 107 { 108 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 109 if(olefont_hdc) 110 { 111 DeleteDC(olefont_hdc); 112 olefont_hdc = NULL; 113 } 114 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 115 } 116 117 static void HFONTItem_Delete(PHFONTItem item) 118 { 119 DeleteObject(item->gdiFont); 120 list_remove(&item->entry); 121 HeapFree(GetProcessHeap(), 0, item); 122 } 123 124 /* Find hfont item entry in the list. Should be called while holding the crit sect */ 125 static HFONTItem *find_hfontitem(HFONT hfont) 126 { 127 HFONTItem *item; 128 129 LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry) 130 { 131 if (item->gdiFont == hfont) 132 return item; 133 } 134 return NULL; 135 } 136 137 /* Add an item to the list with one internal reference */ 138 static HRESULT add_hfontitem(HFONT hfont) 139 { 140 HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item)); 141 142 if(!new_item) return E_OUTOFMEMORY; 143 144 new_item->int_refs = 1; 145 new_item->total_refs = 1; 146 new_item->gdiFont = hfont; 147 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 148 list_add_tail(&OLEFontImpl_hFontList,&new_item->entry); 149 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 150 return S_OK; 151 } 152 153 static HRESULT inc_int_ref(HFONT hfont) 154 { 155 HFONTItem *item; 156 HRESULT hr = S_FALSE; 157 158 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 159 item = find_hfontitem(hfont); 160 161 if(item) 162 { 163 item->int_refs++; 164 item->total_refs++; 165 hr = S_OK; 166 } 167 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 168 169 return hr; 170 } 171 172 /* decrements the internal ref of a hfont item. If both refs are zero it'll 173 remove the item from the list and delete the hfont */ 174 static HRESULT dec_int_ref(HFONT hfont) 175 { 176 HFONTItem *item; 177 HRESULT hr = S_FALSE; 178 179 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 180 item = find_hfontitem(hfont); 181 182 if(item) 183 { 184 item->int_refs--; 185 item->total_refs--; 186 if(item->int_refs == 0 && item->total_refs == 0) 187 HFONTItem_Delete(item); 188 hr = S_OK; 189 } 190 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 191 192 return hr; 193 } 194 195 static HRESULT inc_ext_ref(HFONT hfont) 196 { 197 HFONTItem *item; 198 HRESULT hr = S_FALSE; 199 200 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 201 202 item = find_hfontitem(hfont); 203 if(item) 204 { 205 item->total_refs++; 206 hr = S_OK; 207 } 208 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 209 210 return hr; 211 } 212 213 static HRESULT dec_ext_ref(HFONT hfont) 214 { 215 HFONTItem *item; 216 HRESULT hr = S_FALSE; 217 218 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 219 220 item = find_hfontitem(hfont); 221 if(item) 222 { 223 if(--item->total_refs >= 0) hr = S_OK; 224 } 225 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 226 227 return hr; 228 } 229 230 static WCHAR *strdupW(const WCHAR* str) 231 { 232 WCHAR *ret; 233 DWORD size = (strlenW(str) + 1) * sizeof(WCHAR); 234 235 ret = HeapAlloc(GetProcessHeap(), 0, size); 236 if(ret) 237 memcpy(ret, str, size); 238 return ret; 239 } 240 241 /*********************************************************************** 242 * Declaration of the implementation class for the IFont interface 243 */ 244 typedef struct OLEFontImpl OLEFontImpl; 245 246 struct OLEFontImpl 247 { 248 /* 249 * This class supports many interfaces. IUnknown, IFont, 250 * IDispatch, IDispFont IPersistStream and IConnectionPointContainer. 251 * The first two are supported by the first vtable, the next two are 252 * supported by the second table and the last two have their own. 253 */ 254 IFont IFont_iface; 255 IDispatch IDispatch_iface; 256 IPersistStream IPersistStream_iface; 257 IConnectionPointContainer IConnectionPointContainer_iface; 258 IPersistPropertyBag IPersistPropertyBag_iface; 259 IPersistStreamInit IPersistStreamInit_iface; 260 /* 261 * Reference count for that instance of the class. 262 */ 263 LONG ref; 264 265 /* 266 * This structure contains the description of the class. 267 */ 268 FONTDESC description; 269 270 /* 271 * Contain the font associated with this object. 272 */ 273 HFONT gdiFont; 274 BOOL dirty; 275 /* 276 * Size ratio 277 */ 278 LONG cyLogical; 279 LONG cyHimetric; 280 281 /* 282 * Stash realized height (pixels) from TEXTMETRIC - used in get_Size() 283 */ 284 LONG nRealHeight; 285 286 IConnectionPoint *pPropertyNotifyCP; 287 IConnectionPoint *pFontEventsCP; 288 }; 289 290 static inline OLEFontImpl *impl_from_IFont(IFont *iface) 291 { 292 return CONTAINING_RECORD(iface, OLEFontImpl, IFont_iface); 293 } 294 295 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface ) 296 { 297 return CONTAINING_RECORD(iface, OLEFontImpl, IDispatch_iface); 298 } 299 300 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface ) 301 { 302 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStream_iface); 303 } 304 305 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface ) 306 { 307 return CONTAINING_RECORD(iface, OLEFontImpl, IConnectionPointContainer_iface); 308 } 309 310 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface ) 311 { 312 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistPropertyBag_iface); 313 } 314 315 static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface ) 316 { 317 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStreamInit_iface); 318 } 319 320 321 /*********************************************************************** 322 * Prototypes for the implementation functions for the IFont 323 * interface 324 */ 325 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc); 326 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc); 327 static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface); 328 329 /****************************************************************************** 330 * OleCreateFontIndirect [OLEAUT32.420] 331 */ 332 HRESULT WINAPI OleCreateFontIndirect( 333 LPFONTDESC lpFontDesc, 334 REFIID riid, 335 LPVOID* ppvObj) 336 { 337 OLEFontImpl* newFont; 338 HRESULT hr; 339 FONTDESC fd; 340 341 TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj); 342 343 if (!ppvObj) return E_POINTER; 344 345 *ppvObj = 0; 346 347 if (!lpFontDesc) { 348 static WCHAR fname[] = { 'S','y','s','t','e','m',0 }; 349 350 fd.cbSizeofstruct = sizeof(fd); 351 fd.lpstrName = fname; 352 fd.cySize.s.Lo = 80000; 353 fd.cySize.s.Hi = 0; 354 fd.sWeight = 0; 355 fd.sCharset = 0; 356 fd.fItalic = FALSE; 357 fd.fUnderline = FALSE; 358 fd.fStrikethrough = FALSE; 359 lpFontDesc = &fd; 360 } 361 362 newFont = OLEFontImpl_Construct(lpFontDesc); 363 if (!newFont) return E_OUTOFMEMORY; 364 365 hr = IFont_QueryInterface(&newFont->IFont_iface, riid, ppvObj); 366 IFont_Release(&newFont->IFont_iface); 367 368 return hr; 369 } 370 371 372 /*********************************************************************** 373 * Implementation of the OLEFontImpl class. 374 */ 375 376 /*********************************************************************** 377 * OLEFont_SendNotify (internal) 378 * 379 * Sends notification messages of changed properties to any interested 380 * connections. 381 */ 382 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID) 383 { 384 static const WCHAR wszName[] = {'N','a','m','e',0}; 385 static const WCHAR wszSize[] = {'S','i','z','e',0}; 386 static const WCHAR wszBold[] = {'B','o','l','d',0}; 387 static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0}; 388 static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0}; 389 static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; 390 static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0}; 391 static const WCHAR wszCharset[] = {'C','h','a','r','s','e','t',0}; 392 static const LPCWSTR dispid_mapping[] = 393 { 394 wszName, 395 NULL, 396 wszSize, 397 wszBold, 398 wszItalic, 399 wszUnder, 400 wszStrike, 401 wszWeight, 402 wszCharset 403 }; 404 405 IEnumConnections *pEnum; 406 CONNECTDATA CD; 407 HRESULT hres; 408 409 this->dirty = TRUE; 410 411 hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum); 412 if (SUCCEEDED(hres)) 413 { 414 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { 415 IPropertyNotifySink *sink; 416 417 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (void**)&sink); 418 IPropertyNotifySink_OnChanged(sink, dispID); 419 IPropertyNotifySink_Release(sink); 420 IUnknown_Release(CD.pUnk); 421 } 422 IEnumConnections_Release(pEnum); 423 } 424 425 hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum); 426 if (SUCCEEDED(hres)) 427 { 428 DISPPARAMS dispparams; 429 VARIANTARG vararg; 430 431 VariantInit(&vararg); 432 V_VT(&vararg) = VT_BSTR; 433 V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]); 434 435 dispparams.cArgs = 1; 436 dispparams.cNamedArgs = 0; 437 dispparams.rgdispidNamedArgs = NULL; 438 dispparams.rgvarg = &vararg; 439 440 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { 441 IFontEventsDisp *disp; 442 443 IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (void**)&disp); 444 IFontEventsDisp_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL, 445 LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL, 446 NULL, NULL); 447 448 IFontEventsDisp_Release(disp); 449 IUnknown_Release(CD.pUnk); 450 } 451 VariantClear(&vararg); 452 IEnumConnections_Release(pEnum); 453 } 454 } 455 456 /************************************************************************ 457 * OLEFontImpl_QueryInterface (IUnknown) 458 * 459 * See Windows documentation for more details on IUnknown methods. 460 */ 461 static HRESULT WINAPI OLEFontImpl_QueryInterface( 462 IFont* iface, 463 REFIID riid, 464 void** ppvObject) 465 { 466 OLEFontImpl *this = impl_from_IFont(iface); 467 468 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject); 469 470 *ppvObject = 0; 471 472 if (IsEqualGUID(&IID_IUnknown, riid) || 473 IsEqualGUID(&IID_IFont, riid)) 474 { 475 *ppvObject = this; 476 } 477 else if (IsEqualGUID(&IID_IDispatch, riid) || 478 IsEqualGUID(&IID_IFontDisp, riid)) 479 { 480 *ppvObject = &this->IDispatch_iface; 481 } 482 else if (IsEqualGUID(&IID_IPersist, riid) || 483 IsEqualGUID(&IID_IPersistStream, riid)) 484 { 485 *ppvObject = &this->IPersistStream_iface; 486 } 487 else if (IsEqualGUID(&IID_IConnectionPointContainer, riid)) 488 { 489 *ppvObject = &this->IConnectionPointContainer_iface; 490 } 491 else if (IsEqualGUID(&IID_IPersistPropertyBag, riid)) 492 { 493 *ppvObject = &this->IPersistPropertyBag_iface; 494 } 495 else if (IsEqualGUID(&IID_IPersistStreamInit, riid)) 496 { 497 *ppvObject = &this->IPersistStreamInit_iface; 498 } 499 500 if (!*ppvObject) 501 { 502 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid)); 503 return E_NOINTERFACE; 504 } 505 506 IFont_AddRef(iface); 507 508 return S_OK; 509 } 510 511 /************************************************************************ 512 * OLEFontImpl_AddRef (IUnknown) 513 */ 514 static ULONG WINAPI OLEFontImpl_AddRef( 515 IFont* iface) 516 { 517 OLEFontImpl *this = impl_from_IFont(iface); 518 TRACE("(%p)->(ref=%d)\n", this, this->ref); 519 return InterlockedIncrement(&this->ref); 520 } 521 522 /************************************************************************ 523 * OLEFontImpl_Release (IUnknown) 524 */ 525 static ULONG WINAPI OLEFontImpl_Release(IFont* iface) 526 { 527 OLEFontImpl *this = impl_from_IFont(iface); 528 ULONG ref; 529 530 TRACE("(%p)->(ref=%d)\n", this, this->ref); 531 532 ref = InterlockedDecrement(&this->ref); 533 534 if (ref == 0) 535 { 536 ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt); 537 538 /* Final IFont object so destroy font cache */ 539 if (fontlist_refs == 0) 540 { 541 HFONTItem *item, *cursor2; 542 543 EnterCriticalSection(&OLEFontImpl_csHFONTLIST); 544 LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry) 545 HFONTItem_Delete(item); 546 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST); 547 delete_dc(); 548 } 549 else 550 { 551 dec_int_ref(this->gdiFont); 552 } 553 OLEFontImpl_Destroy(this); 554 } 555 556 return ref; 557 } 558 559 typedef struct 560 { 561 short orig_cs; 562 short avail_cs; 563 } enum_data; 564 565 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp) 566 { 567 enum_data *data = (enum_data*)lp; 568 569 if(elf->lfCharSet == data->orig_cs) 570 { 571 data->avail_cs = data->orig_cs; 572 return 0; 573 } 574 if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet; 575 return 1; 576 } 577 578 static void realize_font(OLEFontImpl *This) 579 { 580 LOGFONTW logFont; 581 INT fontHeight; 582 WCHAR text_face[LF_FACESIZE]; 583 HDC hdc = get_dc(); 584 HFONT old_font; 585 TEXTMETRICW tm; 586 587 if (!This->dirty) return; 588 589 text_face[0] = 0; 590 591 if(This->gdiFont) 592 { 593 old_font = SelectObject(hdc, This->gdiFont); 594 GetTextFaceW(hdc, ARRAY_SIZE(text_face), text_face); 595 SelectObject(hdc, old_font); 596 dec_int_ref(This->gdiFont); 597 This->gdiFont = 0; 598 } 599 600 memset(&logFont, 0, sizeof(LOGFONTW)); 601 602 lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE); 603 logFont.lfCharSet = This->description.sCharset; 604 605 /* If the font name has been changed then enumerate all charsets 606 and pick one that'll result in the font specified being selected */ 607 if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName)) 608 { 609 enum_data data; 610 data.orig_cs = This->description.sCharset; 611 data.avail_cs = -1; 612 logFont.lfCharSet = DEFAULT_CHARSET; 613 EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0); 614 if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs; 615 } 616 617 /* 618 * The height of the font returned by the get_Size property is the 619 * height of the font in points multiplied by 10000... Using some 620 * simple conversions and the ratio given by the application, it can 621 * be converted to a height in pixels. 622 * 623 * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms. 624 * Ratio is applied here relative to the standard. 625 */ 626 627 fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 ); 628 629 logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 : 630 (-fontHeight/10000L); 631 logFont.lfItalic = This->description.fItalic; 632 logFont.lfUnderline = This->description.fUnderline; 633 logFont.lfStrikeOut = This->description.fStrikethrough; 634 logFont.lfWeight = This->description.sWeight; 635 logFont.lfOutPrecision = OUT_CHARACTER_PRECIS; 636 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS; 637 logFont.lfQuality = DEFAULT_QUALITY; 638 logFont.lfPitchAndFamily = DEFAULT_PITCH; 639 640 This->gdiFont = CreateFontIndirectW(&logFont); 641 This->dirty = FALSE; 642 643 add_hfontitem(This->gdiFont); 644 645 /* Fixup the name and charset properties so that they match the 646 selected font */ 647 old_font = SelectObject(get_dc(), This->gdiFont); 648 GetTextFaceW(hdc, ARRAY_SIZE(text_face), text_face); 649 if(lstrcmpiW(text_face, This->description.lpstrName)) 650 { 651 HeapFree(GetProcessHeap(), 0, This->description.lpstrName); 652 This->description.lpstrName = strdupW(text_face); 653 } 654 GetTextMetricsW(hdc, &tm); 655 This->description.sCharset = tm.tmCharSet; 656 /* While we have it handy, stash the realized font height for use by get_Size() */ 657 This->nRealHeight = tm.tmHeight - tm.tmInternalLeading; /* corresponds to LOGFONT lfHeight */ 658 SelectObject(hdc, old_font); 659 } 660 661 /************************************************************************ 662 * OLEFontImpl_get_Name (IFont) 663 * 664 * See Windows documentation for more details on IFont methods. 665 */ 666 static HRESULT WINAPI OLEFontImpl_get_Name( 667 IFont* iface, 668 BSTR* pname) 669 { 670 OLEFontImpl *this = impl_from_IFont(iface); 671 TRACE("(%p)->(%p)\n", this, pname); 672 673 if (pname==0) 674 return E_POINTER; 675 676 realize_font(this); 677 678 if (this->description.lpstrName!=0) 679 *pname = SysAllocString(this->description.lpstrName); 680 else 681 *pname = 0; 682 683 return S_OK; 684 } 685 686 /************************************************************************ 687 * OLEFontImpl_put_Name (IFont) 688 */ 689 static HRESULT WINAPI OLEFontImpl_put_Name( 690 IFont* iface, 691 BSTR name) 692 { 693 OLEFontImpl *This = impl_from_IFont(iface); 694 TRACE("(%p)->(%p)\n", This, name); 695 696 if (!name) 697 return CTL_E_INVALIDPROPERTYVALUE; 698 699 HeapFree(GetProcessHeap(), 0, This->description.lpstrName); 700 This->description.lpstrName = strdupW(name); 701 if (!This->description.lpstrName) return E_OUTOFMEMORY; 702 703 TRACE("new name %s\n", debugstr_w(This->description.lpstrName)); 704 OLEFont_SendNotify(This, DISPID_FONT_NAME); 705 return S_OK; 706 } 707 708 /************************************************************************ 709 * OLEFontImpl_get_Size (IFont) 710 */ 711 static HRESULT WINAPI OLEFontImpl_get_Size( 712 IFont* iface, 713 CY* psize) 714 { 715 OLEFontImpl *this = impl_from_IFont(iface); 716 TRACE("(%p)->(%p)\n", this, psize); 717 718 if (!psize) return E_POINTER; 719 720 realize_font(this); 721 722 /* 723 * Convert realized font height in pixels to points descaled by current 724 * scaling ratio then scaled up by 10000. 725 */ 726 psize->s.Lo = MulDiv(this->nRealHeight, 727 this->cyHimetric * 72 * 10000, 728 this->cyLogical * 2540); 729 psize->s.Hi = 0; 730 731 return S_OK; 732 } 733 734 /************************************************************************ 735 * OLEFontImpl_put_Size (IFont) 736 */ 737 static HRESULT WINAPI OLEFontImpl_put_Size( 738 IFont* iface, 739 CY size) 740 { 741 OLEFontImpl *this = impl_from_IFont(iface); 742 TRACE("(%p)->(%d)\n", this, size.s.Lo); 743 this->description.cySize.s.Hi = 0; 744 this->description.cySize.s.Lo = size.s.Lo; 745 OLEFont_SendNotify(this, DISPID_FONT_SIZE); 746 747 return S_OK; 748 } 749 750 /************************************************************************ 751 * OLEFontImpl_get_Bold (IFont) 752 * 753 * See Windows documentation for more details on IFont methods. 754 */ 755 static HRESULT WINAPI OLEFontImpl_get_Bold( 756 IFont* iface, 757 BOOL* pbold) 758 { 759 OLEFontImpl *this = impl_from_IFont(iface); 760 TRACE("(%p)->(%p)\n", this, pbold); 761 762 if (!pbold) return E_POINTER; 763 764 realize_font(this); 765 766 *pbold = this->description.sWeight > 550; 767 768 return S_OK; 769 } 770 771 /************************************************************************ 772 * OLEFontImpl_put_Bold (IFont) 773 */ 774 static HRESULT WINAPI OLEFontImpl_put_Bold( 775 IFont* iface, 776 BOOL bold) 777 { 778 OLEFontImpl *this = impl_from_IFont(iface); 779 TRACE("(%p)->(%d)\n", this, bold); 780 this->description.sWeight = bold ? FW_BOLD : FW_NORMAL; 781 OLEFont_SendNotify(this, DISPID_FONT_BOLD); 782 783 return S_OK; 784 } 785 786 /************************************************************************ 787 * OLEFontImpl_get_Italic (IFont) 788 */ 789 static HRESULT WINAPI OLEFontImpl_get_Italic( 790 IFont* iface, 791 BOOL* pitalic) 792 { 793 OLEFontImpl *this = impl_from_IFont(iface); 794 TRACE("(%p)->(%p)\n", this, pitalic); 795 796 if (pitalic==0) 797 return E_POINTER; 798 799 realize_font(this); 800 801 *pitalic = this->description.fItalic; 802 803 return S_OK; 804 } 805 806 /************************************************************************ 807 * OLEFontImpl_put_Italic (IFont) 808 */ 809 static HRESULT WINAPI OLEFontImpl_put_Italic( 810 IFont* iface, 811 BOOL italic) 812 { 813 OLEFontImpl *this = impl_from_IFont(iface); 814 TRACE("(%p)->(%d)\n", this, italic); 815 816 this->description.fItalic = italic; 817 818 OLEFont_SendNotify(this, DISPID_FONT_ITALIC); 819 return S_OK; 820 } 821 822 /************************************************************************ 823 * OLEFontImpl_get_Underline (IFont) 824 */ 825 static HRESULT WINAPI OLEFontImpl_get_Underline( 826 IFont* iface, 827 BOOL* punderline) 828 { 829 OLEFontImpl *this = impl_from_IFont(iface); 830 TRACE("(%p)->(%p)\n", this, punderline); 831 832 if (punderline==0) 833 return E_POINTER; 834 835 realize_font(this); 836 837 *punderline = this->description.fUnderline; 838 839 return S_OK; 840 } 841 842 /************************************************************************ 843 * OLEFontImpl_put_Underline (IFont) 844 */ 845 static HRESULT WINAPI OLEFontImpl_put_Underline( 846 IFont* iface, 847 BOOL underline) 848 { 849 OLEFontImpl *this = impl_from_IFont(iface); 850 TRACE("(%p)->(%d)\n", this, underline); 851 852 this->description.fUnderline = underline; 853 854 OLEFont_SendNotify(this, DISPID_FONT_UNDER); 855 return S_OK; 856 } 857 858 /************************************************************************ 859 * OLEFontImpl_get_Strikethrough (IFont) 860 */ 861 static HRESULT WINAPI OLEFontImpl_get_Strikethrough( 862 IFont* iface, 863 BOOL* pstrikethrough) 864 { 865 OLEFontImpl *this = impl_from_IFont(iface); 866 TRACE("(%p)->(%p)\n", this, pstrikethrough); 867 868 if (pstrikethrough==0) 869 return E_POINTER; 870 871 realize_font(this); 872 873 *pstrikethrough = this->description.fStrikethrough; 874 875 return S_OK; 876 } 877 878 /************************************************************************ 879 * OLEFontImpl_put_Strikethrough (IFont) 880 */ 881 static HRESULT WINAPI OLEFontImpl_put_Strikethrough( 882 IFont* iface, 883 BOOL strikethrough) 884 { 885 OLEFontImpl *this = impl_from_IFont(iface); 886 TRACE("(%p)->(%d)\n", this, strikethrough); 887 888 this->description.fStrikethrough = strikethrough; 889 OLEFont_SendNotify(this, DISPID_FONT_STRIKE); 890 891 return S_OK; 892 } 893 894 /************************************************************************ 895 * OLEFontImpl_get_Weight (IFont) 896 */ 897 static HRESULT WINAPI OLEFontImpl_get_Weight( 898 IFont* iface, 899 short* pweight) 900 { 901 OLEFontImpl *this = impl_from_IFont(iface); 902 TRACE("(%p)->(%p)\n", this, pweight); 903 904 if (pweight==0) 905 return E_POINTER; 906 907 realize_font(this); 908 909 *pweight = this->description.sWeight; 910 911 return S_OK; 912 } 913 914 /************************************************************************ 915 * OLEFontImpl_put_Weight (IFont) 916 */ 917 static HRESULT WINAPI OLEFontImpl_put_Weight( 918 IFont* iface, 919 short weight) 920 { 921 OLEFontImpl *this = impl_from_IFont(iface); 922 TRACE("(%p)->(%d)\n", this, weight); 923 924 this->description.sWeight = weight; 925 926 OLEFont_SendNotify(this, DISPID_FONT_WEIGHT); 927 return S_OK; 928 } 929 930 /************************************************************************ 931 * OLEFontImpl_get_Charset (IFont) 932 */ 933 static HRESULT WINAPI OLEFontImpl_get_Charset( 934 IFont* iface, 935 short* pcharset) 936 { 937 OLEFontImpl *this = impl_from_IFont(iface); 938 TRACE("(%p)->(%p)\n", this, pcharset); 939 940 if (pcharset==0) 941 return E_POINTER; 942 943 realize_font(this); 944 945 *pcharset = this->description.sCharset; 946 947 return S_OK; 948 } 949 950 /************************************************************************ 951 * OLEFontImpl_put_Charset (IFont) 952 */ 953 static HRESULT WINAPI OLEFontImpl_put_Charset( 954 IFont* iface, 955 short charset) 956 { 957 OLEFontImpl *this = impl_from_IFont(iface); 958 TRACE("(%p)->(%d)\n", this, charset); 959 960 this->description.sCharset = charset; 961 OLEFont_SendNotify(this, DISPID_FONT_CHARSET); 962 963 return S_OK; 964 } 965 966 /************************************************************************ 967 * OLEFontImpl_get_hFont (IFont) 968 */ 969 static HRESULT WINAPI OLEFontImpl_get_hFont( 970 IFont* iface, 971 HFONT* phfont) 972 { 973 OLEFontImpl *this = impl_from_IFont(iface); 974 TRACE("(%p)->(%p)\n", this, phfont); 975 if (phfont==NULL) 976 return E_POINTER; 977 978 realize_font(this); 979 980 *phfont = this->gdiFont; 981 TRACE("Returning %p\n", *phfont); 982 return S_OK; 983 } 984 985 /************************************************************************ 986 * OLEFontImpl_Clone (IFont) 987 */ 988 static HRESULT WINAPI OLEFontImpl_Clone( 989 IFont* iface, 990 IFont** ppfont) 991 { 992 OLEFontImpl *this = impl_from_IFont(iface); 993 OLEFontImpl* newObject; 994 995 TRACE("(%p)->(%p)\n", this, ppfont); 996 997 if (ppfont == NULL) 998 return E_POINTER; 999 1000 *ppfont = NULL; 1001 1002 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl)); 1003 if (newObject==NULL) 1004 return E_OUTOFMEMORY; 1005 1006 *newObject = *this; 1007 /* allocate separate buffer */ 1008 newObject->description.lpstrName = strdupW(this->description.lpstrName); 1009 1010 /* Increment internal ref in hfont item list */ 1011 if(newObject->gdiFont) inc_int_ref(newObject->gdiFont); 1012 1013 InterlockedIncrement(&ifont_cnt); 1014 1015 newObject->pPropertyNotifyCP = NULL; 1016 newObject->pFontEventsCP = NULL; 1017 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IPropertyNotifySink, 1018 &newObject->pPropertyNotifyCP); 1019 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IFontEventsDisp, 1020 &newObject->pFontEventsCP); 1021 1022 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) 1023 { 1024 OLEFontImpl_Destroy(newObject); 1025 return E_OUTOFMEMORY; 1026 } 1027 1028 /* The cloned object starts with a reference count of 1 */ 1029 newObject->ref = 1; 1030 1031 *ppfont = &newObject->IFont_iface; 1032 1033 return S_OK; 1034 } 1035 1036 /************************************************************************ 1037 * OLEFontImpl_IsEqual (IFont) 1038 */ 1039 static HRESULT WINAPI OLEFontImpl_IsEqual( 1040 IFont* iface, 1041 IFont* pFontOther) 1042 { 1043 OLEFontImpl *left = impl_from_IFont(iface); 1044 OLEFontImpl *right = impl_from_IFont(pFontOther); 1045 INT ret; 1046 INT left_len,right_len; 1047 1048 if(pFontOther == NULL) 1049 return E_POINTER; 1050 else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo) 1051 return S_FALSE; 1052 else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi) 1053 return S_FALSE; 1054 else if (left->description.sWeight != right->description.sWeight) 1055 return S_FALSE; 1056 else if (left->description.sCharset != right->description.sCharset) 1057 return S_FALSE; 1058 else if (left->description.fItalic != right->description.fItalic) 1059 return S_FALSE; 1060 else if (left->description.fUnderline != right->description.fUnderline) 1061 return S_FALSE; 1062 else if (left->description.fStrikethrough != right->description.fStrikethrough) 1063 return S_FALSE; 1064 1065 /* Check from string */ 1066 left_len = strlenW(left->description.lpstrName); 1067 right_len = strlenW(right->description.lpstrName); 1068 ret = CompareStringW(0,0,left->description.lpstrName, left_len, 1069 right->description.lpstrName, right_len); 1070 if (ret != CSTR_EQUAL) 1071 return S_FALSE; 1072 1073 return S_OK; 1074 } 1075 1076 /************************************************************************ 1077 * OLEFontImpl_SetRatio (IFont) 1078 */ 1079 static HRESULT WINAPI OLEFontImpl_SetRatio( 1080 IFont* iface, 1081 LONG cyLogical, 1082 LONG cyHimetric) 1083 { 1084 OLEFontImpl *this = impl_from_IFont(iface); 1085 TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric); 1086 1087 if(cyLogical == 0 || cyHimetric == 0) 1088 return E_FAIL; 1089 1090 /* cyLogical and cyHimetric both set to 1 is a special case that 1091 does not change the scaling but also does not fail */ 1092 if(cyLogical == 1 && cyHimetric == 1) 1093 return S_OK; 1094 1095 this->cyLogical = cyLogical; 1096 this->cyHimetric = cyHimetric; 1097 this->dirty = TRUE; 1098 1099 return S_OK; 1100 } 1101 1102 /************************************************************************ 1103 * OLEFontImpl_QueryTextMetrics (IFont) 1104 */ 1105 static HRESULT WINAPI OLEFontImpl_QueryTextMetrics( 1106 IFont* iface, 1107 TEXTMETRICOLE* ptm) 1108 { 1109 HDC hdcRef; 1110 HFONT hOldFont, hNewFont; 1111 1112 hdcRef = GetDC(0); 1113 IFont_get_hFont(iface, &hNewFont); 1114 hOldFont = SelectObject(hdcRef, hNewFont); 1115 GetTextMetricsW(hdcRef, ptm); 1116 SelectObject(hdcRef, hOldFont); 1117 ReleaseDC(0, hdcRef); 1118 return S_OK; 1119 } 1120 1121 /************************************************************************ 1122 * OLEFontImpl_AddRefHfont (IFont) 1123 */ 1124 static HRESULT WINAPI OLEFontImpl_AddRefHfont( 1125 IFont* iface, 1126 HFONT hfont) 1127 { 1128 OLEFontImpl *this = impl_from_IFont(iface); 1129 1130 TRACE("(%p)->(%p)\n", this, hfont); 1131 1132 if (!hfont) return E_INVALIDARG; 1133 1134 return inc_ext_ref(hfont); 1135 } 1136 1137 /************************************************************************ 1138 * OLEFontImpl_ReleaseHfont (IFont) 1139 */ 1140 static HRESULT WINAPI OLEFontImpl_ReleaseHfont( 1141 IFont* iface, 1142 HFONT hfont) 1143 { 1144 OLEFontImpl *this = impl_from_IFont(iface); 1145 1146 TRACE("(%p)->(%p)\n", this, hfont); 1147 1148 if (!hfont) return E_INVALIDARG; 1149 1150 return dec_ext_ref(hfont); 1151 } 1152 1153 /************************************************************************ 1154 * OLEFontImpl_SetHdc (IFont) 1155 */ 1156 static HRESULT WINAPI OLEFontImpl_SetHdc( 1157 IFont* iface, 1158 HDC hdc) 1159 { 1160 OLEFontImpl *this = impl_from_IFont(iface); 1161 FIXME("(%p)->(%p): Stub\n", this, hdc); 1162 return E_NOTIMPL; 1163 } 1164 1165 static const IFontVtbl OLEFontImpl_VTable = 1166 { 1167 OLEFontImpl_QueryInterface, 1168 OLEFontImpl_AddRef, 1169 OLEFontImpl_Release, 1170 OLEFontImpl_get_Name, 1171 OLEFontImpl_put_Name, 1172 OLEFontImpl_get_Size, 1173 OLEFontImpl_put_Size, 1174 OLEFontImpl_get_Bold, 1175 OLEFontImpl_put_Bold, 1176 OLEFontImpl_get_Italic, 1177 OLEFontImpl_put_Italic, 1178 OLEFontImpl_get_Underline, 1179 OLEFontImpl_put_Underline, 1180 OLEFontImpl_get_Strikethrough, 1181 OLEFontImpl_put_Strikethrough, 1182 OLEFontImpl_get_Weight, 1183 OLEFontImpl_put_Weight, 1184 OLEFontImpl_get_Charset, 1185 OLEFontImpl_put_Charset, 1186 OLEFontImpl_get_hFont, 1187 OLEFontImpl_Clone, 1188 OLEFontImpl_IsEqual, 1189 OLEFontImpl_SetRatio, 1190 OLEFontImpl_QueryTextMetrics, 1191 OLEFontImpl_AddRefHfont, 1192 OLEFontImpl_ReleaseHfont, 1193 OLEFontImpl_SetHdc 1194 }; 1195 1196 /************************************************************************ 1197 * OLEFontImpl_IDispatch_QueryInterface (IUnknown) 1198 */ 1199 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface( 1200 IDispatch* iface, 1201 REFIID riid, 1202 VOID** ppvoid) 1203 { 1204 OLEFontImpl *this = impl_from_IDispatch(iface); 1205 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid); 1206 } 1207 1208 /************************************************************************ 1209 * OLEFontImpl_IDispatch_Release (IUnknown) 1210 */ 1211 static ULONG WINAPI OLEFontImpl_IDispatch_Release( 1212 IDispatch* iface) 1213 { 1214 OLEFontImpl *this = impl_from_IDispatch(iface); 1215 return IFont_Release(&this->IFont_iface); 1216 } 1217 1218 /************************************************************************ 1219 * OLEFontImpl_IDispatch_AddRef (IUnknown) 1220 */ 1221 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef( 1222 IDispatch* iface) 1223 { 1224 OLEFontImpl *this = impl_from_IDispatch(iface); 1225 return IFont_AddRef(&this->IFont_iface); 1226 } 1227 1228 /************************************************************************ 1229 * OLEFontImpl_GetTypeInfoCount (IDispatch) 1230 */ 1231 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount( 1232 IDispatch* iface, 1233 unsigned int* pctinfo) 1234 { 1235 OLEFontImpl *this = impl_from_IDispatch(iface); 1236 TRACE("(%p)->(%p)\n", this, pctinfo); 1237 *pctinfo = 1; 1238 1239 return S_OK; 1240 } 1241 1242 /************************************************************************ 1243 * OLEFontImpl_GetTypeInfo (IDispatch) 1244 */ 1245 static HRESULT WINAPI OLEFontImpl_GetTypeInfo( 1246 IDispatch* iface, 1247 UINT iTInfo, 1248 LCID lcid, 1249 ITypeInfo** ppTInfo) 1250 { 1251 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0}; 1252 ITypeLib *tl; 1253 HRESULT hres; 1254 1255 OLEFontImpl *this = impl_from_IDispatch(iface); 1256 TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo); 1257 if (iTInfo != 0) 1258 return E_FAIL; 1259 hres = LoadTypeLib(stdole2tlb, &tl); 1260 if (FAILED(hres)) { 1261 ERR("Could not load the stdole2.tlb?\n"); 1262 return hres; 1263 } 1264 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo); 1265 ITypeLib_Release(tl); 1266 if (FAILED(hres)) { 1267 FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres); 1268 } 1269 return hres; 1270 } 1271 1272 /************************************************************************ 1273 * OLEFontImpl_GetIDsOfNames (IDispatch) 1274 */ 1275 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames( 1276 IDispatch* iface, 1277 REFIID riid, 1278 LPOLESTR* rgszNames, 1279 UINT cNames, 1280 LCID lcid, 1281 DISPID* rgDispId) 1282 { 1283 ITypeInfo * pTInfo; 1284 HRESULT hres; 1285 1286 OLEFontImpl *this = impl_from_IDispatch(iface); 1287 1288 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid), 1289 rgszNames, cNames, (int)lcid, rgDispId); 1290 1291 if (cNames == 0) return E_INVALIDARG; 1292 1293 hres = IDispatch_GetTypeInfo(iface, 0, lcid, &pTInfo); 1294 if (FAILED(hres)) 1295 { 1296 ERR("GetTypeInfo failed.\n"); 1297 return hres; 1298 } 1299 1300 /* convert names to DISPIDs */ 1301 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId); 1302 ITypeInfo_Release(pTInfo); 1303 1304 return hres; 1305 } 1306 1307 /************************************************************************ 1308 * OLEFontImpl_Invoke (IDispatch) 1309 * 1310 */ 1311 static HRESULT WINAPI OLEFontImpl_Invoke( 1312 IDispatch* iface, 1313 DISPID dispIdMember, 1314 REFIID riid, 1315 LCID lcid, 1316 WORD wFlags, 1317 DISPPARAMS* pDispParams, 1318 VARIANT* pVarResult, 1319 EXCEPINFO* pExepInfo, 1320 UINT* puArgErr) 1321 { 1322 OLEFontImpl *this = impl_from_IDispatch(iface); 1323 HRESULT hr; 1324 1325 TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember, 1326 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo, 1327 puArgErr); 1328 1329 /* validate parameters */ 1330 1331 if (!IsEqualIID(riid, &IID_NULL)) 1332 { 1333 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid)); 1334 return DISP_E_UNKNOWNINTERFACE; 1335 } 1336 1337 if (wFlags & DISPATCH_PROPERTYGET) 1338 { 1339 if (!pVarResult) 1340 { 1341 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n"); 1342 return DISP_E_PARAMNOTOPTIONAL; 1343 } 1344 } 1345 else if (wFlags & DISPATCH_PROPERTYPUT) 1346 { 1347 if (!pDispParams) 1348 { 1349 ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n"); 1350 return DISP_E_PARAMNOTOPTIONAL; 1351 } 1352 if (pDispParams->cArgs != 1) 1353 { 1354 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs); 1355 return DISP_E_BADPARAMCOUNT; 1356 } 1357 } 1358 else 1359 { 1360 ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n"); 1361 return DISP_E_MEMBERNOTFOUND; 1362 } 1363 1364 switch (dispIdMember) { 1365 case DISPID_FONT_NAME: 1366 if (wFlags & DISPATCH_PROPERTYGET) { 1367 V_VT(pVarResult) = VT_BSTR; 1368 return IFont_get_Name(&this->IFont_iface, &V_BSTR(pVarResult)); 1369 } else { 1370 VARIANTARG vararg; 1371 1372 VariantInit(&vararg); 1373 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR); 1374 if (FAILED(hr)) 1375 return hr; 1376 1377 hr = IFont_put_Name(&this->IFont_iface, V_BSTR(&vararg)); 1378 1379 VariantClear(&vararg); 1380 return hr; 1381 } 1382 break; 1383 case DISPID_FONT_BOLD: 1384 if (wFlags & DISPATCH_PROPERTYGET) { 1385 BOOL value; 1386 hr = IFont_get_Bold(&this->IFont_iface, &value); 1387 V_VT(pVarResult) = VT_BOOL; 1388 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE; 1389 return hr; 1390 } else { 1391 VARIANTARG vararg; 1392 1393 VariantInit(&vararg); 1394 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL); 1395 if (FAILED(hr)) 1396 return hr; 1397 1398 hr = IFont_put_Bold(&this->IFont_iface, V_BOOL(&vararg)); 1399 1400 VariantClear(&vararg); 1401 return hr; 1402 } 1403 break; 1404 case DISPID_FONT_ITALIC: 1405 if (wFlags & DISPATCH_PROPERTYGET) { 1406 BOOL value; 1407 hr = IFont_get_Italic(&this->IFont_iface, &value); 1408 V_VT(pVarResult) = VT_BOOL; 1409 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE; 1410 return hr; 1411 } else { 1412 VARIANTARG vararg; 1413 1414 VariantInit(&vararg); 1415 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL); 1416 if (FAILED(hr)) 1417 return hr; 1418 1419 hr = IFont_put_Italic(&this->IFont_iface, V_BOOL(&vararg)); 1420 1421 VariantClear(&vararg); 1422 return hr; 1423 } 1424 break; 1425 case DISPID_FONT_UNDER: 1426 if (wFlags & DISPATCH_PROPERTYGET) { 1427 BOOL value; 1428 hr = IFont_get_Underline(&this->IFont_iface, &value); 1429 V_VT(pVarResult) = VT_BOOL; 1430 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE; 1431 return hr; 1432 } else { 1433 VARIANTARG vararg; 1434 1435 VariantInit(&vararg); 1436 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL); 1437 if (FAILED(hr)) 1438 return hr; 1439 1440 hr = IFont_put_Underline(&this->IFont_iface, V_BOOL(&vararg)); 1441 1442 VariantClear(&vararg); 1443 return hr; 1444 } 1445 break; 1446 case DISPID_FONT_STRIKE: 1447 if (wFlags & DISPATCH_PROPERTYGET) { 1448 BOOL value; 1449 hr = IFont_get_Strikethrough(&this->IFont_iface, &value); 1450 V_VT(pVarResult) = VT_BOOL; 1451 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE; 1452 return hr; 1453 } else { 1454 VARIANTARG vararg; 1455 1456 VariantInit(&vararg); 1457 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL); 1458 if (FAILED(hr)) 1459 return hr; 1460 1461 hr = IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&vararg)); 1462 1463 VariantClear(&vararg); 1464 return hr; 1465 } 1466 break; 1467 case DISPID_FONT_SIZE: 1468 if (wFlags & DISPATCH_PROPERTYGET) { 1469 V_VT(pVarResult) = VT_CY; 1470 return IFont_get_Size(&this->IFont_iface, &V_CY(pVarResult)); 1471 } else { 1472 VARIANTARG vararg; 1473 1474 VariantInit(&vararg); 1475 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY); 1476 if (FAILED(hr)) 1477 return hr; 1478 1479 hr = IFont_put_Size(&this->IFont_iface, V_CY(&vararg)); 1480 1481 VariantClear(&vararg); 1482 return hr; 1483 } 1484 break; 1485 case DISPID_FONT_WEIGHT: 1486 if (wFlags & DISPATCH_PROPERTYGET) { 1487 V_VT(pVarResult) = VT_I2; 1488 return IFont_get_Weight(&this->IFont_iface, &V_I2(pVarResult)); 1489 } else { 1490 VARIANTARG vararg; 1491 1492 VariantInit(&vararg); 1493 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2); 1494 if (FAILED(hr)) 1495 return hr; 1496 1497 hr = IFont_put_Weight(&this->IFont_iface, V_I2(&vararg)); 1498 1499 VariantClear(&vararg); 1500 return hr; 1501 } 1502 break; 1503 case DISPID_FONT_CHARSET: 1504 if (wFlags & DISPATCH_PROPERTYGET) { 1505 V_VT(pVarResult) = VT_I2; 1506 return OLEFontImpl_get_Charset(&this->IFont_iface, &V_I2(pVarResult)); 1507 } else { 1508 VARIANTARG vararg; 1509 1510 VariantInit(&vararg); 1511 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2); 1512 if (FAILED(hr)) 1513 return hr; 1514 1515 hr = IFont_put_Charset(&this->IFont_iface, V_I2(&vararg)); 1516 1517 VariantClear(&vararg); 1518 return hr; 1519 } 1520 break; 1521 default: 1522 ERR("member not found for dispid 0x%x\n", dispIdMember); 1523 return DISP_E_MEMBERNOTFOUND; 1524 } 1525 } 1526 1527 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable = 1528 { 1529 OLEFontImpl_IDispatch_QueryInterface, 1530 OLEFontImpl_IDispatch_AddRef, 1531 OLEFontImpl_IDispatch_Release, 1532 OLEFontImpl_GetTypeInfoCount, 1533 OLEFontImpl_GetTypeInfo, 1534 OLEFontImpl_GetIDsOfNames, 1535 OLEFontImpl_Invoke 1536 }; 1537 1538 /************************************************************************ 1539 * OLEFontImpl_IPersistStream_QueryInterface (IUnknown) 1540 */ 1541 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface( 1542 IPersistStream* iface, 1543 REFIID riid, 1544 VOID** ppvoid) 1545 { 1546 OLEFontImpl *this = impl_from_IPersistStream(iface); 1547 1548 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid); 1549 } 1550 1551 /************************************************************************ 1552 * OLEFontImpl_IPersistStream_Release (IUnknown) 1553 */ 1554 static ULONG WINAPI OLEFontImpl_IPersistStream_Release( 1555 IPersistStream* iface) 1556 { 1557 OLEFontImpl *this = impl_from_IPersistStream(iface); 1558 1559 return IFont_Release(&this->IFont_iface); 1560 } 1561 1562 /************************************************************************ 1563 * OLEFontImpl_IPersistStream_AddRef (IUnknown) 1564 */ 1565 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef( 1566 IPersistStream* iface) 1567 { 1568 OLEFontImpl *this = impl_from_IPersistStream(iface); 1569 1570 return IFont_AddRef(&this->IFont_iface); 1571 } 1572 1573 /************************************************************************ 1574 * OLEFontImpl_GetClassID (IPersistStream) 1575 */ 1576 static HRESULT WINAPI OLEFontImpl_GetClassID( 1577 IPersistStream* iface, 1578 CLSID* pClassID) 1579 { 1580 TRACE("(%p,%p)\n",iface,pClassID); 1581 if (pClassID==0) 1582 return E_POINTER; 1583 1584 *pClassID = CLSID_StdFont; 1585 1586 return S_OK; 1587 } 1588 1589 /************************************************************************ 1590 * OLEFontImpl_IsDirty (IPersistStream) 1591 * 1592 * See Windows documentation for more details on IPersistStream methods. 1593 */ 1594 static HRESULT WINAPI OLEFontImpl_IsDirty( 1595 IPersistStream* iface) 1596 { 1597 TRACE("(%p)\n",iface); 1598 return S_OK; 1599 } 1600 1601 /************************************************************************ 1602 * OLEFontImpl_Load (IPersistStream) 1603 * 1604 * See Windows documentation for more details on IPersistStream methods. 1605 * 1606 * This is the format of the standard font serialization as far as I 1607 * know 1608 * 1609 * Offset Type Value Comment 1610 * 0x0000 Byte Unknown Probably a version number, contains 0x01 1611 * 0x0001 Short Charset Charset value from the FONTDESC structure 1612 * 0x0003 Byte Attributes Flags defined as follows: 1613 * 00000010 - Italic 1614 * 00000100 - Underline 1615 * 00001000 - Strikethrough 1616 * 0x0004 Short Weight Weight value from FONTDESC structure 1617 * 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC 1618 * structure/ 1619 * 0x000A Byte name length Length of the font name string (no null character) 1620 * 0x000B String name Name of the font (ASCII, no nul character) 1621 */ 1622 static HRESULT WINAPI OLEFontImpl_Load( 1623 IPersistStream* iface, 1624 IStream* pLoadStream) 1625 { 1626 OLEFontImpl *this = impl_from_IPersistStream(iface); 1627 BYTE version, attributes, string_size; 1628 char readBuffer[0x100]; 1629 ULONG cbRead; 1630 INT len; 1631 1632 /* Version */ 1633 IStream_Read(pLoadStream, &version, sizeof(BYTE), &cbRead); 1634 if ((cbRead != sizeof(BYTE)) || (version != 0x01)) return E_FAIL; 1635 1636 /* Charset */ 1637 IStream_Read(pLoadStream, &this->description.sCharset, sizeof(WORD), &cbRead); 1638 if (cbRead != sizeof(WORD)) return E_FAIL; 1639 1640 /* Attributes */ 1641 IStream_Read(pLoadStream, &attributes, sizeof(BYTE), &cbRead); 1642 if (cbRead != sizeof(BYTE)) return E_FAIL; 1643 1644 this->description.fItalic = (attributes & FONTPERSIST_ITALIC) != 0; 1645 this->description.fStrikethrough = (attributes & FONTPERSIST_STRIKETHROUGH) != 0; 1646 this->description.fUnderline = (attributes & FONTPERSIST_UNDERLINE) != 0; 1647 1648 /* Weight */ 1649 IStream_Read(pLoadStream, &this->description.sWeight, sizeof(WORD), &cbRead); 1650 if (cbRead != sizeof(WORD)) return E_FAIL; 1651 1652 /* Size */ 1653 IStream_Read(pLoadStream, &this->description.cySize.s.Lo, sizeof(DWORD), &cbRead); 1654 if (cbRead != sizeof(DWORD)) return E_FAIL; 1655 1656 this->description.cySize.s.Hi = 0; 1657 1658 /* Name */ 1659 IStream_Read(pLoadStream, &string_size, sizeof(BYTE), &cbRead); 1660 if (cbRead != sizeof(BYTE)) return E_FAIL; 1661 1662 IStream_Read(pLoadStream, readBuffer, string_size, &cbRead); 1663 if (cbRead != string_size) return E_FAIL; 1664 1665 HeapFree(GetProcessHeap(), 0, this->description.lpstrName); 1666 1667 len = MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, NULL, 0 ); 1668 this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) ); 1669 MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, this->description.lpstrName, len ); 1670 this->description.lpstrName[len] = 0; 1671 1672 /* Ensure use of this font causes a new one to be created */ 1673 dec_int_ref(this->gdiFont); 1674 this->gdiFont = 0; 1675 this->dirty = TRUE; 1676 1677 return S_OK; 1678 } 1679 1680 /************************************************************************ 1681 * OLEFontImpl_Save (IPersistStream) 1682 */ 1683 static HRESULT WINAPI OLEFontImpl_Save( 1684 IPersistStream* iface, 1685 IStream* pOutStream, 1686 BOOL fClearDirty) 1687 { 1688 OLEFontImpl *this = impl_from_IPersistStream(iface); 1689 BYTE attributes, string_size; 1690 const BYTE version = 0x01; 1691 char* writeBuffer = NULL; 1692 ULONG written; 1693 1694 TRACE("(%p)->(%p %d)\n", this, pOutStream, fClearDirty); 1695 1696 /* Version */ 1697 IStream_Write(pOutStream, &version, sizeof(BYTE), &written); 1698 if (written != sizeof(BYTE)) return E_FAIL; 1699 1700 /* Charset */ 1701 IStream_Write(pOutStream, &this->description.sCharset, sizeof(WORD), &written); 1702 if (written != sizeof(WORD)) return E_FAIL; 1703 1704 /* Attributes */ 1705 attributes = 0; 1706 1707 if (this->description.fItalic) 1708 attributes |= FONTPERSIST_ITALIC; 1709 1710 if (this->description.fStrikethrough) 1711 attributes |= FONTPERSIST_STRIKETHROUGH; 1712 1713 if (this->description.fUnderline) 1714 attributes |= FONTPERSIST_UNDERLINE; 1715 1716 IStream_Write(pOutStream, &attributes, sizeof(BYTE), &written); 1717 if (written != sizeof(BYTE)) return E_FAIL; 1718 1719 /* Weight */ 1720 IStream_Write(pOutStream, &this->description.sWeight, sizeof(WORD), &written); 1721 if (written != sizeof(WORD)) return E_FAIL; 1722 1723 /* Size */ 1724 IStream_Write(pOutStream, &this->description.cySize.s.Lo, sizeof(DWORD), &written); 1725 if (written != sizeof(DWORD)) return E_FAIL; 1726 1727 /* FontName */ 1728 if (this->description.lpstrName) 1729 string_size = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName, 1730 strlenW(this->description.lpstrName), NULL, 0, NULL, NULL ); 1731 else 1732 string_size = 0; 1733 1734 IStream_Write(pOutStream, &string_size, sizeof(BYTE), &written); 1735 if (written != sizeof(BYTE)) return E_FAIL; 1736 1737 if (string_size) 1738 { 1739 if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, string_size ))) return E_OUTOFMEMORY; 1740 WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName, 1741 strlenW(this->description.lpstrName), 1742 writeBuffer, string_size, NULL, NULL ); 1743 1744 IStream_Write(pOutStream, writeBuffer, string_size, &written); 1745 HeapFree(GetProcessHeap(), 0, writeBuffer); 1746 1747 if (written != string_size) return E_FAIL; 1748 } 1749 1750 return S_OK; 1751 } 1752 1753 /************************************************************************ 1754 * OLEFontImpl_GetSizeMax (IPersistStream) 1755 */ 1756 static HRESULT WINAPI OLEFontImpl_GetSizeMax( 1757 IPersistStream* iface, 1758 ULARGE_INTEGER* pcbSize) 1759 { 1760 OLEFontImpl *this = impl_from_IPersistStream(iface); 1761 1762 if (pcbSize==NULL) 1763 return E_POINTER; 1764 1765 pcbSize->u.HighPart = 0; 1766 pcbSize->u.LowPart = 0; 1767 1768 pcbSize->u.LowPart += sizeof(BYTE); /* Version */ 1769 pcbSize->u.LowPart += sizeof(WORD); /* Lang code */ 1770 pcbSize->u.LowPart += sizeof(BYTE); /* Flags */ 1771 pcbSize->u.LowPart += sizeof(WORD); /* Weight */ 1772 pcbSize->u.LowPart += sizeof(DWORD); /* Size */ 1773 pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */ 1774 1775 if (this->description.lpstrName!=0) 1776 pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName, 1777 strlenW(this->description.lpstrName), 1778 NULL, 0, NULL, NULL ); 1779 1780 return S_OK; 1781 } 1782 1783 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable = 1784 { 1785 OLEFontImpl_IPersistStream_QueryInterface, 1786 OLEFontImpl_IPersistStream_AddRef, 1787 OLEFontImpl_IPersistStream_Release, 1788 OLEFontImpl_GetClassID, 1789 OLEFontImpl_IsDirty, 1790 OLEFontImpl_Load, 1791 OLEFontImpl_Save, 1792 OLEFontImpl_GetSizeMax 1793 }; 1794 1795 /************************************************************************ 1796 * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown) 1797 */ 1798 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface( 1799 IConnectionPointContainer* iface, 1800 REFIID riid, 1801 VOID** ppvoid) 1802 { 1803 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); 1804 1805 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid); 1806 } 1807 1808 /************************************************************************ 1809 * OLEFontImpl_IConnectionPointContainer_Release (IUnknown) 1810 */ 1811 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release( 1812 IConnectionPointContainer* iface) 1813 { 1814 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); 1815 1816 return IFont_Release(&this->IFont_iface); 1817 } 1818 1819 /************************************************************************ 1820 * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown) 1821 */ 1822 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef( 1823 IConnectionPointContainer* iface) 1824 { 1825 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); 1826 1827 return IFont_AddRef(&this->IFont_iface); 1828 } 1829 1830 /************************************************************************ 1831 * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer) 1832 */ 1833 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints( 1834 IConnectionPointContainer* iface, 1835 IEnumConnectionPoints **ppEnum) 1836 { 1837 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); 1838 1839 FIXME("(%p)->(%p): stub\n", this, ppEnum); 1840 return E_NOTIMPL; 1841 } 1842 1843 /************************************************************************ 1844 * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer) 1845 */ 1846 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint( 1847 IConnectionPointContainer* iface, 1848 REFIID riid, 1849 IConnectionPoint **ppCp) 1850 { 1851 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); 1852 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp); 1853 1854 if(IsEqualIID(riid, &IID_IPropertyNotifySink)) { 1855 return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP, &IID_IConnectionPoint, 1856 (void**)ppCp); 1857 } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) { 1858 return IConnectionPoint_QueryInterface(this->pFontEventsCP, &IID_IConnectionPoint, 1859 (void**)ppCp); 1860 } else { 1861 FIXME("no connection point for %s\n", debugstr_guid(riid)); 1862 return CONNECT_E_NOCONNECTION; 1863 } 1864 } 1865 1866 static const IConnectionPointContainerVtbl 1867 OLEFontImpl_IConnectionPointContainer_VTable = 1868 { 1869 OLEFontImpl_IConnectionPointContainer_QueryInterface, 1870 OLEFontImpl_IConnectionPointContainer_AddRef, 1871 OLEFontImpl_IConnectionPointContainer_Release, 1872 OLEFontImpl_EnumConnectionPoints, 1873 OLEFontImpl_FindConnectionPoint 1874 }; 1875 1876 /************************************************************************ 1877 * OLEFontImpl implementation of IPersistPropertyBag. 1878 */ 1879 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface( 1880 IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj 1881 ) { 1882 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); 1883 return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj); 1884 } 1885 1886 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef( 1887 IPersistPropertyBag *iface 1888 ) { 1889 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); 1890 return IFont_AddRef(&this->IFont_iface); 1891 } 1892 1893 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release( 1894 IPersistPropertyBag *iface 1895 ) { 1896 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); 1897 return IFont_Release(&this->IFont_iface); 1898 } 1899 1900 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID( 1901 IPersistPropertyBag *iface, CLSID *classid 1902 ) { 1903 FIXME("(%p,%p), stub!\n", iface, classid); 1904 return E_FAIL; 1905 } 1906 1907 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew( 1908 IPersistPropertyBag *iface 1909 ) { 1910 FIXME("(%p), stub!\n", iface); 1911 return S_OK; 1912 } 1913 1914 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load( 1915 IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog 1916 ) { 1917 /* (from Visual Basic 6 property bag) 1918 Name = "MS Sans Serif" 1919 Size = 13.8 1920 Charset = 0 1921 Weight = 400 1922 Underline = 0 'False 1923 Italic = 0 'False 1924 Strikethrough = 0 'False 1925 */ 1926 static const WCHAR sAttrName[] = {'N','a','m','e',0}; 1927 static const WCHAR sAttrSize[] = {'S','i','z','e',0}; 1928 static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0}; 1929 static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0}; 1930 static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0}; 1931 static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0}; 1932 static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; 1933 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); 1934 VARIANT value; 1935 HRESULT iRes; 1936 1937 VariantInit(&value); 1938 1939 iRes = IPropertyBag_Read(pPropBag, sAttrName, &value, pErrorLog); 1940 if (iRes == S_OK) 1941 { 1942 iRes = VariantChangeType(&value, &value, 0, VT_BSTR); 1943 if (iRes == S_OK) 1944 iRes = IFont_put_Name(&this->IFont_iface, V_BSTR(&value)); 1945 } 1946 else if (iRes == E_INVALIDARG) 1947 iRes = S_OK; 1948 1949 VariantClear(&value); 1950 1951 if (iRes == S_OK) { 1952 iRes = IPropertyBag_Read(pPropBag, sAttrSize, &value, pErrorLog); 1953 if (iRes == S_OK) 1954 { 1955 iRes = VariantChangeType(&value, &value, 0, VT_CY); 1956 if (iRes == S_OK) 1957 iRes = IFont_put_Size(&this->IFont_iface, V_CY(&value)); 1958 } 1959 else if (iRes == E_INVALIDARG) 1960 iRes = S_OK; 1961 1962 VariantClear(&value); 1963 } 1964 1965 if (iRes == S_OK) { 1966 iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &value, pErrorLog); 1967 if (iRes == S_OK) 1968 { 1969 iRes = VariantChangeType(&value, &value, 0, VT_I2); 1970 if (iRes == S_OK) 1971 iRes = IFont_put_Charset(&this->IFont_iface, V_I2(&value)); 1972 } 1973 else if (iRes == E_INVALIDARG) 1974 iRes = S_OK; 1975 1976 VariantClear(&value); 1977 } 1978 1979 if (iRes == S_OK) { 1980 iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &value, pErrorLog); 1981 if (iRes == S_OK) 1982 { 1983 iRes = VariantChangeType(&value, &value, 0, VT_I2); 1984 if (iRes == S_OK) 1985 iRes = IFont_put_Weight(&this->IFont_iface, V_I2(&value)); 1986 } 1987 else if (iRes == E_INVALIDARG) 1988 iRes = S_OK; 1989 1990 VariantClear(&value); 1991 } 1992 1993 if (iRes == S_OK) { 1994 iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &value, pErrorLog); 1995 if (iRes == S_OK) 1996 { 1997 iRes = VariantChangeType(&value, &value, 0, VT_BOOL); 1998 if (iRes == S_OK) 1999 iRes = IFont_put_Underline(&this->IFont_iface, V_BOOL(&value)); 2000 } 2001 else if (iRes == E_INVALIDARG) 2002 iRes = S_OK; 2003 2004 VariantClear(&value); 2005 } 2006 2007 if (iRes == S_OK) { 2008 iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &value, pErrorLog); 2009 if (iRes == S_OK) 2010 { 2011 iRes = VariantChangeType(&value, &value, 0, VT_BOOL); 2012 if (iRes == S_OK) 2013 iRes = IFont_put_Italic(&this->IFont_iface, V_BOOL(&value)); 2014 } 2015 else if (iRes == E_INVALIDARG) 2016 iRes = S_OK; 2017 2018 VariantClear(&value); 2019 } 2020 2021 if (iRes == S_OK) { 2022 iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &value, pErrorLog); 2023 if (iRes == S_OK) 2024 { 2025 iRes = VariantChangeType(&value, &value, 0, VT_BOOL); 2026 if (iRes == S_OK) 2027 IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&value)); 2028 } 2029 else if (iRes == E_INVALIDARG) 2030 iRes = S_OK; 2031 2032 VariantClear(&value); 2033 } 2034 2035 if (FAILED(iRes)) 2036 WARN("-- 0x%08x\n", iRes); 2037 return iRes; 2038 } 2039 2040 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save( 2041 IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty, 2042 BOOL fSaveAllProperties 2043 ) { 2044 FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties); 2045 return E_FAIL; 2046 } 2047 2048 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 2049 { 2050 OLEFontImpl_IPersistPropertyBag_QueryInterface, 2051 OLEFontImpl_IPersistPropertyBag_AddRef, 2052 OLEFontImpl_IPersistPropertyBag_Release, 2053 2054 OLEFontImpl_IPersistPropertyBag_GetClassID, 2055 OLEFontImpl_IPersistPropertyBag_InitNew, 2056 OLEFontImpl_IPersistPropertyBag_Load, 2057 OLEFontImpl_IPersistPropertyBag_Save 2058 }; 2059 2060 /************************************************************************ 2061 * OLEFontImpl implementation of IPersistStreamInit. 2062 */ 2063 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface( 2064 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj 2065 ) { 2066 OLEFontImpl *this = impl_from_IPersistStreamInit(iface); 2067 return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj); 2068 } 2069 2070 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef( 2071 IPersistStreamInit *iface 2072 ) { 2073 OLEFontImpl *this = impl_from_IPersistStreamInit(iface); 2074 return IFont_AddRef(&this->IFont_iface); 2075 } 2076 2077 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release( 2078 IPersistStreamInit *iface 2079 ) { 2080 OLEFontImpl *this = impl_from_IPersistStreamInit(iface); 2081 return IFont_Release(&this->IFont_iface); 2082 } 2083 2084 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID( 2085 IPersistStreamInit *iface, CLSID *classid 2086 ) { 2087 FIXME("(%p,%p), stub!\n", iface, classid); 2088 return E_FAIL; 2089 } 2090 2091 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty( 2092 IPersistStreamInit *iface 2093 ) { 2094 FIXME("(%p), stub!\n", iface); 2095 return E_FAIL; 2096 } 2097 2098 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load( 2099 IPersistStreamInit *iface, LPSTREAM pStm 2100 ) { 2101 FIXME("(%p,%p), stub!\n", iface, pStm); 2102 return E_FAIL; 2103 } 2104 2105 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save( 2106 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty 2107 ) { 2108 FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty); 2109 return E_FAIL; 2110 } 2111 2112 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax( 2113 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize 2114 ) { 2115 FIXME("(%p,%p), stub!\n", iface, pcbSize); 2116 return E_FAIL; 2117 } 2118 2119 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew( 2120 IPersistStreamInit *iface 2121 ) { 2122 FIXME("(%p), stub!\n", iface); 2123 return S_OK; 2124 } 2125 2126 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 2127 { 2128 OLEFontImpl_IPersistStreamInit_QueryInterface, 2129 OLEFontImpl_IPersistStreamInit_AddRef, 2130 OLEFontImpl_IPersistStreamInit_Release, 2131 2132 OLEFontImpl_IPersistStreamInit_GetClassID, 2133 OLEFontImpl_IPersistStreamInit_IsDirty, 2134 OLEFontImpl_IPersistStreamInit_Load, 2135 OLEFontImpl_IPersistStreamInit_Save, 2136 OLEFontImpl_IPersistStreamInit_GetSizeMax, 2137 OLEFontImpl_IPersistStreamInit_InitNew 2138 }; 2139 2140 /************************************************************************ 2141 * OLEFontImpl_Construct 2142 * 2143 * This method will construct a new instance of the OLEFontImpl 2144 * class. 2145 * 2146 * The caller of this method must release the object when it's 2147 * done with it. 2148 */ 2149 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc) 2150 { 2151 OLEFontImpl* newObject; 2152 2153 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl)); 2154 2155 if (newObject==0) 2156 return newObject; 2157 2158 newObject->IFont_iface.lpVtbl = &OLEFontImpl_VTable; 2159 newObject->IDispatch_iface.lpVtbl = &OLEFontImpl_IDispatch_VTable; 2160 newObject->IPersistStream_iface.lpVtbl = &OLEFontImpl_IPersistStream_VTable; 2161 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEFontImpl_IConnectionPointContainer_VTable; 2162 newObject->IPersistPropertyBag_iface.lpVtbl = &OLEFontImpl_IPersistPropertyBag_VTable; 2163 newObject->IPersistStreamInit_iface.lpVtbl = &OLEFontImpl_IPersistStreamInit_VTable; 2164 2165 newObject->ref = 1; 2166 2167 newObject->description.cbSizeofstruct = sizeof(FONTDESC); 2168 newObject->description.lpstrName = strdupW(fontDesc->lpstrName); 2169 newObject->description.cySize = fontDesc->cySize; 2170 newObject->description.sWeight = fontDesc->sWeight; 2171 newObject->description.sCharset = fontDesc->sCharset; 2172 newObject->description.fItalic = fontDesc->fItalic; 2173 newObject->description.fUnderline = fontDesc->fUnderline; 2174 newObject->description.fStrikethrough = fontDesc->fStrikethrough; 2175 2176 newObject->gdiFont = 0; 2177 newObject->dirty = TRUE; 2178 newObject->cyLogical = GetDeviceCaps(get_dc(), LOGPIXELSY); 2179 newObject->cyHimetric = 2540L; 2180 newObject->pPropertyNotifyCP = NULL; 2181 newObject->pFontEventsCP = NULL; 2182 2183 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP); 2184 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IFontEventsDisp, &newObject->pFontEventsCP); 2185 2186 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) 2187 { 2188 OLEFontImpl_Destroy(newObject); 2189 return NULL; 2190 } 2191 2192 InterlockedIncrement(&ifont_cnt); 2193 2194 TRACE("returning %p\n", newObject); 2195 return newObject; 2196 } 2197 2198 /************************************************************************ 2199 * OLEFontImpl_Destroy 2200 * 2201 * This method is called by the Release method when the reference 2202 * count goes down to 0. It will free all resources used by 2203 * this object. 2204 */ 2205 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc) 2206 { 2207 TRACE("(%p)\n", fontDesc); 2208 2209 HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName); 2210 2211 if (fontDesc->pPropertyNotifyCP) 2212 IConnectionPoint_Release(fontDesc->pPropertyNotifyCP); 2213 if (fontDesc->pFontEventsCP) 2214 IConnectionPoint_Release(fontDesc->pFontEventsCP); 2215 2216 HeapFree(GetProcessHeap(), 0, fontDesc); 2217 } 2218 2219 /******************************************************************************* 2220 * StdFont ClassFactory 2221 */ 2222 typedef struct 2223 { 2224 /* IUnknown fields */ 2225 IClassFactory IClassFactory_iface; 2226 LONG ref; 2227 } IClassFactoryImpl; 2228 2229 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 2230 { 2231 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 2232 } 2233 2234 static HRESULT WINAPI SFCF_QueryInterface(IClassFactory *iface, REFIID riid, void **obj) 2235 { 2236 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2237 2238 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj); 2239 2240 *obj = NULL; 2241 2242 if (IsEqualIID(&IID_IClassFactory, riid) || IsEqualIID(&IID_IUnknown, riid)) 2243 { 2244 *obj = iface; 2245 IClassFactory_AddRef(iface); 2246 return S_OK; 2247 } 2248 2249 return E_NOINTERFACE; 2250 } 2251 2252 static ULONG WINAPI 2253 SFCF_AddRef(LPCLASSFACTORY iface) { 2254 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2255 return InterlockedIncrement(&This->ref); 2256 } 2257 2258 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) { 2259 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2260 /* static class, won't be freed */ 2261 return InterlockedDecrement(&This->ref); 2262 } 2263 2264 static HRESULT WINAPI SFCF_CreateInstance( 2265 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj 2266 ) { 2267 return OleCreateFontIndirect(NULL,riid,ppobj); 2268 2269 } 2270 2271 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { 2272 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 2273 FIXME("(%p)->(%d),stub!\n",This,dolock); 2274 return S_OK; 2275 } 2276 2277 static const IClassFactoryVtbl SFCF_Vtbl = { 2278 SFCF_QueryInterface, 2279 SFCF_AddRef, 2280 SFCF_Release, 2281 SFCF_CreateInstance, 2282 SFCF_LockServer 2283 }; 2284 static IClassFactoryImpl STDFONT_CF = {{&SFCF_Vtbl}, 1 }; 2285 2286 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; } 2287