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