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