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