msxml3: Orphan a node removed with removeChild().
[wine/multimedia.git] / dlls / oleaut32 / olefont.c
blobe65504c8684d1e125fa28ad3adfa1c88ebcdd3a6
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 "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"
47 WINE_DEFAULT_DEBUG_CHANNEL(ole);
49 /***********************************************************************
50 * Declaration of constants used when serializing the font object.
52 #define FONTPERSIST_ITALIC 0x02
53 #define FONTPERSIST_UNDERLINE 0x04
54 #define FONTPERSIST_STRIKETHROUGH 0x08
56 static HDC olefont_hdc;
58 /***********************************************************************
59 * List of the HFONTs it has given out, with each one having a separate
60 * ref count.
62 typedef struct _HFONTItem
64 struct list entry;
66 /* Reference count of any IFont objects that own this hfont */
67 LONG int_refs;
69 /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
70 LONG total_refs;
72 /* The font associated with this object. */
73 HFONT gdiFont;
75 } HFONTItem, *PHFONTItem;
77 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
79 /* Counts how many fonts contain at least one lock */
80 static LONG ifont_cnt = 0;
82 /***********************************************************************
83 * Critical section for OLEFontImpl_hFontList
85 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
86 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
88 0, 0, &OLEFontImpl_csHFONTLIST,
89 { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
90 &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
91 0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
93 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
95 static HDC get_dc(void)
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;
106 static void delete_dc(void)
108 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
109 if(olefont_hdc)
111 DeleteDC(olefont_hdc);
112 olefont_hdc = NULL;
114 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
117 static void HFONTItem_Delete(PHFONTItem item)
119 DeleteObject(item->gdiFont);
120 list_remove(&item->entry);
121 HeapFree(GetProcessHeap(), 0, item);
124 /* Find hfont item entry in the list. Should be called while holding the crit sect */
125 static HFONTItem *find_hfontitem(HFONT hfont)
127 HFONTItem *item;
129 LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
131 if (item->gdiFont == hfont)
132 return item;
134 return NULL;
137 /* Add an item to the list with one internal reference */
138 static HRESULT add_hfontitem(HFONT hfont)
140 HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
142 if(!new_item) return E_OUTOFMEMORY;
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;
153 static HRESULT inc_int_ref(HFONT hfont)
155 HFONTItem *item;
156 HRESULT hr = S_FALSE;
158 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
159 item = find_hfontitem(hfont);
161 if(item)
163 item->int_refs++;
164 item->total_refs++;
165 hr = S_OK;
167 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
169 return hr;
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)
176 HFONTItem *item;
177 HRESULT hr = S_FALSE;
179 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
180 item = find_hfontitem(hfont);
182 if(item)
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;
190 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
192 return hr;
195 static HRESULT inc_ext_ref(HFONT hfont)
197 HFONTItem *item;
198 HRESULT hr = S_FALSE;
200 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
202 item = find_hfontitem(hfont);
203 if(item)
205 item->total_refs++;
206 hr = S_OK;
208 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
210 return hr;
213 static HRESULT dec_ext_ref(HFONT hfont)
215 HFONTItem *item;
216 HRESULT hr = S_FALSE;
218 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
220 item = find_hfontitem(hfont);
221 if(item)
223 if(--item->total_refs >= 0) hr = S_OK;
225 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
227 return hr;
230 static WCHAR *strdupW(const WCHAR* str)
232 WCHAR *ret;
233 DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
235 ret = HeapAlloc(GetProcessHeap(), 0, size);
236 if(ret)
237 memcpy(ret, str, size);
238 return ret;
241 /***********************************************************************
242 * Declaration of the implementation class for the IFont interface
244 typedef struct OLEFontImpl OLEFontImpl;
246 struct OLEFontImpl
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.
254 IFont IFont_iface;
255 IDispatch IDispatch_iface;
256 IPersistStream IPersistStream_iface;
257 IConnectionPointContainer IConnectionPointContainer_iface;
258 IPersistPropertyBag IPersistPropertyBag_iface;
259 IPersistStreamInit IPersistStreamInit_iface;
261 * Reference count for that instance of the class.
263 LONG ref;
266 * This structure contains the description of the class.
268 FONTDESC description;
271 * Contain the font associated with this object.
273 HFONT gdiFont;
274 BOOL dirty;
276 * Size ratio
278 LONG cyLogical;
279 LONG cyHimetric;
281 IConnectionPoint *pPropertyNotifyCP;
282 IConnectionPoint *pFontEventsCP;
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.
292 static inline OLEFontImpl *impl_from_IFont(IFont *iface)
294 return CONTAINING_RECORD(iface, OLEFontImpl, IFont_iface);
297 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
299 return CONTAINING_RECORD(iface, OLEFontImpl, IDispatch_iface);
302 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
304 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStream_iface);
307 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
309 return CONTAINING_RECORD(iface, OLEFontImpl, IConnectionPointContainer_iface);
312 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
314 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistPropertyBag_iface);
317 static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
319 return CONTAINING_RECORD(iface, OLEFontImpl, IPersistStreamInit_iface);
323 /***********************************************************************
324 * Prototypes for the implementation functions for the IFont
325 * interface
327 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
328 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
329 static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
331 /******************************************************************************
332 * OleCreateFontIndirect [OLEAUT32.420]
334 HRESULT WINAPI OleCreateFontIndirect(
335 LPFONTDESC lpFontDesc,
336 REFIID riid,
337 LPVOID* ppvObj)
339 OLEFontImpl* newFont = 0;
340 HRESULT hr = S_OK;
341 FONTDESC fd;
343 TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
345 * Sanity check
347 if (ppvObj==0)
348 return E_POINTER;
350 *ppvObj = 0;
352 if (!lpFontDesc) {
353 static WCHAR fname[] = { 'S','y','s','t','e','m',0 };
355 fd.cbSizeofstruct = sizeof(fd);
356 fd.lpstrName = fname;
357 fd.cySize.s.Lo = 80000;
358 fd.cySize.s.Hi = 0;
359 fd.sWeight = 0;
360 fd.sCharset = 0;
361 fd.fItalic = 0;
362 fd.fUnderline = 0;
363 fd.fStrikethrough = 0;
364 lpFontDesc = &fd;
368 * Try to construct a new instance of the class.
370 newFont = OLEFontImpl_Construct(lpFontDesc);
372 if (newFont == 0)
373 return E_OUTOFMEMORY;
376 * Make sure it supports the interface required by the caller.
378 hr = IFont_QueryInterface(&newFont->IFont_iface, riid, ppvObj);
381 * Release the reference obtained in the constructor. If
382 * the QueryInterface was unsuccessful, it will free the class.
384 IFont_Release(&newFont->IFont_iface);
386 return hr;
390 /***********************************************************************
391 * Implementation of the OLEFontImpl class.
394 /***********************************************************************
395 * OLEFont_SendNotify (internal)
397 * Sends notification messages of changed properties to any interested
398 * connections.
400 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
402 static const WCHAR wszName[] = {'N','a','m','e',0};
403 static const WCHAR wszSize[] = {'S','i','z','e',0};
404 static const WCHAR wszBold[] = {'B','o','l','d',0};
405 static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0};
406 static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0};
407 static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
408 static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0};
409 static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0};
410 static const LPCWSTR dispid_mapping[] =
412 wszName,
413 NULL,
414 wszSize,
415 wszBold,
416 wszItalic,
417 wszUnder,
418 wszStrike,
419 wszWeight,
420 wszCharset
423 IEnumConnections *pEnum;
424 CONNECTDATA CD;
425 HRESULT hres;
427 this->dirty = TRUE;
429 hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
430 if (SUCCEEDED(hres))
432 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
433 IPropertyNotifySink *sink;
435 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
436 IPropertyNotifySink_OnChanged(sink, dispID);
437 IPropertyNotifySink_Release(sink);
438 IUnknown_Release(CD.pUnk);
440 IEnumConnections_Release(pEnum);
443 hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
444 if (SUCCEEDED(hres))
446 DISPPARAMS dispparams;
447 VARIANTARG vararg;
449 VariantInit(&vararg);
450 V_VT(&vararg) = VT_BSTR;
451 V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
453 dispparams.cArgs = 1;
454 dispparams.cNamedArgs = 0;
455 dispparams.rgdispidNamedArgs = NULL;
456 dispparams.rgvarg = &vararg;
458 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
459 IFontEventsDisp *disp;
461 IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp);
462 IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
463 LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
464 NULL, NULL);
466 IDispatch_Release(disp);
467 IUnknown_Release(CD.pUnk);
469 VariantClear(&vararg);
470 IEnumConnections_Release(pEnum);
474 /************************************************************************
475 * OLEFontImpl_QueryInterface (IUnknown)
477 * See Windows documentation for more details on IUnknown methods.
479 static HRESULT WINAPI OLEFontImpl_QueryInterface(
480 IFont* iface,
481 REFIID riid,
482 void** ppvObject)
484 OLEFontImpl *this = impl_from_IFont(iface);
485 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
487 *ppvObject = 0;
490 * Compare the riid with the interface IDs implemented by this object.
492 if (IsEqualGUID(&IID_IUnknown, riid))
493 *ppvObject = this;
494 if (IsEqualGUID(&IID_IFont, riid))
495 *ppvObject = this;
496 if (IsEqualGUID(&IID_IDispatch, riid))
497 *ppvObject = &this->IDispatch_iface;
498 if (IsEqualGUID(&IID_IFontDisp, riid))
499 *ppvObject = &this->IDispatch_iface;
500 if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid))
501 *ppvObject = &this->IPersistStream_iface;
502 if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
503 *ppvObject = &this->IConnectionPointContainer_iface;
504 if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
505 *ppvObject = &this->IPersistPropertyBag_iface;
506 if (IsEqualGUID(&IID_IPersistStreamInit, riid))
507 *ppvObject = &this->IPersistStreamInit_iface;
510 * Check that we obtained an interface.
512 if ((*ppvObject)==0)
514 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
515 return E_NOINTERFACE;
517 OLEFontImpl_AddRef(&this->IFont_iface);
518 return S_OK;
521 /************************************************************************
522 * OLEFontImpl_AddRef (IUnknown)
524 * See Windows documentation for more details on IUnknown methods.
526 static ULONG WINAPI OLEFontImpl_AddRef(
527 IFont* iface)
529 OLEFontImpl *this = impl_from_IFont(iface);
530 TRACE("(%p)->(ref=%d)\n", this, this->ref);
531 return InterlockedIncrement(&this->ref);
534 /************************************************************************
535 * OLEFontImpl_Release (IUnknown)
537 * See Windows documentation for more details on IUnknown methods.
539 static ULONG WINAPI OLEFontImpl_Release(
540 IFont* iface)
542 OLEFontImpl *this = impl_from_IFont(iface);
543 ULONG ret;
544 TRACE("(%p)->(ref=%d)\n", this, this->ref);
546 /* Decrease the reference count for current interface */
547 ret = InterlockedDecrement(&this->ref);
549 /* If the reference count goes down to 0, destroy. */
550 if (ret == 0)
552 ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
554 /* Final IFont object so destroy font cache */
555 if (fontlist_refs == 0)
557 HFONTItem *item, *cursor2;
559 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
560 LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
561 HFONTItem_Delete(item);
562 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
563 delete_dc();
565 else
567 dec_int_ref(this->gdiFont);
569 OLEFontImpl_Destroy(this);
572 return ret;
575 typedef struct
577 short orig_cs;
578 short avail_cs;
579 } enum_data;
581 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
583 enum_data *data = (enum_data*)lp;
585 if(elf->lfCharSet == data->orig_cs)
587 data->avail_cs = data->orig_cs;
588 return 0;
590 if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
591 return 1;
594 static void realize_font(OLEFontImpl *This)
596 if (This->dirty)
598 LOGFONTW logFont;
599 INT fontHeight;
600 WCHAR text_face[LF_FACESIZE];
601 HDC hdc = get_dc();
602 HFONT old_font;
603 TEXTMETRICW tm;
605 text_face[0] = 0;
607 if(This->gdiFont)
609 old_font = SelectObject(hdc, This->gdiFont);
610 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
611 SelectObject(hdc, old_font);
612 dec_int_ref(This->gdiFont);
613 This->gdiFont = 0;
616 memset(&logFont, 0, sizeof(LOGFONTW));
618 lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
619 logFont.lfCharSet = This->description.sCharset;
621 /* If the font name has been changed then enumerate all charsets
622 and pick one that'll result in the font specified being selected */
623 if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
625 enum_data data;
626 data.orig_cs = This->description.sCharset;
627 data.avail_cs = -1;
628 logFont.lfCharSet = DEFAULT_CHARSET;
629 EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
630 if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
635 * The height of the font returned by the get_Size property is the
636 * height of the font in points multiplied by 10000... Using some
637 * simple conversions and the ratio given by the application, it can
638 * be converted to a height in pixels.
640 * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
641 * Ratio is applied here relative to the standard.
644 fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
647 logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
648 (-fontHeight/10000L);
649 logFont.lfItalic = This->description.fItalic;
650 logFont.lfUnderline = This->description.fUnderline;
651 logFont.lfStrikeOut = This->description.fStrikethrough;
652 logFont.lfWeight = This->description.sWeight;
653 logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
654 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
655 logFont.lfQuality = DEFAULT_QUALITY;
656 logFont.lfPitchAndFamily = DEFAULT_PITCH;
658 This->gdiFont = CreateFontIndirectW(&logFont);
659 This->dirty = FALSE;
661 add_hfontitem(This->gdiFont);
663 /* Fixup the name and charset properties so that they match the
664 selected font */
665 old_font = SelectObject(get_dc(), This->gdiFont);
666 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
667 if(lstrcmpiW(text_face, This->description.lpstrName))
669 HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
670 This->description.lpstrName = strdupW(text_face);
672 GetTextMetricsW(hdc, &tm);
673 This->description.sCharset = tm.tmCharSet;
674 SelectObject(hdc, old_font);
678 /************************************************************************
679 * OLEFontImpl_get_Name (IFont)
681 * See Windows documentation for more details on IFont methods.
683 static HRESULT WINAPI OLEFontImpl_get_Name(
684 IFont* iface,
685 BSTR* pname)
687 OLEFontImpl *this = impl_from_IFont(iface);
688 TRACE("(%p)->(%p)\n", this, pname);
690 * Sanity check.
692 if (pname==0)
693 return E_POINTER;
695 if(this->dirty) realize_font(this);
697 if (this->description.lpstrName!=0)
698 *pname = SysAllocString(this->description.lpstrName);
699 else
700 *pname = 0;
702 return S_OK;
705 /************************************************************************
706 * OLEFontImpl_put_Name (IFont)
708 * See Windows documentation for more details on IFont methods.
710 static HRESULT WINAPI OLEFontImpl_put_Name(
711 IFont* iface,
712 BSTR name)
714 OLEFontImpl *this = impl_from_IFont(iface);
715 TRACE("(%p)->(%p)\n", this, name);
717 if (!name)
718 return CTL_E_INVALIDPROPERTYVALUE;
720 if (this->description.lpstrName==0)
722 this->description.lpstrName = HeapAlloc(GetProcessHeap(),
724 (lstrlenW(name)+1) * sizeof(WCHAR));
726 else
728 this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
730 this->description.lpstrName,
731 (lstrlenW(name)+1) * sizeof(WCHAR));
734 if (this->description.lpstrName==0)
735 return E_OUTOFMEMORY;
737 strcpyW(this->description.lpstrName, name);
738 TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
739 OLEFont_SendNotify(this, DISPID_FONT_NAME);
740 return S_OK;
743 /************************************************************************
744 * OLEFontImpl_get_Size (IFont)
746 * See Windows documentation for more details on IFont methods.
748 static HRESULT WINAPI OLEFontImpl_get_Size(
749 IFont* iface,
750 CY* psize)
752 OLEFontImpl *this = impl_from_IFont(iface);
753 TRACE("(%p)->(%p)\n", this, psize);
756 * Sanity check
758 if (psize==0)
759 return E_POINTER;
761 if(this->dirty) realize_font(this);
763 psize->s.Hi = 0;
764 psize->s.Lo = this->description.cySize.s.Lo;
766 return S_OK;
769 /************************************************************************
770 * OLEFontImpl_put_Size (IFont)
772 * See Windows documentation for more details on IFont methods.
774 static HRESULT WINAPI OLEFontImpl_put_Size(
775 IFont* iface,
776 CY size)
778 OLEFontImpl *this = impl_from_IFont(iface);
779 TRACE("(%p)->(%d)\n", this, size.s.Lo);
780 this->description.cySize.s.Hi = 0;
781 this->description.cySize.s.Lo = size.s.Lo;
782 OLEFont_SendNotify(this, DISPID_FONT_SIZE);
784 return S_OK;
787 /************************************************************************
788 * OLEFontImpl_get_Bold (IFont)
790 * See Windows documentation for more details on IFont methods.
792 static HRESULT WINAPI OLEFontImpl_get_Bold(
793 IFont* iface,
794 BOOL* pbold)
796 OLEFontImpl *this = impl_from_IFont(iface);
797 TRACE("(%p)->(%p)\n", this, pbold);
799 * Sanity check
801 if (pbold==0)
802 return E_POINTER;
804 if(this->dirty) realize_font(this);
806 *pbold = this->description.sWeight > 550;
808 return S_OK;
811 /************************************************************************
812 * OLEFontImpl_put_Bold (IFont)
814 * See Windows documentation for more details on IFont methods.
816 static HRESULT WINAPI OLEFontImpl_put_Bold(
817 IFont* iface,
818 BOOL bold)
820 OLEFontImpl *this = impl_from_IFont(iface);
821 TRACE("(%p)->(%d)\n", this, bold);
822 this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
823 OLEFont_SendNotify(this, DISPID_FONT_BOLD);
825 return S_OK;
828 /************************************************************************
829 * OLEFontImpl_get_Italic (IFont)
831 * See Windows documentation for more details on IFont methods.
833 static HRESULT WINAPI OLEFontImpl_get_Italic(
834 IFont* iface,
835 BOOL* pitalic)
837 OLEFontImpl *this = impl_from_IFont(iface);
838 TRACE("(%p)->(%p)\n", this, pitalic);
840 * Sanity check
842 if (pitalic==0)
843 return E_POINTER;
845 if(this->dirty) realize_font(this);
847 *pitalic = this->description.fItalic;
849 return S_OK;
852 /************************************************************************
853 * OLEFontImpl_put_Italic (IFont)
855 * See Windows documentation for more details on IFont methods.
857 static HRESULT WINAPI OLEFontImpl_put_Italic(
858 IFont* iface,
859 BOOL italic)
861 OLEFontImpl *this = impl_from_IFont(iface);
862 TRACE("(%p)->(%d)\n", this, italic);
864 this->description.fItalic = italic;
866 OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
867 return S_OK;
870 /************************************************************************
871 * OLEFontImpl_get_Underline (IFont)
873 * See Windows documentation for more details on IFont methods.
875 static HRESULT WINAPI OLEFontImpl_get_Underline(
876 IFont* iface,
877 BOOL* punderline)
879 OLEFontImpl *this = impl_from_IFont(iface);
880 TRACE("(%p)->(%p)\n", this, punderline);
883 * Sanity check
885 if (punderline==0)
886 return E_POINTER;
888 if(this->dirty) realize_font(this);
890 *punderline = this->description.fUnderline;
892 return S_OK;
895 /************************************************************************
896 * OLEFontImpl_put_Underline (IFont)
898 * See Windows documentation for more details on IFont methods.
900 static HRESULT WINAPI OLEFontImpl_put_Underline(
901 IFont* iface,
902 BOOL underline)
904 OLEFontImpl *this = impl_from_IFont(iface);
905 TRACE("(%p)->(%d)\n", this, underline);
907 this->description.fUnderline = underline;
909 OLEFont_SendNotify(this, DISPID_FONT_UNDER);
910 return S_OK;
913 /************************************************************************
914 * OLEFontImpl_get_Strikethrough (IFont)
916 * See Windows documentation for more details on IFont methods.
918 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
919 IFont* iface,
920 BOOL* pstrikethrough)
922 OLEFontImpl *this = impl_from_IFont(iface);
923 TRACE("(%p)->(%p)\n", this, pstrikethrough);
926 * Sanity check
928 if (pstrikethrough==0)
929 return E_POINTER;
931 if(this->dirty) realize_font(this);
933 *pstrikethrough = this->description.fStrikethrough;
935 return S_OK;
938 /************************************************************************
939 * OLEFontImpl_put_Strikethrough (IFont)
941 * See Windows documentation for more details on IFont methods.
943 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
944 IFont* iface,
945 BOOL strikethrough)
947 OLEFontImpl *this = impl_from_IFont(iface);
948 TRACE("(%p)->(%d)\n", this, strikethrough);
950 this->description.fStrikethrough = strikethrough;
951 OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
953 return S_OK;
956 /************************************************************************
957 * OLEFontImpl_get_Weight (IFont)
959 * See Windows documentation for more details on IFont methods.
961 static HRESULT WINAPI OLEFontImpl_get_Weight(
962 IFont* iface,
963 short* pweight)
965 OLEFontImpl *this = impl_from_IFont(iface);
966 TRACE("(%p)->(%p)\n", this, pweight);
969 * Sanity check
971 if (pweight==0)
972 return E_POINTER;
974 if(this->dirty) realize_font(this);
976 *pweight = this->description.sWeight;
978 return S_OK;
981 /************************************************************************
982 * OLEFontImpl_put_Weight (IFont)
984 * See Windows documentation for more details on IFont methods.
986 static HRESULT WINAPI OLEFontImpl_put_Weight(
987 IFont* iface,
988 short weight)
990 OLEFontImpl *this = impl_from_IFont(iface);
991 TRACE("(%p)->(%d)\n", this, weight);
993 this->description.sWeight = weight;
995 OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
996 return S_OK;
999 /************************************************************************
1000 * OLEFontImpl_get_Charset (IFont)
1002 * See Windows documentation for more details on IFont methods.
1004 static HRESULT WINAPI OLEFontImpl_get_Charset(
1005 IFont* iface,
1006 short* pcharset)
1008 OLEFontImpl *this = impl_from_IFont(iface);
1009 TRACE("(%p)->(%p)\n", this, pcharset);
1012 * Sanity check
1014 if (pcharset==0)
1015 return E_POINTER;
1017 if(this->dirty) realize_font(this);
1019 *pcharset = this->description.sCharset;
1021 return S_OK;
1024 /************************************************************************
1025 * OLEFontImpl_put_Charset (IFont)
1027 * See Windows documentation for more details on IFont methods.
1029 static HRESULT WINAPI OLEFontImpl_put_Charset(
1030 IFont* iface,
1031 short charset)
1033 OLEFontImpl *this = impl_from_IFont(iface);
1034 TRACE("(%p)->(%d)\n", this, charset);
1036 this->description.sCharset = charset;
1037 OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
1039 return S_OK;
1042 /************************************************************************
1043 * OLEFontImpl_get_hFont (IFont)
1045 * See Windows documentation for more details on IFont methods.
1047 static HRESULT WINAPI OLEFontImpl_get_hFont(
1048 IFont* iface,
1049 HFONT* phfont)
1051 OLEFontImpl *this = impl_from_IFont(iface);
1052 TRACE("(%p)->(%p)\n", this, phfont);
1053 if (phfont==NULL)
1054 return E_POINTER;
1056 if(this->dirty) realize_font(this);
1058 *phfont = this->gdiFont;
1059 TRACE("Returning %p\n", *phfont);
1060 return S_OK;
1063 /************************************************************************
1064 * OLEFontImpl_Clone (IFont)
1066 * See Windows documentation for more details on IFont methods.
1068 static HRESULT WINAPI OLEFontImpl_Clone(
1069 IFont* iface,
1070 IFont** ppfont)
1072 OLEFontImpl* newObject = 0;
1073 OLEFontImpl *this = impl_from_IFont(iface);
1075 TRACE("(%p)->(%p)\n", this, ppfont);
1077 if (ppfont == NULL)
1078 return E_POINTER;
1080 *ppfont = NULL;
1083 * Allocate space for the object.
1085 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
1087 if (newObject==NULL)
1088 return E_OUTOFMEMORY;
1090 *newObject = *this;
1092 /* We need to alloc new memory for the string, otherwise
1093 * we free memory twice.
1095 newObject->description.lpstrName = HeapAlloc(
1096 GetProcessHeap(),0,
1097 (1+strlenW(this->description.lpstrName))*2
1099 strcpyW(newObject->description.lpstrName, this->description.lpstrName);
1102 /* Increment internal ref in hfont item list */
1103 if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
1105 InterlockedIncrement(&ifont_cnt);
1107 /* create new connection points */
1108 newObject->pPropertyNotifyCP = NULL;
1109 newObject->pFontEventsCP = NULL;
1110 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
1111 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
1113 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
1115 OLEFontImpl_Destroy(newObject);
1116 return E_OUTOFMEMORY;
1119 /* The cloned object starts with a reference count of 1 */
1120 newObject->ref = 1;
1122 *ppfont = &newObject->IFont_iface;
1124 return S_OK;
1127 /************************************************************************
1128 * OLEFontImpl_IsEqual (IFont)
1130 * See Windows documentation for more details on IFont methods.
1132 static HRESULT WINAPI OLEFontImpl_IsEqual(
1133 IFont* iface,
1134 IFont* pFontOther)
1136 OLEFontImpl *left = impl_from_IFont(iface);
1137 OLEFontImpl *right = impl_from_IFont(pFontOther);
1138 INT ret;
1139 INT left_len,right_len;
1141 if(pFontOther == NULL)
1142 return E_POINTER;
1143 else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
1144 return S_FALSE;
1145 else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
1146 return S_FALSE;
1147 else if (left->description.sWeight != right->description.sWeight)
1148 return S_FALSE;
1149 else if (left->description.sCharset != right->description.sCharset)
1150 return S_FALSE;
1151 else if (left->description.fItalic != right->description.fItalic)
1152 return S_FALSE;
1153 else if (left->description.fUnderline != right->description.fUnderline)
1154 return S_FALSE;
1155 else if (left->description.fStrikethrough != right->description.fStrikethrough)
1156 return S_FALSE;
1158 /* Check from string */
1159 left_len = strlenW(left->description.lpstrName);
1160 right_len = strlenW(right->description.lpstrName);
1161 ret = CompareStringW(0,0,left->description.lpstrName, left_len,
1162 right->description.lpstrName, right_len);
1163 if (ret != CSTR_EQUAL)
1164 return S_FALSE;
1166 return S_OK;
1169 /************************************************************************
1170 * OLEFontImpl_SetRatio (IFont)
1172 * See Windows documentation for more details on IFont methods.
1174 static HRESULT WINAPI OLEFontImpl_SetRatio(
1175 IFont* iface,
1176 LONG cyLogical,
1177 LONG cyHimetric)
1179 OLEFontImpl *this = impl_from_IFont(iface);
1180 TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
1182 this->cyLogical = cyLogical;
1183 this->cyHimetric = cyHimetric;
1185 return S_OK;
1188 /************************************************************************
1189 * OLEFontImpl_QueryTextMetrics (IFont)
1191 * See Windows documentation for more details on IFont methods.
1193 static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(
1194 IFont* iface,
1195 TEXTMETRICOLE* ptm)
1197 HDC hdcRef;
1198 HFONT hOldFont, hNewFont;
1200 hdcRef = GetDC(0);
1201 OLEFontImpl_get_hFont(iface, &hNewFont);
1202 hOldFont = SelectObject(hdcRef, hNewFont);
1203 GetTextMetricsW(hdcRef, ptm);
1204 SelectObject(hdcRef, hOldFont);
1205 ReleaseDC(0, hdcRef);
1206 return S_OK;
1209 /************************************************************************
1210 * OLEFontImpl_AddRefHfont (IFont)
1212 * See Windows documentation for more details on IFont methods.
1214 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1215 IFont* iface,
1216 HFONT hfont)
1218 OLEFontImpl *this = impl_from_IFont(iface);
1220 TRACE("(%p)->(%p)\n", this, hfont);
1222 if (!hfont) return E_INVALIDARG;
1224 return inc_ext_ref(hfont);
1227 /************************************************************************
1228 * OLEFontImpl_ReleaseHfont (IFont)
1230 * See Windows documentation for more details on IFont methods.
1232 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1233 IFont* iface,
1234 HFONT hfont)
1236 OLEFontImpl *this = impl_from_IFont(iface);
1238 TRACE("(%p)->(%p)\n", this, hfont);
1240 if (!hfont) return E_INVALIDARG;
1242 return dec_ext_ref(hfont);
1245 /************************************************************************
1246 * OLEFontImpl_SetHdc (IFont)
1248 * See Windows documentation for more details on IFont methods.
1250 static HRESULT WINAPI OLEFontImpl_SetHdc(
1251 IFont* iface,
1252 HDC hdc)
1254 OLEFontImpl *this = impl_from_IFont(iface);
1255 FIXME("(%p)->(%p): Stub\n", this, hdc);
1256 return E_NOTIMPL;
1260 * Virtual function tables for the OLEFontImpl class.
1262 static const IFontVtbl OLEFontImpl_VTable =
1264 OLEFontImpl_QueryInterface,
1265 OLEFontImpl_AddRef,
1266 OLEFontImpl_Release,
1267 OLEFontImpl_get_Name,
1268 OLEFontImpl_put_Name,
1269 OLEFontImpl_get_Size,
1270 OLEFontImpl_put_Size,
1271 OLEFontImpl_get_Bold,
1272 OLEFontImpl_put_Bold,
1273 OLEFontImpl_get_Italic,
1274 OLEFontImpl_put_Italic,
1275 OLEFontImpl_get_Underline,
1276 OLEFontImpl_put_Underline,
1277 OLEFontImpl_get_Strikethrough,
1278 OLEFontImpl_put_Strikethrough,
1279 OLEFontImpl_get_Weight,
1280 OLEFontImpl_put_Weight,
1281 OLEFontImpl_get_Charset,
1282 OLEFontImpl_put_Charset,
1283 OLEFontImpl_get_hFont,
1284 OLEFontImpl_Clone,
1285 OLEFontImpl_IsEqual,
1286 OLEFontImpl_SetRatio,
1287 OLEFontImpl_QueryTextMetrics,
1288 OLEFontImpl_AddRefHfont,
1289 OLEFontImpl_ReleaseHfont,
1290 OLEFontImpl_SetHdc
1293 /************************************************************************
1294 * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1296 * See Windows documentation for more details on IUnknown methods.
1298 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1299 IDispatch* iface,
1300 REFIID riid,
1301 VOID** ppvoid)
1303 OLEFontImpl *this = impl_from_IDispatch(iface);
1305 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
1308 /************************************************************************
1309 * OLEFontImpl_IDispatch_Release (IUnknown)
1311 * See Windows documentation for more details on IUnknown methods.
1313 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1314 IDispatch* iface)
1316 OLEFontImpl *this = impl_from_IDispatch(iface);
1318 return IFont_Release(&this->IFont_iface);
1321 /************************************************************************
1322 * OLEFontImpl_IDispatch_AddRef (IUnknown)
1324 * See Windows documentation for more details on IUnknown methods.
1326 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1327 IDispatch* iface)
1329 OLEFontImpl *this = impl_from_IDispatch(iface);
1331 return IFont_AddRef(&this->IFont_iface);
1334 /************************************************************************
1335 * OLEFontImpl_GetTypeInfoCount (IDispatch)
1337 * See Windows documentation for more details on IDispatch methods.
1339 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1340 IDispatch* iface,
1341 unsigned int* pctinfo)
1343 OLEFontImpl *this = impl_from_IDispatch(iface);
1344 TRACE("(%p)->(%p)\n", this, pctinfo);
1345 *pctinfo = 1;
1347 return S_OK;
1350 /************************************************************************
1351 * OLEFontImpl_GetTypeInfo (IDispatch)
1353 * See Windows documentation for more details on IDispatch methods.
1355 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1356 IDispatch* iface,
1357 UINT iTInfo,
1358 LCID lcid,
1359 ITypeInfo** ppTInfo)
1361 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1362 ITypeLib *tl;
1363 HRESULT hres;
1365 OLEFontImpl *this = impl_from_IDispatch(iface);
1366 TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1367 if (iTInfo != 0)
1368 return E_FAIL;
1369 hres = LoadTypeLib(stdole2tlb, &tl);
1370 if (FAILED(hres)) {
1371 ERR("Could not load the stdole2.tlb?\n");
1372 return hres;
1374 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
1375 ITypeLib_Release(tl);
1376 if (FAILED(hres)) {
1377 FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
1379 return hres;
1382 /************************************************************************
1383 * OLEFontImpl_GetIDsOfNames (IDispatch)
1385 * See Windows documentation for more details on IDispatch methods.
1387 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1388 IDispatch* iface,
1389 REFIID riid,
1390 LPOLESTR* rgszNames,
1391 UINT cNames,
1392 LCID lcid,
1393 DISPID* rgDispId)
1395 ITypeInfo * pTInfo;
1396 HRESULT hres;
1398 OLEFontImpl *this = impl_from_IDispatch(iface);
1400 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
1401 rgszNames, cNames, (int)lcid, rgDispId);
1403 if (cNames == 0)
1405 return E_INVALIDARG;
1407 else
1409 /* retrieve type information */
1410 hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1412 if (FAILED(hres))
1414 ERR("GetTypeInfo failed.\n");
1415 return hres;
1418 /* convert names to DISPIDs */
1419 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1420 ITypeInfo_Release(pTInfo);
1422 return hres;
1426 /************************************************************************
1427 * OLEFontImpl_Invoke (IDispatch)
1429 * See Windows documentation for more details on IDispatch methods.
1431 * Note: Do not call _put_Xxx methods, since setting things here
1432 * should not call notify functions as I found out debugging the generic
1433 * MS VB5 installer.
1435 static HRESULT WINAPI OLEFontImpl_Invoke(
1436 IDispatch* iface,
1437 DISPID dispIdMember,
1438 REFIID riid,
1439 LCID lcid,
1440 WORD wFlags,
1441 DISPPARAMS* pDispParams,
1442 VARIANT* pVarResult,
1443 EXCEPINFO* pExepInfo,
1444 UINT* puArgErr)
1446 OLEFontImpl *this = impl_from_IDispatch(iface);
1447 HRESULT hr;
1449 TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
1450 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
1451 puArgErr);
1453 /* validate parameters */
1455 if (!IsEqualIID(riid, &IID_NULL))
1457 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1458 return DISP_E_UNKNOWNINTERFACE;
1461 if (wFlags & DISPATCH_PROPERTYGET)
1463 if (!pVarResult)
1465 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
1466 return DISP_E_PARAMNOTOPTIONAL;
1469 else if (wFlags & DISPATCH_PROPERTYPUT)
1471 if (!pDispParams)
1473 ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
1474 return DISP_E_PARAMNOTOPTIONAL;
1476 if (pDispParams->cArgs != 1)
1478 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
1479 return DISP_E_BADPARAMCOUNT;
1482 else
1484 ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
1485 return DISP_E_MEMBERNOTFOUND;
1488 switch (dispIdMember) {
1489 case DISPID_FONT_NAME:
1490 if (wFlags & DISPATCH_PROPERTYGET) {
1491 V_VT(pVarResult) = VT_BSTR;
1492 return IFont_get_Name(&this->IFont_iface, &V_BSTR(pVarResult));
1493 } else {
1494 VARIANTARG vararg;
1496 VariantInit(&vararg);
1497 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
1498 if (FAILED(hr))
1499 return hr;
1501 hr = IFont_put_Name(&this->IFont_iface, V_BSTR(&vararg));
1503 VariantClear(&vararg);
1504 return hr;
1506 break;
1507 case DISPID_FONT_BOLD:
1508 if (wFlags & DISPATCH_PROPERTYGET) {
1509 BOOL value;
1510 hr = IFont_get_Bold(&this->IFont_iface, &value);
1511 V_VT(pVarResult) = VT_BOOL;
1512 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1513 return hr;
1514 } else {
1515 VARIANTARG vararg;
1517 VariantInit(&vararg);
1518 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1519 if (FAILED(hr))
1520 return hr;
1522 hr = IFont_put_Bold(&this->IFont_iface, V_BOOL(&vararg));
1524 VariantClear(&vararg);
1525 return hr;
1527 break;
1528 case DISPID_FONT_ITALIC:
1529 if (wFlags & DISPATCH_PROPERTYGET) {
1530 BOOL value;
1531 hr = IFont_get_Italic(&this->IFont_iface, &value);
1532 V_VT(pVarResult) = VT_BOOL;
1533 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1534 return hr;
1535 } else {
1536 VARIANTARG vararg;
1538 VariantInit(&vararg);
1539 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1540 if (FAILED(hr))
1541 return hr;
1543 hr = IFont_put_Italic(&this->IFont_iface, V_BOOL(&vararg));
1545 VariantClear(&vararg);
1546 return hr;
1548 break;
1549 case DISPID_FONT_UNDER:
1550 if (wFlags & DISPATCH_PROPERTYGET) {
1551 BOOL value;
1552 hr = IFont_get_Underline(&this->IFont_iface, &value);
1553 V_VT(pVarResult) = VT_BOOL;
1554 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1555 return hr;
1556 } else {
1557 VARIANTARG vararg;
1559 VariantInit(&vararg);
1560 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1561 if (FAILED(hr))
1562 return hr;
1564 hr = IFont_put_Underline(&this->IFont_iface, V_BOOL(&vararg));
1566 VariantClear(&vararg);
1567 return hr;
1569 break;
1570 case DISPID_FONT_STRIKE:
1571 if (wFlags & DISPATCH_PROPERTYGET) {
1572 BOOL value;
1573 hr = IFont_get_Strikethrough(&this->IFont_iface, &value);
1574 V_VT(pVarResult) = VT_BOOL;
1575 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1576 return hr;
1577 } else {
1578 VARIANTARG vararg;
1580 VariantInit(&vararg);
1581 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1582 if (FAILED(hr))
1583 return hr;
1585 hr = IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&vararg));
1587 VariantClear(&vararg);
1588 return hr;
1590 break;
1591 case DISPID_FONT_SIZE:
1592 if (wFlags & DISPATCH_PROPERTYGET) {
1593 V_VT(pVarResult) = VT_CY;
1594 return OLEFontImpl_get_Size(&this->IFont_iface, &V_CY(pVarResult));
1595 } else {
1596 VARIANTARG vararg;
1598 VariantInit(&vararg);
1599 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
1600 if (FAILED(hr))
1601 return hr;
1603 hr = IFont_put_Size(&this->IFont_iface, V_CY(&vararg));
1605 VariantClear(&vararg);
1606 return hr;
1608 break;
1609 case DISPID_FONT_WEIGHT:
1610 if (wFlags & DISPATCH_PROPERTYGET) {
1611 V_VT(pVarResult) = VT_I2;
1612 return OLEFontImpl_get_Weight(&this->IFont_iface, &V_I2(pVarResult));
1613 } else {
1614 VARIANTARG vararg;
1616 VariantInit(&vararg);
1617 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1618 if (FAILED(hr))
1619 return hr;
1621 hr = IFont_put_Weight(&this->IFont_iface, V_I2(&vararg));
1623 VariantClear(&vararg);
1624 return hr;
1626 break;
1627 case DISPID_FONT_CHARSET:
1628 if (wFlags & DISPATCH_PROPERTYGET) {
1629 V_VT(pVarResult) = VT_I2;
1630 return OLEFontImpl_get_Charset(&this->IFont_iface, &V_I2(pVarResult));
1631 } else {
1632 VARIANTARG vararg;
1634 VariantInit(&vararg);
1635 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1636 if (FAILED(hr))
1637 return hr;
1639 hr = IFont_put_Charset(&this->IFont_iface, V_I2(&vararg));
1641 VariantClear(&vararg);
1642 return hr;
1644 break;
1645 default:
1646 ERR("member not found for dispid 0x%x\n", dispIdMember);
1647 return DISP_E_MEMBERNOTFOUND;
1651 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
1653 OLEFontImpl_IDispatch_QueryInterface,
1654 OLEFontImpl_IDispatch_AddRef,
1655 OLEFontImpl_IDispatch_Release,
1656 OLEFontImpl_GetTypeInfoCount,
1657 OLEFontImpl_GetTypeInfo,
1658 OLEFontImpl_GetIDsOfNames,
1659 OLEFontImpl_Invoke
1662 /************************************************************************
1663 * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1665 * See Windows documentation for more details on IUnknown methods.
1667 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1668 IPersistStream* iface,
1669 REFIID riid,
1670 VOID** ppvoid)
1672 OLEFontImpl *this = impl_from_IPersistStream(iface);
1674 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
1677 /************************************************************************
1678 * OLEFontImpl_IPersistStream_Release (IUnknown)
1680 * See Windows documentation for more details on IUnknown methods.
1682 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1683 IPersistStream* iface)
1685 OLEFontImpl *this = impl_from_IPersistStream(iface);
1687 return IFont_Release(&this->IFont_iface);
1690 /************************************************************************
1691 * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1693 * See Windows documentation for more details on IUnknown methods.
1695 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1696 IPersistStream* iface)
1698 OLEFontImpl *this = impl_from_IPersistStream(iface);
1700 return IFont_AddRef(&this->IFont_iface);
1703 /************************************************************************
1704 * OLEFontImpl_GetClassID (IPersistStream)
1706 * See Windows documentation for more details on IPersistStream methods.
1708 static HRESULT WINAPI OLEFontImpl_GetClassID(
1709 IPersistStream* iface,
1710 CLSID* pClassID)
1712 TRACE("(%p,%p)\n",iface,pClassID);
1713 if (pClassID==0)
1714 return E_POINTER;
1716 *pClassID = CLSID_StdFont;
1718 return S_OK;
1721 /************************************************************************
1722 * OLEFontImpl_IsDirty (IPersistStream)
1724 * See Windows documentation for more details on IPersistStream methods.
1726 static HRESULT WINAPI OLEFontImpl_IsDirty(
1727 IPersistStream* iface)
1729 TRACE("(%p)\n",iface);
1730 return S_OK;
1733 /************************************************************************
1734 * OLEFontImpl_Load (IPersistStream)
1736 * See Windows documentation for more details on IPersistStream methods.
1738 * This is the format of the standard font serialization as far as I
1739 * know
1741 * Offset Type Value Comment
1742 * 0x0000 Byte Unknown Probably a version number, contains 0x01
1743 * 0x0001 Short Charset Charset value from the FONTDESC structure
1744 * 0x0003 Byte Attributes Flags defined as follows:
1745 * 00000010 - Italic
1746 * 00000100 - Underline
1747 * 00001000 - Strikethrough
1748 * 0x0004 Short Weight Weight value from FONTDESC structure
1749 * 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC
1750 * structure/
1751 * 0x000A Byte name length Length of the font name string (no null character)
1752 * 0x000B String name Name of the font (ASCII, no nul character)
1754 static HRESULT WINAPI OLEFontImpl_Load(
1755 IPersistStream* iface,
1756 IStream* pLoadStream)
1758 char readBuffer[0x100];
1759 ULONG cbRead;
1760 BYTE bVersion;
1761 BYTE bAttributes;
1762 BYTE bStringSize;
1763 INT len;
1765 OLEFontImpl *this = impl_from_IPersistStream(iface);
1768 * Read the version byte
1770 IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1772 if ( (cbRead!=1) ||
1773 (bVersion!=0x01) )
1774 return E_FAIL;
1777 * Charset
1779 IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1781 if (cbRead!=2)
1782 return E_FAIL;
1785 * Attributes
1787 IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1789 if (cbRead!=1)
1790 return E_FAIL;
1792 this->description.fItalic = (bAttributes & FONTPERSIST_ITALIC) != 0;
1793 this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1794 this->description.fUnderline = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1797 * Weight
1799 IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1801 if (cbRead!=2)
1802 return E_FAIL;
1805 * Size
1807 IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1809 if (cbRead!=4)
1810 return E_FAIL;
1812 this->description.cySize.s.Hi = 0;
1815 * FontName
1817 IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1819 if (cbRead!=1)
1820 return E_FAIL;
1822 IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1824 if (cbRead!=bStringSize)
1825 return E_FAIL;
1827 HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1829 len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1830 this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1831 MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1832 this->description.lpstrName[len] = 0;
1834 /* Ensure use of this font causes a new one to be created */
1835 dec_int_ref(this->gdiFont);
1836 this->gdiFont = 0;
1837 this->dirty = TRUE;
1839 return S_OK;
1842 /************************************************************************
1843 * OLEFontImpl_Save (IPersistStream)
1845 * See Windows documentation for more details on IPersistStream methods.
1847 static HRESULT WINAPI OLEFontImpl_Save(
1848 IPersistStream* iface,
1849 IStream* pOutStream,
1850 BOOL fClearDirty)
1852 char* writeBuffer = NULL;
1853 ULONG cbWritten;
1854 BYTE bVersion = 0x01;
1855 BYTE bAttributes;
1856 BYTE bStringSize;
1858 OLEFontImpl *this = impl_from_IPersistStream(iface);
1861 * Read the version byte
1863 IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1865 if (cbWritten!=1)
1866 return E_FAIL;
1869 * Charset
1871 IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1873 if (cbWritten!=2)
1874 return E_FAIL;
1877 * Attributes
1879 bAttributes = 0;
1881 if (this->description.fItalic)
1882 bAttributes |= FONTPERSIST_ITALIC;
1884 if (this->description.fStrikethrough)
1885 bAttributes |= FONTPERSIST_STRIKETHROUGH;
1887 if (this->description.fUnderline)
1888 bAttributes |= FONTPERSIST_UNDERLINE;
1890 IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1892 if (cbWritten!=1)
1893 return E_FAIL;
1896 * Weight
1898 IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1900 if (cbWritten!=2)
1901 return E_FAIL;
1904 * Size
1906 IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1908 if (cbWritten!=4)
1909 return E_FAIL;
1912 * FontName
1914 if (this->description.lpstrName!=0)
1915 bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1916 strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1917 else
1918 bStringSize = 0;
1920 IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1922 if (cbWritten!=1)
1923 return E_FAIL;
1925 if (bStringSize!=0)
1927 if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1928 WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1929 strlenW(this->description.lpstrName),
1930 writeBuffer, bStringSize, NULL, NULL );
1932 IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1933 HeapFree(GetProcessHeap(), 0, writeBuffer);
1935 if (cbWritten!=bStringSize)
1936 return E_FAIL;
1939 return S_OK;
1942 /************************************************************************
1943 * OLEFontImpl_GetSizeMax (IPersistStream)
1945 * See Windows documentation for more details on IPersistStream methods.
1947 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1948 IPersistStream* iface,
1949 ULARGE_INTEGER* pcbSize)
1951 OLEFontImpl *this = impl_from_IPersistStream(iface);
1953 if (pcbSize==NULL)
1954 return E_POINTER;
1956 pcbSize->u.HighPart = 0;
1957 pcbSize->u.LowPart = 0;
1959 pcbSize->u.LowPart += sizeof(BYTE); /* Version */
1960 pcbSize->u.LowPart += sizeof(WORD); /* Lang code */
1961 pcbSize->u.LowPart += sizeof(BYTE); /* Flags */
1962 pcbSize->u.LowPart += sizeof(WORD); /* Weight */
1963 pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1964 pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */
1966 if (this->description.lpstrName!=0)
1967 pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1968 strlenW(this->description.lpstrName),
1969 NULL, 0, NULL, NULL );
1971 return S_OK;
1974 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
1976 OLEFontImpl_IPersistStream_QueryInterface,
1977 OLEFontImpl_IPersistStream_AddRef,
1978 OLEFontImpl_IPersistStream_Release,
1979 OLEFontImpl_GetClassID,
1980 OLEFontImpl_IsDirty,
1981 OLEFontImpl_Load,
1982 OLEFontImpl_Save,
1983 OLEFontImpl_GetSizeMax
1986 /************************************************************************
1987 * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1989 * See Windows documentation for more details on IUnknown methods.
1991 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1992 IConnectionPointContainer* iface,
1993 REFIID riid,
1994 VOID** ppvoid)
1996 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1998 return IFont_QueryInterface(&this->IFont_iface, riid, ppvoid);
2001 /************************************************************************
2002 * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
2004 * See Windows documentation for more details on IUnknown methods.
2006 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
2007 IConnectionPointContainer* iface)
2009 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2011 return IFont_Release(&this->IFont_iface);
2014 /************************************************************************
2015 * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
2017 * See Windows documentation for more details on IUnknown methods.
2019 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
2020 IConnectionPointContainer* iface)
2022 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2024 return IFont_AddRef(&this->IFont_iface);
2027 /************************************************************************
2028 * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
2030 * See Windows documentation for more details on IConnectionPointContainer
2031 * methods.
2033 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
2034 IConnectionPointContainer* iface,
2035 IEnumConnectionPoints **ppEnum)
2037 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2039 FIXME("(%p)->(%p): stub\n", this, ppEnum);
2040 return E_NOTIMPL;
2043 /************************************************************************
2044 * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
2046 * See Windows documentation for more details on IConnectionPointContainer
2047 * methods.
2049 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
2050 IConnectionPointContainer* iface,
2051 REFIID riid,
2052 IConnectionPoint **ppCp)
2054 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2055 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
2057 if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
2058 return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
2059 &IID_IConnectionPoint,
2060 (LPVOID)ppCp);
2061 } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
2062 return IConnectionPoint_QueryInterface(this->pFontEventsCP,
2063 &IID_IConnectionPoint,
2064 (LPVOID)ppCp);
2065 } else {
2066 FIXME("no connection point for %s\n", debugstr_guid(riid));
2067 return CONNECT_E_NOCONNECTION;
2071 static const IConnectionPointContainerVtbl
2072 OLEFontImpl_IConnectionPointContainer_VTable =
2074 OLEFontImpl_IConnectionPointContainer_QueryInterface,
2075 OLEFontImpl_IConnectionPointContainer_AddRef,
2076 OLEFontImpl_IConnectionPointContainer_Release,
2077 OLEFontImpl_EnumConnectionPoints,
2078 OLEFontImpl_FindConnectionPoint
2081 /************************************************************************
2082 * OLEFontImpl implementation of IPersistPropertyBag.
2084 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
2085 IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
2087 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2088 return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj);
2091 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
2092 IPersistPropertyBag *iface
2094 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2095 return IFont_AddRef(&this->IFont_iface);
2098 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
2099 IPersistPropertyBag *iface
2101 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2102 return IFont_Release(&this->IFont_iface);
2105 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
2106 IPersistPropertyBag *iface, CLSID *classid
2108 FIXME("(%p,%p), stub!\n", iface, classid);
2109 return E_FAIL;
2112 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
2113 IPersistPropertyBag *iface
2115 FIXME("(%p), stub!\n", iface);
2116 return S_OK;
2119 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
2120 IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
2122 /* (from Visual Basic 6 property bag)
2123 Name = "MS Sans Serif"
2124 Size = 13.8
2125 Charset = 0
2126 Weight = 400
2127 Underline = 0 'False
2128 Italic = 0 'False
2129 Strikethrough = 0 'False
2131 static const WCHAR sAttrName[] = {'N','a','m','e',0};
2132 static const WCHAR sAttrSize[] = {'S','i','z','e',0};
2133 static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
2134 static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
2135 static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
2136 static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
2137 static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
2138 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2139 VARIANT value;
2140 HRESULT iRes;
2142 VariantInit(&value);
2144 iRes = IPropertyBag_Read(pPropBag, sAttrName, &value, pErrorLog);
2145 if (iRes == S_OK)
2147 iRes = VariantChangeType(&value, &value, 0, VT_BSTR);
2148 if (iRes == S_OK)
2149 iRes = IFont_put_Name(&this->IFont_iface, V_BSTR(&value));
2151 else if (iRes == E_INVALIDARG)
2152 iRes = S_OK;
2154 VariantClear(&value);
2156 if (iRes == S_OK) {
2157 iRes = IPropertyBag_Read(pPropBag, sAttrSize, &value, pErrorLog);
2158 if (iRes == S_OK)
2160 iRes = VariantChangeType(&value, &value, 0, VT_CY);
2161 if (iRes == S_OK)
2162 iRes = IFont_put_Size(&this->IFont_iface, V_CY(&value));
2164 else if (iRes == E_INVALIDARG)
2165 iRes = S_OK;
2167 VariantClear(&value);
2170 if (iRes == S_OK) {
2171 iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &value, pErrorLog);
2172 if (iRes == S_OK)
2174 iRes = VariantChangeType(&value, &value, 0, VT_I2);
2175 if (iRes == S_OK)
2176 iRes = IFont_put_Charset(&this->IFont_iface, V_I2(&value));
2178 else if (iRes == E_INVALIDARG)
2179 iRes = S_OK;
2181 VariantClear(&value);
2184 if (iRes == S_OK) {
2185 iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &value, pErrorLog);
2186 if (iRes == S_OK)
2188 iRes = VariantChangeType(&value, &value, 0, VT_I2);
2189 if (iRes == S_OK)
2190 iRes = IFont_put_Weight(&this->IFont_iface, V_I2(&value));
2192 else if (iRes == E_INVALIDARG)
2193 iRes = S_OK;
2195 VariantClear(&value);
2198 if (iRes == S_OK) {
2199 iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &value, pErrorLog);
2200 if (iRes == S_OK)
2202 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
2203 if (iRes == S_OK)
2204 iRes = IFont_put_Underline(&this->IFont_iface, V_BOOL(&value));
2206 else if (iRes == E_INVALIDARG)
2207 iRes = S_OK;
2209 VariantClear(&value);
2212 if (iRes == S_OK) {
2213 iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &value, pErrorLog);
2214 if (iRes == S_OK)
2216 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
2217 if (iRes == S_OK)
2218 iRes = IFont_put_Italic(&this->IFont_iface, V_BOOL(&value));
2220 else if (iRes == E_INVALIDARG)
2221 iRes = S_OK;
2223 VariantClear(&value);
2226 if (iRes == S_OK) {
2227 iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &value, pErrorLog);
2228 if (iRes == S_OK)
2230 iRes = VariantChangeType(&value, &value, 0, VT_BOOL);
2231 if (iRes == S_OK)
2232 IFont_put_Strikethrough(&this->IFont_iface, V_BOOL(&value));
2234 else if (iRes == E_INVALIDARG)
2235 iRes = S_OK;
2237 VariantClear(&value);
2240 if (FAILED(iRes))
2241 WARN("-- 0x%08x\n", iRes);
2242 return iRes;
2245 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2246 IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2247 BOOL fSaveAllProperties
2249 FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2250 return E_FAIL;
2253 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable =
2255 OLEFontImpl_IPersistPropertyBag_QueryInterface,
2256 OLEFontImpl_IPersistPropertyBag_AddRef,
2257 OLEFontImpl_IPersistPropertyBag_Release,
2259 OLEFontImpl_IPersistPropertyBag_GetClassID,
2260 OLEFontImpl_IPersistPropertyBag_InitNew,
2261 OLEFontImpl_IPersistPropertyBag_Load,
2262 OLEFontImpl_IPersistPropertyBag_Save
2265 /************************************************************************
2266 * OLEFontImpl implementation of IPersistStreamInit.
2268 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2269 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2271 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2272 return IFont_QueryInterface(&this->IFont_iface,riid,ppvObj);
2275 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2276 IPersistStreamInit *iface
2278 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2279 return IFont_AddRef(&this->IFont_iface);
2282 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2283 IPersistStreamInit *iface
2285 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2286 return IFont_Release(&this->IFont_iface);
2289 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2290 IPersistStreamInit *iface, CLSID *classid
2292 FIXME("(%p,%p), stub!\n", iface, classid);
2293 return E_FAIL;
2296 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2297 IPersistStreamInit *iface
2299 FIXME("(%p), stub!\n", iface);
2300 return E_FAIL;
2303 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2304 IPersistStreamInit *iface, LPSTREAM pStm
2306 FIXME("(%p,%p), stub!\n", iface, pStm);
2307 return E_FAIL;
2310 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2311 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2313 FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2314 return E_FAIL;
2317 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2318 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2320 FIXME("(%p,%p), stub!\n", iface, pcbSize);
2321 return E_FAIL;
2324 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2325 IPersistStreamInit *iface
2327 FIXME("(%p), stub!\n", iface);
2328 return S_OK;
2331 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable =
2333 OLEFontImpl_IPersistStreamInit_QueryInterface,
2334 OLEFontImpl_IPersistStreamInit_AddRef,
2335 OLEFontImpl_IPersistStreamInit_Release,
2337 OLEFontImpl_IPersistStreamInit_GetClassID,
2338 OLEFontImpl_IPersistStreamInit_IsDirty,
2339 OLEFontImpl_IPersistStreamInit_Load,
2340 OLEFontImpl_IPersistStreamInit_Save,
2341 OLEFontImpl_IPersistStreamInit_GetSizeMax,
2342 OLEFontImpl_IPersistStreamInit_InitNew
2345 /************************************************************************
2346 * OLEFontImpl_Construct
2348 * This method will construct a new instance of the OLEFontImpl
2349 * class.
2351 * The caller of this method must release the object when it's
2352 * done with it.
2354 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
2356 OLEFontImpl* newObject = 0;
2359 * Allocate space for the object.
2361 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
2363 if (newObject==0)
2364 return newObject;
2367 * Initialize the virtual function table.
2369 newObject->IFont_iface.lpVtbl = &OLEFontImpl_VTable;
2370 newObject->IDispatch_iface.lpVtbl = &OLEFontImpl_IDispatch_VTable;
2371 newObject->IPersistStream_iface.lpVtbl = &OLEFontImpl_IPersistStream_VTable;
2372 newObject->IConnectionPointContainer_iface.lpVtbl = &OLEFontImpl_IConnectionPointContainer_VTable;
2373 newObject->IPersistPropertyBag_iface.lpVtbl = &OLEFontImpl_IPersistPropertyBag_VTable;
2374 newObject->IPersistStreamInit_iface.lpVtbl = &OLEFontImpl_IPersistStreamInit_VTable;
2377 * Start with one reference count. The caller of this function
2378 * must release the interface pointer when it is done.
2380 newObject->ref = 1;
2383 * Copy the description of the font in the object.
2385 assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
2387 newObject->description.cbSizeofstruct = sizeof(FONTDESC);
2388 newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
2390 (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
2391 strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
2392 newObject->description.cySize = fontDesc->cySize;
2393 newObject->description.sWeight = fontDesc->sWeight;
2394 newObject->description.sCharset = fontDesc->sCharset;
2395 newObject->description.fItalic = fontDesc->fItalic;
2396 newObject->description.fUnderline = fontDesc->fUnderline;
2397 newObject->description.fStrikethrough = fontDesc->fStrikethrough;
2400 * Initializing all the other members.
2402 newObject->gdiFont = 0;
2403 newObject->dirty = TRUE;
2404 newObject->cyLogical = 72L;
2405 newObject->cyHimetric = 2540L;
2406 newObject->pPropertyNotifyCP = NULL;
2407 newObject->pFontEventsCP = NULL;
2409 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
2410 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
2412 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
2414 OLEFontImpl_Destroy(newObject);
2415 return NULL;
2418 InterlockedIncrement(&ifont_cnt);
2420 TRACE("returning %p\n", newObject);
2421 return newObject;
2424 /************************************************************************
2425 * OLEFontImpl_Destroy
2427 * This method is called by the Release method when the reference
2428 * count goes down to 0. It will free all resources used by
2429 * this object.
2431 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
2433 TRACE("(%p)\n", fontDesc);
2435 HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
2437 if (fontDesc->pPropertyNotifyCP)
2438 IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
2439 if (fontDesc->pFontEventsCP)
2440 IConnectionPoint_Release(fontDesc->pFontEventsCP);
2442 HeapFree(GetProcessHeap(), 0, fontDesc);
2445 /*******************************************************************************
2446 * StdFont ClassFactory
2448 typedef struct
2450 /* IUnknown fields */
2451 IClassFactory IClassFactory_iface;
2452 LONG ref;
2453 } IClassFactoryImpl;
2455 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
2457 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
2460 static HRESULT WINAPI
2461 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2462 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2464 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2465 return E_NOINTERFACE;
2468 static ULONG WINAPI
2469 SFCF_AddRef(LPCLASSFACTORY iface) {
2470 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2471 return InterlockedIncrement(&This->ref);
2474 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2475 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2476 /* static class, won't be freed */
2477 return InterlockedDecrement(&This->ref);
2480 static HRESULT WINAPI SFCF_CreateInstance(
2481 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2483 return OleCreateFontIndirect(NULL,riid,ppobj);
2487 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2488 IClassFactoryImpl *This = impl_from_IClassFactory(iface);
2489 FIXME("(%p)->(%d),stub!\n",This,dolock);
2490 return S_OK;
2493 static const IClassFactoryVtbl SFCF_Vtbl = {
2494 SFCF_QueryInterface,
2495 SFCF_AddRef,
2496 SFCF_Release,
2497 SFCF_CreateInstance,
2498 SFCF_LockServer
2500 static IClassFactoryImpl STDFONT_CF = {{&SFCF_Vtbl}, 1 };
2502 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }