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