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