oleaut32: Fixed compiler warning.
[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   FIXME("(%p)->(%p): Stub\n", this, pctinfo);
1303
1304   return E_NOTIMPL;
1305 }
1306
1307 /************************************************************************
1308  * OLEFontImpl_GetTypeInfo (IDispatch)
1309  *
1310  * See Windows documentation for more details on IDispatch methods.
1311  */
1312 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1313   IDispatch*  iface,
1314   UINT      iTInfo,
1315   LCID        lcid,
1316   ITypeInfo** ppTInfo)
1317 {
1318   static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1319   ITypeLib *tl;
1320   HRESULT hres;
1321
1322   OLEFontImpl *this = impl_from_IDispatch(iface);
1323   TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1324   if (iTInfo != 0)
1325     return E_FAIL;
1326   hres = LoadTypeLib(stdole2tlb, &tl);
1327   if (FAILED(hres)) {
1328     ERR("Could not load the stdole2.tlb?\n");
1329     return hres;
1330   }
1331   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
1332   if (FAILED(hres)) {
1333     FIXME("Did not IDispatch typeinfo from typelib, hres %lx\n",hres);
1334   }
1335   return hres;
1336 }
1337
1338 /************************************************************************
1339  * OLEFontImpl_GetIDsOfNames (IDispatch)
1340  *
1341  * See Windows documentation for more details on IDispatch methods.
1342  */
1343 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1344   IDispatch*  iface,
1345   REFIID      riid,
1346   LPOLESTR* rgszNames,
1347   UINT      cNames,
1348   LCID        lcid,
1349   DISPID*     rgDispId)
1350 {
1351   ITypeInfo * pTInfo;
1352   HRESULT hres;
1353
1354   OLEFontImpl *this = impl_from_IDispatch(iface);
1355
1356   TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
1357         rgszNames, cNames, (int)lcid, rgDispId);
1358
1359   if (cNames == 0)
1360   {
1361     return E_INVALIDARG;
1362   }
1363   else
1364   {
1365     /* retrieve type information */
1366     hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1367
1368     if (FAILED(hres))
1369     {
1370       ERR("GetTypeInfo failed.\n");
1371       return hres;
1372     }
1373
1374     /* convert names to DISPIDs */
1375     hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1376     ITypeInfo_Release(pTInfo);
1377
1378     return hres;
1379   }
1380 }
1381
1382 /************************************************************************
1383  * OLEFontImpl_Invoke (IDispatch)
1384  *
1385  * See Windows documentation for more details on IDispatch methods.
1386  * 
1387  * Note: Do not call _put_Xxx methods, since setting things here
1388  * should not call notify functions as I found out debugging the generic
1389  * MS VB5 installer.
1390  */
1391 static HRESULT WINAPI OLEFontImpl_Invoke(
1392   IDispatch*  iface,
1393   DISPID      dispIdMember,
1394   REFIID      riid,
1395   LCID        lcid,
1396   WORD        wFlags,
1397   DISPPARAMS* pDispParams,
1398   VARIANT*    pVarResult,
1399   EXCEPINFO*  pExepInfo,
1400   UINT*     puArgErr)
1401 {
1402   OLEFontImpl *this = impl_from_IDispatch(iface);
1403   HRESULT hr;
1404
1405   /* validate parameters */
1406
1407   if (!IsEqualIID(riid, &IID_NULL))
1408   {
1409     ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1410     return DISP_E_UNKNOWNINTERFACE;
1411   }
1412
1413   if (wFlags & DISPATCH_PROPERTYGET)
1414   {
1415     if (!pVarResult)
1416     {
1417       ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
1418       return DISP_E_PARAMNOTOPTIONAL;
1419     }
1420   }
1421   else if (wFlags & DISPATCH_PROPERTYPUT)
1422   {
1423     if (!pDispParams)
1424     {
1425       ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
1426       return DISP_E_PARAMNOTOPTIONAL;
1427     }
1428     if (pDispParams->cArgs != 1)
1429     {
1430       ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
1431       return DISP_E_BADPARAMCOUNT;
1432     }
1433   }
1434   else
1435   {
1436     ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
1437     return DISP_E_MEMBERNOTFOUND;
1438   }
1439
1440   switch (dispIdMember) {
1441   case DISPID_FONT_NAME:
1442     if (wFlags & DISPATCH_PROPERTYGET) {
1443       V_VT(pVarResult) = VT_BSTR;
1444       return IFont_get_Name((IFont *)this, &V_BSTR(pVarResult));
1445     } else {
1446       VARIANTARG vararg;
1447
1448       VariantInit(&vararg);
1449       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
1450       if (FAILED(hr))
1451         return hr;
1452
1453       hr = IFont_put_Name((IFont *)this, V_BSTR(&vararg));
1454
1455       VariantClear(&vararg);
1456       return hr;
1457     }
1458     break;
1459   case DISPID_FONT_BOLD:
1460     if (wFlags & DISPATCH_PROPERTYGET) {
1461       BOOL value;
1462       hr = IFont_get_Bold((IFont *)this, &value);
1463       V_VT(pVarResult) = VT_BOOL;
1464       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1465       return hr;
1466     } else {
1467       VARIANTARG vararg;
1468
1469       VariantInit(&vararg);
1470       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1471       if (FAILED(hr))
1472         return hr;
1473
1474       hr = IFont_put_Bold((IFont *)this, V_BOOL(&vararg));
1475
1476       VariantClear(&vararg);
1477       return hr;
1478     }
1479     break;
1480   case DISPID_FONT_ITALIC:
1481     if (wFlags & DISPATCH_PROPERTYGET) {
1482       BOOL value;
1483       hr = IFont_get_Italic((IFont *)this, &value);
1484       V_VT(pVarResult) = VT_BOOL;
1485       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1486       return hr;
1487     } else {
1488       VARIANTARG vararg;
1489       HRESULT hr;
1490
1491       VariantInit(&vararg);
1492       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1493       if (FAILED(hr))
1494         return hr;
1495
1496       hr = IFont_put_Italic((IFont *)this, V_BOOL(&vararg));
1497
1498       VariantClear(&vararg);
1499       return hr;
1500     }
1501     break;
1502   case DISPID_FONT_UNDER:
1503     if (wFlags & DISPATCH_PROPERTYGET) {
1504       BOOL value;
1505       hr = IFont_get_Underline((IFont *)this, &value);
1506       V_VT(pVarResult) = VT_BOOL;
1507       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1508       return hr;
1509     } else {
1510       VARIANTARG vararg;
1511       HRESULT hr;
1512
1513       VariantInit(&vararg);
1514       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1515       if (FAILED(hr))
1516         return hr;
1517
1518       hr = IFont_put_Underline((IFont *)this, V_BOOL(&vararg));
1519
1520       VariantClear(&vararg);
1521       return hr;
1522     }
1523     break;
1524   case DISPID_FONT_STRIKE:
1525     if (wFlags & DISPATCH_PROPERTYGET) {
1526       BOOL value;
1527       hr = IFont_get_Strikethrough((IFont *)this, &value);
1528       V_VT(pVarResult) = VT_BOOL;
1529       V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1530       return hr;
1531     } else {
1532       VARIANTARG vararg;
1533       HRESULT hr;
1534
1535       VariantInit(&vararg);
1536       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1537       if (FAILED(hr))
1538         return hr;
1539
1540       hr = IFont_put_Strikethrough((IFont *)this, V_BOOL(&vararg));
1541
1542       VariantClear(&vararg);
1543       return hr;
1544     }
1545     break;
1546   case DISPID_FONT_SIZE:
1547     if (wFlags & DISPATCH_PROPERTYGET) {
1548       V_VT(pVarResult) = VT_CY;
1549       return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
1550     } else {
1551       VARIANTARG vararg;
1552       HRESULT hr;
1553
1554       VariantInit(&vararg);
1555       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
1556       if (FAILED(hr))
1557         return hr;
1558
1559       hr = IFont_put_Size((IFont *)this, V_CY(&vararg));
1560
1561       VariantClear(&vararg);
1562       return hr;
1563     }
1564     break;
1565   case DISPID_FONT_CHARSET:
1566     if (wFlags & DISPATCH_PROPERTYGET) {
1567       V_VT(pVarResult) = VT_I2;
1568       return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
1569     } else {
1570       VARIANTARG vararg;
1571       HRESULT hr;
1572
1573       VariantInit(&vararg);
1574       hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1575       if (FAILED(hr))
1576         return hr;
1577
1578       hr = IFont_put_Charset((IFont *)this, V_I2(&vararg));
1579
1580       VariantClear(&vararg);
1581       return hr;
1582     }
1583     break;
1584   }
1585   FIXME("%p->(%ld,%s,%lx,%x,%p,%p,%p,%p), unhandled dispid/flag!\n",
1586     this,dispIdMember,debugstr_guid(riid),lcid,
1587     wFlags,pDispParams,pVarResult,pExepInfo,puArgErr
1588   );
1589   return S_OK;
1590 }
1591
1592 /************************************************************************
1593  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1594  *
1595  * See Windows documentation for more details on IUnknown methods.
1596  */
1597 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1598   IPersistStream* iface,
1599   REFIID     riid,
1600   VOID**     ppvoid)
1601 {
1602   OLEFontImpl *this = impl_from_IPersistStream(iface);
1603
1604   return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1605 }
1606
1607 /************************************************************************
1608  * OLEFontImpl_IPersistStream_Release (IUnknown)
1609  *
1610  * See Windows documentation for more details on IUnknown methods.
1611  */
1612 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1613   IPersistStream* iface)
1614 {
1615   OLEFontImpl *this = impl_from_IPersistStream(iface);
1616
1617   return IFont_Release((IFont *)this);
1618 }
1619
1620 /************************************************************************
1621  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1622  *
1623  * See Windows documentation for more details on IUnknown methods.
1624  */
1625 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1626   IPersistStream* iface)
1627 {
1628   OLEFontImpl *this = impl_from_IPersistStream(iface);
1629
1630   return IFont_AddRef((IFont *)this);
1631 }
1632
1633 /************************************************************************
1634  * OLEFontImpl_GetClassID (IPersistStream)
1635  *
1636  * See Windows documentation for more details on IPersistStream methods.
1637  */
1638 static HRESULT WINAPI OLEFontImpl_GetClassID(
1639   IPersistStream* iface,
1640   CLSID*                pClassID)
1641 {
1642   TRACE("(%p,%p)\n",iface,pClassID);
1643   if (pClassID==0)
1644     return E_POINTER;
1645
1646   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1647
1648   return S_OK;
1649 }
1650
1651 /************************************************************************
1652  * OLEFontImpl_IsDirty (IPersistStream)
1653  *
1654  * See Windows documentation for more details on IPersistStream methods.
1655  */
1656 static HRESULT WINAPI OLEFontImpl_IsDirty(
1657   IPersistStream*  iface)
1658 {
1659   TRACE("(%p)\n",iface);
1660   return S_OK;
1661 }
1662
1663 /************************************************************************
1664  * OLEFontImpl_Load (IPersistStream)
1665  *
1666  * See Windows documentation for more details on IPersistStream methods.
1667  *
1668  * This is the format of the standard font serialization as far as I
1669  * know
1670  *
1671  * Offset   Type   Value           Comment
1672  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1673  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1674  * 0x0003   Byte   Attributes      Flags defined as follows:
1675  *                                     00000010 - Italic
1676  *                                     00000100 - Underline
1677  *                                     00001000 - Strikethrough
1678  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1679  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1680  *                                 structure/
1681  * 0x000A   Byte   name length     Length of the font name string (no null character)
1682  * 0x000B   String name            Name of the font (ASCII, no nul character)
1683  */
1684 static HRESULT WINAPI OLEFontImpl_Load(
1685   IPersistStream*  iface,
1686   IStream*         pLoadStream)
1687 {
1688   char  readBuffer[0x100];
1689   ULONG cbRead;
1690   BYTE  bVersion;
1691   BYTE  bAttributes;
1692   BYTE  bStringSize;
1693   INT len;
1694
1695   OLEFontImpl *this = impl_from_IPersistStream(iface);
1696
1697   /*
1698    * Read the version byte
1699    */
1700   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1701
1702   if ( (cbRead!=1) ||
1703        (bVersion!=0x01) )
1704     return E_FAIL;
1705
1706   /*
1707    * Charset
1708    */
1709   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1710
1711   if (cbRead!=2)
1712     return E_FAIL;
1713
1714   /*
1715    * Attributes
1716    */
1717   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1718
1719   if (cbRead!=1)
1720     return E_FAIL;
1721
1722   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1723   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1724   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1725
1726   /*
1727    * Weight
1728    */
1729   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1730
1731   if (cbRead!=2)
1732     return E_FAIL;
1733
1734   /*
1735    * Size
1736    */
1737   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1738
1739   if (cbRead!=4)
1740     return E_FAIL;
1741
1742   this->description.cySize.s.Hi = 0;
1743
1744   /*
1745    * FontName
1746    */
1747   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1748
1749   if (cbRead!=1)
1750     return E_FAIL;
1751
1752   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1753
1754   if (cbRead!=bStringSize)
1755     return E_FAIL;
1756
1757   HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1758
1759   len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1760   this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1761   MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1762   this->description.lpstrName[len] = 0;
1763
1764   /* Ensure use of this font causes a new one to be created @@@@ */
1765   DeleteObject(this->gdiFont);
1766   this->gdiFont = 0;
1767
1768   return S_OK;
1769 }
1770
1771 /************************************************************************
1772  * OLEFontImpl_Save (IPersistStream)
1773  *
1774  * See Windows documentation for more details on IPersistStream methods.
1775  */
1776 static HRESULT WINAPI OLEFontImpl_Save(
1777   IPersistStream*  iface,
1778   IStream*         pOutStream,
1779   BOOL             fClearDirty)
1780 {
1781   char* writeBuffer = NULL;
1782   ULONG cbWritten;
1783   BYTE  bVersion = 0x01;
1784   BYTE  bAttributes;
1785   BYTE  bStringSize;
1786
1787   OLEFontImpl *this = impl_from_IPersistStream(iface);
1788
1789   /*
1790    * Read the version byte
1791    */
1792   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1793
1794   if (cbWritten!=1)
1795     return E_FAIL;
1796
1797   /*
1798    * Charset
1799    */
1800   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1801
1802   if (cbWritten!=2)
1803     return E_FAIL;
1804
1805   /*
1806    * Attributes
1807    */
1808   bAttributes = 0;
1809
1810   if (this->description.fItalic)
1811     bAttributes |= FONTPERSIST_ITALIC;
1812
1813   if (this->description.fStrikethrough)
1814     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1815
1816   if (this->description.fUnderline)
1817     bAttributes |= FONTPERSIST_UNDERLINE;
1818
1819   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1820
1821   if (cbWritten!=1)
1822     return E_FAIL;
1823
1824   /*
1825    * Weight
1826    */
1827   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1828
1829   if (cbWritten!=2)
1830     return E_FAIL;
1831
1832   /*
1833    * Size
1834    */
1835   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1836
1837   if (cbWritten!=4)
1838     return E_FAIL;
1839
1840   /*
1841    * FontName
1842    */
1843   if (this->description.lpstrName!=0)
1844     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1845                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1846   else
1847     bStringSize = 0;
1848
1849   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1850
1851   if (cbWritten!=1)
1852     return E_FAIL;
1853
1854   if (bStringSize!=0)
1855   {
1856       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1857       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1858                            strlenW(this->description.lpstrName),
1859                            writeBuffer, bStringSize, NULL, NULL );
1860
1861     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1862     HeapFree(GetProcessHeap(), 0, writeBuffer);
1863
1864     if (cbWritten!=bStringSize)
1865       return E_FAIL;
1866   }
1867
1868   return S_OK;
1869 }
1870
1871 /************************************************************************
1872  * OLEFontImpl_GetSizeMax (IPersistStream)
1873  *
1874  * See Windows documentation for more details on IPersistStream methods.
1875  */
1876 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1877   IPersistStream*  iface,
1878   ULARGE_INTEGER*  pcbSize)
1879 {
1880   OLEFontImpl *this = impl_from_IPersistStream(iface);
1881
1882   if (pcbSize==NULL)
1883     return E_POINTER;
1884
1885   pcbSize->u.HighPart = 0;
1886   pcbSize->u.LowPart = 0;
1887
1888   pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
1889   pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
1890   pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
1891   pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
1892   pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1893   pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
1894
1895   if (this->description.lpstrName!=0)
1896     pcbSize->u.LowPart += lstrlenW(this->description.lpstrName);
1897
1898   return S_OK;
1899 }
1900
1901 /************************************************************************
1902  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1903  *
1904  * See Windows documentation for more details on IUnknown methods.
1905  */
1906 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1907   IConnectionPointContainer* iface,
1908   REFIID     riid,
1909   VOID**     ppvoid)
1910 {
1911   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1912
1913   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
1914 }
1915
1916 /************************************************************************
1917  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
1918  *
1919  * See Windows documentation for more details on IUnknown methods.
1920  */
1921 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
1922   IConnectionPointContainer* iface)
1923 {
1924   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1925
1926   return IFont_Release((IFont*)this);
1927 }
1928
1929 /************************************************************************
1930  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
1931  *
1932  * See Windows documentation for more details on IUnknown methods.
1933  */
1934 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
1935   IConnectionPointContainer* iface)
1936 {
1937   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1938
1939   return IFont_AddRef((IFont*)this);
1940 }
1941
1942 /************************************************************************
1943  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
1944  *
1945  * See Windows documentation for more details on IConnectionPointContainer
1946  * methods.
1947  */
1948 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
1949   IConnectionPointContainer* iface,
1950   IEnumConnectionPoints **ppEnum)
1951 {
1952   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1953
1954   FIXME("(%p)->(%p): stub\n", this, ppEnum);
1955   return E_NOTIMPL;
1956 }
1957
1958 /************************************************************************
1959  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
1960  *
1961  * See Windows documentation for more details on IConnectionPointContainer
1962  * methods.
1963  */
1964 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
1965    IConnectionPointContainer* iface,
1966    REFIID riid,
1967    IConnectionPoint **ppCp)
1968 {
1969   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1970   TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
1971
1972   if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
1973     return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
1974                                            &IID_IConnectionPoint,
1975                                            (LPVOID)ppCp);
1976   } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
1977     return IConnectionPoint_QueryInterface(this->pFontEventsCP,
1978                                            &IID_IConnectionPoint,
1979                                            (LPVOID)ppCp);
1980   } else {
1981     FIXME("no connection point for %s\n", debugstr_guid(riid));
1982     return CONNECT_E_NOCONNECTION;
1983   }
1984 }
1985
1986 /************************************************************************
1987  * OLEFontImpl implementation of IPersistPropertyBag.
1988  */
1989 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
1990    IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
1991 ) {
1992   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1993   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
1994 }
1995
1996 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
1997    IPersistPropertyBag *iface
1998 ) {
1999   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2000   return IFont_AddRef((IFont *)this);
2001 }
2002
2003 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
2004    IPersistPropertyBag *iface
2005 ) {
2006   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2007   return IFont_Release((IFont *)this);
2008 }
2009
2010 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
2011    IPersistPropertyBag *iface, CLSID *classid
2012 ) {
2013   FIXME("(%p,%p), stub!\n", iface, classid);
2014   return E_FAIL;
2015 }
2016
2017 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
2018    IPersistPropertyBag *iface
2019 ) {
2020   FIXME("(%p), stub!\n", iface);
2021   return S_OK;
2022 }
2023
2024 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
2025    IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
2026 ) {
2027 /* (from Visual Basic 6 property bag)
2028          Name            =   "MS Sans Serif"
2029          Size            =   13.8
2030          Charset         =   0
2031          Weight          =   400
2032          Underline       =   0   'False
2033          Italic          =   0   'False
2034          Strikethrough   =   0   'False
2035 */
2036     static const WCHAR sAttrName[] = {'N','a','m','e',0};
2037     static const WCHAR sAttrSize[] = {'S','i','z','e',0};
2038     static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
2039     static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
2040     static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
2041     static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
2042     static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
2043     VARIANT rawAttr;
2044     VARIANT valueAttr;
2045     HRESULT iRes = S_OK;
2046     OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2047
2048     VariantInit(&rawAttr);
2049     VariantInit(&valueAttr);
2050
2051     if (iRes == S_OK) {
2052         iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
2053         if (iRes == S_OK)
2054         {
2055             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
2056             if (iRes == S_OK)
2057                 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
2058         }
2059         else if (iRes == E_INVALIDARG)
2060             iRes = S_OK;
2061         VariantClear(&rawAttr);
2062         VariantClear(&valueAttr);
2063     }
2064
2065     if (iRes == S_OK) {
2066         iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
2067         if (iRes == S_OK)
2068         {
2069             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
2070             if (iRes == S_OK)
2071                 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
2072         }
2073         else if (iRes == E_INVALIDARG)
2074             iRes = S_OK;
2075         VariantClear(&rawAttr);
2076         VariantClear(&valueAttr);
2077     }
2078
2079     if (iRes == S_OK) {
2080         iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
2081         if (iRes == S_OK)
2082         {
2083             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2084             if (iRes == S_OK)
2085                 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
2086         }
2087         else if (iRes == E_INVALIDARG)
2088             iRes = S_OK;
2089         VariantClear(&rawAttr);
2090         VariantClear(&valueAttr);
2091     }
2092
2093     if (iRes == S_OK) {
2094         iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
2095         if (iRes == S_OK)
2096         {
2097             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2098             if (iRes == S_OK)
2099                 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
2100         }
2101         else if (iRes == E_INVALIDARG)
2102             iRes = S_OK;
2103         VariantClear(&rawAttr);
2104         VariantClear(&valueAttr);
2105
2106     }
2107
2108     if (iRes == S_OK) {
2109         iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
2110         if (iRes == S_OK)
2111         {
2112             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2113             if (iRes == S_OK)
2114                 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
2115         }
2116         else if (iRes == E_INVALIDARG)
2117             iRes = S_OK;
2118         VariantClear(&rawAttr);
2119         VariantClear(&valueAttr);
2120     }
2121
2122     if (iRes == S_OK) {
2123         iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
2124         if (iRes == S_OK)
2125         {
2126             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2127             if (iRes == S_OK)
2128                 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
2129         }
2130         else if (iRes == E_INVALIDARG)
2131             iRes = S_OK;
2132         VariantClear(&rawAttr);
2133         VariantClear(&valueAttr);
2134     }
2135
2136     if (iRes == S_OK) {
2137         iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
2138         if (iRes == S_OK)
2139         {
2140             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2141             if (iRes == S_OK)
2142                 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
2143         }
2144         else if (iRes == E_INVALIDARG)
2145             iRes = S_OK;
2146         VariantClear(&rawAttr);
2147         VariantClear(&valueAttr);
2148     }
2149
2150     if (FAILED(iRes))
2151         WARN("-- 0x%08lx\n", iRes);
2152     return iRes;
2153 }
2154
2155 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2156    IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2157    BOOL fSaveAllProperties
2158 ) {
2159   FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2160   return E_FAIL;
2161 }
2162
2163 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
2164 {
2165   OLEFontImpl_IPersistPropertyBag_QueryInterface,
2166   OLEFontImpl_IPersistPropertyBag_AddRef,
2167   OLEFontImpl_IPersistPropertyBag_Release,
2168
2169   OLEFontImpl_IPersistPropertyBag_GetClassID,
2170   OLEFontImpl_IPersistPropertyBag_InitNew,
2171   OLEFontImpl_IPersistPropertyBag_Load,
2172   OLEFontImpl_IPersistPropertyBag_Save
2173 };
2174
2175 /************************************************************************
2176  * OLEFontImpl implementation of IPersistStreamInit.
2177  */
2178 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2179    IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2180 ) {
2181   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2182   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2183 }
2184
2185 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2186    IPersistStreamInit *iface
2187 ) {
2188   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2189   return IFont_AddRef((IFont *)this);
2190 }
2191
2192 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2193    IPersistStreamInit *iface
2194 ) {
2195   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2196   return IFont_Release((IFont *)this);
2197 }
2198
2199 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2200    IPersistStreamInit *iface, CLSID *classid
2201 ) {
2202   FIXME("(%p,%p), stub!\n", iface, classid);
2203   return E_FAIL;
2204 }
2205
2206 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2207    IPersistStreamInit *iface
2208 ) {
2209   FIXME("(%p), stub!\n", iface);
2210   return E_FAIL;
2211 }
2212
2213 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2214    IPersistStreamInit *iface, LPSTREAM pStm
2215 ) {
2216   FIXME("(%p,%p), stub!\n", iface, pStm);
2217   return E_FAIL;
2218 }
2219
2220 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2221    IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2222 ) {
2223   FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2224   return E_FAIL;
2225 }
2226
2227 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2228    IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2229 ) {
2230   FIXME("(%p,%p), stub!\n", iface, pcbSize);
2231   return E_FAIL;
2232 }
2233
2234 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2235    IPersistStreamInit *iface
2236 ) {
2237   FIXME("(%p), stub!\n", iface);
2238   return S_OK;
2239 }
2240
2241 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
2242 {
2243   OLEFontImpl_IPersistStreamInit_QueryInterface,
2244   OLEFontImpl_IPersistStreamInit_AddRef,
2245   OLEFontImpl_IPersistStreamInit_Release,
2246
2247   OLEFontImpl_IPersistStreamInit_GetClassID,
2248   OLEFontImpl_IPersistStreamInit_IsDirty,
2249   OLEFontImpl_IPersistStreamInit_Load,
2250   OLEFontImpl_IPersistStreamInit_Save,
2251   OLEFontImpl_IPersistStreamInit_GetSizeMax,
2252   OLEFontImpl_IPersistStreamInit_InitNew
2253 };
2254
2255 /*******************************************************************************
2256  * StdFont ClassFactory
2257  */
2258 typedef struct
2259 {
2260     /* IUnknown fields */
2261     const IClassFactoryVtbl    *lpVtbl;
2262     LONG                        ref;
2263 } IClassFactoryImpl;
2264
2265 static HRESULT WINAPI
2266 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2267         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2268
2269         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2270         return E_NOINTERFACE;
2271 }
2272
2273 static ULONG WINAPI
2274 SFCF_AddRef(LPCLASSFACTORY iface) {
2275         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2276         return InterlockedIncrement(&This->ref);
2277 }
2278
2279 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2280         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2281         /* static class, won't be  freed */
2282         return InterlockedDecrement(&This->ref);
2283 }
2284
2285 static HRESULT WINAPI SFCF_CreateInstance(
2286         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2287 ) {
2288         return OleCreateFontIndirect(NULL,riid,ppobj);
2289
2290 }
2291
2292 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2293         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2294         FIXME("(%p)->(%d),stub!\n",This,dolock);
2295         return S_OK;
2296 }
2297
2298 static const IClassFactoryVtbl SFCF_Vtbl = {
2299         SFCF_QueryInterface,
2300         SFCF_AddRef,
2301         SFCF_Release,
2302         SFCF_CreateInstance,
2303         SFCF_LockServer
2304 };
2305 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2306
2307 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }