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