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