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