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