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