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