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