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