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