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