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