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