Release 6.15.
[wine.git] / dlls / oleaut32 / olefont.c
blobf071d00c6027e0f53f9a334954ee80f3038066a6
1 /*
2 * OLE Font encapsulation implementation
4 * This file contains an implementation of the IFont
5 * interface and the OleCreateFontIndirect API call.
7 * Copyright 1999 Francis Beaudet
8 * Copyright 2006 (Google) Benjamin Arai
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.
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.
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
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <string.h>
28 #define COBJMACROS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
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"
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48 /***********************************************************************
49 * Declaration of constants used when serializing the font object.
51 #define FONTPERSIST_ITALIC 0x02
52 #define FONTPERSIST_UNDERLINE 0x04
53 #define FONTPERSIST_STRIKETHROUGH 0x08
55 static HDC olefont_hdc;
57 /***********************************************************************
58 * List of the HFONTs it has given out, with each one having a separate
59 * ref count.
61 typedef struct _HFONTItem
63 struct list entry;
65 /* Reference count of any IFont objects that own this hfont */
66 LONG int_refs;
68 /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
69 LONG total_refs;
71 /* The font associated with this object. */
72 HFONT gdiFont;
74 } HFONTItem, *PHFONTItem;
76 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
78 /* Counts how many fonts contain at least one lock */
79 static LONG ifont_cnt = 0;
81 /***********************************************************************
82 * Critical section for OLEFontImpl_hFontList
84 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
85 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
87 0, 0, &OLEFontImpl_csHFONTLIST,
88 { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
89 &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
90 0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
92 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
94 static HDC get_dc(void)
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;
105 static void delete_dc(void)
107 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
108 if(olefont_hdc)
110 DeleteDC(olefont_hdc);
111 olefont_hdc = NULL;
113 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
116 static void HFONTItem_Delete(PHFONTItem item)
118 DeleteObject(item->gdiFont);
119 list_remove(&item->entry);
120 HeapFree(GetProcessHeap(), 0, item);
123 /* Find hfont item entry in the list. Should be called while holding the crit sect */
124 static HFONTItem *find_hfontitem(HFONT hfont)
126 HFONTItem *item;
128 LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
130 if (item->gdiFont == hfont)
131 return item;
133 return NULL;
136 /* Add an item to the list with one internal reference */
137 static HRESULT add_hfontitem(HFONT hfont)
139 HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
141 if(!new_item) return E_OUTOFMEMORY;
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;
152 static HRESULT inc_int_ref(HFONT hfont)
154 HFONTItem *item;
155 HRESULT hr = S_FALSE;
157 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
158 item = find_hfontitem(hfont);
160 if(item)
162 item->int_refs++;
163 item->total_refs++;
164 hr = S_OK;
166 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
168 return hr;
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)
175 HFONTItem *item;
176 HRESULT hr = S_FALSE;
178 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
179 item = find_hfontitem(hfont);
181 if(item)
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;
189 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
191 return hr;
194 static HRESULT inc_ext_ref(HFONT hfont)
196 HFONTItem *item;
197 HRESULT hr = S_FALSE;
199 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
201 item = find_hfontitem(hfont);
202 if(item)
204 item->total_refs++;
205 hr = S_OK;
207 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
209 return hr;
212 static HRESULT dec_ext_ref(HFONT hfont)
214 HFONTItem *item;
215 HRESULT hr = S_FALSE;
217 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
219 item = find_hfontitem(hfont);
220 if(item)
222 if(--item->total_refs >= 0) hr = S_OK;
224 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
226 return hr;
229 static WCHAR *strdupW(const WCHAR* str)
231 WCHAR *ret;
232 DWORD size = (lstrlenW(str) + 1) * sizeof(WCHAR);
234 ret = HeapAlloc(GetProcessHeap(), 0, size);
235 if(ret)
236 memcpy(ret, str, size);
237 return ret;
240 /***********************************************************************
241 * Declaration of the implementation class for the IFont interface
243 typedef struct OLEFontImpl OLEFontImpl;
245 struct OLEFontImpl
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.
253 IFont IFont_iface;
254 IDispatch IDispatch_iface;
255 IPersistStream IPersistStream_iface;
256 IConnectionPointContainer IConnectionPointContainer_iface;
257 IPersistPropertyBag IPersistPropertyBag_iface;
259 * Reference count for that instance of the class.
261 LONG ref;
264 * This structure contains the description of the class.
266 FONTDESC description;
269 * Contain the font associated with this object.
271 HFONT gdiFont;
272 BOOL dirty;
274 * Size ratio
276 LONG cyLogical;
277 LONG cyHimetric;
280 * Stash realized height (pixels) from TEXTMETRIC - used in get_Size()
282 LONG nRealHeight;
284 IConnectionPoint *pPropertyNotifyCP;
285 IConnectionPoint *pFontEventsCP;
288 static inline OLEFontImpl *impl_from_IFont(IFont *iface)
290 return CONTAINING_RECORD(iface, OLEFontImpl, IFont_iface);
293 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
295 return CONTAINING_RECORD(iface, OLEFontImpl, IDispatch_iface);
298 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
300 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStream_iface);
303 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
305 return CONTAINING_RECORD(iface, OLEFontImpl, IConnectionPointContainer_iface);
308 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
310 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistPropertyBag_iface);
314 /***********************************************************************
315 * Prototypes for the implementation functions for the IFont
316 * interface
318 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
319 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
320 static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
322 /******************************************************************************
323 * OleCreateFontIndirect [OLEAUT32.420]
325 HRESULT WINAPI OleCreateFontIndirect(
326 LPFONTDESC lpFontDesc,
327 REFIID riid,
328 LPVOID* ppvObj)
330 OLEFontImpl* newFont;
331 HRESULT hr;
332 FONTDESC fd;
334 TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
336 if (!ppvObj) return E_POINTER;
338 *ppvObj = 0;
340 if (!lpFontDesc) {
341 static WCHAR fname[] = L"System";
343 fd.cbSizeofstruct = sizeof(fd);
344 fd.lpstrName = fname;
345 fd.cySize.s.Lo = 80000;
346 fd.cySize.s.Hi = 0;
347 fd.sWeight = 0;
348 fd.sCharset = 0;
349 fd.fItalic = FALSE;
350 fd.fUnderline = FALSE;
351 fd.fStrikethrough = FALSE;
352 lpFontDesc = &fd;
355 newFont = OLEFontImpl_Construct(lpFontDesc);
356 if (!newFont) return E_OUTOFMEMORY;
358 hr = IFont_QueryInterface(&newFont->IFont_iface, riid, ppvObj);
359 IFont_Release(&newFont->IFont_iface);
361 return hr;
365 /***********************************************************************
366 * Implementation of the OLEFontImpl class.
369 /***********************************************************************
370 * OLEFont_SendNotify (internal)
372 * Sends notification messages of changed properties to any interested
373 * connections.
375 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
377 static const LPCWSTR dispid_mapping[] =
379 L"Name",
380 NULL,
381 L"Size",
382 L"Bold",
383 L"Italic",
384 L"Underline",
385 L"Strikethrough",
386 L"Weight",
387 L"Charset"
390 IEnumConnections *pEnum;
391 CONNECTDATA CD;
392 HRESULT hres;
394 this->dirty = TRUE;
396 hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
397 if (SUCCEEDED(hres))
399 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
400 IPropertyNotifySink *sink;
402 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (void**)&sink);
403 IPropertyNotifySink_OnChanged(sink, dispID);
404 IPropertyNotifySink_Release(sink);
405 IUnknown_Release(CD.pUnk);
407 IEnumConnections_Release(pEnum);
410 hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
411 if (SUCCEEDED(hres))
413 DISPPARAMS dispparams;
414 VARIANTARG vararg;
416 VariantInit(&vararg);
417 V_VT(&vararg) = VT_BSTR;
418 V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
420 dispparams.cArgs = 1;
421 dispparams.cNamedArgs = 0;
422 dispparams.rgdispidNamedArgs = NULL;
423 dispparams.rgvarg = &vararg;
425 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
426 IFontEventsDisp *disp;
428 IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (void**)&disp);
429 IFontEventsDisp_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
430 LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
431 NULL, NULL);
433 IFontEventsDisp_Release(disp);
434 IUnknown_Release(CD.pUnk);
436 VariantClear(&vararg);
437 IEnumConnections_Release(pEnum);
441 /************************************************************************
442 * OLEFontImpl_QueryInterface (IUnknown)
444 * See Windows documentation for more details on IUnknown methods.
446 static HRESULT WINAPI OLEFontImpl_QueryInterface(
447 IFont* iface,
448 REFIID riid,
449 void** ppvObject)
451 OLEFontImpl *this = impl_from_IFont(iface);
453 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
455 *ppvObject = 0;
457 if (IsEqualGUID(&IID_IUnknown, riid) ||
458 IsEqualGUID(&IID_IFont, riid))
460 *ppvObject = this;
462 else if (IsEqualGUID(&IID_IDispatch, riid) ||
463 IsEqualGUID(&IID_IFontDisp, riid))
465 *ppvObject = &this->IDispatch_iface;
467 else if (IsEqualGUID(&IID_IPersist, riid) ||
468 IsEqualGUID(&IID_IPersistStream, riid))
470 *ppvObject = &this->IPersistStream_iface;
472 else if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
474 *ppvObject = &this->IConnectionPointContainer_iface;
476 else if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
478 *ppvObject = &this->IPersistPropertyBag_iface;
481 if (!*ppvObject)
483 FIXME("() : asking for unsupported interface %s\n", debugstr_guid(riid));
484 return E_NOINTERFACE;
487 IFont_AddRef(iface);
489 return S_OK;
492 /************************************************************************
493 * OLEFontImpl_AddRef (IUnknown)
495 static ULONG WINAPI OLEFontImpl_AddRef(
496 IFont* iface)
498 OLEFontImpl *this = impl_from_IFont(iface);
499 TRACE("(%p)->(ref=%d)\n", this, this->ref);
500 return InterlockedIncrement(&this->ref);
503 /************************************************************************
504 * OLEFontImpl_Release (IUnknown)
506 static ULONG WINAPI OLEFontImpl_Release(IFont* iface)
508 OLEFontImpl *this = impl_from_IFont(iface);
509 ULONG ref;
511 TRACE("(%p)->(ref=%d)\n", this, this->ref);
513 ref = InterlockedDecrement(&this->ref);
515 if (ref == 0)
517 ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
519 /* Final IFont object so destroy font cache */
520 if (fontlist_refs == 0)
522 HFONTItem *item, *cursor2;
524 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
525 LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
526 HFONTItem_Delete(item);
527 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
528 delete_dc();
530 else
532 dec_int_ref(this->gdiFont);
534 OLEFontImpl_Destroy(this);
537 return ref;
540 typedef struct
542 short orig_cs;
543 short avail_cs;
544 } enum_data;
546 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
548 enum_data *data = (enum_data*)lp;
550 if(elf->lfCharSet == data->orig_cs)
552 data->avail_cs = data->orig_cs;
553 return 0;
555 if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
556 return 1;
559 static void realize_font(OLEFontImpl *This)
561 LOGFONTW logFont;
562 INT fontHeight;
563 WCHAR text_face[LF_FACESIZE];
564 HDC hdc = get_dc();
565 HFONT old_font;
566 TEXTMETRICW tm;
568 if (!This->dirty) return;
570 text_face[0] = 0;
572 if(This->gdiFont)
574 old_font = SelectObject(hdc, This->gdiFont);
575 GetTextFaceW(hdc, ARRAY_SIZE(text_face), text_face);
576 SelectObject(hdc, old_font);
577 dec_int_ref(This->gdiFont);
578 This->gdiFont = 0;
581 memset(&logFont, 0, sizeof(LOGFONTW));
583 lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
584 logFont.lfCharSet = This->description.sCharset;
586 /* If the font name has been changed then enumerate all charsets
587 and pick one that'll result in the font specified being selected */
588 if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
590 enum_data data;
591 data.orig_cs = This->description.sCharset;
592 data.avail_cs = -1;
593 logFont.lfCharSet = DEFAULT_CHARSET;
594 EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
595 if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
599 * The height of the font returned by the get_Size property is the
600 * height of the font in points multiplied by 10000... Using some
601 * simple conversions and the ratio given by the application, it can
602 * be converted to a height in pixels.
604 * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
605 * Ratio is applied here relative to the standard.
608 fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
610 logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
611 (-fontHeight/10000L);
612 logFont.lfItalic = This->description.fItalic;
613 logFont.lfUnderline = This->description.fUnderline;
614 logFont.lfStrikeOut = This->description.fStrikethrough;
615 logFont.lfWeight = This->description.sWeight;
616 logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
617 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
618 logFont.lfQuality = DEFAULT_QUALITY;
619 logFont.lfPitchAndFamily = DEFAULT_PITCH;
621 This->gdiFont = CreateFontIndirectW(&logFont);
622 This->dirty = FALSE;
624 add_hfontitem(This->gdiFont);
626 /* Fixup the name and charset properties so that they match the
627 selected font */
628 old_font = SelectObject(get_dc(), This->gdiFont);
629 GetTextFaceW(hdc, ARRAY_SIZE(text_face), text_face);
630 if(lstrcmpiW(text_face, This->description.lpstrName))
632 HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
633 This->description.lpstrName = strdupW(text_face);
635 GetTextMetricsW(hdc, &tm);
636 This->description.sCharset = tm.tmCharSet;
637 /* While we have it handy, stash the realized font height for use by get_Size() */
638 This->nRealHeight = tm.tmHeight - tm.tmInternalLeading; /* corresponds to LOGFONT lfHeight */
639 SelectObject(hdc, old_font);
642 /************************************************************************
643 * OLEFontImpl_get_Name (IFont)
645 * See Windows documentation for more details on IFont methods.
647 static HRESULT WINAPI OLEFontImpl_get_Name(
648 IFont* iface,
649 BSTR* pname)
651 OLEFontImpl *this = impl_from_IFont(iface);
652 TRACE("(%p)->(%p)\n", this, pname);
654 if (pname==0)
655 return E_POINTER;
657 realize_font(this);
659 if (this->description.lpstrName!=0)
660 *pname = SysAllocString(this->description.lpstrName);
661 else
662 *pname = 0;
664 return S_OK;
667 /************************************************************************
668 * OLEFontImpl_put_Name (IFont)
670 static HRESULT WINAPI OLEFontImpl_put_Name(
671 IFont* iface,
672 BSTR name)
674 OLEFontImpl *This = impl_from_IFont(iface);
675 TRACE("(%p)->(%p)\n", This, name);
677 if (!name)
678 return CTL_E_INVALIDPROPERTYVALUE;
680 HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
681 This->description.lpstrName = strdupW(name);
682 if (!This->description.lpstrName) return E_OUTOFMEMORY;
684 TRACE("new name %s\n", debugstr_w(This->description.lpstrName));
685 OLEFont_SendNotify(This, DISPID_FONT_NAME);
686 return S_OK;
689 /************************************************************************
690 * OLEFontImpl_get_Size (IFont)
692 static HRESULT WINAPI OLEFontImpl_get_Size(
693 IFont* iface,
694 CY* psize)
696 OLEFontImpl *this = impl_from_IFont(iface);
697 TRACE("(%p)->(%p)\n", this, psize);
699 if (!psize) return E_POINTER;
701 realize_font(this);
704 * Convert realized font height in pixels to points descaled by current
705 * scaling ratio then scaled up by 10000.
707 psize->s.Lo = MulDiv(this->nRealHeight,
708 this->cyHimetric * 72 * 10000,
709 this->cyLogical * 2540);
710 psize->s.Hi = 0;
712 return S_OK;
715 /************************************************************************
716 * OLEFontImpl_put_Size (IFont)
718 static HRESULT WINAPI OLEFontImpl_put_Size(
719 IFont* iface,
720 CY size)
722 OLEFontImpl *this = impl_from_IFont(iface);
723 TRACE("(%p)->(%d)\n", this, size.s.Lo);
724 this->description.cySize.s.Hi = 0;
725 this->description.cySize.s.Lo = size.s.Lo;
726 OLEFont_SendNotify(this, DISPID_FONT_SIZE);
728 return S_OK;
731 /************************************************************************
732 * OLEFontImpl_get_Bold (IFont)
734 * See Windows documentation for more details on IFont methods.
736 static HRESULT WINAPI OLEFontImpl_get_Bold(
737 IFont* iface,
738 BOOL* pbold)
740 OLEFontImpl *this = impl_from_IFont(iface);
741 TRACE("(%p)->(%p)\n", this, pbold);
743 if (!pbold) return E_POINTER;
745 realize_font(this);
747 *pbold = this->description.sWeight > 550;
749 return S_OK;
752 /************************************************************************
753 * OLEFontImpl_put_Bold (IFont)
755 static HRESULT WINAPI OLEFontImpl_put_Bold(
756 IFont* iface,
757 BOOL bold)
759 OLEFontImpl *this = impl_from_IFont(iface);
760 TRACE("(%p)->(%d)\n", this, bold);
761 this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
762 OLEFont_SendNotify(this, DISPID_FONT_BOLD);
764 return S_OK;
767 /************************************************************************
768 * OLEFontImpl_get_Italic (IFont)
770 static HRESULT WINAPI OLEFontImpl_get_Italic(
771 IFont* iface,
772 BOOL* pitalic)
774 OLEFontImpl *this = impl_from_IFont(iface);
775 TRACE("(%p)->(%p)\n", this, pitalic);
777 if (pitalic==0)
778 return E_POINTER;
780 realize_font(this);
782 *pitalic = this->description.fItalic;
784 return S_OK;
787 /************************************************************************
788 * OLEFontImpl_put_Italic (IFont)
790 static HRESULT WINAPI OLEFontImpl_put_Italic(
791 IFont* iface,
792 BOOL italic)
794 OLEFontImpl *this = impl_from_IFont(iface);
795 TRACE("(%p)->(%d)\n", this, italic);
797 this->description.fItalic = italic;
799 OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
800 return S_OK;
803 /************************************************************************
804 * OLEFontImpl_get_Underline (IFont)
806 static HRESULT WINAPI OLEFontImpl_get_Underline(
807 IFont* iface,
808 BOOL* punderline)
810 OLEFontImpl *this = impl_from_IFont(iface);
811 TRACE("(%p)->(%p)\n", this, punderline);
813 if (punderline==0)
814 return E_POINTER;
816 realize_font(this);
818 *punderline = this->description.fUnderline;
820 return S_OK;
823 /************************************************************************
824 * OLEFontImpl_put_Underline (IFont)
826 static HRESULT WINAPI OLEFontImpl_put_Underline(
827 IFont* iface,
828 BOOL underline)
830 OLEFontImpl *this = impl_from_IFont(iface);
831 TRACE("(%p)->(%d)\n", this, underline);
833 this->description.fUnderline = underline;
835 OLEFont_SendNotify(this, DISPID_FONT_UNDER);
836 return S_OK;
839 /************************************************************************
840 * OLEFontImpl_get_Strikethrough (IFont)
842 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
843 IFont* iface,
844 BOOL* pstrikethrough)
846 OLEFontImpl *this = impl_from_IFont(iface);
847 TRACE("(%p)->(%p)\n", this, pstrikethrough);
849 if (pstrikethrough==0)
850 return E_POINTER;
852 realize_font(this);
854 *pstrikethrough = this->description.fStrikethrough;
856 return S_OK;
859 /************************************************************************
860 * OLEFontImpl_put_Strikethrough (IFont)
862 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
863 IFont* iface,
864 BOOL strikethrough)
866 OLEFontImpl *this = impl_from_IFont(iface);
867 TRACE("(%p)->(%d)\n", this, strikethrough);
869 this->description.fStrikethrough = strikethrough;
870 OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
872 return S_OK;
875 /************************************************************************
876 * OLEFontImpl_get_Weight (IFont)
878 static HRESULT WINAPI OLEFontImpl_get_Weight(
879 IFont* iface,
880 short* pweight)
882 OLEFontImpl *this = impl_from_IFont(iface);
883 TRACE("(%p)->(%p)\n", this, pweight);
885 if (pweight==0)
886 return E_POINTER;
888 realize_font(this);
890 *pweight = this->description.sWeight;
892 return S_OK;
895 /************************************************************************
896 * OLEFontImpl_put_Weight (IFont)
898 static HRESULT WINAPI OLEFontImpl_put_Weight(
899 IFont* iface,
900 short weight)
902 OLEFontImpl *this = impl_from_IFont(iface);
903 TRACE("(%p)->(%d)\n", this, weight);
905 this->description.sWeight = weight;
907 OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
908 return S_OK;
911 /************************************************************************
912 * OLEFontImpl_get_Charset (IFont)
914 static HRESULT WINAPI OLEFontImpl_get_Charset(
915 IFont* iface,
916 short* pcharset)
918 OLEFontImpl *this = impl_from_IFont(iface);
919 TRACE("(%p)->(%p)\n", this, pcharset);
921 if (pcharset==0)
922 return E_POINTER;
924 realize_font(this);
926 *pcharset = this->description.sCharset;
928 return S_OK;
931 /************************************************************************
932 * OLEFontImpl_put_Charset (IFont)
934 static HRESULT WINAPI OLEFontImpl_put_Charset(
935 IFont* iface,
936 short charset)
938 OLEFontImpl *this = impl_from_IFont(iface);
939 TRACE("(%p)->(%d)\n", this, charset);
941 this->description.sCharset = charset;
942 OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
944 return S_OK;
947 /************************************************************************
948 * OLEFontImpl_get_hFont (IFont)
950 static HRESULT WINAPI OLEFontImpl_get_hFont(
951 IFont* iface,
952 HFONT* phfont)
954 OLEFontImpl *this = impl_from_IFont(iface);
955 TRACE("(%p)->(%p)\n", this, phfont);
956 if (phfont==NULL)
957 return E_POINTER;
959 realize_font(this);
961 *phfont = this->gdiFont;
962 TRACE("Returning %p\n", *phfont);
963 return S_OK;
966 /************************************************************************
967 * OLEFontImpl_Clone (IFont)
969 static HRESULT WINAPI OLEFontImpl_Clone(
970 IFont* iface,
971 IFont** ppfont)
973 OLEFontImpl *this = impl_from_IFont(iface);
974 OLEFontImpl* newObject;
976 TRACE("(%p)->(%p)\n", this, ppfont);
978 if (ppfont == NULL)
979 return E_POINTER;
981 *ppfont = NULL;
983 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
984 if (newObject==NULL)
985 return E_OUTOFMEMORY;
987 *newObject = *this;
988 /* allocate separate buffer */
989 newObject->description.lpstrName = strdupW(this->description.lpstrName);
991 /* Increment internal ref in hfont item list */
992 if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
994 InterlockedIncrement(&ifont_cnt);
996 newObject->pPropertyNotifyCP = NULL;
997 newObject->pFontEventsCP = NULL;
998 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IPropertyNotifySink,
999 &newObject->pPropertyNotifyCP);
1000 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IFontEventsDisp,
1001 &newObject->pFontEventsCP);
1003 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
1005 OLEFontImpl_Destroy(newObject);
1006 return E_OUTOFMEMORY;
1009 /* The cloned object starts with a reference count of 1 */
1010 newObject->ref = 1;
1012 *ppfont = &newObject->IFont_iface;
1014 return S_OK;
1017 /************************************************************************
1018 * OLEFontImpl_IsEqual (IFont)
1020 static HRESULT WINAPI OLEFontImpl_IsEqual(
1021 IFont* iface,
1022 IFont* pFontOther)
1024 OLEFontImpl *left = impl_from_IFont(iface);
1025 OLEFontImpl *right = impl_from_IFont(pFontOther);
1026 INT ret;
1027 INT left_len,right_len;
1029 if(pFontOther == NULL)
1030 return E_POINTER;
1031 else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
1032 return S_FALSE;
1033 else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
1034 return S_FALSE;
1035 else if (left->description.sWeight != right->description.sWeight)
1036 return S_FALSE;
1037 else if (left->description.sCharset != right->description.sCharset)
1038 return S_FALSE;
1039 else if (left->description.fItalic != right->description.fItalic)
1040 return S_FALSE;
1041 else if (left->description.fUnderline != right->description.fUnderline)
1042 return S_FALSE;
1043 else if (left->description.fStrikethrough != right->description.fStrikethrough)
1044 return S_FALSE;
1046 /* Check from string */
1047 left_len = lstrlenW(left->description.lpstrName);
1048 right_len = lstrlenW(right->description.lpstrName);
1049 ret = CompareStringW(0,0,left->description.lpstrName, left_len,
1050 right->description.lpstrName, right_len);
1051 if (ret != CSTR_EQUAL)
1052 return S_FALSE;
1054 return S_OK;
1057 /************************************************************************
1058 * OLEFontImpl_SetRatio (IFont)
1060 static HRESULT WINAPI OLEFontImpl_SetRatio(
1061 IFont* iface,
1062 LONG cyLogical,
1063 LONG cyHimetric)
1065 OLEFontImpl *this = impl_from_IFont(iface);
1066 TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
1068 if(cyLogical == 0 || cyHimetric == 0)
1069 return E_FAIL;
1071 /* cyLogical and cyHimetric both set to 1 is a special case that
1072 does not change the scaling but also does not fail */
1073 if(cyLogical == 1 && cyHimetric == 1)
1074 return S_OK;
1076 this->cyLogical = cyLogical;
1077 this->cyHimetric = cyHimetric;
1078 this->dirty = TRUE;
1080 return S_OK;
1083 /************************************************************************
1084 * OLEFontImpl_QueryTextMetrics (IFont)
1086 static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(
1087 IFont* iface,
1088 TEXTMETRICOLE* ptm)
1090 HDC hdcRef;
1091 HFONT hOldFont, hNewFont;
1093 hdcRef = GetDC(0);
1094 IFont_get_hFont(iface, &hNewFont);
1095 hOldFont = SelectObject(hdcRef, hNewFont);
1096 GetTextMetricsW(hdcRef, ptm);
1097 SelectObject(hdcRef, hOldFont);
1098 ReleaseDC(0, hdcRef);
1099 return S_OK;
1102 /************************************************************************
1103 * OLEFontImpl_AddRefHfont (IFont)
1105 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1106 IFont* iface,
1107 HFONT hfont)
1109 OLEFontImpl *this = impl_from_IFont(iface);
1111 TRACE("(%p)->(%p)\n", this, hfont);
1113 if (!hfont) return E_INVALIDARG;
1115 return inc_ext_ref(hfont);
1118 /************************************************************************
1119 * OLEFontImpl_ReleaseHfont (IFont)
1121 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1122 IFont* iface,
1123 HFONT hfont)
1125 OLEFontImpl *this = impl_from_IFont(iface);
1127 TRACE("(%p)->(%p)\n", this, hfont);
1129 if (!hfont) return E_INVALIDARG;
1131 return dec_ext_ref(hfont);
1134 /************************************************************************
1135 * OLEFontImpl_SetHdc (IFont)
1137 static HRESULT WINAPI OLEFontImpl_SetHdc(
1138 IFont* iface,
1139 HDC hdc)
1141 OLEFontImpl *this = impl_from_IFont(iface);
1142 FIXME("(%p)->(%p): Stub\n", this, hdc);
1143 return E_NOTIMPL;
1146 static const IFontVtbl OLEFontImpl_VTable =
1148 OLEFontImpl_QueryInterface,
1149 OLEFontImpl_AddRef,
1150 OLEFontImpl_Release,
1151 OLEFontImpl_get_Name,
1152 OLEFontImpl_put_Name,
1153 OLEFontImpl_get_Size,
1154 OLEFontImpl_put_Size,
1155 OLEFontImpl_get_Bold,
1156 OLEFontImpl_put_Bold,
1157 OLEFontImpl_get_Italic,
1158 OLEFontImpl_put_Italic,
1159 OLEFontImpl_get_Underline,
1160 OLEFontImpl_put_Underline,
1161 OLEFontImpl_get_Strikethrough,
1162 OLEFontImpl_put_Strikethrough,
1163 OLEFontImpl_get_Weight,
1164 OLEFontImpl_put_Weight,
1165 OLEFontImpl_get_Charset,
1166 OLEFontImpl_put_Charset,
1167 OLEFontImpl_get_hFont,
1168 OLEFontImpl_Clone,
1169 OLEFontImpl_IsEqual,
1170 OLEFontImpl_SetRatio,
1171 OLEFontImpl_QueryTextMetrics,
1172 OLEFontImpl_AddRefHfont,
1173 OLEFontImpl_ReleaseHfont,
1174 OLEFontImpl_SetHdc
1177 /************************************************************************
1178 * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1180 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1181 IDispatch* iface,
1182 REFIID riid,
1183 VOID** ppvoid)
1185 OLEFontImpl *this = impl_from_IDispatch(iface);
1186 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
1189 /************************************************************************
1190 * OLEFontImpl_IDispatch_Release (IUnknown)
1192 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1193 IDispatch* iface)
1195 OLEFontImpl *this = impl_from_IDispatch(iface);
1196 return IFont_Release(&this->IFont_iface);
1199 /************************************************************************
1200 * OLEFontImpl_IDispatch_AddRef (IUnknown)
1202 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1203 IDispatch* iface)
1205 OLEFontImpl *this = impl_from_IDispatch(iface);
1206 return IFont_AddRef(&this->IFont_iface);
1209 /************************************************************************
1210 * OLEFontImpl_GetTypeInfoCount (IDispatch)
1212 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1213 IDispatch* iface,
1214 unsigned int* pctinfo)
1216 OLEFontImpl *this = impl_from_IDispatch(iface);
1217 TRACE("(%p)->(%p)\n", this, pctinfo);
1218 *pctinfo = 1;
1220 return S_OK;
1223 /************************************************************************
1224 * OLEFontImpl_GetTypeInfo (IDispatch)
1226 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1227 IDispatch* iface,
1228 UINT iTInfo,
1229 LCID lcid,
1230 ITypeInfo** ppTInfo)
1232 ITypeLib *tl;
1233 HRESULT hres;
1235 OLEFontImpl *this = impl_from_IDispatch(iface);
1236 TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1237 if (iTInfo != 0)
1238 return E_FAIL;
1239 hres = LoadTypeLib(L"stdole2.tlb", &tl);
1240 if (FAILED(hres)) {
1241 ERR("Could not load the stdole2.tlb?\n");
1242 return hres;
1244 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
1245 ITypeLib_Release(tl);
1246 if (FAILED(hres)) {
1247 FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
1249 return hres;
1252 /************************************************************************
1253 * OLEFontImpl_GetIDsOfNames (IDispatch)
1255 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1256 IDispatch* iface,
1257 REFIID riid,
1258 LPOLESTR* rgszNames,
1259 UINT cNames,
1260 LCID lcid,
1261 DISPID* rgDispId)
1263 ITypeInfo * pTInfo;
1264 HRESULT hres;
1266 OLEFontImpl *this = impl_from_IDispatch(iface);
1268 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
1269 rgszNames, cNames, (int)lcid, rgDispId);
1271 if (cNames == 0) return E_INVALIDARG;
1273 hres = IDispatch_GetTypeInfo(iface, 0, lcid, &pTInfo);
1274 if (FAILED(hres))
1276 ERR("GetTypeInfo failed.\n");
1277 return hres;
1280 /* convert names to DISPIDs */
1281 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1282 ITypeInfo_Release(pTInfo);
1284 return hres;
1287 /************************************************************************
1288 * OLEFontImpl_Invoke (IDispatch)
1291 static HRESULT WINAPI OLEFontImpl_Invoke(
1292 IDispatch* iface,
1293 DISPID dispIdMember,
1294 REFIID riid,
1295 LCID lcid,
1296 WORD wFlags,
1297 DISPPARAMS* pDispParams,
1298 VARIANT* pVarResult,
1299 EXCEPINFO* pExepInfo,
1300 UINT* puArgErr)
1302 OLEFontImpl *this = impl_from_IDispatch(iface);
1303 HRESULT hr;
1305 TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
1306 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
1307 puArgErr);
1309 /* validate parameters */
1311 if (!IsEqualIID(riid, &IID_NULL))
1313 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1314 return DISP_E_UNKNOWNINTERFACE;
1317 if (wFlags & DISPATCH_PROPERTYGET)
1319 if (!pVarResult)
1321 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
1322 return DISP_E_PARAMNOTOPTIONAL;
1325 else if (wFlags & DISPATCH_PROPERTYPUT)
1327 if (!pDispParams)
1329 ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
1330 return DISP_E_PARAMNOTOPTIONAL;
1332 if (pDispParams->cArgs != 1)
1334 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
1335 return DISP_E_BADPARAMCOUNT;
1338 else
1340 ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
1341 return DISP_E_MEMBERNOTFOUND;
1344 switch (dispIdMember) {
1345 case DISPID_FONT_NAME:
1346 if (wFlags & DISPATCH_PROPERTYGET) {
1347 V_VT(pVarResult) = VT_BSTR;
1348 return IFont_get_Name(&this->IFont_iface, &V_BSTR(pVarResult));
1349 } else {
1350 VARIANTARG vararg;
1352 VariantInit(&vararg);
1353 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
1354 if (FAILED(hr))
1355 return hr;
1357 hr = IFont_put_Name(&this->IFont_iface, V_BSTR(&vararg));
1359 VariantClear(&vararg);
1360 return hr;
1362 break;
1363 case DISPID_FONT_BOLD:
1364 if (wFlags & DISPATCH_PROPERTYGET) {
1365 BOOL value;
1366 hr = IFont_get_Bold(&this->IFont_iface, &value);
1367 V_VT(pVarResult) = VT_BOOL;
1368 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1369 return hr;
1370 } else {
1371 VARIANTARG vararg;
1373 VariantInit(&vararg);
1374 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1375 if (FAILED(hr))
1376 return hr;
1378 hr = IFont_put_Bold(&this->IFont_iface, V_BOOL(&vararg));
1380 VariantClear(&vararg);
1381 return hr;
1383 break;
1384 case DISPID_FONT_ITALIC:
1385 if (wFlags & DISPATCH_PROPERTYGET) {
1386 BOOL value;
1387 hr = IFont_get_Italic(&this->IFont_iface, &value);
1388 V_VT(pVarResult) = VT_BOOL;
1389 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1390 return hr;
1391 } else {
1392 VARIANTARG vararg;
1394 VariantInit(&vararg);
1395 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1396 if (FAILED(hr))
1397 return hr;
1399 hr = IFont_put_Italic(&this->IFont_iface, V_BOOL(&vararg));
1401 VariantClear(&vararg);
1402 return hr;
1404 break;
1405 case DISPID_FONT_UNDER:
1406 if (wFlags & DISPATCH_PROPERTYGET) {
1407 BOOL value;
1408 hr = IFont_get_Underline(&this->IFont_iface, &value);
1409 V_VT(pVarResult) = VT_BOOL;
1410 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1411 return hr;
1412 } else {
1413 VARIANTARG vararg;
1415 VariantInit(&vararg);
1416 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1417 if (FAILED(hr))
1418 return hr;
1420 hr = IFont_put_Underline(&this->IFont_iface, V_BOOL(&vararg));
1422 VariantClear(&vararg);
1423 return hr;
1425 break;
1426 case DISPID_FONT_STRIKE:
1427 if (wFlags & DISPATCH_PROPERTYGET) {
1428 BOOL value;
1429 hr = IFont_get_Strikethrough(&this->IFont_iface, &value);
1430 V_VT(pVarResult) = VT_BOOL;
1431 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1432 return hr;
1433 } else {
1434 VARIANTARG vararg;
1436 VariantInit(&vararg);
1437 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1438 if (FAILED(hr))
1439 return hr;
1441 hr = IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&vararg));
1443 VariantClear(&vararg);
1444 return hr;
1446 break;
1447 case DISPID_FONT_SIZE:
1448 if (wFlags & DISPATCH_PROPERTYGET) {
1449 V_VT(pVarResult) = VT_CY;
1450 return IFont_get_Size(&this->IFont_iface, &V_CY(pVarResult));
1451 } else {
1452 VARIANTARG vararg;
1454 VariantInit(&vararg);
1455 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
1456 if (FAILED(hr))
1457 return hr;
1459 hr = IFont_put_Size(&this->IFont_iface, V_CY(&vararg));
1461 VariantClear(&vararg);
1462 return hr;
1464 break;
1465 case DISPID_FONT_WEIGHT:
1466 if (wFlags & DISPATCH_PROPERTYGET) {
1467 V_VT(pVarResult) = VT_I2;
1468 return IFont_get_Weight(&this->IFont_iface, &V_I2(pVarResult));
1469 } else {
1470 VARIANTARG vararg;
1472 VariantInit(&vararg);
1473 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1474 if (FAILED(hr))
1475 return hr;
1477 hr = IFont_put_Weight(&this->IFont_iface, V_I2(&vararg));
1479 VariantClear(&vararg);
1480 return hr;
1482 break;
1483 case DISPID_FONT_CHARSET:
1484 if (wFlags & DISPATCH_PROPERTYGET) {
1485 V_VT(pVarResult) = VT_I2;
1486 return OLEFontImpl_get_Charset(&this->IFont_iface, &V_I2(pVarResult));
1487 } else {
1488 VARIANTARG vararg;
1490 VariantInit(&vararg);
1491 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1492 if (FAILED(hr))
1493 return hr;
1495 hr = IFont_put_Charset(&this->IFont_iface, V_I2(&vararg));
1497 VariantClear(&vararg);
1498 return hr;
1500 break;
1501 default:
1502 ERR("member not found for dispid 0x%x\n", dispIdMember);
1503 return DISP_E_MEMBERNOTFOUND;
1507 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
1509 OLEFontImpl_IDispatch_QueryInterface,
1510 OLEFontImpl_IDispatch_AddRef,
1511 OLEFontImpl_IDispatch_Release,
1512 OLEFontImpl_GetTypeInfoCount,
1513 OLEFontImpl_GetTypeInfo,
1514 OLEFontImpl_GetIDsOfNames,
1515 OLEFontImpl_Invoke
1518 /************************************************************************
1519 * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1521 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1522 IPersistStream* iface,
1523 REFIID riid,
1524 VOID** ppvoid)
1526 OLEFontImpl *this = impl_from_IPersistStream(iface);
1528 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
1531 /************************************************************************
1532 * OLEFontImpl_IPersistStream_Release (IUnknown)
1534 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1535 IPersistStream* iface)
1537 OLEFontImpl *this = impl_from_IPersistStream(iface);
1539 return IFont_Release(&this->IFont_iface);
1542 /************************************************************************
1543 * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1545 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1546 IPersistStream* iface)
1548 OLEFontImpl *this = impl_from_IPersistStream(iface);
1550 return IFont_AddRef(&this->IFont_iface);
1553 /************************************************************************
1554 * OLEFontImpl_GetClassID (IPersistStream)
1556 static HRESULT WINAPI OLEFontImpl_GetClassID(
1557 IPersistStream* iface,
1558 CLSID* pClassID)
1560 TRACE("(%p,%p)\n",iface,pClassID);
1561 if (pClassID==0)
1562 return E_POINTER;
1564 *pClassID = CLSID_StdFont;
1566 return S_OK;
1569 /************************************************************************
1570 * OLEFontImpl_IsDirty (IPersistStream)
1572 * See Windows documentation for more details on IPersistStream methods.
1574 static HRESULT WINAPI OLEFontImpl_IsDirty(
1575 IPersistStream* iface)
1577 TRACE("(%p)\n",iface);
1578 return S_OK;
1581 /************************************************************************
1582 * OLEFontImpl_Load (IPersistStream)
1584 * See Windows documentation for more details on IPersistStream methods.
1586 * This is the format of the standard font serialization as far as I
1587 * know
1589 * Offset Type Value Comment
1590 * 0x0000 Byte Unknown Probably a version number, contains 0x01
1591 * 0x0001 Short Charset Charset value from the FONTDESC structure
1592 * 0x0003 Byte Attributes Flags defined as follows:
1593 * 00000010 - Italic
1594 * 00000100 - Underline
1595 * 00001000 - Strikethrough
1596 * 0x0004 Short Weight Weight value from FONTDESC structure
1597 * 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC
1598 * structure/
1599 * 0x000A Byte name length Length of the font name string (no null character)
1600 * 0x000B String name Name of the font (ASCII, no nul character)
1602 static HRESULT WINAPI OLEFontImpl_Load(
1603 IPersistStream* iface,
1604 IStream* pLoadStream)
1606 OLEFontImpl *this = impl_from_IPersistStream(iface);
1607 BYTE version, attributes, string_size;
1608 char readBuffer[0x100];
1609 ULONG cbRead;
1610 INT len;
1612 /* Version */
1613 IStream_Read(pLoadStream, &version, sizeof(BYTE), &cbRead);
1614 if ((cbRead != sizeof(BYTE)) || (version != 0x01)) return E_FAIL;
1616 /* Charset */
1617 IStream_Read(pLoadStream, &this->description.sCharset, sizeof(WORD), &cbRead);
1618 if (cbRead != sizeof(WORD)) return E_FAIL;
1620 /* Attributes */
1621 IStream_Read(pLoadStream, &attributes, sizeof(BYTE), &cbRead);
1622 if (cbRead != sizeof(BYTE)) return E_FAIL;
1624 this->description.fItalic = (attributes & FONTPERSIST_ITALIC) != 0;
1625 this->description.fStrikethrough = (attributes & FONTPERSIST_STRIKETHROUGH) != 0;
1626 this->description.fUnderline = (attributes & FONTPERSIST_UNDERLINE) != 0;
1628 /* Weight */
1629 IStream_Read(pLoadStream, &this->description.sWeight, sizeof(WORD), &cbRead);
1630 if (cbRead != sizeof(WORD)) return E_FAIL;
1632 /* Size */
1633 IStream_Read(pLoadStream, &this->description.cySize.s.Lo, sizeof(DWORD), &cbRead);
1634 if (cbRead != sizeof(DWORD)) return E_FAIL;
1636 this->description.cySize.s.Hi = 0;
1638 /* Name */
1639 IStream_Read(pLoadStream, &string_size, sizeof(BYTE), &cbRead);
1640 if (cbRead != sizeof(BYTE)) return E_FAIL;
1642 IStream_Read(pLoadStream, readBuffer, string_size, &cbRead);
1643 if (cbRead != string_size) return E_FAIL;
1645 HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1647 len = MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, NULL, 0 );
1648 this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1649 MultiByteToWideChar( CP_ACP, 0, readBuffer, string_size, this->description.lpstrName, len );
1650 this->description.lpstrName[len] = 0;
1652 /* Ensure use of this font causes a new one to be created */
1653 dec_int_ref(this->gdiFont);
1654 this->gdiFont = 0;
1655 this->dirty = TRUE;
1657 return S_OK;
1660 /************************************************************************
1661 * OLEFontImpl_Save (IPersistStream)
1663 static HRESULT WINAPI OLEFontImpl_Save(
1664 IPersistStream* iface,
1665 IStream* pOutStream,
1666 BOOL fClearDirty)
1668 OLEFontImpl *this = impl_from_IPersistStream(iface);
1669 BYTE attributes, string_size;
1670 const BYTE version = 0x01;
1671 char* writeBuffer = NULL;
1672 ULONG written;
1674 TRACE("(%p)->(%p %d)\n", this, pOutStream, fClearDirty);
1676 /* Version */
1677 IStream_Write(pOutStream, &version, sizeof(BYTE), &written);
1678 if (written != sizeof(BYTE)) return E_FAIL;
1680 /* Charset */
1681 IStream_Write(pOutStream, &this->description.sCharset, sizeof(WORD), &written);
1682 if (written != sizeof(WORD)) return E_FAIL;
1684 /* Attributes */
1685 attributes = 0;
1687 if (this->description.fItalic)
1688 attributes |= FONTPERSIST_ITALIC;
1690 if (this->description.fStrikethrough)
1691 attributes |= FONTPERSIST_STRIKETHROUGH;
1693 if (this->description.fUnderline)
1694 attributes |= FONTPERSIST_UNDERLINE;
1696 IStream_Write(pOutStream, &attributes, sizeof(BYTE), &written);
1697 if (written != sizeof(BYTE)) return E_FAIL;
1699 /* Weight */
1700 IStream_Write(pOutStream, &this->description.sWeight, sizeof(WORD), &written);
1701 if (written != sizeof(WORD)) return E_FAIL;
1703 /* Size */
1704 IStream_Write(pOutStream, &this->description.cySize.s.Lo, sizeof(DWORD), &written);
1705 if (written != sizeof(DWORD)) return E_FAIL;
1707 /* FontName */
1708 if (this->description.lpstrName)
1709 string_size = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1710 lstrlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1711 else
1712 string_size = 0;
1714 IStream_Write(pOutStream, &string_size, sizeof(BYTE), &written);
1715 if (written != sizeof(BYTE)) return E_FAIL;
1717 if (string_size)
1719 if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, string_size ))) return E_OUTOFMEMORY;
1720 WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1721 lstrlenW(this->description.lpstrName),
1722 writeBuffer, string_size, NULL, NULL );
1724 IStream_Write(pOutStream, writeBuffer, string_size, &written);
1725 HeapFree(GetProcessHeap(), 0, writeBuffer);
1727 if (written != string_size) return E_FAIL;
1730 return S_OK;
1733 /************************************************************************
1734 * OLEFontImpl_GetSizeMax (IPersistStream)
1736 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1737 IPersistStream* iface,
1738 ULARGE_INTEGER* pcbSize)
1740 OLEFontImpl *this = impl_from_IPersistStream(iface);
1742 if (pcbSize==NULL)
1743 return E_POINTER;
1745 pcbSize->u.HighPart = 0;
1746 pcbSize->u.LowPart = 0;
1748 pcbSize->u.LowPart += sizeof(BYTE); /* Version */
1749 pcbSize->u.LowPart += sizeof(WORD); /* Lang code */
1750 pcbSize->u.LowPart += sizeof(BYTE); /* Flags */
1751 pcbSize->u.LowPart += sizeof(WORD); /* Weight */
1752 pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1753 pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */
1755 if (this->description.lpstrName!=0)
1756 pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1757 lstrlenW(this->description.lpstrName),
1758 NULL, 0, NULL, NULL );
1760 return S_OK;
1763 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
1765 OLEFontImpl_IPersistStream_QueryInterface,
1766 OLEFontImpl_IPersistStream_AddRef,
1767 OLEFontImpl_IPersistStream_Release,
1768 OLEFontImpl_GetClassID,
1769 OLEFontImpl_IsDirty,
1770 OLEFontImpl_Load,
1771 OLEFontImpl_Save,
1772 OLEFontImpl_GetSizeMax
1775 /************************************************************************
1776 * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1778 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1779 IConnectionPointContainer* iface,
1780 REFIID riid,
1781 VOID** ppvoid)
1783 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1785 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
1788 /************************************************************************
1789 * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
1791 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
1792 IConnectionPointContainer* iface)
1794 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1796 return IFont_Release(&this->IFont_iface);
1799 /************************************************************************
1800 * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
1802 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
1803 IConnectionPointContainer* iface)
1805 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1807 return IFont_AddRef(&this->IFont_iface);
1810 /************************************************************************
1811 * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
1813 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
1814 IConnectionPointContainer* iface,
1815 IEnumConnectionPoints **ppEnum)
1817 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1819 FIXME("(%p)->(%p): stub\n", this, ppEnum);
1820 return E_NOTIMPL;
1823 /************************************************************************
1824 * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
1826 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
1827 IConnectionPointContainer* iface,
1828 REFIID riid,
1829 IConnectionPoint **ppCp)
1831 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1832 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
1834 if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
1835 return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP, &IID_IConnectionPoint,
1836 (void**)ppCp);
1837 } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
1838 return IConnectionPoint_QueryInterface(this->pFontEventsCP, &IID_IConnectionPoint,
1839 (void**)ppCp);
1840 } else {
1841 FIXME("no connection point for %s\n", debugstr_guid(riid));
1842 return CONNECT_E_NOCONNECTION;
1846 static const IConnectionPointContainerVtbl
1847 OLEFontImpl_IConnectionPointContainer_VTable =
1849 OLEFontImpl_IConnectionPointContainer_QueryInterface,
1850 OLEFontImpl_IConnectionPointContainer_AddRef,
1851 OLEFontImpl_IConnectionPointContainer_Release,
1852 OLEFontImpl_EnumConnectionPoints,
1853 OLEFontImpl_FindConnectionPoint
1856 /************************************************************************
1857 * OLEFontImpl implementation of IPersistPropertyBag.
1859 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
1860 IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
1862 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1863 return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj);
1866 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
1867 IPersistPropertyBag *iface
1869 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1870 return IFont_AddRef(&this->IFont_iface);
1873 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
1874 IPersistPropertyBag *iface
1876 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1877 return IFont_Release(&this->IFont_iface);
1880 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
1881 IPersistPropertyBag *iface, CLSID *classid
1883 FIXME("(%p,%p), stub!\n", iface, classid);
1884 return E_FAIL;
1887 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
1888 IPersistPropertyBag *iface
1890 FIXME("(%p), stub!\n", iface);
1891 return S_OK;
1894 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
1895 IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
1897 /* (from Visual Basic 6 property bag)
1898 Name = "MS Sans Serif"
1899 Size = 13.8
1900 Charset = 0
1901 Weight = 400
1902 Underline = 0 'False
1903 Italic = 0 'False
1904 Strikethrough = 0 'False
1906 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1907 VARIANT value;
1908 HRESULT iRes;
1910 VariantInit(&value);
1912 iRes = IPropertyBag_Read(pPropBag, L"Name", &value, pErrorLog);
1913 if (iRes == S_OK)
1915 iRes = VariantChangeType(&value, &value, 0, VT_BSTR);
1916 if (iRes == S_OK)
1917 iRes = IFont_put_Name(&this->IFont_iface, V_BSTR(&value));
1919 else if (iRes == E_INVALIDARG)
1920 iRes = S_OK;
1922 VariantClear(&value);
1924 if (iRes == S_OK) {
1925 iRes = IPropertyBag_Read(pPropBag, L"Size", &value, pErrorLog);
1926 if (iRes == S_OK)
1928 iRes = VariantChangeType(&value, &value, 0, VT_CY);
1929 if (iRes == S_OK)
1930 iRes = IFont_put_Size(&this->IFont_iface, V_CY(&value));
1932 else if (iRes == E_INVALIDARG)
1933 iRes = S_OK;
1935 VariantClear(&value);
1938 if (iRes == S_OK) {
1939 iRes = IPropertyBag_Read(pPropBag, L"Charset", &value, pErrorLog);
1940 if (iRes == S_OK)
1942 iRes = VariantChangeType(&value, &value, 0, VT_I2);
1943 if (iRes == S_OK)
1944 iRes = IFont_put_Charset(&this->IFont_iface, V_I2(&value));
1946 else if (iRes == E_INVALIDARG)
1947 iRes = S_OK;
1949 VariantClear(&value);
1952 if (iRes == S_OK) {
1953 iRes = IPropertyBag_Read(pPropBag, L"Weight", &value, pErrorLog);
1954 if (iRes == S_OK)
1956 iRes = VariantChangeType(&value, &value, 0, VT_I2);
1957 if (iRes == S_OK)
1958 iRes = IFont_put_Weight(&this->IFont_iface, V_I2(&value));
1960 else if (iRes == E_INVALIDARG)
1961 iRes = S_OK;
1963 VariantClear(&value);
1966 if (iRes == S_OK) {
1967 iRes = IPropertyBag_Read(pPropBag, L"Underline", &value, pErrorLog);
1968 if (iRes == S_OK)
1970 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
1971 if (iRes == S_OK)
1972 iRes = IFont_put_Underline(&this->IFont_iface, V_BOOL(&value));
1974 else if (iRes == E_INVALIDARG)
1975 iRes = S_OK;
1977 VariantClear(&value);
1980 if (iRes == S_OK) {
1981 iRes = IPropertyBag_Read(pPropBag, L"Italic", &value, pErrorLog);
1982 if (iRes == S_OK)
1984 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
1985 if (iRes == S_OK)
1986 iRes = IFont_put_Italic(&this->IFont_iface, V_BOOL(&value));
1988 else if (iRes == E_INVALIDARG)
1989 iRes = S_OK;
1991 VariantClear(&value);
1994 if (iRes == S_OK) {
1995 iRes = IPropertyBag_Read(pPropBag, L"Strikethrough", &value, pErrorLog);
1996 if (iRes == S_OK)
1998 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
1999 if (iRes == S_OK)
2000 IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&value));
2002 else if (iRes == E_INVALIDARG)
2003 iRes = S_OK;
2005 VariantClear(&value);
2008 if (FAILED(iRes))
2009 WARN("-- 0x%08x\n", iRes);
2010 return iRes;
2013 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2014 IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2015 BOOL fSaveAllProperties
2017 FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2018 return E_FAIL;
2021 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable =
2023 OLEFontImpl_IPersistPropertyBag_QueryInterface,
2024 OLEFontImpl_IPersistPropertyBag_AddRef,
2025 OLEFontImpl_IPersistPropertyBag_Release,
2027 OLEFontImpl_IPersistPropertyBag_GetClassID,
2028 OLEFontImpl_IPersistPropertyBag_InitNew,
2029 OLEFontImpl_IPersistPropertyBag_Load,
2030 OLEFontImpl_IPersistPropertyBag_Save
2033 /************************************************************************
2034 * OLEFontImpl_Construct
2036 * This method will construct a new instance of the OLEFontImpl
2037 * class.
2039 * The caller of this method must release the object when it's
2040 * done with it.
2042 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
2044 OLEFontImpl* newObject;
2046 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
2048 if (newObject==0)
2049 return newObject;
2051 newObject->IFont_iface.lpVtbl = &OLEFontImpl_VTable;
2052 newObject->IDispatch_iface.lpVtbl = &OLEFontImpl_IDispatch_VTable;
2053 newObject->IPersistStream_iface.lpVtbl = &OLEFontImpl_IPersistStream_VTable;
2054 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEFontImpl_IConnectionPointContainer_VTable;
2055 newObject->IPersistPropertyBag_iface.lpVtbl = &OLEFontImpl_IPersistPropertyBag_VTable;
2057 newObject->ref = 1;
2059 newObject->description.cbSizeofstruct = sizeof(FONTDESC);
2060 newObject->description.lpstrName = strdupW(fontDesc->lpstrName);
2061 newObject->description.cySize = fontDesc->cySize;
2062 newObject->description.sWeight = fontDesc->sWeight;
2063 newObject->description.sCharset = fontDesc->sCharset;
2064 newObject->description.fItalic = fontDesc->fItalic;
2065 newObject->description.fUnderline = fontDesc->fUnderline;
2066 newObject->description.fStrikethrough = fontDesc->fStrikethrough;
2068 newObject->gdiFont = 0;
2069 newObject->dirty = TRUE;
2070 newObject->cyLogical = GetDeviceCaps(get_dc(), LOGPIXELSY);
2071 newObject->cyHimetric = 2540L;
2072 newObject->pPropertyNotifyCP = NULL;
2073 newObject->pFontEventsCP = NULL;
2075 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
2076 CreateConnectionPoint((IUnknown*)&newObject->IFont_iface, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
2078 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
2080 OLEFontImpl_Destroy(newObject);
2081 return NULL;
2084 InterlockedIncrement(&ifont_cnt);
2086 TRACE("returning %p\n", newObject);
2087 return newObject;
2090 /************************************************************************
2091 * OLEFontImpl_Destroy
2093 * This method is called by the Release method when the reference
2094 * count goes down to 0. It will free all resources used by
2095 * this object.
2097 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
2099 TRACE("(%p)\n", fontDesc);
2101 HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
2103 if (fontDesc->pPropertyNotifyCP)
2104 IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
2105 if (fontDesc->pFontEventsCP)
2106 IConnectionPoint_Release(fontDesc->pFontEventsCP);
2108 HeapFree(GetProcessHeap(), 0, fontDesc);
2111 /*******************************************************************************
2112 * StdFont ClassFactory
2114 typedef struct
2116 /* IUnknown fields */
2117 IClassFactory IClassFactory_iface;
2118 LONG ref;
2119 } IClassFactoryImpl;
2121 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
2123 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
2126 static HRESULT WINAPI SFCF_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
2128 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2130 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
2132 *obj = NULL;
2134 if (IsEqualIID(&IID_IClassFactory, riid) || IsEqualIID(&IID_IUnknown, riid))
2136 *obj = iface;
2137 IClassFactory_AddRef(iface);
2138 return S_OK;
2141 return E_NOINTERFACE;
2144 static ULONG WINAPI
2145 SFCF_AddRef(LPCLASSFACTORY iface) {
2146 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2147 return InterlockedIncrement(&This->ref);
2150 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2151 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2152 /* static class, won't be freed */
2153 return InterlockedDecrement(&This->ref);
2156 static HRESULT WINAPI SFCF_CreateInstance(
2157 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2159 return OleCreateFontIndirect(NULL,riid,ppobj);
2163 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2164 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2165 FIXME("(%p)->(%d),stub!\n",This,dolock);
2166 return S_OK;
2169 static const IClassFactoryVtbl SFCF_Vtbl = {
2170 SFCF_QueryInterface,
2171 SFCF_AddRef,
2172 SFCF_Release,
2173 SFCF_CreateInstance,
2174 SFCF_LockServer
2176 static IClassFactoryImpl STDFONT_CF = {{&SFCF_Vtbl}, 1 };
2178 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }