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