Implement asn.1 encoding/decoding of times, with tests.
[wine] / dlls / oleaut32 / olefont.c
1 /*
2  * OLE Font encapsulation implementation
3  *
4  * This file contains an implementation of the IFont
5  * interface and the OleCreateFontIndirect API call.
6  *
7  * Copyright 1999 Francis Beaudet
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <string.h>
26
27 #define COBJMACROS
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "wingdi.h"
35 #include "winuser.h"
36 #include "wine/unicode.h"
37 #include "objbase.h"
38 #include "oleauto.h"    /* for SysAllocString(....) */
39 #include "ole2.h"
40 #include "olectl.h"
41 #include "wine/debug.h"
42 #include "connpt.h" /* for CreateConnectionPoint */
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ole);
45
46 /***********************************************************************
47  * Declaration of constants used when serializing the font object.
48  */
49 #define FONTPERSIST_ITALIC        0x02
50 #define FONTPERSIST_UNDERLINE     0x04
51 #define FONTPERSIST_STRIKETHROUGH 0x08
52
53 /***********************************************************************
54  * Declaration of the implementation class for the IFont interface
55  */
56 typedef struct OLEFontImpl OLEFontImpl;
57
58 struct OLEFontImpl
59 {
60   /*
61    * This class supports many interfaces. IUnknown, IFont,
62    * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
63    * The first two are supported by the first vtable, the next two are
64    * supported by the second table and the last two have their own.
65    */
66   const IFontVtbl*                     lpvtbl1;
67   const IDispatchVtbl*                 lpvtbl2;
68   const IPersistStreamVtbl*            lpvtbl3;
69   const IConnectionPointContainerVtbl* lpvtbl4;
70   const IPersistPropertyBagVtbl*       lpvtbl5;
71   const 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 const 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 const 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 const 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 const 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 const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable;
287 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable;
288
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   HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
459
460   if (fontDesc->gdiFont!=0)
461     DeleteObject(fontDesc->gdiFont);
462
463   HeapFree(GetProcessHeap(), 0, fontDesc);
464 }
465
466 /************************************************************************
467  * OLEFontImpl_QueryInterface (IUnknown)
468  *
469  * See Windows documentation for more details on IUnknown methods.
470  */
471 HRESULT WINAPI OLEFontImpl_QueryInterface(
472   IFont*  iface,
473   REFIID  riid,
474   void**  ppvObject)
475 {
476   OLEFontImpl *this = (OLEFontImpl *)iface;
477   TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
478
479   /*
480    * Perform a sanity check on the parameters.
481    */
482   if ( (this==0) || (ppvObject==0) )
483     return E_INVALIDARG;
484
485   /*
486    * Initialize the return parameter.
487    */
488   *ppvObject = 0;
489
490   /*
491    * Compare the riid with the interface IDs implemented by this object.
492    */
493   if (IsEqualGUID(&IID_IUnknown, riid))
494     *ppvObject = (IFont*)this;
495   if (IsEqualGUID(&IID_IFont, riid))
496     *ppvObject = (IFont*)this;
497   if (IsEqualGUID(&IID_IDispatch, riid))
498     *ppvObject = (IDispatch*)&(this->lpvtbl2);
499   if (IsEqualGUID(&IID_IFontDisp, riid))
500     *ppvObject = (IDispatch*)&(this->lpvtbl2);
501   if (IsEqualGUID(&IID_IPersistStream, riid))
502     *ppvObject = (IPersistStream*)&(this->lpvtbl3);
503   if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
504     *ppvObject = (IConnectionPointContainer*)&(this->lpvtbl4);
505   if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
506     *ppvObject = (IPersistPropertyBag*)&(this->lpvtbl5);
507   if (IsEqualGUID(&IID_IPersistStreamInit, riid))
508     *ppvObject = (IPersistStreamInit*)&(this->lpvtbl6);
509
510   /*
511    * Check that we obtained an interface.
512    */
513   if ((*ppvObject)==0)
514   {
515     FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
516     return E_NOINTERFACE;
517   }
518   OLEFontImpl_AddRef((IFont*)this);
519   return S_OK;
520 }
521
522 /************************************************************************
523  * OLEFontImpl_AddRef (IUnknown)
524  *
525  * See Windows documentation for more details on IUnknown methods.
526  */
527 ULONG WINAPI OLEFontImpl_AddRef(
528   IFont* iface)
529 {
530   OLEFontImpl *this = (OLEFontImpl *)iface;
531   TRACE("(%p)->(ref=%ld)\n", this, this->ref);
532   return InterlockedIncrement(&this->ref);
533 }
534
535 /************************************************************************
536  * OLEFontImpl_Release (IUnknown)
537  *
538  * See Windows documentation for more details on IUnknown methods.
539  */
540 ULONG WINAPI OLEFontImpl_Release(
541       IFont* iface)
542 {
543   OLEFontImpl *this = (OLEFontImpl *)iface;
544   ULONG ret;
545   TRACE("(%p)->(ref=%ld)\n", this, this->ref);
546
547   /*
548    * Decrease the reference count on this object.
549    */
550   ret = InterlockedDecrement(&this->ref);
551
552   /*
553    * If the reference count goes down to 0, perform suicide.
554    */
555   if (ret==0) OLEFontImpl_Destroy(this);
556
557   return ret;
558 }
559
560 /************************************************************************
561  * OLEFontImpl_get_Name (IFont)
562  *
563  * See Windows documentation for more details on IFont methods.
564  */
565 static HRESULT WINAPI OLEFontImpl_get_Name(
566   IFont*  iface,
567   BSTR* pname)
568 {
569   OLEFontImpl *this = (OLEFontImpl *)iface;
570   TRACE("(%p)->(%p)\n", this, pname);
571   /*
572    * Sanity check.
573    */
574   if (pname==0)
575     return E_POINTER;
576
577   if (this->description.lpstrName!=0)
578     *pname = SysAllocString(this->description.lpstrName);
579   else
580     *pname = 0;
581
582   return S_OK;
583 }
584
585 /************************************************************************
586  * OLEFontImpl_put_Name (IFont)
587  *
588  * See Windows documentation for more details on IFont methods.
589  */
590 static HRESULT WINAPI OLEFontImpl_put_Name(
591   IFont* iface,
592   BSTR name)
593 {
594   OLEFontImpl *this = (OLEFontImpl *)iface;
595   TRACE("(%p)->(%p)\n", this, name);
596
597   if (this->description.lpstrName==0)
598   {
599     this->description.lpstrName = HeapAlloc(GetProcessHeap(),
600                                             0,
601                                             (lstrlenW(name)+1) * sizeof(WCHAR));
602   }
603   else
604   {
605     this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
606                                               0,
607                                               this->description.lpstrName,
608                                               (lstrlenW(name)+1) * sizeof(WCHAR));
609   }
610
611   if (this->description.lpstrName==0)
612     return E_OUTOFMEMORY;
613
614   strcpyW(this->description.lpstrName, name);
615   TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
616   OLEFont_SendNotify(this, DISPID_FONT_NAME);
617   return S_OK;
618 }
619
620 /************************************************************************
621  * OLEFontImpl_get_Size (IFont)
622  *
623  * See Windows documentation for more details on IFont methods.
624  */
625 static HRESULT WINAPI OLEFontImpl_get_Size(
626   IFont* iface,
627   CY*    psize)
628 {
629   OLEFontImpl *this = (OLEFontImpl *)iface;
630   TRACE("(%p)->(%p)\n", this, psize);
631
632   /*
633    * Sanity check
634    */
635   if (psize==0)
636     return E_POINTER;
637
638   psize->s.Hi = 0;
639   psize->s.Lo = this->description.cySize.s.Lo;
640
641   return S_OK;
642 }
643
644 /************************************************************************
645  * OLEFontImpl_put_Size (IFont)
646  *
647  * See Windows documentation for more details on IFont methods.
648  */
649 static HRESULT WINAPI OLEFontImpl_put_Size(
650   IFont* iface,
651   CY     size)
652 {
653   OLEFontImpl *this = (OLEFontImpl *)iface;
654   TRACE("(%p)->(%ld)\n", this, size.s.Lo);
655   this->description.cySize.s.Hi = 0;
656   this->description.cySize.s.Lo = size.s.Lo;
657   OLEFont_SendNotify(this, DISPID_FONT_SIZE);
658
659   return S_OK;
660 }
661
662 /************************************************************************
663  * OLEFontImpl_get_Bold (IFont)
664  *
665  * See Windows documentation for more details on IFont methods.
666  */
667 static HRESULT WINAPI OLEFontImpl_get_Bold(
668   IFont*  iface,
669   BOOL* pbold)
670 {
671   OLEFontImpl *this = (OLEFontImpl *)iface;
672   TRACE("(%p)->(%p)\n", this, pbold);
673   /*
674    * Sanity check
675    */
676   if (pbold==0)
677     return E_POINTER;
678
679   *pbold = this->description.sWeight > 550;
680
681   return S_OK;
682 }
683
684 /************************************************************************
685  * OLEFontImpl_put_Bold (IFont)
686  *
687  * See Windows documentation for more details on IFont methods.
688  */
689 static HRESULT WINAPI OLEFontImpl_put_Bold(
690   IFont* iface,
691   BOOL bold)
692 {
693   OLEFontImpl *this = (OLEFontImpl *)iface;
694   TRACE("(%p)->(%d)\n", this, bold);
695   this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
696   OLEFont_SendNotify(this, DISPID_FONT_BOLD);
697
698   return S_OK;
699 }
700
701 /************************************************************************
702  * OLEFontImpl_get_Italic (IFont)
703  *
704  * See Windows documentation for more details on IFont methods.
705  */
706 static HRESULT WINAPI OLEFontImpl_get_Italic(
707   IFont*  iface,
708   BOOL* pitalic)
709 {
710   OLEFontImpl *this = (OLEFontImpl *)iface;
711   TRACE("(%p)->(%p)\n", this, pitalic);
712   /*
713    * Sanity check
714    */
715   if (pitalic==0)
716     return E_POINTER;
717
718   *pitalic = this->description.fItalic;
719
720   return S_OK;
721 }
722
723 /************************************************************************
724  * OLEFontImpl_put_Italic (IFont)
725  *
726  * See Windows documentation for more details on IFont methods.
727  */
728 static HRESULT WINAPI OLEFontImpl_put_Italic(
729   IFont* iface,
730   BOOL italic)
731 {
732   OLEFontImpl *this = (OLEFontImpl *)iface;
733   TRACE("(%p)->(%d)\n", this, italic);
734
735   this->description.fItalic = italic;
736
737   OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
738   return S_OK;
739 }
740
741 /************************************************************************
742  * OLEFontImpl_get_Underline (IFont)
743  *
744  * See Windows documentation for more details on IFont methods.
745  */
746 static HRESULT WINAPI OLEFontImpl_get_Underline(
747   IFont*  iface,
748   BOOL* punderline)
749 {
750   OLEFontImpl *this = (OLEFontImpl *)iface;
751   TRACE("(%p)->(%p)\n", this, punderline);
752
753   /*
754    * Sanity check
755    */
756   if (punderline==0)
757     return E_POINTER;
758
759   *punderline = this->description.fUnderline;
760
761   return S_OK;
762 }
763
764 /************************************************************************
765  * OLEFontImpl_put_Underline (IFont)
766  *
767  * See Windows documentation for more details on IFont methods.
768  */
769 static HRESULT WINAPI OLEFontImpl_put_Underline(
770   IFont* iface,
771   BOOL underline)
772 {
773   OLEFontImpl *this = (OLEFontImpl *)iface;
774   TRACE("(%p)->(%d)\n", this, underline);
775
776   this->description.fUnderline = underline;
777
778   OLEFont_SendNotify(this, DISPID_FONT_UNDER);
779   return S_OK;
780 }
781
782 /************************************************************************
783  * OLEFontImpl_get_Strikethrough (IFont)
784  *
785  * See Windows documentation for more details on IFont methods.
786  */
787 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
788   IFont*  iface,
789   BOOL* pstrikethrough)
790 {
791   OLEFontImpl *this = (OLEFontImpl *)iface;
792   TRACE("(%p)->(%p)\n", this, pstrikethrough);
793
794   /*
795    * Sanity check
796    */
797   if (pstrikethrough==0)
798     return E_POINTER;
799
800   *pstrikethrough = this->description.fStrikethrough;
801
802   return S_OK;
803 }
804
805 /************************************************************************
806  * OLEFontImpl_put_Strikethrough (IFont)
807  *
808  * See Windows documentation for more details on IFont methods.
809  */
810 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
811  IFont* iface,
812  BOOL strikethrough)
813 {
814   OLEFontImpl *this = (OLEFontImpl *)iface;
815   TRACE("(%p)->(%d)\n", this, strikethrough);
816
817   this->description.fStrikethrough = strikethrough;
818   OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
819
820   return S_OK;
821 }
822
823 /************************************************************************
824  * OLEFontImpl_get_Weight (IFont)
825  *
826  * See Windows documentation for more details on IFont methods.
827  */
828 static HRESULT WINAPI OLEFontImpl_get_Weight(
829   IFont* iface,
830   short* pweight)
831 {
832   OLEFontImpl *this = (OLEFontImpl *)iface;
833   TRACE("(%p)->(%p)\n", this, pweight);
834
835   /*
836    * Sanity check
837    */
838   if (pweight==0)
839     return E_POINTER;
840
841   *pweight = this->description.sWeight;
842
843   return S_OK;
844 }
845
846 /************************************************************************
847  * OLEFontImpl_put_Weight (IFont)
848  *
849  * See Windows documentation for more details on IFont methods.
850  */
851 static HRESULT WINAPI OLEFontImpl_put_Weight(
852   IFont* iface,
853   short  weight)
854 {
855   OLEFontImpl *this = (OLEFontImpl *)iface;
856   TRACE("(%p)->(%d)\n", this, weight);
857
858   this->description.sWeight = weight;
859
860   OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
861   return S_OK;
862 }
863
864 /************************************************************************
865  * OLEFontImpl_get_Charset (IFont)
866  *
867  * See Windows documentation for more details on IFont methods.
868  */
869 static HRESULT WINAPI OLEFontImpl_get_Charset(
870   IFont* iface,
871   short* pcharset)
872 {
873   OLEFontImpl *this = (OLEFontImpl *)iface;
874   TRACE("(%p)->(%p)\n", this, pcharset);
875
876   /*
877    * Sanity check
878    */
879   if (pcharset==0)
880     return E_POINTER;
881
882   *pcharset = this->description.sCharset;
883
884   return S_OK;
885 }
886
887 /************************************************************************
888  * OLEFontImpl_put_Charset (IFont)
889  *
890  * See Windows documentation for more details on IFont methods.
891  */
892 static HRESULT WINAPI OLEFontImpl_put_Charset(
893   IFont* iface,
894   short charset)
895 {
896   OLEFontImpl *this = (OLEFontImpl *)iface;
897   TRACE("(%p)->(%d)\n", this, charset);
898
899   this->description.sCharset = charset;
900   OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
901
902   return S_OK;
903 }
904
905 /************************************************************************
906  * OLEFontImpl_get_hFont (IFont)
907  *
908  * See Windows documentation for more details on IFont methods.
909  */
910 static HRESULT WINAPI OLEFontImpl_get_hFont(
911   IFont*   iface,
912   HFONT* phfont)
913 {
914   OLEFontImpl *this = (OLEFontImpl *)iface;
915   TRACE("(%p)->(%p)\n", this, phfont);
916   if (phfont==NULL)
917     return E_POINTER;
918
919   /*
920    * Realize the font if necessary
921  */
922   if (this->gdiFont==0)
923 {
924     LOGFONTW logFont;
925     INT      fontHeight;
926     CY       cySize;
927
928     /*
929      * The height of the font returned by the get_Size property is the
930      * height of the font in points multiplied by 10000... Using some
931      * simple conversions and the ratio given by the application, it can
932      * be converted to a height in pixels.
933      */
934     IFont_get_Size(iface, &cySize);
935
936     fontHeight = MulDiv( cySize.s.Lo, this->cyLogical, this->cyHimetric );
937
938     memset(&logFont, 0, sizeof(LOGFONTW));
939
940     logFont.lfHeight          = ((fontHeight%10000L)>5000L) ?   (-fontHeight/10000L)-1 :
941                                                                 (-fontHeight/10000L);
942     logFont.lfItalic          = this->description.fItalic;
943     logFont.lfUnderline       = this->description.fUnderline;
944     logFont.lfStrikeOut       = this->description.fStrikethrough;
945     logFont.lfWeight          = this->description.sWeight;
946     logFont.lfCharSet         = this->description.sCharset;
947     logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
948     logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
949     logFont.lfQuality         = DEFAULT_QUALITY;
950     logFont.lfPitchAndFamily  = DEFAULT_PITCH;
951     strcpyW(logFont.lfFaceName,this->description.lpstrName);
952
953     this->gdiFont = CreateFontIndirectW(&logFont);
954   }
955
956   *phfont = this->gdiFont;
957   TRACE("Returning %p\n", *phfont);
958   return S_OK;
959 }
960
961 /************************************************************************
962  * OLEFontImpl_Clone (IFont)
963  *
964  * See Windows documentation for more details on IFont methods.
965  */
966 static HRESULT WINAPI OLEFontImpl_Clone(
967   IFont*  iface,
968   IFont** ppfont)
969 {
970   OLEFontImpl* newObject = 0;
971   LOGFONTW logFont;
972   INT      fontHeight;
973   CY       cySize;
974   OLEFontImpl *this = (OLEFontImpl *)iface;
975   TRACE("(%p)->(%p)\n", this, ppfont);
976
977   if (ppfont == NULL)
978     return E_POINTER;
979
980   *ppfont = NULL;
981
982   /*
983    * Allocate space for the object.
984    */
985   newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
986
987   if (newObject==NULL)
988     return E_OUTOFMEMORY;
989
990   *newObject = *this;
991
992   /* We need to alloc new memory for the string, otherwise
993    * we free memory twice.
994    */
995   newObject->description.lpstrName = HeapAlloc(
996         GetProcessHeap(),0,
997         (1+strlenW(this->description.lpstrName))*2
998   );
999   strcpyW(newObject->description.lpstrName, this->description.lpstrName);
1000   /* We need to clone the HFONT too. This is just cut & paste from above */
1001   IFont_get_Size(iface, &cySize);
1002
1003   fontHeight = MulDiv(cySize.s.Lo, this->cyLogical,this->cyHimetric);
1004
1005   memset(&logFont, 0, sizeof(LOGFONTW));
1006
1007   logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
1008                                                             (-fontHeight/10000L);
1009   logFont.lfItalic          = this->description.fItalic;
1010   logFont.lfUnderline       = this->description.fUnderline;
1011   logFont.lfStrikeOut       = this->description.fStrikethrough;
1012   logFont.lfWeight          = this->description.sWeight;
1013   logFont.lfCharSet         = this->description.sCharset;
1014   logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
1015   logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
1016   logFont.lfQuality         = DEFAULT_QUALITY;
1017   logFont.lfPitchAndFamily  = DEFAULT_PITCH;
1018   strcpyW(logFont.lfFaceName,this->description.lpstrName);
1019
1020   newObject->gdiFont = CreateFontIndirectW(&logFont);
1021
1022
1023   /* The cloned object starts with a reference count of 1 */
1024   newObject->ref          = 1;
1025
1026   *ppfont = (IFont*)newObject;
1027
1028   return S_OK;
1029 }
1030
1031 /************************************************************************
1032  * OLEFontImpl_IsEqual (IFont)
1033  *
1034  * See Windows documentation for more details on IFont methods.
1035  */
1036 static HRESULT WINAPI OLEFontImpl_IsEqual(
1037   IFont* iface,
1038   IFont* pFontOther)
1039 {
1040   FIXME("(%p, %p), stub!\n",iface,pFontOther);
1041   return E_NOTIMPL;
1042 }
1043
1044 /************************************************************************
1045  * OLEFontImpl_SetRatio (IFont)
1046  *
1047  * See Windows documentation for more details on IFont methods.
1048  */
1049 static HRESULT WINAPI OLEFontImpl_SetRatio(
1050   IFont* iface,
1051   LONG   cyLogical,
1052   LONG   cyHimetric)
1053 {
1054   OLEFontImpl *this = (OLEFontImpl *)iface;
1055   TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric);
1056
1057   this->cyLogical  = cyLogical;
1058   this->cyHimetric = cyHimetric;
1059
1060   return S_OK;
1061 }
1062
1063 /************************************************************************
1064  * OLEFontImpl_QueryTextMetrics (IFont)
1065  *
1066  * See Windows documentation for more details on IFont methods.
1067  */
1068 static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
1069   IFont*         iface,
1070   TEXTMETRICOLE* ptm)
1071 {
1072   HDC hdcRef;
1073   HFONT hOldFont, hNewFont;
1074
1075   hdcRef = GetDC(0);
1076   OLEFontImpl_get_hFont(iface, &hNewFont);
1077   hOldFont = SelectObject(hdcRef, hNewFont);
1078   GetTextMetricsW(hdcRef, ptm);
1079   SelectObject(hdcRef, hOldFont);
1080   ReleaseDC(0, hdcRef);
1081   return S_OK;
1082 }
1083
1084 /************************************************************************
1085  * OLEFontImpl_AddRefHfont (IFont)
1086  *
1087  * See Windows documentation for more details on IFont methods.
1088  */
1089 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1090   IFont*  iface,
1091   HFONT hfont)
1092 {
1093   OLEFontImpl *this = (OLEFontImpl *)iface;
1094   TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
1095
1096   if ( (hfont == 0) ||
1097        (hfont != this->gdiFont) )
1098     return E_INVALIDARG;
1099
1100   this->fontLock++;
1101
1102   return S_OK;
1103 }
1104
1105 /************************************************************************
1106  * OLEFontImpl_ReleaseHfont (IFont)
1107  *
1108  * See Windows documentation for more details on IFont methods.
1109  */
1110 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1111   IFont*  iface,
1112   HFONT hfont)
1113 {
1114   OLEFontImpl *this = (OLEFontImpl *)iface;
1115   TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
1116
1117   if ( (hfont == 0) ||
1118        (hfont != this->gdiFont) )
1119     return E_INVALIDARG;
1120
1121   this->fontLock--;
1122
1123   /*
1124    * If we just released our last font reference, destroy it.
1125    */
1126   if (this->fontLock==0)
1127   {
1128     DeleteObject(this->gdiFont);
1129     this->gdiFont = 0;
1130   }
1131
1132   return S_OK;
1133 }
1134
1135 /************************************************************************
1136  * OLEFontImpl_SetHdc (IFont)
1137  *
1138  * See Windows documentation for more details on IFont methods.
1139  */
1140 static HRESULT WINAPI OLEFontImpl_SetHdc(
1141   IFont* iface,
1142   HDC  hdc)
1143 {
1144   OLEFontImpl *this = (OLEFontImpl *)iface;
1145   FIXME("(%p)->(%p): Stub\n", this, hdc);
1146   return E_NOTIMPL;
1147 }
1148
1149 /************************************************************************
1150  * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1151  *
1152  * See Windows documentation for more details on IUnknown methods.
1153  */
1154 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1155   IDispatch* iface,
1156   REFIID     riid,
1157   VOID**     ppvoid)
1158 {
1159   _ICOM_THIS_From_IDispatch(IFont, iface);
1160
1161   return IFont_QueryInterface(this, riid, ppvoid);
1162 }
1163
1164 /************************************************************************
1165  * OLEFontImpl_IDispatch_Release (IUnknown)
1166  *
1167  * See Windows documentation for more details on IUnknown methods.
1168  */
1169 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1170   IDispatch* iface)
1171 {
1172   _ICOM_THIS_From_IDispatch(IFont, iface);
1173
1174   return IFont_Release(this);
1175 }
1176
1177 /************************************************************************
1178  * OLEFontImpl_IDispatch_AddRef (IUnknown)
1179  *
1180  * See Windows documentation for more details on IUnknown methods.
1181  */
1182 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1183   IDispatch* iface)
1184 {
1185   _ICOM_THIS_From_IDispatch(IFont, iface);
1186
1187   return IFont_AddRef(this);
1188 }
1189
1190 /************************************************************************
1191  * OLEFontImpl_GetTypeInfoCount (IDispatch)
1192  *
1193  * See Windows documentation for more details on IDispatch methods.
1194  */
1195 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1196   IDispatch*    iface,
1197   unsigned int* pctinfo)
1198 {
1199   _ICOM_THIS_From_IDispatch(IFont, iface);
1200   FIXME("(%p)->(%p): Stub\n", this, pctinfo);
1201
1202   return E_NOTIMPL;
1203 }
1204
1205 /************************************************************************
1206  * OLEFontImpl_GetTypeInfo (IDispatch)
1207  *
1208  * See Windows documentation for more details on IDispatch methods.
1209  */
1210 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1211   IDispatch*  iface,
1212   UINT      iTInfo,
1213   LCID        lcid,
1214   ITypeInfo** ppTInfo)
1215 {
1216   static const WCHAR stdole32tlb[] = {'s','t','d','o','l','e','3','2','.','t','l','b',0};
1217   ITypeLib *tl;
1218   HRESULT hres;
1219
1220   _ICOM_THIS_From_IDispatch(OLEFontImpl, iface);
1221   TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1222   if (iTInfo != 0)
1223     return E_FAIL;
1224   hres = LoadTypeLib(stdole32tlb, &tl);
1225   if (FAILED(hres)) {
1226     ERR("Could not load the stdole32.tlb?\n");
1227     return hres;
1228   }
1229   hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IDispatch, ppTInfo);
1230   if (FAILED(hres)) {
1231     FIXME("Did not IDispatch typeinfo from typelib, hres %lx\n",hres);
1232   }
1233   return hres;
1234 }
1235
1236 /************************************************************************
1237  * OLEFontImpl_GetIDsOfNames (IDispatch)
1238  *
1239  * See Windows documentation for more details on IDispatch methods.
1240  */
1241 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1242   IDispatch*  iface,
1243   REFIID      riid,
1244   LPOLESTR* rgszNames,
1245   UINT      cNames,
1246   LCID        lcid,
1247   DISPID*     rgDispId)
1248 {
1249   _ICOM_THIS_From_IDispatch(IFont, iface);
1250   FIXME("(%p,%s,%p,%d,%04x,%p), stub!\n", this, debugstr_guid(riid), rgszNames,
1251         cNames, (int)lcid, rgDispId
1252   );
1253   return E_NOTIMPL;
1254 }
1255
1256 /************************************************************************
1257  * OLEFontImpl_Invoke (IDispatch)
1258  *
1259  * See Windows documentation for more details on IDispatch methods.
1260  * 
1261  * Note: Do not call _put_Xxx methods, since setting things here
1262  * should not call notify functions as I found out debugging the generic
1263  * MS VB5 installer.
1264  */
1265 static HRESULT WINAPI OLEFontImpl_Invoke(
1266   IDispatch*  iface,
1267   DISPID      dispIdMember,
1268   REFIID      riid,
1269   LCID        lcid,
1270   WORD        wFlags,
1271   DISPPARAMS* pDispParams,
1272   VARIANT*    pVarResult,
1273   EXCEPINFO*  pExepInfo,
1274   UINT*     puArgErr)
1275 {
1276   _ICOM_THIS_From_IDispatch(IFont, iface);
1277   OLEFontImpl *xthis = (OLEFontImpl*)this;
1278
1279   switch (dispIdMember) {
1280   case DISPID_FONT_NAME:
1281     switch (wFlags) {
1282     case DISPATCH_PROPERTYGET:
1283     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1284       V_VT(pVarResult) = VT_BSTR;
1285       return OLEFontImpl_get_Name(this, &V_BSTR(pVarResult));
1286     case DISPATCH_PROPERTYPUT: {
1287       BSTR name;
1288       BOOL freename;
1289       
1290       if (V_VT(&pDispParams->rgvarg[0]) == VT_DISPATCH) {
1291         IFont *font;
1292         HRESULT hr = S_OK;
1293         
1294         hr = IUnknown_QueryInterface(V_DISPATCH(&pDispParams->rgvarg[0]), &IID_IFont, (void **) &font);
1295         if (FAILED(hr))
1296         {
1297             FIXME("dispatch value for name property is not an OleFont, returning hr=0x%lx\n", hr);
1298             return hr;
1299         }
1300
1301         hr = IFont_get_Name(font, &name); /* this allocates a new BSTR so free it later */
1302         if (FAILED(hr)) return hr;
1303
1304         IUnknown_Release(font);
1305         
1306         freename = TRUE;
1307       } else if (V_VT(&pDispParams->rgvarg[0]) == VT_BSTR) {
1308         name = V_BSTR(&pDispParams->rgvarg[0]);
1309         freename = FALSE;
1310       } else {
1311         FIXME("app is trying to set name property with a non BSTR, non dispatch value. returning E_FAIL\n");
1312         return E_FAIL;
1313       }
1314
1315       TRACE("name is %s\n", debugstr_w(name));
1316       
1317       if (!xthis->description.lpstrName)
1318         xthis->description.lpstrName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1) * sizeof(WCHAR));
1319       else
1320         xthis->description.lpstrName = HeapReAlloc(GetProcessHeap(), 0, xthis->description.lpstrName, (lstrlenW(name)+1) * sizeof(WCHAR));
1321
1322       if (xthis->description.lpstrName==0)
1323         return E_OUTOFMEMORY;
1324       strcpyW(xthis->description.lpstrName, name);
1325
1326       if (freename) SysFreeString(name);
1327       
1328       return S_OK;
1329     }
1330     }
1331     break;
1332   case DISPID_FONT_BOLD:
1333     switch (wFlags) {
1334     case DISPATCH_PROPERTYGET:
1335     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1336       V_VT(pVarResult) = VT_BOOL;
1337       return OLEFontImpl_get_Bold(this, (BOOL*)&V_BOOL(pVarResult));
1338     case DISPATCH_PROPERTYPUT:
1339       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1340         FIXME("DISPID_FONT_BOLD/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1341         return E_FAIL;
1342       } else {
1343         xthis->description.sWeight = V_BOOL(&pDispParams->rgvarg[0]) ? FW_BOLD : FW_NORMAL;
1344         return S_OK;
1345       }
1346     }
1347     break;
1348   case DISPID_FONT_ITALIC:
1349     switch (wFlags) {
1350     case DISPATCH_PROPERTYGET:
1351     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1352       V_VT(pVarResult) = VT_BOOL;
1353       return OLEFontImpl_get_Italic(this, (BOOL*)&V_BOOL(pVarResult));
1354     case DISPATCH_PROPERTYPUT:
1355       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1356         FIXME("DISPID_FONT_ITALIC/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1357         return E_FAIL;
1358       } else {
1359         xthis->description.fItalic = V_BOOL(&pDispParams->rgvarg[0]);
1360         return S_OK;
1361       }
1362     }
1363     break;
1364   case DISPID_FONT_UNDER:
1365     switch (wFlags) {
1366     case DISPATCH_PROPERTYGET:
1367     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1368       V_VT(pVarResult) = VT_BOOL;
1369       return OLEFontImpl_get_Underline(this, (BOOL*)&V_BOOL(pVarResult));
1370     case DISPATCH_PROPERTYPUT:
1371       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1372         FIXME("DISPID_FONT_UNDER/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1373         return E_FAIL;
1374       } else {
1375         xthis->description.fUnderline = V_BOOL(&pDispParams->rgvarg[0]);
1376         return S_OK;
1377       }
1378     }
1379     break;
1380   case DISPID_FONT_STRIKE:
1381     switch (wFlags) {
1382     case DISPATCH_PROPERTYGET:
1383     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1384       V_VT(pVarResult) = VT_BOOL;
1385       return OLEFontImpl_get_Strikethrough(this, (BOOL*)&V_BOOL(pVarResult));
1386     case DISPATCH_PROPERTYPUT:
1387       if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
1388         FIXME("DISPID_FONT_STRIKE/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
1389         return E_FAIL;
1390       } else {
1391         xthis->description.fStrikethrough = V_BOOL(&pDispParams->rgvarg[0]);
1392         return S_OK;
1393       }
1394     }
1395     break;
1396   case DISPID_FONT_SIZE:
1397     switch (wFlags) {
1398     case DISPATCH_PROPERTYPUT: {
1399       assert (pDispParams->cArgs == 1);
1400       xthis->description.cySize.s.Hi = 0;
1401       if (V_VT(&pDispParams->rgvarg[0]) != VT_CY) {
1402         if (V_VT(&pDispParams->rgvarg[0]) == VT_I2) {
1403           xthis->description.cySize.s.Lo = V_I2(&pDispParams->rgvarg[0]) * 10000;
1404         } else {
1405           FIXME("property put for Size with vt %d unsupported!\n",V_VT(&pDispParams->rgvarg[0]));
1406         }
1407       } else {
1408         xthis->description.cySize.s.Lo = V_CY(&pDispParams->rgvarg[0]).s.Lo;
1409       }
1410       return S_OK;
1411     }
1412     case DISPATCH_PROPERTYGET:
1413     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1414       V_VT(pVarResult) = VT_CY;
1415       return OLEFontImpl_get_Size(this, &V_CY(pVarResult));
1416     }
1417     break;
1418   case DISPID_FONT_CHARSET:
1419     switch (wFlags) {
1420     case DISPATCH_PROPERTYPUT:
1421       assert (pDispParams->cArgs == 1);
1422       if (V_VT(&pDispParams->rgvarg[0]) != VT_I2)
1423         FIXME("varg of first disparg is not VT_I2, but %d\n",V_VT(&pDispParams->rgvarg[0]));
1424       xthis->description.sCharset = V_I2(&pDispParams->rgvarg[0]);
1425       return S_OK;
1426     case DISPATCH_PROPERTYGET:
1427     case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
1428       V_VT(pVarResult) = VT_I2;
1429       return OLEFontImpl_get_Charset(this, &V_I2(pVarResult));
1430     }
1431     break;
1432   }
1433   FIXME("%p->(%ld,%s,%lx,%x,%p,%p,%p,%p), unhandled dispid/flag!\n",
1434     this,dispIdMember,debugstr_guid(riid),lcid,
1435     wFlags,pDispParams,pVarResult,pExepInfo,puArgErr
1436   );
1437   return S_OK;
1438 }
1439
1440 /************************************************************************
1441  * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1442  *
1443  * See Windows documentation for more details on IUnknown methods.
1444  */
1445 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1446   IPersistStream* iface,
1447   REFIID     riid,
1448   VOID**     ppvoid)
1449 {
1450   _ICOM_THIS_From_IPersistStream(IFont, iface);
1451
1452   return IFont_QueryInterface(this, riid, ppvoid);
1453 }
1454
1455 /************************************************************************
1456  * OLEFontImpl_IPersistStream_Release (IUnknown)
1457  *
1458  * See Windows documentation for more details on IUnknown methods.
1459  */
1460 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1461   IPersistStream* iface)
1462 {
1463   _ICOM_THIS_From_IPersistStream(IFont, iface);
1464
1465   return IFont_Release(this);
1466 }
1467
1468 /************************************************************************
1469  * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1470  *
1471  * See Windows documentation for more details on IUnknown methods.
1472  */
1473 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1474   IPersistStream* iface)
1475 {
1476   _ICOM_THIS_From_IPersistStream(IFont, iface);
1477
1478   return IFont_AddRef(this);
1479 }
1480
1481 /************************************************************************
1482  * OLEFontImpl_GetClassID (IPersistStream)
1483  *
1484  * See Windows documentation for more details on IPersistStream methods.
1485  */
1486 static HRESULT WINAPI OLEFontImpl_GetClassID(
1487   IPersistStream* iface,
1488   CLSID*                pClassID)
1489 {
1490   TRACE("(%p,%p)\n",iface,pClassID);
1491   if (pClassID==0)
1492     return E_POINTER;
1493
1494   memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
1495
1496   return S_OK;
1497 }
1498
1499 /************************************************************************
1500  * OLEFontImpl_IsDirty (IPersistStream)
1501  *
1502  * See Windows documentation for more details on IPersistStream methods.
1503  */
1504 static HRESULT WINAPI OLEFontImpl_IsDirty(
1505   IPersistStream*  iface)
1506 {
1507   TRACE("(%p)\n",iface);
1508   return S_OK;
1509 }
1510
1511 /************************************************************************
1512  * OLEFontImpl_Load (IPersistStream)
1513  *
1514  * See Windows documentation for more details on IPersistStream methods.
1515  *
1516  * This is the format of the standard font serialization as far as I
1517  * know
1518  *
1519  * Offset   Type   Value           Comment
1520  * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
1521  * 0x0001   Short  Charset         Charset value from the FONTDESC structure
1522  * 0x0003   Byte   Attributes      Flags defined as follows:
1523  *                                     00000010 - Italic
1524  *                                     00000100 - Underline
1525  *                                     00001000 - Strikethrough
1526  * 0x0004   Short  Weight          Weight value from FONTDESC structure
1527  * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
1528  *                                 structure/
1529  * 0x000A   Byte   name length     Length of the font name string (no null character)
1530  * 0x000B   String name            Name of the font (ASCII, no nul character)
1531  */
1532 static HRESULT WINAPI OLEFontImpl_Load(
1533   IPersistStream*  iface,
1534   IStream*         pLoadStream)
1535 {
1536   char  readBuffer[0x100];
1537   ULONG cbRead;
1538   BYTE  bVersion;
1539   BYTE  bAttributes;
1540   BYTE  bStringSize;
1541   INT len;
1542
1543   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1544
1545   /*
1546    * Read the version byte
1547    */
1548   IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1549
1550   if ( (cbRead!=1) ||
1551        (bVersion!=0x01) )
1552     return E_FAIL;
1553
1554   /*
1555    * Charset
1556    */
1557   IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1558
1559   if (cbRead!=2)
1560     return E_FAIL;
1561
1562   /*
1563    * Attributes
1564    */
1565   IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1566
1567   if (cbRead!=1)
1568     return E_FAIL;
1569
1570   this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
1571   this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1572   this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1573
1574   /*
1575    * Weight
1576    */
1577   IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1578
1579   if (cbRead!=2)
1580     return E_FAIL;
1581
1582   /*
1583    * Size
1584    */
1585   IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1586
1587   if (cbRead!=4)
1588     return E_FAIL;
1589
1590   this->description.cySize.s.Hi = 0;
1591
1592   /*
1593    * FontName
1594    */
1595   IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1596
1597   if (cbRead!=1)
1598     return E_FAIL;
1599
1600   IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1601
1602   if (cbRead!=bStringSize)
1603     return E_FAIL;
1604
1605   HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1606
1607   len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1608   this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1609   MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1610   this->description.lpstrName[len] = 0;
1611
1612   /* Ensure use of this font causes a new one to be created @@@@ */
1613   DeleteObject(this->gdiFont);
1614   this->gdiFont = 0;
1615
1616   return S_OK;
1617 }
1618
1619 /************************************************************************
1620  * OLEFontImpl_Save (IPersistStream)
1621  *
1622  * See Windows documentation for more details on IPersistStream methods.
1623  */
1624 static HRESULT WINAPI OLEFontImpl_Save(
1625   IPersistStream*  iface,
1626   IStream*         pOutStream,
1627   BOOL             fClearDirty)
1628 {
1629   char* writeBuffer = NULL;
1630   ULONG cbWritten;
1631   BYTE  bVersion = 0x01;
1632   BYTE  bAttributes;
1633   BYTE  bStringSize;
1634
1635   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1636
1637   /*
1638    * Read the version byte
1639    */
1640   IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1641
1642   if (cbWritten!=1)
1643     return E_FAIL;
1644
1645   /*
1646    * Charset
1647    */
1648   IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1649
1650   if (cbWritten!=2)
1651     return E_FAIL;
1652
1653   /*
1654    * Attributes
1655    */
1656   bAttributes = 0;
1657
1658   if (this->description.fItalic)
1659     bAttributes |= FONTPERSIST_ITALIC;
1660
1661   if (this->description.fStrikethrough)
1662     bAttributes |= FONTPERSIST_STRIKETHROUGH;
1663
1664   if (this->description.fUnderline)
1665     bAttributes |= FONTPERSIST_UNDERLINE;
1666
1667   IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1668
1669   if (cbWritten!=1)
1670     return E_FAIL;
1671
1672   /*
1673    * Weight
1674    */
1675   IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1676
1677   if (cbWritten!=2)
1678     return E_FAIL;
1679
1680   /*
1681    * Size
1682    */
1683   IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1684
1685   if (cbWritten!=4)
1686     return E_FAIL;
1687
1688   /*
1689    * FontName
1690    */
1691   if (this->description.lpstrName!=0)
1692     bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1693                                        strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1694   else
1695     bStringSize = 0;
1696
1697   IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1698
1699   if (cbWritten!=1)
1700     return E_FAIL;
1701
1702   if (bStringSize!=0)
1703   {
1704       if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1705       WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1706                            strlenW(this->description.lpstrName),
1707                            writeBuffer, bStringSize, NULL, NULL );
1708
1709     IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1710     HeapFree(GetProcessHeap(), 0, writeBuffer);
1711
1712     if (cbWritten!=bStringSize)
1713       return E_FAIL;
1714   }
1715
1716   return S_OK;
1717 }
1718
1719 /************************************************************************
1720  * OLEFontImpl_GetSizeMax (IPersistStream)
1721  *
1722  * See Windows documentation for more details on IPersistStream methods.
1723  */
1724 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1725   IPersistStream*  iface,
1726   ULARGE_INTEGER*  pcbSize)
1727 {
1728   _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
1729
1730   if (pcbSize==NULL)
1731     return E_POINTER;
1732
1733   pcbSize->u.HighPart = 0;
1734   pcbSize->u.LowPart = 0;
1735
1736   pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
1737   pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
1738   pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
1739   pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
1740   pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1741   pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
1742
1743   if (this->description.lpstrName!=0)
1744     pcbSize->u.LowPart += lstrlenW(this->description.lpstrName);
1745
1746   return S_OK;
1747 }
1748
1749 /************************************************************************
1750  * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1751  *
1752  * See Windows documentation for more details on IUnknown methods.
1753  */
1754 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1755   IConnectionPointContainer* iface,
1756   REFIID     riid,
1757   VOID**     ppvoid)
1758 {
1759   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1760
1761   return IFont_QueryInterface((IFont*)this, riid, ppvoid);
1762 }
1763
1764 /************************************************************************
1765  * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
1766  *
1767  * See Windows documentation for more details on IUnknown methods.
1768  */
1769 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
1770   IConnectionPointContainer* iface)
1771 {
1772   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1773
1774   return IFont_Release((IFont*)this);
1775 }
1776
1777 /************************************************************************
1778  * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
1779  *
1780  * See Windows documentation for more details on IUnknown methods.
1781  */
1782 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
1783   IConnectionPointContainer* iface)
1784 {
1785   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1786
1787   return IFont_AddRef((IFont*)this);
1788 }
1789
1790 /************************************************************************
1791  * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
1792  *
1793  * See Windows documentation for more details on IConnectionPointContainer
1794  * methods.
1795  */
1796 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
1797   IConnectionPointContainer* iface,
1798   IEnumConnectionPoints **ppEnum)
1799 {
1800   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1801
1802   FIXME("(%p)->(%p): stub\n", this, ppEnum);
1803   return E_NOTIMPL;
1804 }
1805
1806 /************************************************************************
1807  * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
1808  *
1809  * See Windows documentation for more details on IConnectionPointContainer
1810  * methods.
1811  */
1812 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
1813    IConnectionPointContainer* iface,
1814    REFIID riid,
1815    IConnectionPoint **ppCp)
1816 {
1817   _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
1818   TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
1819
1820   if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) {
1821     return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint,
1822                                            (LPVOID)ppCp);
1823   } else {
1824     FIXME("Tried to find connection point on %s\n", debugstr_guid(riid));
1825     return E_NOINTERFACE;
1826   }
1827 }
1828
1829 /************************************************************************
1830  * OLEFontImpl implementation of IPersistPropertyBag.
1831  */
1832 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
1833    IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
1834 ) {
1835   _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
1836   return IFont_QueryInterface(this,riid,ppvObj);
1837 }
1838
1839 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
1840    IPersistPropertyBag *iface
1841 ) {
1842   _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
1843   return IFont_AddRef(this);
1844 }
1845
1846 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
1847    IPersistPropertyBag *iface
1848 ) {
1849   _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
1850   return IFont_Release(this);
1851 }
1852
1853 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
1854    IPersistPropertyBag *iface, CLSID *classid
1855 ) {
1856   FIXME("(%p,%p), stub!\n", iface, classid);
1857   return E_FAIL;
1858 }
1859
1860 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
1861    IPersistPropertyBag *iface
1862 ) {
1863   FIXME("(%p), stub!\n", iface);
1864   return S_OK;
1865 }
1866
1867 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
1868    IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
1869 ) {
1870 /* (from Visual Basic 6 property bag)
1871          Name            =   "MS Sans Serif"
1872          Size            =   13.8
1873          Charset         =   0
1874          Weight          =   400
1875          Underline       =   0   'False
1876          Italic          =   0   'False
1877          Strikethrough   =   0   'False
1878 */
1879     static const WCHAR sAttrName[] = {'N','a','m','e',0};
1880     static const WCHAR sAttrSize[] = {'S','i','z','e',0};
1881     static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
1882     static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
1883     static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
1884     static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
1885     static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
1886     VARIANT rawAttr;
1887     VARIANT valueAttr;
1888     HRESULT iRes = S_OK;
1889     _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
1890
1891     VariantInit(&rawAttr);
1892     VariantInit(&valueAttr);
1893
1894     if (iRes == S_OK) {
1895         iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
1896         if (iRes == S_OK)
1897         {
1898             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
1899             if (iRes == S_OK)
1900                 iRes = IFont_put_Name(this, V_BSTR(&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, sAttrSize, &rawAttr, pErrorLog);
1910         if (iRes == S_OK)
1911         {
1912             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
1913             if (iRes == S_OK)
1914                 iRes = IFont_put_Size(this, V_CY(&valueAttr));
1915         }
1916         else if (iRes == E_INVALIDARG)
1917             iRes = S_OK;
1918         VariantClear(&rawAttr);
1919         VariantClear(&valueAttr);
1920     }
1921
1922     if (iRes == S_OK) {
1923         iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
1924         if (iRes == S_OK)
1925         {
1926             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
1927             if (iRes == S_OK)
1928                 iRes = IFont_put_Charset(this, V_I2(&valueAttr));
1929         }
1930         else if (iRes == E_INVALIDARG)
1931             iRes = S_OK;
1932         VariantClear(&rawAttr);
1933         VariantClear(&valueAttr);
1934     }
1935
1936     if (iRes == S_OK) {
1937         iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
1938         if (iRes == S_OK)
1939         {
1940             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
1941             if (iRes == S_OK)
1942                 iRes = IFont_put_Weight(this, V_I2(&valueAttr));
1943         }
1944         else if (iRes == E_INVALIDARG)
1945             iRes = S_OK;
1946         VariantClear(&rawAttr);
1947         VariantClear(&valueAttr);
1948
1949     }
1950
1951     if (iRes == S_OK) {
1952         iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
1953         if (iRes == S_OK)
1954         {
1955             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
1956             if (iRes == S_OK)
1957                 iRes = IFont_put_Underline(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 (iRes == S_OK) {
1966         iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
1967         if (iRes == S_OK)
1968         {
1969             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
1970             if (iRes == S_OK)
1971                 iRes = IFont_put_Italic(this, V_BOOL(&valueAttr));
1972         }
1973         else if (iRes == E_INVALIDARG)
1974             iRes = S_OK;
1975         VariantClear(&rawAttr);
1976         VariantClear(&valueAttr);
1977     }
1978
1979     if (iRes == S_OK) {
1980         iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
1981         if (iRes == S_OK)
1982         {
1983             iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
1984             if (iRes == S_OK)
1985                 IFont_put_Strikethrough(this, V_BOOL(&valueAttr));
1986         }
1987         else if (iRes == E_INVALIDARG)
1988             iRes = S_OK;
1989         VariantClear(&rawAttr);
1990         VariantClear(&valueAttr);
1991     }
1992
1993     if (FAILED(iRes))
1994         WARN("-- 0x%08lx\n", iRes);
1995     return iRes;
1996 }
1997
1998 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
1999    IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2000    BOOL fSaveAllProperties
2001 ) {
2002   FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2003   return E_FAIL;
2004 }
2005
2006 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
2007 {
2008   OLEFontImpl_IPersistPropertyBag_QueryInterface,
2009   OLEFontImpl_IPersistPropertyBag_AddRef,
2010   OLEFontImpl_IPersistPropertyBag_Release,
2011
2012   OLEFontImpl_IPersistPropertyBag_GetClassID,
2013   OLEFontImpl_IPersistPropertyBag_InitNew,
2014   OLEFontImpl_IPersistPropertyBag_Load,
2015   OLEFontImpl_IPersistPropertyBag_Save
2016 };
2017
2018 /************************************************************************
2019  * OLEFontImpl implementation of IPersistStreamInit.
2020  */
2021 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2022    IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2023 ) {
2024   _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
2025   return IFont_QueryInterface(this,riid,ppvObj);
2026 }
2027
2028 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2029    IPersistStreamInit *iface
2030 ) {
2031   _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
2032   return IFont_AddRef(this);
2033 }
2034
2035 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2036    IPersistStreamInit *iface
2037 ) {
2038   _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
2039   return IFont_Release(this);
2040 }
2041
2042 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2043    IPersistStreamInit *iface, CLSID *classid
2044 ) {
2045   FIXME("(%p,%p), stub!\n", iface, classid);
2046   return E_FAIL;
2047 }
2048
2049 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2050    IPersistStreamInit *iface
2051 ) {
2052   FIXME("(%p), stub!\n", iface);
2053   return E_FAIL;
2054 }
2055
2056 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2057    IPersistStreamInit *iface, LPSTREAM pStm
2058 ) {
2059   FIXME("(%p,%p), stub!\n", iface, pStm);
2060   return E_FAIL;
2061 }
2062
2063 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2064    IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2065 ) {
2066   FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2067   return E_FAIL;
2068 }
2069
2070 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2071    IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2072 ) {
2073   FIXME("(%p,%p), stub!\n", iface, pcbSize);
2074   return E_FAIL;
2075 }
2076
2077 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2078    IPersistStreamInit *iface
2079 ) {
2080   FIXME("(%p), stub!\n", iface);
2081   return S_OK;
2082 }
2083
2084 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
2085 {
2086   OLEFontImpl_IPersistStreamInit_QueryInterface,
2087   OLEFontImpl_IPersistStreamInit_AddRef,
2088   OLEFontImpl_IPersistStreamInit_Release,
2089
2090   OLEFontImpl_IPersistStreamInit_GetClassID,
2091   OLEFontImpl_IPersistStreamInit_IsDirty,
2092   OLEFontImpl_IPersistStreamInit_Load,
2093   OLEFontImpl_IPersistStreamInit_Save,
2094   OLEFontImpl_IPersistStreamInit_GetSizeMax,
2095   OLEFontImpl_IPersistStreamInit_InitNew
2096 };
2097
2098 /*******************************************************************************
2099  * StdFont ClassFactory
2100  */
2101 typedef struct
2102 {
2103     /* IUnknown fields */
2104     const IClassFactoryVtbl    *lpVtbl;
2105     DWORD                       ref;
2106 } IClassFactoryImpl;
2107
2108 static HRESULT WINAPI
2109 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2110         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2111
2112         FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2113         return E_NOINTERFACE;
2114 }
2115
2116 static ULONG WINAPI
2117 SFCF_AddRef(LPCLASSFACTORY iface) {
2118         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2119         return InterlockedIncrement(&This->ref);
2120 }
2121
2122 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2123         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2124         /* static class, won't be  freed */
2125         return InterlockedDecrement(&This->ref);
2126 }
2127
2128 static HRESULT WINAPI SFCF_CreateInstance(
2129         LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2130 ) {
2131         return OleCreateFontIndirect(NULL,riid,ppobj);
2132
2133 }
2134
2135 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2136         IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2137         FIXME("(%p)->(%d),stub!\n",This,dolock);
2138         return S_OK;
2139 }
2140
2141 static const IClassFactoryVtbl SFCF_Vtbl = {
2142         SFCF_QueryInterface,
2143         SFCF_AddRef,
2144         SFCF_Release,
2145         SFCF_CreateInstance,
2146         SFCF_LockServer
2147 };
2148 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2149
2150 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }