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