oleaut32: Implement ICreateTypeInfo2::SetCustData method.
[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   this->dirty = TRUE;
1843
1844   return S_OK;
1845 }
1846
1847 /************************************************************************
1848  * OLEFontImpl_Save (IPersistStream)
1849  *
1850  * See Windows documentation for more details on IPersistStream methods.
1851  */
1852 static HRESULT WINAPI OLEFontImpl_Save(
1853   IPersistStream*  iface,
1854   IStream*         pOutStream,
1855   BOOL             fClearDirty)
1856 {
1857   char* writeBuffer = NULL;
1858   ULONG cbWritten;
1859   BYTE  bVersion = 0x01;
1860   BYTE  bAttributes;
1861   BYTE  bStringSize;
1862
1863   OLEFontImpl *this = impl_from_IPersistStream(iface);
1864
1865   /*
1866    * Read the version byte
1867    */
1868   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1869
1870   if (cbWritten!=1)
1871     return E_FAIL;
1872
1873   /*
1874    * Charset
1875    */
1876   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1877
1878   if (cbWritten!=2)
1879     return E_FAIL;
1880
1881   /*
1882    * Attributes
1883    */
1884   bAttributes = 0;
1885
1886   if (this->description.fItalic)
1887     bAttributes |= FONTPERSIST_ITALIC;
1888
1889   if (this->description.fStrikethrough)
1890     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1891
1892   if (this->description.fUnderline)
1893     bAttributes |= FONTPERSIST_UNDERLINE;
1894
1895   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1896
1897   if (cbWritten!=1)
1898     return E_FAIL;
1899
1900   /*
1901    * Weight
1902    */
1903   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1904
1905   if (cbWritten!=2)
1906     return E_FAIL;
1907
1908   /*
1909    * Size
1910    */
1911   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1912
1913   if (cbWritten!=4)
1914     return E_FAIL;
1915
1916   /*
1917    * FontName
1918    */
1919   if (this->description.lpstrName!=0)
1920     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1921                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1922   else
1923     bStringSize = 0;
1924
1925   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1926
1927   if (cbWritten!=1)
1928     return E_FAIL;
1929
1930   if (bStringSize!=0)
1931   {
1932       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1933       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1934                            strlenW(this->description.lpstrName),
1935                            writeBuffer, bStringSize, NULL, NULL );
1936
1937     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1938     HeapFree(GetProcessHeap(), 0, writeBuffer);
1939
1940     if (cbWritten!=bStringSize)
1941       return E_FAIL;
1942   }
1943
1944   return S_OK;
1945 }
1946
1947 /************************************************************************
1948  * OLEFontImpl_GetSizeMax (IPersistStream)
1949  *
1950  * See Windows documentation for more details on IPersistStream methods.
1951  */
1952 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1953   IPersistStream*  iface,
1954   ULARGE_INTEGER*  pcbSize)
1955 {
1956   OLEFontImpl *this = impl_from_IPersistStream(iface);
1957
1958   if (pcbSize==NULL)
1959     return E_POINTER;
1960
1961   pcbSize->u.HighPart = 0;
1962   pcbSize->u.LowPart = 0;
1963
1964   pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
1965   pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
1966   pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
1967   pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
1968   pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1969   pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
1970
1971   if (this->description.lpstrName!=0)
1972       pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1973                                                  strlenW(this->description.lpstrName),
1974                                                  NULL, 0, NULL, NULL );
1975
1976   return S_OK;
1977 }
1978
1979 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
1980 {
1981   OLEFontImpl_IPersistStream_QueryInterface,
1982   OLEFontImpl_IPersistStream_AddRef,
1983   OLEFontImpl_IPersistStream_Release,
1984   OLEFontImpl_GetClassID,
1985   OLEFontImpl_IsDirty,
1986   OLEFontImpl_Load,
1987   OLEFontImpl_Save,
1988   OLEFontImpl_GetSizeMax
1989 };
1990
1991 /************************************************************************
1992  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1993  *
1994  * See Windows documentation for more details on IUnknown methods.
1995  */
1996 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1997   IConnectionPointContainer* iface,
1998   REFIID     riid,
1999   VOID**     ppvoid)
2000 {
2001   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2002
2003   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
2004 }
2005
2006 /************************************************************************
2007  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
2008  *
2009  * See Windows documentation for more details on IUnknown methods.
2010  */
2011 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
2012   IConnectionPointContainer* iface)
2013 {
2014   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2015
2016   return IFont_Release((IFont*)this);
2017 }
2018
2019 /************************************************************************
2020  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
2021  *
2022  * See Windows documentation for more details on IUnknown methods.
2023  */
2024 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
2025   IConnectionPointContainer* iface)
2026 {
2027   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2028
2029   return IFont_AddRef((IFont*)this);
2030 }
2031
2032 /************************************************************************
2033  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
2034  *
2035  * See Windows documentation for more details on IConnectionPointContainer
2036  * methods.
2037  */
2038 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
2039   IConnectionPointContainer* iface,
2040   IEnumConnectionPoints **ppEnum)
2041 {
2042   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2043
2044   FIXME("(%p)->(%p): stub\n", this, ppEnum);
2045   return E_NOTIMPL;
2046 }
2047
2048 /************************************************************************
2049  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
2050  *
2051  * See Windows documentation for more details on IConnectionPointContainer
2052  * methods.
2053  */
2054 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
2055    IConnectionPointContainer* iface,
2056    REFIID riid,
2057    IConnectionPoint **ppCp)
2058 {
2059   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2060   TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
2061
2062   if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
2063     return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
2064                                            &IID_IConnectionPoint,
2065                                            (LPVOID)ppCp);
2066   } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
2067     return IConnectionPoint_QueryInterface(this->pFontEventsCP,
2068                                            &IID_IConnectionPoint,
2069                                            (LPVOID)ppCp);
2070   } else {
2071     FIXME("no connection point for %s\n", debugstr_guid(riid));
2072     return CONNECT_E_NOCONNECTION;
2073   }
2074 }
2075
2076 static const IConnectionPointContainerVtbl
2077      OLEFontImpl_IConnectionPointContainer_VTable =
2078 {
2079   OLEFontImpl_IConnectionPointContainer_QueryInterface,
2080   OLEFontImpl_IConnectionPointContainer_AddRef,
2081   OLEFontImpl_IConnectionPointContainer_Release,
2082   OLEFontImpl_EnumConnectionPoints,
2083   OLEFontImpl_FindConnectionPoint
2084 };
2085
2086 /************************************************************************
2087  * OLEFontImpl implementation of IPersistPropertyBag.
2088  */
2089 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
2090    IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
2091 ) {
2092   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2093   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2094 }
2095
2096 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
2097    IPersistPropertyBag *iface
2098 ) {
2099   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2100   return IFont_AddRef((IFont *)this);
2101 }
2102
2103 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
2104    IPersistPropertyBag *iface
2105 ) {
2106   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2107   return IFont_Release((IFont *)this);
2108 }
2109
2110 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
2111    IPersistPropertyBag *iface, CLSID *classid
2112 ) {
2113   FIXME("(%p,%p), stub!\n", iface, classid);
2114   return E_FAIL;
2115 }
2116
2117 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
2118    IPersistPropertyBag *iface
2119 ) {
2120   FIXME("(%p), stub!\n", iface);
2121   return S_OK;
2122 }
2123
2124 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
2125    IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
2126 ) {
2127 /* (from Visual Basic 6 property bag)
2128          Name            =   "MS Sans Serif"
2129          Size            =   13.8
2130          Charset         =   0
2131          Weight          =   400
2132          Underline       =   0   'False
2133          Italic          =   0   'False
2134          Strikethrough   =   0   'False
2135 */
2136     static const WCHAR sAttrName[] = {'N','a','m','e',0};
2137     static const WCHAR sAttrSize[] = {'S','i','z','e',0};
2138     static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
2139     static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
2140     static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
2141     static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
2142     static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
2143     VARIANT rawAttr;
2144     VARIANT valueAttr;
2145     HRESULT iRes = S_OK;
2146     OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2147
2148     VariantInit(&rawAttr);
2149     VariantInit(&valueAttr);
2150
2151     if (iRes == S_OK) {
2152         iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
2153         if (iRes == S_OK)
2154         {
2155             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
2156             if (iRes == S_OK)
2157                 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
2158         }
2159         else if (iRes == E_INVALIDARG)
2160             iRes = S_OK;
2161         VariantClear(&rawAttr);
2162         VariantClear(&valueAttr);
2163     }
2164
2165     if (iRes == S_OK) {
2166         iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
2167         if (iRes == S_OK)
2168         {
2169             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
2170             if (iRes == S_OK)
2171                 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
2172         }
2173         else if (iRes == E_INVALIDARG)
2174             iRes = S_OK;
2175         VariantClear(&rawAttr);
2176         VariantClear(&valueAttr);
2177     }
2178
2179     if (iRes == S_OK) {
2180         iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
2181         if (iRes == S_OK)
2182         {
2183             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2184             if (iRes == S_OK)
2185                 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
2186         }
2187         else if (iRes == E_INVALIDARG)
2188             iRes = S_OK;
2189         VariantClear(&rawAttr);
2190         VariantClear(&valueAttr);
2191     }
2192
2193     if (iRes == S_OK) {
2194         iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
2195         if (iRes == S_OK)
2196         {
2197             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2198             if (iRes == S_OK)
2199                 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
2200         }
2201         else if (iRes == E_INVALIDARG)
2202             iRes = S_OK;
2203         VariantClear(&rawAttr);
2204         VariantClear(&valueAttr);
2205
2206     }
2207
2208     if (iRes == S_OK) {
2209         iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
2210         if (iRes == S_OK)
2211         {
2212             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2213             if (iRes == S_OK)
2214                 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
2215         }
2216         else if (iRes == E_INVALIDARG)
2217             iRes = S_OK;
2218         VariantClear(&rawAttr);
2219         VariantClear(&valueAttr);
2220     }
2221
2222     if (iRes == S_OK) {
2223         iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
2224         if (iRes == S_OK)
2225         {
2226             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2227             if (iRes == S_OK)
2228                 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
2229         }
2230         else if (iRes == E_INVALIDARG)
2231             iRes = S_OK;
2232         VariantClear(&rawAttr);
2233         VariantClear(&valueAttr);
2234     }
2235
2236     if (iRes == S_OK) {
2237         iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
2238         if (iRes == S_OK)
2239         {
2240             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2241             if (iRes == S_OK)
2242                 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
2243         }
2244         else if (iRes == E_INVALIDARG)
2245             iRes = S_OK;
2246         VariantClear(&rawAttr);
2247         VariantClear(&valueAttr);
2248     }
2249
2250     if (FAILED(iRes))
2251         WARN("-- 0x%08x\n", iRes);
2252     return iRes;
2253 }
2254
2255 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2256    IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2257    BOOL fSaveAllProperties
2258 ) {
2259   FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2260   return E_FAIL;
2261 }
2262
2263 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
2264 {
2265   OLEFontImpl_IPersistPropertyBag_QueryInterface,
2266   OLEFontImpl_IPersistPropertyBag_AddRef,
2267   OLEFontImpl_IPersistPropertyBag_Release,
2268
2269   OLEFontImpl_IPersistPropertyBag_GetClassID,
2270   OLEFontImpl_IPersistPropertyBag_InitNew,
2271   OLEFontImpl_IPersistPropertyBag_Load,
2272   OLEFontImpl_IPersistPropertyBag_Save
2273 };
2274
2275 /************************************************************************
2276  * OLEFontImpl implementation of IPersistStreamInit.
2277  */
2278 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2279    IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2280 ) {
2281   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2282   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2283 }
2284
2285 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2286    IPersistStreamInit *iface
2287 ) {
2288   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2289   return IFont_AddRef((IFont *)this);
2290 }
2291
2292 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2293    IPersistStreamInit *iface
2294 ) {
2295   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2296   return IFont_Release((IFont *)this);
2297 }
2298
2299 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2300    IPersistStreamInit *iface, CLSID *classid
2301 ) {
2302   FIXME("(%p,%p), stub!\n", iface, classid);
2303   return E_FAIL;
2304 }
2305
2306 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2307    IPersistStreamInit *iface
2308 ) {
2309   FIXME("(%p), stub!\n", iface);
2310   return E_FAIL;
2311 }
2312
2313 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2314    IPersistStreamInit *iface, LPSTREAM pStm
2315 ) {
2316   FIXME("(%p,%p), stub!\n", iface, pStm);
2317   return E_FAIL;
2318 }
2319
2320 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2321    IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2322 ) {
2323   FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2324   return E_FAIL;
2325 }
2326
2327 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2328    IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2329 ) {
2330   FIXME("(%p,%p), stub!\n", iface, pcbSize);
2331   return E_FAIL;
2332 }
2333
2334 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2335    IPersistStreamInit *iface
2336 ) {
2337   FIXME("(%p), stub!\n", iface);
2338   return S_OK;
2339 }
2340
2341 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
2342 {
2343   OLEFontImpl_IPersistStreamInit_QueryInterface,
2344   OLEFontImpl_IPersistStreamInit_AddRef,
2345   OLEFontImpl_IPersistStreamInit_Release,
2346
2347   OLEFontImpl_IPersistStreamInit_GetClassID,
2348   OLEFontImpl_IPersistStreamInit_IsDirty,
2349   OLEFontImpl_IPersistStreamInit_Load,
2350   OLEFontImpl_IPersistStreamInit_Save,
2351   OLEFontImpl_IPersistStreamInit_GetSizeMax,
2352   OLEFontImpl_IPersistStreamInit_InitNew
2353 };
2354
2355 /************************************************************************
2356  * OLEFontImpl_Construct
2357  *
2358  * This method will construct a new instance of the OLEFontImpl
2359  * class.
2360  *
2361  * The caller of this method must release the object when it's
2362  * done with it.
2363  */
2364 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
2365 {
2366   OLEFontImpl* newObject = 0;
2367
2368   /*
2369    * Allocate space for the object.
2370    */
2371   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
2372
2373   if (newObject==0)
2374     return newObject;
2375
2376   /*
2377    * Initialize the virtual function table.
2378    */
2379   newObject->lpVtbl = &OLEFontImpl_VTable;
2380   newObject->lpvtblIDispatch = &OLEFontImpl_IDispatch_VTable;
2381   newObject->lpvtblIPersistStream = &OLEFontImpl_IPersistStream_VTable;
2382   newObject->lpvtblIConnectionPointContainer = &OLEFontImpl_IConnectionPointContainer_VTable;
2383   newObject->lpvtblIPersistPropertyBag = &OLEFontImpl_IPersistPropertyBag_VTable;
2384   newObject->lpvtblIPersistStreamInit = &OLEFontImpl_IPersistStreamInit_VTable;
2385
2386   /*
2387    * Start with one reference count. The caller of this function
2388    * must release the interface pointer when it is done.
2389    */
2390   newObject->ref = 1;
2391
2392   /*
2393    * Copy the description of the font in the object.
2394    */
2395   assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
2396
2397   newObject->description.cbSizeofstruct = sizeof(FONTDESC);
2398   newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
2399                                                0,
2400                                                (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
2401   strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
2402   newObject->description.cySize         = fontDesc->cySize;
2403   newObject->description.sWeight        = fontDesc->sWeight;
2404   newObject->description.sCharset       = fontDesc->sCharset;
2405   newObject->description.fItalic        = fontDesc->fItalic;
2406   newObject->description.fUnderline     = fontDesc->fUnderline;
2407   newObject->description.fStrikethrough = fontDesc->fStrikethrough;
2408
2409   /*
2410    * Initializing all the other members.
2411    */
2412   newObject->gdiFont  = 0;
2413   newObject->dirty = TRUE;
2414   newObject->cyLogical  = 72L;
2415   newObject->cyHimetric = 2540L;
2416   newObject->pPropertyNotifyCP = NULL;
2417   newObject->pFontEventsCP = NULL;
2418
2419   CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
2420   CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
2421
2422   if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
2423   {
2424     OLEFontImpl_Destroy(newObject);
2425     return NULL;
2426   }
2427
2428   InterlockedIncrement(&ifont_cnt);
2429
2430   TRACE("returning %p\n", newObject);
2431   return newObject;
2432 }
2433
2434 /************************************************************************
2435  * OLEFontImpl_Destroy
2436  *
2437  * This method is called by the Release method when the reference
2438  * count goes down to 0. It will free all resources used by
2439  * this object.
2440  */
2441 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
2442 {
2443   TRACE("(%p)\n", fontDesc);
2444
2445   HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
2446
2447   if (fontDesc->pPropertyNotifyCP)
2448       IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
2449   if (fontDesc->pFontEventsCP)
2450       IConnectionPoint_Release(fontDesc->pFontEventsCP);
2451
2452   HeapFree(GetProcessHeap(), 0, fontDesc);
2453 }
2454
2455 /*******************************************************************************
2456  * StdFont ClassFactory
2457  */
2458 typedef struct
2459 {
2460     /* IUnknown fields */
2461     const IClassFactoryVtbl    *lpVtbl;
2462     LONG                        ref;
2463 } IClassFactoryImpl;
2464
2465 static HRESULT WINAPI
2466 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2467         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2468
2469         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2470         return E_NOINTERFACE;
2471 }
2472
2473 static ULONG WINAPI
2474 SFCF_AddRef(LPCLASSFACTORY iface) {
2475         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2476         return InterlockedIncrement(&This->ref);
2477 }
2478
2479 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2480         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2481         /* static class, won't be  freed */
2482         return InterlockedDecrement(&This->ref);
2483 }
2484
2485 static HRESULT WINAPI SFCF_CreateInstance(
2486         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2487 ) {
2488         return OleCreateFontIndirect(NULL,riid,ppobj);
2489
2490 }
2491
2492 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2493         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2494         FIXME("(%p)->(%d),stub!\n",This,dolock);
2495         return S_OK;
2496 }
2497
2498 static const IClassFactoryVtbl SFCF_Vtbl = {
2499         SFCF_QueryInterface,
2500         SFCF_AddRef,
2501         SFCF_Release,
2502         SFCF_CreateInstance,
2503         SFCF_LockServer
2504 };
2505 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2506
2507 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }