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