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