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