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