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