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