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