Unicodify wineesd.
[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     fontHeight = MulDiv( cySize.s.Lo, this->cyLogical, this->cyHimetric );
957
958     memset(&logFont, 0, sizeof(LOGFONTW));
959
960     logFont.lfHeight          = ((fontHeight%10000L)>5000L) ?   (-fontHeight/10000L)-1 :
961                                                                 (-fontHeight/10000L);
962     logFont.lfItalic          = this->description.fItalic;
963     logFont.lfUnderline       = this->description.fUnderline;
964     logFont.lfStrikeOut       = this->description.fStrikethrough;
965     logFont.lfWeight          = this->description.sWeight;
966     logFont.lfCharSet         = this->description.sCharset;
967     logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
968     logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
969     logFont.lfQuality         = DEFAULT_QUALITY;
970     logFont.lfPitchAndFamily  = DEFAULT_PITCH;
971     strcpyW(logFont.lfFaceName,this->description.lpstrName);
972
973     this->gdiFont = CreateFontIndirectW(&logFont);
974   }
975
976   *phfont = this->gdiFont;
977   TRACE("Returning %p\n", *phfont);
978   return S_OK;
979 }
980
981 /************************************************************************
982  * OLEFontImpl_Clone (IFont)
983  *
984  * See Windows documentation for more details on IFont methods.
985  */
986 static HRESULT WINAPI OLEFontImpl_Clone(
987   IFont*  iface,
988   IFont** ppfont)
989 {
990   OLEFontImpl* newObject = 0;
991   LOGFONTW logFont;
992   INT      fontHeight;
993   CY       cySize;
994   OLEFontImpl *this = (OLEFontImpl *)iface;
995   TRACE("(%p)->(%p)\n", this, ppfont);
996
997   if (ppfont == NULL)
998     return E_POINTER;
999
1000   *ppfont = NULL;
1001
1002   /*
1003    * Allocate space for the object.
1004    */
1005   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
1006
1007   if (newObject==NULL)
1008     return E_OUTOFMEMORY;
1009
1010   *newObject = *this;
1011
1012   /* We need to alloc new memory for the string, otherwise
1013    * we free memory twice.
1014    */
1015   newObject->description.lpstrName = HeapAlloc(
1016         GetProcessHeap(),0,
1017         (1+strlenW(this->description.lpstrName))*2
1018   );
1019   strcpyW(newObject->description.lpstrName, this->description.lpstrName);
1020   /* We need to clone the HFONT too. This is just cut & paste from above */
1021   IFont_get_Size(iface, &cySize);
1022
1023   fontHeight = MulDiv(cySize.s.Lo, this->cyLogical,this->cyHimetric);
1024
1025   memset(&logFont, 0, sizeof(LOGFONTW));
1026
1027   logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
1028                                                             (-fontHeight/10000L);
1029   logFont.lfItalic          = this->description.fItalic;
1030   logFont.lfUnderline       = this->description.fUnderline;
1031   logFont.lfStrikeOut       = this->description.fStrikethrough;
1032   logFont.lfWeight          = this->description.sWeight;
1033   logFont.lfCharSet         = this->description.sCharset;
1034   logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
1035   logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
1036   logFont.lfQuality         = DEFAULT_QUALITY;
1037   logFont.lfPitchAndFamily  = DEFAULT_PITCH;
1038   strcpyW(logFont.lfFaceName,this->description.lpstrName);
1039
1040   newObject->gdiFont = CreateFontIndirectW(&logFont);
1041
1042
1043   /* The cloned object starts with a reference count of 1 */
1044   newObject->ref          = 1;
1045
1046   *ppfont = (IFont*)newObject;
1047
1048   return S_OK;
1049 }
1050
1051 /************************************************************************
1052  * OLEFontImpl_IsEqual (IFont)
1053  *
1054  * See Windows documentation for more details on IFont methods.
1055  */
1056 static HRESULT WINAPI OLEFontImpl_IsEqual(
1057   IFont* iface,
1058   IFont* pFontOther)
1059 {
1060   FIXME("(%p, %p), stub!\n",iface,pFontOther);
1061   return E_NOTIMPL;
1062 }
1063
1064 /************************************************************************
1065  * OLEFontImpl_SetRatio (IFont)
1066  *
1067  * See Windows documentation for more details on IFont methods.
1068  */
1069 static HRESULT WINAPI OLEFontImpl_SetRatio(
1070   IFont* iface,
1071   LONG   cyLogical,
1072   LONG   cyHimetric)
1073 {
1074   OLEFontImpl *this = (OLEFontImpl *)iface;
1075   TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric);
1076
1077   this->cyLogical  = cyLogical;
1078   this->cyHimetric = cyHimetric;
1079
1080   return S_OK;
1081 }
1082
1083 /************************************************************************
1084  * OLEFontImpl_QueryTextMetrics (IFont)
1085  *
1086  * See Windows documentation for more details on IFont methods.
1087  */
1088 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
1089   IFont*         iface,
1090   TEXTMETRICOLE* ptm)
1091 {
1092   HDC hdcRef;
1093   HFONT hOldFont, hNewFont;
1094
1095   hdcRef = GetDC(0);
1096   OLEFontImpl_get_hFont(iface, &hNewFont);
1097   hOldFont = SelectObject(hdcRef, hNewFont);
1098   GetTextMetricsW(hdcRef, ptm);
1099   SelectObject(hdcRef, hOldFont);
1100   ReleaseDC(0, hdcRef);
1101   return S_OK;
1102 }
1103
1104 /************************************************************************
1105  * OLEFontImpl_AddRefHfont (IFont)
1106  *
1107  * See Windows documentation for more details on IFont methods.
1108  */
1109 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1110   IFont*  iface,
1111   HFONT hfont)
1112 {
1113   OLEFontImpl *this = (OLEFontImpl *)iface;
1114   TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
1115
1116   if ( (hfont == 0) ||
1117        (hfont != this->gdiFont) )
1118     return E_INVALIDARG;
1119
1120   this->fontLock++;
1121
1122   return S_OK;
1123 }
1124
1125 /************************************************************************
1126  * OLEFontImpl_ReleaseHfont (IFont)
1127  *
1128  * See Windows documentation for more details on IFont methods.
1129  */
1130 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1131   IFont*  iface,
1132   HFONT hfont)
1133 {
1134   OLEFontImpl *this = (OLEFontImpl *)iface;
1135   TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
1136
1137   if ( (hfont == 0) ||
1138        (hfont != this->gdiFont) )
1139     return E_INVALIDARG;
1140
1141   this->fontLock--;
1142
1143   /*
1144    * If we just released our last font reference, destroy it.
1145    */
1146   if (this->fontLock==0)
1147   {
1148     DeleteObject(this->gdiFont);
1149     this->gdiFont = 0;
1150   }
1151
1152   return S_OK;
1153 }
1154
1155 /************************************************************************
1156  * OLEFontImpl_SetHdc (IFont)
1157  *
1158  * See Windows documentation for more details on IFont methods.
1159  */
1160 static HRESULT WINAPI OLEFontImpl_SetHdc(
1161   IFont* iface,
1162   HDC  hdc)
1163 {
1164   OLEFontImpl *this = (OLEFontImpl *)iface;
1165   FIXME("(%p)->(%p): Stub\n", this, hdc);
1166   return E_NOTIMPL;
1167 }
1168
1169 /************************************************************************
1170  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1171  *
1172  * See Windows documentation for more details on IUnknown methods.
1173  */
1174 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1175   IDispatch* iface,
1176   REFIID     riid,
1177   VOID**     ppvoid)
1178 {
1179   OLEFontImpl *this = impl_from_IDispatch(iface);
1180
1181   return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1182 }
1183
1184 /************************************************************************
1185  * OLEFontImpl_IDispatch_Release (IUnknown)
1186  *
1187  * See Windows documentation for more details on IUnknown methods.
1188  */
1189 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1190   IDispatch* iface)
1191 {
1192   OLEFontImpl *this = impl_from_IDispatch(iface);
1193
1194   return IFont_Release((IFont *)this);
1195 }
1196
1197 /************************************************************************
1198  * OLEFontImpl_IDispatch_AddRef (IUnknown)
1199  *
1200  * See Windows documentation for more details on IUnknown methods.
1201  */
1202 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1203   IDispatch* iface)
1204 {
1205   OLEFontImpl *this = impl_from_IDispatch(iface);
1206
1207   return IFont_AddRef((IFont *)this);
1208 }
1209
1210 /************************************************************************
1211  * OLEFontImpl_GetTypeInfoCount (IDispatch)
1212  *
1213  * See Windows documentation for more details on IDispatch methods.
1214  */
1215 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1216   IDispatch*    iface,
1217   unsigned int* pctinfo)
1218 {
1219   OLEFontImpl *this = impl_from_IDispatch(iface);
1220   FIXME("(%p)->(%p): Stub\n", this, pctinfo);
1221
1222   return E_NOTIMPL;
1223 }
1224
1225 /************************************************************************
1226  * OLEFontImpl_GetTypeInfo (IDispatch)
1227  *
1228  * See Windows documentation for more details on IDispatch methods.
1229  */
1230 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1231   IDispatch*  iface,
1232   UINT      iTInfo,
1233   LCID        lcid,
1234   ITypeInfo** ppTInfo)
1235 {
1236   static const WCHAR stdole32tlb[] = {'s','t','d','o','l','e','3','2','.','t','l','b',0};
1237   ITypeLib *tl;
1238   HRESULT hres;
1239
1240   OLEFontImpl *this = impl_from_IDispatch(iface);
1241   TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1242   if (iTInfo != 0)
1243     return E_FAIL;
1244   hres = LoadTypeLib(stdole32tlb, &tl);
1245   if (FAILED(hres)) {
1246     ERR("Could not load the stdole32.tlb?\n");
1247     return hres;
1248   }
1249   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IDispatch, ppTInfo);
1250   if (FAILED(hres)) {
1251     FIXME("Did not IDispatch typeinfo from typelib, hres %lx\n",hres);
1252   }
1253   return hres;
1254 }
1255
1256 /************************************************************************
1257  * OLEFontImpl_GetIDsOfNames (IDispatch)
1258  *
1259  * See Windows documentation for more details on IDispatch methods.
1260  */
1261 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1262   IDispatch*  iface,
1263   REFIID      riid,
1264   LPOLESTR* rgszNames,
1265   UINT      cNames,
1266   LCID        lcid,
1267   DISPID*     rgDispId)
1268 {
1269   OLEFontImpl *this = impl_from_IDispatch(iface);
1270   FIXME("(%p,%s,%p,%d,%04x,%p), stub!\n", this, debugstr_guid(riid), rgszNames,
1271         cNames, (int)lcid, rgDispId
1272   );
1273   return E_NOTIMPL;
1274 }
1275
1276 /************************************************************************
1277  * OLEFontImpl_Invoke (IDispatch)
1278  *
1279  * See Windows documentation for more details on IDispatch methods.
1280  * 
1281  * Note: Do not call _put_Xxx methods, since setting things here
1282  * should not call notify functions as I found out debugging the generic
1283  * MS VB5 installer.
1284  */
1285 static HRESULT WINAPI OLEFontImpl_Invoke(
1286   IDispatch*  iface,
1287   DISPID      dispIdMember,
1288   REFIID      riid,
1289   LCID        lcid,
1290   WORD        wFlags,
1291   DISPPARAMS* pDispParams,
1292   VARIANT*    pVarResult,
1293   EXCEPINFO*  pExepInfo,
1294   UINT*     puArgErr)
1295 {
1296   OLEFontImpl *this = impl_from_IDispatch(iface);
1297   OLEFontImpl *xthis = (OLEFontImpl*)this;
1298
1299   switch (dispIdMember) {
1300   case DISPID_FONT_NAME:
1301     switch (wFlags) {
1302     case DISPATCH_PROPERTYGET:
1303     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1304       V_VT(pVarResult) = VT_BSTR;
1305       return OLEFontImpl_get_Name((IFont *)this, &V_BSTR(pVarResult));
1306     case DISPATCH_PROPERTYPUT: {
1307       BSTR name;
1308       BOOL freename;
1309       
1310       if (V_VT(&pDispParams->rgvarg[0]) == VT_DISPATCH) {
1311         IFont *font;
1312         HRESULT hr = S_OK;
1313         
1314         hr = IUnknown_QueryInterface(V_DISPATCH(&pDispParams->rgvarg[0]), &IID_IFont, (void **) &font);
1315         if (FAILED(hr))
1316         {
1317             FIXME("dispatch value for name property is not an OleFont, returning hr=0x%lx\n", hr);
1318             return hr;
1319         }
1320
1321         hr = IFont_get_Name(font, &name); /* this allocates a new BSTR so free it later */
1322         if (FAILED(hr)) return hr;
1323
1324         IUnknown_Release(font);
1325         
1326         freename = TRUE;
1327       } else if (V_VT(&pDispParams->rgvarg[0]) == VT_BSTR) {
1328         name = V_BSTR(&pDispParams->rgvarg[0]);
1329         freename = FALSE;
1330       } else {
1331         FIXME("app is trying to set name property with a non BSTR, non dispatch value. returning E_FAIL\n");
1332         return E_FAIL;
1333       }
1334
1335       TRACE("name is %s\n", debugstr_w(name));
1336       
1337       if (!xthis->description.lpstrName)
1338         xthis->description.lpstrName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1) * sizeof(WCHAR));
1339       else
1340         xthis->description.lpstrName = HeapReAlloc(GetProcessHeap(), 0, xthis->description.lpstrName, (lstrlenW(name)+1) * sizeof(WCHAR));
1341
1342       if (xthis->description.lpstrName==0)
1343         return E_OUTOFMEMORY;
1344       strcpyW(xthis->description.lpstrName, name);
1345
1346       if (freename) SysFreeString(name);
1347       
1348       return S_OK;
1349     }
1350     }
1351     break;
1352   case DISPID_FONT_BOLD:
1353     switch (wFlags) {
1354     case DISPATCH_PROPERTYGET:
1355     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1356       V_VT(pVarResult) = VT_BOOL;
1357       return OLEFontImpl_get_Bold((IFont *)this, (BOOL*)&V_BOOL(pVarResult));
1358     case DISPATCH_PROPERTYPUT:
1359       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1360         FIXME("DISPID_FONT_BOLD/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1361         return E_FAIL;
1362       } else {
1363         xthis->description.sWeight = V_BOOL(&pDispParams->rgvarg[0]) ? FW_BOLD : FW_NORMAL;
1364         return S_OK;
1365       }
1366     }
1367     break;
1368   case DISPID_FONT_ITALIC:
1369     switch (wFlags) {
1370     case DISPATCH_PROPERTYGET:
1371     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1372       V_VT(pVarResult) = VT_BOOL;
1373       return OLEFontImpl_get_Italic((IFont *)this, (BOOL*)&V_BOOL(pVarResult));
1374     case DISPATCH_PROPERTYPUT:
1375       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1376         FIXME("DISPID_FONT_ITALIC/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1377         return E_FAIL;
1378       } else {
1379         xthis->description.fItalic = V_BOOL(&pDispParams->rgvarg[0]);
1380         return S_OK;
1381       }
1382     }
1383     break;
1384   case DISPID_FONT_UNDER:
1385     switch (wFlags) {
1386     case DISPATCH_PROPERTYGET:
1387     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1388       V_VT(pVarResult) = VT_BOOL;
1389       return OLEFontImpl_get_Underline((IFont *)this, (BOOL*)&V_BOOL(pVarResult));
1390     case DISPATCH_PROPERTYPUT:
1391       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1392         FIXME("DISPID_FONT_UNDER/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1393         return E_FAIL;
1394       } else {
1395         xthis->description.fUnderline = V_BOOL(&pDispParams->rgvarg[0]);
1396         return S_OK;
1397       }
1398     }
1399     break;
1400   case DISPID_FONT_STRIKE:
1401     switch (wFlags) {
1402     case DISPATCH_PROPERTYGET:
1403     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1404       V_VT(pVarResult) = VT_BOOL;
1405       return OLEFontImpl_get_Strikethrough((IFont *)this, (BOOL*)&V_BOOL(pVarResult));
1406     case DISPATCH_PROPERTYPUT:
1407       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1408         FIXME("DISPID_FONT_STRIKE/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1409         return E_FAIL;
1410       } else {
1411         xthis->description.fStrikethrough = V_BOOL(&pDispParams->rgvarg[0]);
1412         return S_OK;
1413       }
1414     }
1415     break;
1416   case DISPID_FONT_SIZE:
1417     switch (wFlags) {
1418     case DISPATCH_PROPERTYPUT: {
1419       assert (pDispParams->cArgs == 1);
1420       xthis->description.cySize.s.Hi = 0;
1421       if (V_VT(&pDispParams->rgvarg[0]) != VT_CY) {
1422         if (V_VT(&pDispParams->rgvarg[0]) == VT_I2) {
1423           xthis->description.cySize.s.Lo = V_I2(&pDispParams->rgvarg[0]) * 10000;
1424         } else {
1425           FIXME("property put for Size with vt %d unsupported!\n",V_VT(&pDispParams->rgvarg[0]));
1426         }
1427       } else {
1428         xthis->description.cySize.s.Lo = V_CY(&pDispParams->rgvarg[0]).s.Lo;
1429       }
1430       return S_OK;
1431     }
1432     case DISPATCH_PROPERTYGET:
1433     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1434       V_VT(pVarResult) = VT_CY;
1435       return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
1436     }
1437     break;
1438   case DISPID_FONT_CHARSET:
1439     switch (wFlags) {
1440     case DISPATCH_PROPERTYPUT:
1441       assert (pDispParams->cArgs == 1);
1442       if (V_VT(&pDispParams->rgvarg[0]) != VT_I2)
1443         FIXME("varg of first disparg is not VT_I2, but %d\n",V_VT(&pDispParams->rgvarg[0]));
1444       xthis->description.sCharset = V_I2(&pDispParams->rgvarg[0]);
1445       return S_OK;
1446     case DISPATCH_PROPERTYGET:
1447     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1448       V_VT(pVarResult) = VT_I2;
1449       return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
1450     }
1451     break;
1452   }
1453   FIXME("%p->(%ld,%s,%lx,%x,%p,%p,%p,%p), unhandled dispid/flag!\n",
1454     this,dispIdMember,debugstr_guid(riid),lcid,
1455     wFlags,pDispParams,pVarResult,pExepInfo,puArgErr
1456   );
1457   return S_OK;
1458 }
1459
1460 /************************************************************************
1461  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1462  *
1463  * See Windows documentation for more details on IUnknown methods.
1464  */
1465 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1466   IPersistStream* iface,
1467   REFIID     riid,
1468   VOID**     ppvoid)
1469 {
1470   OLEFontImpl *this = impl_from_IPersistStream(iface);
1471
1472   return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1473 }
1474
1475 /************************************************************************
1476  * OLEFontImpl_IPersistStream_Release (IUnknown)
1477  *
1478  * See Windows documentation for more details on IUnknown methods.
1479  */
1480 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1481   IPersistStream* iface)
1482 {
1483   OLEFontImpl *this = impl_from_IPersistStream(iface);
1484
1485   return IFont_Release((IFont *)this);
1486 }
1487
1488 /************************************************************************
1489  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1490  *
1491  * See Windows documentation for more details on IUnknown methods.
1492  */
1493 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1494   IPersistStream* iface)
1495 {
1496   OLEFontImpl *this = impl_from_IPersistStream(iface);
1497
1498   return IFont_AddRef((IFont *)this);
1499 }
1500
1501 /************************************************************************
1502  * OLEFontImpl_GetClassID (IPersistStream)
1503  *
1504  * See Windows documentation for more details on IPersistStream methods.
1505  */
1506 static HRESULT WINAPI OLEFontImpl_GetClassID(
1507   IPersistStream* iface,
1508   CLSID*                pClassID)
1509 {
1510   TRACE("(%p,%p)\n",iface,pClassID);
1511   if (pClassID==0)
1512     return E_POINTER;
1513
1514   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1515
1516   return S_OK;
1517 }
1518
1519 /************************************************************************
1520  * OLEFontImpl_IsDirty (IPersistStream)
1521  *
1522  * See Windows documentation for more details on IPersistStream methods.
1523  */
1524 static HRESULT WINAPI OLEFontImpl_IsDirty(
1525   IPersistStream*  iface)
1526 {
1527   TRACE("(%p)\n",iface);
1528   return S_OK;
1529 }
1530
1531 /************************************************************************
1532  * OLEFontImpl_Load (IPersistStream)
1533  *
1534  * See Windows documentation for more details on IPersistStream methods.
1535  *
1536  * This is the format of the standard font serialization as far as I
1537  * know
1538  *
1539  * Offset   Type   Value           Comment
1540  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1541  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1542  * 0x0003   Byte   Attributes      Flags defined as follows:
1543  *                                     00000010 - Italic
1544  *                                     00000100 - Underline
1545  *                                     00001000 - Strikethrough
1546  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1547  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1548  *                                 structure/
1549  * 0x000A   Byte   name length     Length of the font name string (no null character)
1550  * 0x000B   String name            Name of the font (ASCII, no nul character)
1551  */
1552 static HRESULT WINAPI OLEFontImpl_Load(
1553   IPersistStream*  iface,
1554   IStream*         pLoadStream)
1555 {
1556   char  readBuffer[0x100];
1557   ULONG cbRead;
1558   BYTE  bVersion;
1559   BYTE  bAttributes;
1560   BYTE  bStringSize;
1561   INT len;
1562
1563   OLEFontImpl *this = impl_from_IPersistStream(iface);
1564
1565   /*
1566    * Read the version byte
1567    */
1568   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1569
1570   if ( (cbRead!=1) ||
1571        (bVersion!=0x01) )
1572     return E_FAIL;
1573
1574   /*
1575    * Charset
1576    */
1577   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1578
1579   if (cbRead!=2)
1580     return E_FAIL;
1581
1582   /*
1583    * Attributes
1584    */
1585   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1586
1587   if (cbRead!=1)
1588     return E_FAIL;
1589
1590   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1591   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1592   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1593
1594   /*
1595    * Weight
1596    */
1597   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1598
1599   if (cbRead!=2)
1600     return E_FAIL;
1601
1602   /*
1603    * Size
1604    */
1605   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1606
1607   if (cbRead!=4)
1608     return E_FAIL;
1609
1610   this->description.cySize.s.Hi = 0;
1611
1612   /*
1613    * FontName
1614    */
1615   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1616
1617   if (cbRead!=1)
1618     return E_FAIL;
1619
1620   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1621
1622   if (cbRead!=bStringSize)
1623     return E_FAIL;
1624
1625   HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1626
1627   len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1628   this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1629   MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1630   this->description.lpstrName[len] = 0;
1631
1632   /* Ensure use of this font causes a new one to be created @@@@ */
1633   DeleteObject(this->gdiFont);
1634   this->gdiFont = 0;
1635
1636   return S_OK;
1637 }
1638
1639 /************************************************************************
1640  * OLEFontImpl_Save (IPersistStream)
1641  *
1642  * See Windows documentation for more details on IPersistStream methods.
1643  */
1644 static HRESULT WINAPI OLEFontImpl_Save(
1645   IPersistStream*  iface,
1646   IStream*         pOutStream,
1647   BOOL             fClearDirty)
1648 {
1649   char* writeBuffer = NULL;
1650   ULONG cbWritten;
1651   BYTE  bVersion = 0x01;
1652   BYTE  bAttributes;
1653   BYTE  bStringSize;
1654
1655   OLEFontImpl *this = impl_from_IPersistStream(iface);
1656
1657   /*
1658    * Read the version byte
1659    */
1660   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1661
1662   if (cbWritten!=1)
1663     return E_FAIL;
1664
1665   /*
1666    * Charset
1667    */
1668   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1669
1670   if (cbWritten!=2)
1671     return E_FAIL;
1672
1673   /*
1674    * Attributes
1675    */
1676   bAttributes = 0;
1677
1678   if (this->description.fItalic)
1679     bAttributes |= FONTPERSIST_ITALIC;
1680
1681   if (this->description.fStrikethrough)
1682     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1683
1684   if (this->description.fUnderline)
1685     bAttributes |= FONTPERSIST_UNDERLINE;
1686
1687   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1688
1689   if (cbWritten!=1)
1690     return E_FAIL;
1691
1692   /*
1693    * Weight
1694    */
1695   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1696
1697   if (cbWritten!=2)
1698     return E_FAIL;
1699
1700   /*
1701    * Size
1702    */
1703   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1704
1705   if (cbWritten!=4)
1706     return E_FAIL;
1707
1708   /*
1709    * FontName
1710    */
1711   if (this->description.lpstrName!=0)
1712     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1713                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1714   else
1715     bStringSize = 0;
1716
1717   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1718
1719   if (cbWritten!=1)
1720     return E_FAIL;
1721
1722   if (bStringSize!=0)
1723   {
1724       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1725       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1726                            strlenW(this->description.lpstrName),
1727                            writeBuffer, bStringSize, NULL, NULL );
1728
1729     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1730     HeapFree(GetProcessHeap(), 0, writeBuffer);
1731
1732     if (cbWritten!=bStringSize)
1733       return E_FAIL;
1734   }
1735
1736   return S_OK;
1737 }
1738
1739 /************************************************************************
1740  * OLEFontImpl_GetSizeMax (IPersistStream)
1741  *
1742  * See Windows documentation for more details on IPersistStream methods.
1743  */
1744 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1745   IPersistStream*  iface,
1746   ULARGE_INTEGER*  pcbSize)
1747 {
1748   OLEFontImpl *this = impl_from_IPersistStream(iface);
1749
1750   if (pcbSize==NULL)
1751     return E_POINTER;
1752
1753   pcbSize->u.HighPart = 0;
1754   pcbSize->u.LowPart = 0;
1755
1756   pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
1757   pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
1758   pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
1759   pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
1760   pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1761   pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
1762
1763   if (this->description.lpstrName!=0)
1764     pcbSize->u.LowPart += lstrlenW(this->description.lpstrName);
1765
1766   return S_OK;
1767 }
1768
1769 /************************************************************************
1770  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1771  *
1772  * See Windows documentation for more details on IUnknown methods.
1773  */
1774 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1775   IConnectionPointContainer* iface,
1776   REFIID     riid,
1777   VOID**     ppvoid)
1778 {
1779   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1780
1781   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
1782 }
1783
1784 /************************************************************************
1785  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
1786  *
1787  * See Windows documentation for more details on IUnknown methods.
1788  */
1789 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
1790   IConnectionPointContainer* iface)
1791 {
1792   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1793
1794   return IFont_Release((IFont*)this);
1795 }
1796
1797 /************************************************************************
1798  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
1799  *
1800  * See Windows documentation for more details on IUnknown methods.
1801  */
1802 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
1803   IConnectionPointContainer* iface)
1804 {
1805   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1806
1807   return IFont_AddRef((IFont*)this);
1808 }
1809
1810 /************************************************************************
1811  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
1812  *
1813  * See Windows documentation for more details on IConnectionPointContainer
1814  * methods.
1815  */
1816 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
1817   IConnectionPointContainer* iface,
1818   IEnumConnectionPoints **ppEnum)
1819 {
1820   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1821
1822   FIXME("(%p)->(%p): stub\n", this, ppEnum);
1823   return E_NOTIMPL;
1824 }
1825
1826 /************************************************************************
1827  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
1828  *
1829  * See Windows documentation for more details on IConnectionPointContainer
1830  * methods.
1831  */
1832 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
1833    IConnectionPointContainer* iface,
1834    REFIID riid,
1835    IConnectionPoint **ppCp)
1836 {
1837   OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
1838   TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
1839
1840   if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) {
1841     return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint,
1842                                            (LPVOID)ppCp);
1843   } else {
1844     FIXME("Tried to find connection point on %s\n", debugstr_guid(riid));
1845     return E_NOINTERFACE;
1846   }
1847 }
1848
1849 /************************************************************************
1850  * OLEFontImpl implementation of IPersistPropertyBag.
1851  */
1852 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
1853    IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
1854 ) {
1855   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1856   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
1857 }
1858
1859 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
1860    IPersistPropertyBag *iface
1861 ) {
1862   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1863   return IFont_AddRef((IFont *)this);
1864 }
1865
1866 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
1867    IPersistPropertyBag *iface
1868 ) {
1869   OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1870   return IFont_Release((IFont *)this);
1871 }
1872
1873 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
1874    IPersistPropertyBag *iface, CLSID *classid
1875 ) {
1876   FIXME("(%p,%p), stub!\n", iface, classid);
1877   return E_FAIL;
1878 }
1879
1880 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
1881    IPersistPropertyBag *iface
1882 ) {
1883   FIXME("(%p), stub!\n", iface);
1884   return S_OK;
1885 }
1886
1887 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
1888    IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
1889 ) {
1890 /* (from Visual Basic 6 property bag)
1891          Name            =   "MS Sans Serif"
1892          Size            =   13.8
1893          Charset         =   0
1894          Weight          =   400
1895          Underline       =   0   'False
1896          Italic          =   0   'False
1897          Strikethrough   =   0   'False
1898 */
1899     static const WCHAR sAttrName[] = {'N','a','m','e',0};
1900     static const WCHAR sAttrSize[] = {'S','i','z','e',0};
1901     static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
1902     static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
1903     static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
1904     static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
1905     static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
1906     VARIANT rawAttr;
1907     VARIANT valueAttr;
1908     HRESULT iRes = S_OK;
1909     OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
1910
1911     VariantInit(&rawAttr);
1912     VariantInit(&valueAttr);
1913
1914     if (iRes == S_OK) {
1915         iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
1916         if (iRes == S_OK)
1917         {
1918             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
1919             if (iRes == S_OK)
1920                 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
1921         }
1922         else if (iRes == E_INVALIDARG)
1923             iRes = S_OK;
1924         VariantClear(&rawAttr);
1925         VariantClear(&valueAttr);
1926     }
1927
1928     if (iRes == S_OK) {
1929         iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
1930         if (iRes == S_OK)
1931         {
1932             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
1933             if (iRes == S_OK)
1934                 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
1935         }
1936         else if (iRes == E_INVALIDARG)
1937             iRes = S_OK;
1938         VariantClear(&rawAttr);
1939         VariantClear(&valueAttr);
1940     }
1941
1942     if (iRes == S_OK) {
1943         iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
1944         if (iRes == S_OK)
1945         {
1946             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
1947             if (iRes == S_OK)
1948                 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
1949         }
1950         else if (iRes == E_INVALIDARG)
1951             iRes = S_OK;
1952         VariantClear(&rawAttr);
1953         VariantClear(&valueAttr);
1954     }
1955
1956     if (iRes == S_OK) {
1957         iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
1958         if (iRes == S_OK)
1959         {
1960             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
1961             if (iRes == S_OK)
1962                 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
1963         }
1964         else if (iRes == E_INVALIDARG)
1965             iRes = S_OK;
1966         VariantClear(&rawAttr);
1967         VariantClear(&valueAttr);
1968
1969     }
1970
1971     if (iRes == S_OK) {
1972         iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
1973         if (iRes == S_OK)
1974         {
1975             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
1976             if (iRes == S_OK)
1977                 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
1978         }
1979         else if (iRes == E_INVALIDARG)
1980             iRes = S_OK;
1981         VariantClear(&rawAttr);
1982         VariantClear(&valueAttr);
1983     }
1984
1985     if (iRes == S_OK) {
1986         iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
1987         if (iRes == S_OK)
1988         {
1989             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
1990             if (iRes == S_OK)
1991                 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
1992         }
1993         else if (iRes == E_INVALIDARG)
1994             iRes = S_OK;
1995         VariantClear(&rawAttr);
1996         VariantClear(&valueAttr);
1997     }
1998
1999     if (iRes == S_OK) {
2000         iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
2001         if (iRes == S_OK)
2002         {
2003             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2004             if (iRes == S_OK)
2005                 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
2006         }
2007         else if (iRes == E_INVALIDARG)
2008             iRes = S_OK;
2009         VariantClear(&rawAttr);
2010         VariantClear(&valueAttr);
2011     }
2012
2013     if (FAILED(iRes))
2014         WARN("-- 0x%08lx\n", iRes);
2015     return iRes;
2016 }
2017
2018 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2019    IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2020    BOOL fSaveAllProperties
2021 ) {
2022   FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2023   return E_FAIL;
2024 }
2025
2026 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
2027 {
2028   OLEFontImpl_IPersistPropertyBag_QueryInterface,
2029   OLEFontImpl_IPersistPropertyBag_AddRef,
2030   OLEFontImpl_IPersistPropertyBag_Release,
2031
2032   OLEFontImpl_IPersistPropertyBag_GetClassID,
2033   OLEFontImpl_IPersistPropertyBag_InitNew,
2034   OLEFontImpl_IPersistPropertyBag_Load,
2035   OLEFontImpl_IPersistPropertyBag_Save
2036 };
2037
2038 /************************************************************************
2039  * OLEFontImpl implementation of IPersistStreamInit.
2040  */
2041 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2042    IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2043 ) {
2044   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2045   return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2046 }
2047
2048 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2049    IPersistStreamInit *iface
2050 ) {
2051   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2052   return IFont_AddRef((IFont *)this);
2053 }
2054
2055 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2056    IPersistStreamInit *iface
2057 ) {
2058   OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2059   return IFont_Release((IFont *)this);
2060 }
2061
2062 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2063    IPersistStreamInit *iface, CLSID *classid
2064 ) {
2065   FIXME("(%p,%p), stub!\n", iface, classid);
2066   return E_FAIL;
2067 }
2068
2069 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2070    IPersistStreamInit *iface
2071 ) {
2072   FIXME("(%p), stub!\n", iface);
2073   return E_FAIL;
2074 }
2075
2076 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2077    IPersistStreamInit *iface, LPSTREAM pStm
2078 ) {
2079   FIXME("(%p,%p), stub!\n", iface, pStm);
2080   return E_FAIL;
2081 }
2082
2083 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2084    IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2085 ) {
2086   FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2087   return E_FAIL;
2088 }
2089
2090 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2091    IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2092 ) {
2093   FIXME("(%p,%p), stub!\n", iface, pcbSize);
2094   return E_FAIL;
2095 }
2096
2097 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2098    IPersistStreamInit *iface
2099 ) {
2100   FIXME("(%p), stub!\n", iface);
2101   return S_OK;
2102 }
2103
2104 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
2105 {
2106   OLEFontImpl_IPersistStreamInit_QueryInterface,
2107   OLEFontImpl_IPersistStreamInit_AddRef,
2108   OLEFontImpl_IPersistStreamInit_Release,
2109
2110   OLEFontImpl_IPersistStreamInit_GetClassID,
2111   OLEFontImpl_IPersistStreamInit_IsDirty,
2112   OLEFontImpl_IPersistStreamInit_Load,
2113   OLEFontImpl_IPersistStreamInit_Save,
2114   OLEFontImpl_IPersistStreamInit_GetSizeMax,
2115   OLEFontImpl_IPersistStreamInit_InitNew
2116 };
2117
2118 /*******************************************************************************
2119  * StdFont ClassFactory
2120  */
2121 typedef struct
2122 {
2123     /* IUnknown fields */
2124     const IClassFactoryVtbl    *lpVtbl;
2125     LONG                        ref;
2126 } IClassFactoryImpl;
2127
2128 static HRESULT WINAPI
2129 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2130         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2131
2132         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2133         return E_NOINTERFACE;
2134 }
2135
2136 static ULONG WINAPI
2137 SFCF_AddRef(LPCLASSFACTORY iface) {
2138         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2139         return InterlockedIncrement(&This->ref);
2140 }
2141
2142 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2143         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2144         /* static class, won't be  freed */
2145         return InterlockedDecrement(&This->ref);
2146 }
2147
2148 static HRESULT WINAPI SFCF_CreateInstance(
2149         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2150 ) {
2151         return OleCreateFontIndirect(NULL,riid,ppobj);
2152
2153 }
2154
2155 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2156         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2157         FIXME("(%p)->(%d),stub!\n",This,dolock);
2158         return S_OK;
2159 }
2160
2161 static const IClassFactoryVtbl SFCF_Vtbl = {
2162         SFCF_QueryInterface,
2163         SFCF_AddRef,
2164         SFCF_Release,
2165         SFCF_CreateInstance,
2166         SFCF_LockServer
2167 };
2168 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2169
2170 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }