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