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