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