set svn:eol-style to native
[reactos.git] / reactos / lib / oleaut32 / olefont.c
index 6ad98e2..eaceefe 100644 (file)
-/*\r
- * OLE Font encapsulation implementation\r
- *\r
- * This file contains an implementation of the IFont\r
- * interface and the OleCreateFontIndirect API call.\r
- *\r
- * Copyright 1999 Francis Beaudet\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-#include <assert.h>\r
-#include <stdarg.h>\r
-#include <string.h>\r
-\r
-#define COBJMACROS\r
-#define NONAMELESSUNION\r
-#define NONAMELESSSTRUCT\r
-\r
-#include "winerror.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "wingdi.h"\r
-#include "winuser.h"\r
-#include "wine/unicode.h"\r
-#include "objbase.h"\r
-#include "oleauto.h"    /* for SysAllocString(....) */\r
-#include "ole2.h"\r
-#include "olectl.h"\r
-#include "wine/debug.h"\r
-#include "connpt.h" /* for CreateConnectionPoint */\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
-\r
-/***********************************************************************\r
- * Declaration of constants used when serializing the font object.\r
- */\r
-#define FONTPERSIST_ITALIC        0x02\r
-#define FONTPERSIST_UNDERLINE     0x04\r
-#define FONTPERSIST_STRIKETHROUGH 0x08\r
-\r
-/***********************************************************************\r
- * Declaration of the implementation class for the IFont interface\r
- */\r
-typedef struct OLEFontImpl OLEFontImpl;\r
-\r
-struct OLEFontImpl\r
-{\r
-  /*\r
-   * This class supports many interfaces. IUnknown, IFont,\r
-   * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.\r
-   * The first two are supported by the first vtable, the next two are\r
-   * supported by the second table and the last two have their own.\r
-   */\r
-  IFontVtbl*                           lpvtbl1;\r
-  IDispatchVtbl*                       lpvtbl2;\r
-  IPersistStreamVtbl*                  lpvtbl3;\r
-  IConnectionPointContainerVtbl*       lpvtbl4;\r
-  IPersistPropertyBagVtbl*             lpvtbl5;\r
-  IPersistStreamInitVtbl*              lpvtbl6;\r
-  /*\r
-   * Reference count for that instance of the class.\r
-   */\r
-  ULONG ref;\r
-\r
-  /*\r
-   * This structure contains the description of the class.\r
-   */\r
-  FONTDESC description;\r
-\r
-  /*\r
-   * Contain the font associated with this object.\r
-   */\r
-  HFONT gdiFont;\r
-\r
-  /*\r
-   * Font lock count.\r
-   */\r
-  DWORD fontLock;\r
-\r
-  /*\r
-   * Size ratio\r
-   */\r
-  long cyLogical;\r
-  long cyHimetric;\r
-\r
-  IConnectionPoint *pCP;\r
-};\r
-\r
-/*\r
- * Here, I define utility macros to help with the casting of the\r
- * "this" parameter.\r
- * There is a version to accommodate all of the VTables implemented\r
- * by this object.\r
- */\r
-#define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*))\r
-#define _ICOM_THIS_From_IPersistStream(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*))\r
-#define _ICOM_THIS_From_IConnectionPointContainer(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*))\r
-#define _ICOM_THIS_From_IPersistPropertyBag(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*))\r
-#define _ICOM_THIS_From_IPersistStreamInit(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*))\r
-\r
-\r
-/***********************************************************************\r
- * Prototypes for the implementation functions for the IFont\r
- * interface\r
- */\r
-static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc);\r
-static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);\r
-static HRESULT      WINAPI OLEFontImpl_QueryInterface(IFont* iface, REFIID riid, VOID** ppvoid);\r
-static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);\r
-static ULONG        WINAPI OLEFontImpl_Release(IFont* iface);\r
-static HRESULT      WINAPI OLEFontImpl_get_Name(IFont* iface, BSTR* pname);\r
-static HRESULT      WINAPI OLEFontImpl_put_Name(IFont* iface, BSTR name);\r
-static HRESULT      WINAPI OLEFontImpl_get_Size(IFont* iface, CY* psize);\r
-static HRESULT      WINAPI OLEFontImpl_put_Size(IFont* iface, CY size);\r
-static HRESULT      WINAPI OLEFontImpl_get_Bold(IFont* iface, BOOL* pbold);\r
-static HRESULT      WINAPI OLEFontImpl_put_Bold(IFont* iface, BOOL bold);\r
-static HRESULT      WINAPI OLEFontImpl_get_Italic(IFont* iface, BOOL* pitalic);\r
-static HRESULT      WINAPI OLEFontImpl_put_Italic(IFont* iface, BOOL italic);\r
-static HRESULT      WINAPI OLEFontImpl_get_Underline(IFont* iface, BOOL* punderline);\r
-static HRESULT      WINAPI OLEFontImpl_put_Underline(IFont* iface, BOOL underline);\r
-static HRESULT      WINAPI OLEFontImpl_get_Strikethrough(IFont* iface, BOOL* pstrikethrough);\r
-static HRESULT      WINAPI OLEFontImpl_put_Strikethrough(IFont* iface, BOOL strikethrough);\r
-static HRESULT      WINAPI OLEFontImpl_get_Weight(IFont* iface, short* pweight);\r
-static HRESULT      WINAPI OLEFontImpl_put_Weight(IFont* iface, short weight);\r
-static HRESULT      WINAPI OLEFontImpl_get_Charset(IFont* iface, short* pcharset);\r
-static HRESULT      WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset);\r
-static HRESULT      WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont);\r
-static HRESULT      WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont);\r
-static HRESULT      WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther);\r
-static HRESULT      WINAPI OLEFontImpl_SetRatio(IFont* iface, LONG cyLogical, LONG cyHimetric);\r
-static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm);\r
-static HRESULT      WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont);\r
-static HRESULT      WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont);\r
-static HRESULT      WINAPI OLEFontImpl_SetHdc(IFont* iface, HDC hdc);\r
-\r
-/***********************************************************************\r
- * Prototypes for the implementation functions for the IDispatch\r
- * interface\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(IDispatch* iface,\r
-                                                   REFIID     riid,\r
-                                                   VOID**     ppvoid);\r
-static ULONG   WINAPI OLEFontImpl_IDispatch_AddRef(IDispatch* iface);\r
-static ULONG   WINAPI OLEFontImpl_IDispatch_Release(IDispatch* iface);\r
-static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(IDispatch*    iface,\r
-                                                  unsigned int* pctinfo);\r
-static HRESULT WINAPI OLEFontImpl_GetTypeInfo(IDispatch*  iface,\r
-                                             UINT      iTInfo,\r
-                                             LCID        lcid,\r
-                                             ITypeInfo** ppTInfo);\r
-static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(IDispatch*  iface,\r
-                                               REFIID      riid,\r
-                                               LPOLESTR* rgszNames,\r
-                                               UINT      cNames,\r
-                                               LCID        lcid,\r
-                                               DISPID*     rgDispId);\r
-static HRESULT WINAPI OLEFontImpl_Invoke(IDispatch*  iface,\r
-                                        DISPID      dispIdMember,\r
-                                        REFIID      riid,\r
-                                        LCID        lcid,\r
-                                        WORD        wFlags,\r
-                                        DISPPARAMS* pDispParams,\r
-                                        VARIANT*    pVarResult,\r
-                                        EXCEPINFO*  pExepInfo,\r
-                                        UINT*     puArgErr);\r
-\r
-/***********************************************************************\r
- * Prototypes for the implementation functions for the IPersistStream\r
- * interface\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(IPersistStream* iface,\r
-                                                   REFIID     riid,\r
-                                                   VOID**     ppvoid);\r
-static ULONG   WINAPI OLEFontImpl_IPersistStream_AddRef(IPersistStream* iface);\r
-static ULONG   WINAPI OLEFontImpl_IPersistStream_Release(IPersistStream* iface);\r
-static HRESULT WINAPI OLEFontImpl_GetClassID(IPersistStream* iface,\r
-                                            CLSID*                pClassID);\r
-static HRESULT WINAPI OLEFontImpl_IsDirty(IPersistStream*  iface);\r
-static HRESULT WINAPI OLEFontImpl_Load(IPersistStream*  iface,\r
-                                      IStream*         pLoadStream);\r
-static HRESULT WINAPI OLEFontImpl_Save(IPersistStream*  iface,\r
-                                      IStream*         pOutStream,\r
-                                      BOOL             fClearDirty);\r
-static HRESULT WINAPI OLEFontImpl_GetSizeMax(IPersistStream*  iface,\r
-                                            ULARGE_INTEGER*  pcbSize);\r
-\r
-/***********************************************************************\r
- * Prototypes for the implementation functions for the\r
- * IConnectionPointContainer interface\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(\r
-                                           IConnectionPointContainer* iface,\r
-                                           REFIID     riid,\r
-                                           VOID**     ppvoid);\r
-static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(\r
-                                           IConnectionPointContainer* iface);\r
-static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_Release(\r
-                                           IConnectionPointContainer* iface);\r
-static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(\r
-                                           IConnectionPointContainer* iface,\r
-                                           IEnumConnectionPoints **ppEnum);\r
-static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(\r
-                                           IConnectionPointContainer* iface,\r
-                                           REFIID riid,\r
-                                           IConnectionPoint **ppCp);\r
-\r
-/*\r
- * Virtual function tables for the OLEFontImpl class.\r
- */\r
-static IFontVtbl OLEFontImpl_VTable =\r
-{\r
-  OLEFontImpl_QueryInterface,\r
-  OLEFontImpl_AddRef,\r
-  OLEFontImpl_Release,\r
-  OLEFontImpl_get_Name,\r
-  OLEFontImpl_put_Name,\r
-  OLEFontImpl_get_Size,\r
-  OLEFontImpl_put_Size,\r
-  OLEFontImpl_get_Bold,\r
-  OLEFontImpl_put_Bold,\r
-  OLEFontImpl_get_Italic,\r
-  OLEFontImpl_put_Italic,\r
-  OLEFontImpl_get_Underline,\r
-  OLEFontImpl_put_Underline,\r
-  OLEFontImpl_get_Strikethrough,\r
-  OLEFontImpl_put_Strikethrough,\r
-  OLEFontImpl_get_Weight,\r
-  OLEFontImpl_put_Weight,\r
-  OLEFontImpl_get_Charset,\r
-  OLEFontImpl_put_Charset,\r
-  OLEFontImpl_get_hFont,\r
-  OLEFontImpl_Clone,\r
-  OLEFontImpl_IsEqual,\r
-  OLEFontImpl_SetRatio,\r
-  OLEFontImpl_QueryTextMetrics,\r
-  OLEFontImpl_AddRefHfont,\r
-  OLEFontImpl_ReleaseHfont,\r
-  OLEFontImpl_SetHdc\r
-};\r
-\r
-static IDispatchVtbl OLEFontImpl_IDispatch_VTable =\r
-{\r
-  OLEFontImpl_IDispatch_QueryInterface,\r
-  OLEFontImpl_IDispatch_AddRef,\r
-  OLEFontImpl_IDispatch_Release,\r
-  OLEFontImpl_GetTypeInfoCount,\r
-  OLEFontImpl_GetTypeInfo,\r
-  OLEFontImpl_GetIDsOfNames,\r
-  OLEFontImpl_Invoke\r
-};\r
-\r
-static IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =\r
-{\r
-  OLEFontImpl_IPersistStream_QueryInterface,\r
-  OLEFontImpl_IPersistStream_AddRef,\r
-  OLEFontImpl_IPersistStream_Release,\r
-  OLEFontImpl_GetClassID,\r
-  OLEFontImpl_IsDirty,\r
-  OLEFontImpl_Load,\r
-  OLEFontImpl_Save,\r
-  OLEFontImpl_GetSizeMax\r
-};\r
-\r
-static IConnectionPointContainerVtbl\r
-     OLEFontImpl_IConnectionPointContainer_VTable =\r
-{\r
-  OLEFontImpl_IConnectionPointContainer_QueryInterface,\r
-  OLEFontImpl_IConnectionPointContainer_AddRef,\r
-  OLEFontImpl_IConnectionPointContainer_Release,\r
-  OLEFontImpl_EnumConnectionPoints,\r
-  OLEFontImpl_FindConnectionPoint\r
-};\r
-\r
-static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable;\r
-static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable;\r
-/******************************************************************************\r
- *             OleCreateFontIndirect   [OLEAUT32.420]\r
- */\r
-HRESULT WINAPI OleCreateFontIndirect(\r
-  LPFONTDESC lpFontDesc,\r
-  REFIID     riid,\r
-  LPVOID*     ppvObj)\r
-{\r
-  OLEFontImpl* newFont = 0;\r
-  HRESULT      hr      = S_OK;\r
-\r
-  TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (ppvObj==0)\r
-    return E_POINTER;\r
-\r
-  *ppvObj = 0;\r
-\r
-  if (!lpFontDesc) {\r
-    FONTDESC fd;\r
-\r
-    static const WCHAR fname[] = { 'S','y','s','t','e','m',0 };\r
-\r
-    fd.cbSizeofstruct = sizeof(fd);\r
-    fd.lpstrName      = (WCHAR*)fname;\r
-    fd.cySize.s.Lo    = 80000;\r
-    fd.cySize.s.Hi    = 0;\r
-    fd.sWeight               = 0;\r
-    fd.sCharset       = 0;\r
-    fd.fItalic       = 0;\r
-    fd.fUnderline     = 0;\r
-    fd.fStrikethrough = 0;\r
-    lpFontDesc = &fd;\r
-  }\r
-\r
-  /*\r
-   * Try to construct a new instance of the class.\r
-   */\r
-  newFont = OLEFontImpl_Construct(lpFontDesc);\r
-\r
-  if (newFont == 0)\r
-    return E_OUTOFMEMORY;\r
-\r
-  /*\r
-   * Make sure it supports the interface required by the caller.\r
-   */\r
-  hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);\r
-\r
-  /*\r
-   * Release the reference obtained in the constructor. If\r
-   * the QueryInterface was unsuccessful, it will free the class.\r
-   */\r
-  IFont_Release((IFont*)newFont);\r
-\r
-  return hr;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * Implementation of the OLEFontImpl class.\r
- */\r
-\r
-/***********************************************************************\r
- *    OLEFont_SendNotify (internal)\r
- *\r
- * Sends notification messages of changed properties to any interested\r
- * connections.\r
- */\r
-static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)\r
-{\r
-  IEnumConnections *pEnum;\r
-  CONNECTDATA CD;\r
-  HRESULT hres;\r
-\r
-  hres = IConnectionPoint_EnumConnections(this->pCP, &pEnum);\r
-  if (FAILED(hres)) /* When we have 0 connections. */\r
-    return;\r
-\r
-  while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {\r
-    IPropertyNotifySink *sink;\r
-\r
-    IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);\r
-    IPropertyNotifySink_OnChanged(sink, dispID);\r
-    IPropertyNotifySink_Release(sink);\r
-    IUnknown_Release(CD.pUnk);\r
-  }\r
-  IEnumConnections_Release(pEnum);\r
-  return;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Construct\r
- *\r
- * This method will construct a new instance of the OLEFontImpl\r
- * class.\r
- *\r
- * The caller of this method must release the object when it's\r
- * done with it.\r
- */\r
-static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc)\r
-{\r
-  OLEFontImpl* newObject = 0;\r
-\r
-  /*\r
-   * Allocate space for the object.\r
-   */\r
-  newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));\r
-\r
-  if (newObject==0)\r
-    return newObject;\r
-\r
-  /*\r
-   * Initialize the virtual function table.\r
-   */\r
-  newObject->lpvtbl1 = &OLEFontImpl_VTable;\r
-  newObject->lpvtbl2 = &OLEFontImpl_IDispatch_VTable;\r
-  newObject->lpvtbl3 = &OLEFontImpl_IPersistStream_VTable;\r
-  newObject->lpvtbl4 = &OLEFontImpl_IConnectionPointContainer_VTable;\r
-  newObject->lpvtbl5 = &OLEFontImpl_IPersistPropertyBag_VTable;\r
-  newObject->lpvtbl6 = &OLEFontImpl_IPersistStreamInit_VTable;\r
-\r
-  /*\r
-   * Start with one reference count. The caller of this function\r
-   * must release the interface pointer when it is done.\r
-   */\r
-  newObject->ref = 1;\r
-\r
-  /*\r
-   * Copy the description of the font in the object.\r
-   */\r
-  assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));\r
-\r
-  newObject->description.cbSizeofstruct = sizeof(FONTDESC);\r
-  newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),\r
-                                              0,\r
-                                              (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));\r
-  strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);\r
-  newObject->description.cySize         = fontDesc->cySize;\r
-  newObject->description.sWeight        = fontDesc->sWeight;\r
-  newObject->description.sCharset       = fontDesc->sCharset;\r
-  newObject->description.fItalic        = fontDesc->fItalic;\r
-  newObject->description.fUnderline     = fontDesc->fUnderline;\r
-  newObject->description.fStrikethrough = fontDesc->fStrikethrough;\r
-\r
-  /*\r
-   * Initializing all the other members.\r
-   */\r
-  newObject->gdiFont  = 0;\r
-  newObject->fontLock = 0;\r
-  newObject->cyLogical  = 72L;\r
-  newObject->cyHimetric = 2540L;\r
-  CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pCP);\r
-  TRACE("returning %p\n", newObject);\r
-  return newObject;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Destroy\r
- *\r
- * This method is called by the Release method when the reference\r
- * count goes down to 0. It will free all resources used by\r
- * this object.\r
- */\r
-static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)\r
-{\r
-  TRACE("(%p)\n", fontDesc);\r
-\r
-  HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);\r
-\r
-  if (fontDesc->gdiFont!=0)\r
-    DeleteObject(fontDesc->gdiFont);\r
-\r
-  HeapFree(GetProcessHeap(), 0, fontDesc);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_QueryInterface (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-HRESULT WINAPI OLEFontImpl_QueryInterface(\r
-  IFont*  iface,\r
-  REFIID  riid,\r
-  void**  ppvObject)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);\r
-\r
-  /*\r
-   * Perform a sanity check on the parameters.\r
-   */\r
-  if ( (this==0) || (ppvObject==0) )\r
-    return E_INVALIDARG;\r
-\r
-  /*\r
-   * Initialize the return parameter.\r
-   */\r
-  *ppvObject = 0;\r
-\r
-  /*\r
-   * Compare the riid with the interface IDs implemented by this object.\r
-   */\r
-  if (IsEqualGUID(&IID_IUnknown, riid))\r
-    *ppvObject = (IFont*)this;\r
-  if (IsEqualGUID(&IID_IFont, riid))\r
-    *ppvObject = (IFont*)this;\r
-  if (IsEqualGUID(&IID_IDispatch, riid))\r
-    *ppvObject = (IDispatch*)&(this->lpvtbl2);\r
-  if (IsEqualGUID(&IID_IFontDisp, riid))\r
-    *ppvObject = (IDispatch*)&(this->lpvtbl2);\r
-  if (IsEqualGUID(&IID_IPersistStream, riid))\r
-    *ppvObject = (IPersistStream*)&(this->lpvtbl3);\r
-  if (IsEqualGUID(&IID_IConnectionPointContainer, riid))\r
-    *ppvObject = (IConnectionPointContainer*)&(this->lpvtbl4);\r
-  if (IsEqualGUID(&IID_IPersistPropertyBag, riid))\r
-    *ppvObject = (IPersistPropertyBag*)&(this->lpvtbl5);\r
-  if (IsEqualGUID(&IID_IPersistStreamInit, riid))\r
-    *ppvObject = (IPersistStreamInit*)&(this->lpvtbl6);\r
-\r
-  /*\r
-   * Check that we obtained an interface.\r
-   */\r
-  if ((*ppvObject)==0)\r
-  {\r
-    FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));\r
-    return E_NOINTERFACE;\r
-  }\r
-  OLEFontImpl_AddRef((IFont*)this);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_AddRef (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-ULONG WINAPI OLEFontImpl_AddRef(\r
-  IFont* iface)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(ref=%ld)\n", this, this->ref);\r
-  return InterlockedIncrement(&this->ref);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Release (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-ULONG WINAPI OLEFontImpl_Release(\r
-      IFont* iface)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  ULONG ret;\r
-  TRACE("(%p)->(ref=%ld)\n", this, this->ref);\r
-\r
-  /*\r
-   * Decrease the reference count on this object.\r
-   */\r
-  ret = InterlockedDecrement(&this->ref);\r
-\r
-  /*\r
-   * If the reference count goes down to 0, perform suicide.\r
-   */\r
-  if (ret==0) OLEFontImpl_Destroy(this);\r
-\r
-  return ret;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Name (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Name(\r
-  IFont*  iface,\r
-  BSTR* pname)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pname);\r
-  /*\r
-   * Sanity check.\r
-   */\r
-  if (pname==0)\r
-    return E_POINTER;\r
-\r
-  if (this->description.lpstrName!=0)\r
-    *pname = SysAllocString(this->description.lpstrName);\r
-  else\r
-    *pname = 0;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Name (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Name(\r
-  IFont* iface,\r
-  BSTR name)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, name);\r
-\r
-  if (this->description.lpstrName==0)\r
-  {\r
-    this->description.lpstrName = HeapAlloc(GetProcessHeap(),\r
-                                           0,\r
-                                           (lstrlenW(name)+1) * sizeof(WCHAR));\r
-  }\r
-  else\r
-  {\r
-    this->description.lpstrName = HeapReAlloc(GetProcessHeap(),\r
-                                             0,\r
-                                             this->description.lpstrName,\r
-                                             (lstrlenW(name)+1) * sizeof(WCHAR));\r
-  }\r
-\r
-  if (this->description.lpstrName==0)\r
-    return E_OUTOFMEMORY;\r
-\r
-  strcpyW(this->description.lpstrName, name);\r
-  TRACE("new name %s\n", debugstr_w(this->description.lpstrName));\r
-  OLEFont_SendNotify(this, DISPID_FONT_NAME);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Size (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Size(\r
-  IFont* iface,\r
-  CY*    psize)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, psize);\r
-\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (psize==0)\r
-    return E_POINTER;\r
-\r
-  psize->s.Hi = 0;\r
-  psize->s.Lo = this->description.cySize.s.Lo;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Size (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Size(\r
-  IFont* iface,\r
-  CY     size)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%ld)\n", this, size.s.Lo);\r
-  this->description.cySize.s.Hi = 0;\r
-  this->description.cySize.s.Lo = size.s.Lo;\r
-  OLEFont_SendNotify(this, DISPID_FONT_SIZE);\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Bold (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Bold(\r
-  IFont*  iface,\r
-  BOOL* pbold)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pbold);\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (pbold==0)\r
-    return E_POINTER;\r
-\r
-  *pbold = this->description.sWeight > 550;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Bold (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Bold(\r
-  IFont* iface,\r
-  BOOL bold)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, bold);\r
-  this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;\r
-  OLEFont_SendNotify(this, DISPID_FONT_BOLD);\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Italic (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Italic(\r
-  IFont*  iface,\r
-  BOOL* pitalic)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pitalic);\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (pitalic==0)\r
-    return E_POINTER;\r
-\r
-  *pitalic = this->description.fItalic;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Italic (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Italic(\r
-  IFont* iface,\r
-  BOOL italic)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, italic);\r
-\r
-  this->description.fItalic = italic;\r
-\r
-  OLEFont_SendNotify(this, DISPID_FONT_ITALIC);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Underline (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Underline(\r
-  IFont*  iface,\r
-  BOOL* punderline)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, punderline);\r
-\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (punderline==0)\r
-    return E_POINTER;\r
-\r
-  *punderline = this->description.fUnderline;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Underline (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Underline(\r
-  IFont* iface,\r
-  BOOL underline)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, underline);\r
-\r
-  this->description.fUnderline = underline;\r
-\r
-  OLEFont_SendNotify(this, DISPID_FONT_UNDER);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Strikethrough (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Strikethrough(\r
-  IFont*  iface,\r
-  BOOL* pstrikethrough)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pstrikethrough);\r
-\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (pstrikethrough==0)\r
-    return E_POINTER;\r
-\r
-  *pstrikethrough = this->description.fStrikethrough;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Strikethrough (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Strikethrough(\r
- IFont* iface,\r
- BOOL strikethrough)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, strikethrough);\r
-\r
-  this->description.fStrikethrough = strikethrough;\r
-  OLEFont_SendNotify(this, DISPID_FONT_STRIKE);\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Weight (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Weight(\r
-  IFont* iface,\r
-  short* pweight)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pweight);\r
-\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (pweight==0)\r
-    return E_POINTER;\r
-\r
-  *pweight = this->description.sWeight;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Weight (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Weight(\r
-  IFont* iface,\r
-  short  weight)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, weight);\r
-\r
-  this->description.sWeight = weight;\r
-\r
-  OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_Charset (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_Charset(\r
-  IFont* iface,\r
-  short* pcharset)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, pcharset);\r
-\r
-  /*\r
-   * Sanity check\r
-   */\r
-  if (pcharset==0)\r
-    return E_POINTER;\r
-\r
-  *pcharset = this->description.sCharset;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_put_Charset (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_put_Charset(\r
-  IFont* iface,\r
-  short charset)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%d)\n", this, charset);\r
-\r
-  this->description.sCharset = charset;\r
-  OLEFont_SendNotify(this, DISPID_FONT_CHARSET);\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_get_hFont (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_get_hFont(\r
-  IFont*   iface,\r
-  HFONT* phfont)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, phfont);\r
-  if (phfont==NULL)\r
-    return E_POINTER;\r
-\r
-  /*\r
-   * Realize the font if necessary\r
- */\r
-  if (this->gdiFont==0)\r
-{\r
-    LOGFONTW logFont;\r
-    INT      fontHeight;\r
-    CY       cySize;\r
-\r
-    /*\r
-     * The height of the font returned by the get_Size property is the\r
-     * height of the font in points multiplied by 10000... Using some\r
-     * simple conversions and the ratio given by the application, it can\r
-     * be converted to a height in pixels.\r
-     */\r
-    IFont_get_Size(iface, &cySize);\r
-\r
-    fontHeight = MulDiv( cySize.s.Lo, this->cyLogical, this->cyHimetric );\r
-\r
-    memset(&logFont, 0, sizeof(LOGFONTW));\r
-\r
-    logFont.lfHeight          = ((fontHeight%10000L)>5000L) ?  (-fontHeight/10000L)-1 :\r
-                                                               (-fontHeight/10000L);\r
-    logFont.lfItalic          = this->description.fItalic;\r
-    logFont.lfUnderline       = this->description.fUnderline;\r
-    logFont.lfStrikeOut       = this->description.fStrikethrough;\r
-    logFont.lfWeight          = this->description.sWeight;\r
-    logFont.lfCharSet         = this->description.sCharset;\r
-    logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;\r
-    logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;\r
-    logFont.lfQuality         = DEFAULT_QUALITY;\r
-    logFont.lfPitchAndFamily  = DEFAULT_PITCH;\r
-    strcpyW(logFont.lfFaceName,this->description.lpstrName);\r
-\r
-    this->gdiFont = CreateFontIndirectW(&logFont);\r
-  }\r
-\r
-  *phfont = this->gdiFont;\r
-  TRACE("Returning %p\n", *phfont);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Clone (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_Clone(\r
-  IFont*  iface,\r
-  IFont** ppfont)\r
-{\r
-  OLEFontImpl* newObject = 0;\r
-  LOGFONTW logFont;\r
-  INT      fontHeight;\r
-  CY       cySize;\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p)\n", this, ppfont);\r
-\r
-  if (ppfont == NULL)\r
-    return E_POINTER;\r
-\r
-  *ppfont = NULL;\r
-\r
-  /*\r
-   * Allocate space for the object.\r
-   */\r
-  newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));\r
-\r
-  if (newObject==NULL)\r
-    return E_OUTOFMEMORY;\r
-\r
-  *newObject = *this;\r
-\r
-  /* We need to alloc new memory for the string, otherwise\r
-   * we free memory twice.\r
-   */\r
-  newObject->description.lpstrName = HeapAlloc(\r
-       GetProcessHeap(),0,\r
-       (1+strlenW(this->description.lpstrName))*2\r
-  );\r
-  strcpyW(newObject->description.lpstrName, this->description.lpstrName);\r
-  /* We need to clone the HFONT too. This is just cut & paste from above */\r
-  IFont_get_Size(iface, &cySize);\r
-\r
-  fontHeight = MulDiv(cySize.s.Lo, this->cyLogical,this->cyHimetric);\r
-\r
-  memset(&logFont, 0, sizeof(LOGFONTW));\r
-\r
-  logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :\r
-                                                           (-fontHeight/10000L);\r
-  logFont.lfItalic          = this->description.fItalic;\r
-  logFont.lfUnderline       = this->description.fUnderline;\r
-  logFont.lfStrikeOut       = this->description.fStrikethrough;\r
-  logFont.lfWeight          = this->description.sWeight;\r
-  logFont.lfCharSet         = this->description.sCharset;\r
-  logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;\r
-  logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;\r
-  logFont.lfQuality         = DEFAULT_QUALITY;\r
-  logFont.lfPitchAndFamily  = DEFAULT_PITCH;\r
-  strcpyW(logFont.lfFaceName,this->description.lpstrName);\r
-\r
-  newObject->gdiFont = CreateFontIndirectW(&logFont);\r
-\r
-\r
-  /* The cloned object starts with a reference count of 1 */\r
-  newObject->ref          = 1;\r
-\r
-  *ppfont = (IFont*)newObject;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IsEqual (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IsEqual(\r
-  IFont* iface,\r
-  IFont* pFontOther)\r
-{\r
-  FIXME("(%p, %p), stub!\n",iface,pFontOther);\r
-  return E_NOTIMPL;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_SetRatio (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_SetRatio(\r
-  IFont* iface,\r
-  LONG   cyLogical,\r
-  LONG   cyHimetric)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric);\r
-\r
-  this->cyLogical  = cyLogical;\r
-  this->cyHimetric = cyHimetric;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_QueryTextMetrics (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(\r
-  IFont*         iface,\r
-  TEXTMETRICOLE* ptm)\r
-{\r
-  HDC hdcRef;\r
-  HFONT hOldFont, hNewFont;\r
-\r
-  hdcRef = GetDC(0);\r
-  OLEFontImpl_get_hFont(iface, &hNewFont);\r
-  hOldFont = SelectObject(hdcRef, hNewFont);\r
-  GetTextMetricsW(hdcRef, ptm);\r
-  SelectObject(hdcRef, hOldFont);\r
-  ReleaseDC(0, hdcRef);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_AddRefHfont (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_AddRefHfont(\r
-  IFont*  iface,\r
-  HFONT hfont)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);\r
-\r
-  if ( (hfont == 0) ||\r
-       (hfont != this->gdiFont) )\r
-    return E_INVALIDARG;\r
-\r
-  this->fontLock++;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_ReleaseHfont (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_ReleaseHfont(\r
-  IFont*  iface,\r
-  HFONT hfont)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);\r
-\r
-  if ( (hfont == 0) ||\r
-       (hfont != this->gdiFont) )\r
-    return E_INVALIDARG;\r
-\r
-  this->fontLock--;\r
-\r
-  /*\r
-   * If we just released our last font reference, destroy it.\r
-   */\r
-  if (this->fontLock==0)\r
-  {\r
-    DeleteObject(this->gdiFont);\r
-    this->gdiFont = 0;\r
-  }\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_SetHdc (IFont)\r
- *\r
- * See Windows documentation for more details on IFont methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_SetHdc(\r
-  IFont* iface,\r
-  HDC  hdc)\r
-{\r
-  OLEFontImpl *this = (OLEFontImpl *)iface;\r
-  FIXME("(%p)->(%p): Stub\n", this, hdc);\r
-  return E_NOTIMPL;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IDispatch_QueryInterface (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(\r
-  IDispatch* iface,\r
-  REFIID     riid,\r
-  VOID**     ppvoid)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-\r
-  return IFont_QueryInterface(this, riid, ppvoid);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IDispatch_Release (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IDispatch_Release(\r
-  IDispatch* iface)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-\r
-  return IFont_Release(this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IDispatch_AddRef (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(\r
-  IDispatch* iface)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-\r
-  return IFont_AddRef(this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_GetTypeInfoCount (IDispatch)\r
- *\r
- * See Windows documentation for more details on IDispatch methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(\r
-  IDispatch*    iface,\r
-  unsigned int* pctinfo)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-  FIXME("(%p)->(%p): Stub\n", this, pctinfo);\r
-\r
-  return E_NOTIMPL;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_GetTypeInfo (IDispatch)\r
- *\r
- * See Windows documentation for more details on IDispatch methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_GetTypeInfo(\r
-  IDispatch*  iface,\r
-  UINT      iTInfo,\r
-  LCID        lcid,\r
-  ITypeInfo** ppTInfo)\r
-{\r
-  static const WCHAR stdole32tlb[] = {'s','t','d','o','l','e','3','2','.','t','l','b',0};\r
-  ITypeLib *tl;\r
-  HRESULT hres;\r
-\r
-  _ICOM_THIS_From_IDispatch(OLEFontImpl, iface);\r
-  TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);\r
-  if (iTInfo != 0)\r
-    return E_FAIL;\r
-  hres = LoadTypeLib(stdole32tlb, &tl);\r
-  if (FAILED(hres)) {\r
-    ERR("Could not load the stdole32.tlb?\n");\r
-    return hres;\r
-  }\r
-  hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IDispatch, ppTInfo);\r
-  if (FAILED(hres)) {\r
-    FIXME("Did not IDispatch typeinfo from typelib, hres %lx\n",hres);\r
-  }\r
-  return hres;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_GetIDsOfNames (IDispatch)\r
- *\r
- * See Windows documentation for more details on IDispatch methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(\r
-  IDispatch*  iface,\r
-  REFIID      riid,\r
-  LPOLESTR* rgszNames,\r
-  UINT      cNames,\r
-  LCID        lcid,\r
-  DISPID*     rgDispId)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-  FIXME("(%p,%s,%p,%d,%04x,%p), stub!\n", this, debugstr_guid(riid), rgszNames,\r
-       cNames, (int)lcid, rgDispId\r
-  );\r
-  return E_NOTIMPL;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Invoke (IDispatch)\r
- *\r
- * See Windows documentation for more details on IDispatch methods.\r
- * \r
- * Note: Do not call _put_Xxx methods, since setting things here\r
- * should not call notify functions as I found out debugging the generic\r
- * MS VB5 installer.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_Invoke(\r
-  IDispatch*  iface,\r
-  DISPID      dispIdMember,\r
-  REFIID      riid,\r
-  LCID        lcid,\r
-  WORD        wFlags,\r
-  DISPPARAMS* pDispParams,\r
-  VARIANT*    pVarResult,\r
-  EXCEPINFO*  pExepInfo,\r
-  UINT*     puArgErr)\r
-{\r
-  _ICOM_THIS_From_IDispatch(IFont, iface);\r
-  OLEFontImpl *xthis = (OLEFontImpl*)this;\r
-\r
-  switch (dispIdMember) {\r
-  case DISPID_FONT_NAME:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_BSTR;\r
-      return OLEFontImpl_get_Name(this, &V_BSTR(pVarResult));\r
-    case DISPATCH_PROPERTYPUT: {\r
-      BSTR name;\r
-      BOOL freename;\r
-      \r
-      if (V_VT(&pDispParams->rgvarg[0]) == VT_DISPATCH) {\r
-        IFont *font;\r
-        HRESULT hr = S_OK;\r
-        \r
-        hr = IUnknown_QueryInterface(V_DISPATCH(&pDispParams->rgvarg[0]), &IID_IFont, (void **) &font);\r
-        if (FAILED(hr))\r
-        {\r
-            FIXME("dispatch value for name property is not an OleFont, returning hr=0x%lx\n", hr);\r
-            return hr;\r
-        }\r
-\r
-        hr = IFont_get_Name(font, &name); /* this allocates a new BSTR so free it later */\r
-        if (FAILED(hr)) return hr;\r
-\r
-        IUnknown_Release(font);\r
-        \r
-        freename = TRUE;\r
-      } else if (V_VT(&pDispParams->rgvarg[0]) == VT_BSTR) {\r
-        name = V_BSTR(&pDispParams->rgvarg[0]);\r
-        freename = FALSE;\r
-      } else {\r
-        FIXME("app is trying to set name property with a non BSTR, non dispatch value. returning E_FAIL\n");\r
-        return E_FAIL;\r
-      }\r
-\r
-      TRACE("name is %s\n", debugstr_w(name));\r
-      \r
-      if (!xthis->description.lpstrName)\r
-       xthis->description.lpstrName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1) * sizeof(WCHAR));\r
-      else\r
-       xthis->description.lpstrName = HeapReAlloc(GetProcessHeap(), 0, xthis->description.lpstrName, (lstrlenW(name)+1) * sizeof(WCHAR));\r
-\r
-      if (xthis->description.lpstrName==0)\r
-       return E_OUTOFMEMORY;\r
-      strcpyW(xthis->description.lpstrName, name);\r
-\r
-      if (freename) SysFreeString(name);\r
-      \r
-      return S_OK;\r
-    }\r
-    }\r
-    break;\r
-  case DISPID_FONT_BOLD:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_BOOL;\r
-      return OLEFontImpl_get_Bold(this, (BOOL*)&V_BOOL(pVarResult));\r
-    case DISPATCH_PROPERTYPUT:\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {\r
-       FIXME("DISPID_FONT_BOLD/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));\r
-       return E_FAIL;\r
-      } else {\r
-        xthis->description.sWeight = V_BOOL(&pDispParams->rgvarg[0]) ? FW_BOLD : FW_NORMAL;\r
-       return S_OK;\r
-      }\r
-    }\r
-    break;\r
-  case DISPID_FONT_ITALIC:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_BOOL;\r
-      return OLEFontImpl_get_Italic(this, (BOOL*)&V_BOOL(pVarResult));\r
-    case DISPATCH_PROPERTYPUT:\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {\r
-       FIXME("DISPID_FONT_ITALIC/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));\r
-       return E_FAIL;\r
-      } else {\r
-        xthis->description.fItalic = V_BOOL(&pDispParams->rgvarg[0]);\r
-       return S_OK;\r
-      }\r
-    }\r
-    break;\r
-  case DISPID_FONT_UNDER:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_BOOL;\r
-      return OLEFontImpl_get_Underline(this, (BOOL*)&V_BOOL(pVarResult));\r
-    case DISPATCH_PROPERTYPUT:\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {\r
-       FIXME("DISPID_FONT_UNDER/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));\r
-       return E_FAIL;\r
-      } else {\r
-        xthis->description.fUnderline = V_BOOL(&pDispParams->rgvarg[0]);\r
-       return S_OK;\r
-      }\r
-    }\r
-    break;\r
-  case DISPID_FONT_STRIKE:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_BOOL;\r
-      return OLEFontImpl_get_Strikethrough(this, (BOOL*)&V_BOOL(pVarResult));\r
-    case DISPATCH_PROPERTYPUT:\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {\r
-       FIXME("DISPID_FONT_STRIKE/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));\r
-       return E_FAIL;\r
-      } else {\r
-        xthis->description.fStrikethrough = V_BOOL(&pDispParams->rgvarg[0]);\r
-       return S_OK;\r
-      }\r
-    }\r
-    break;\r
-  case DISPID_FONT_SIZE:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYPUT: {\r
-      assert (pDispParams->cArgs == 1);\r
-      xthis->description.cySize.s.Hi = 0;\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_CY) {\r
-        if (V_VT(&pDispParams->rgvarg[0]) == VT_I2) {\r
-         xthis->description.cySize.s.Lo = V_I2(&pDispParams->rgvarg[0]) * 10000;\r
-       } else {\r
-         FIXME("property put for Size with vt %d unsupported!\n",V_VT(&pDispParams->rgvarg[0]));\r
-       }\r
-      } else {\r
-        xthis->description.cySize.s.Lo = V_CY(&pDispParams->rgvarg[0]).s.Lo;\r
-      }\r
-      return S_OK;\r
-    }\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_CY;\r
-      return OLEFontImpl_get_Size(this, &V_CY(pVarResult));\r
-    }\r
-    break;\r
-  case DISPID_FONT_CHARSET:\r
-    switch (wFlags) {\r
-    case DISPATCH_PROPERTYPUT:\r
-      assert (pDispParams->cArgs == 1);\r
-      if (V_VT(&pDispParams->rgvarg[0]) != VT_I2)\r
-       FIXME("varg of first disparg is not VT_I2, but %d\n",V_VT(&pDispParams->rgvarg[0]));\r
-      xthis->description.sCharset = V_I2(&pDispParams->rgvarg[0]);\r
-      return S_OK;\r
-    case DISPATCH_PROPERTYGET:\r
-    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:\r
-      V_VT(pVarResult) = VT_I2;\r
-      return OLEFontImpl_get_Charset(this, &V_I2(pVarResult));\r
-    }\r
-    break;\r
-  }\r
-  FIXME("%p->(%ld,%s,%lx,%x,%p,%p,%p,%p), unhandled dispid/flag!\n",\r
-    this,dispIdMember,debugstr_guid(riid),lcid,\r
-    wFlags,pDispParams,pVarResult,pExepInfo,puArgErr\r
-  );\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(\r
-  IPersistStream* iface,\r
-  REFIID     riid,\r
-  VOID**     ppvoid)\r
-{\r
-  _ICOM_THIS_From_IPersistStream(IFont, iface);\r
-\r
-  return IFont_QueryInterface(this, riid, ppvoid);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IPersistStream_Release (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IPersistStream_Release(\r
-  IPersistStream* iface)\r
-{\r
-  _ICOM_THIS_From_IPersistStream(IFont, iface);\r
-\r
-  return IFont_Release(this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IPersistStream_AddRef (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(\r
-  IPersistStream* iface)\r
-{\r
-  _ICOM_THIS_From_IPersistStream(IFont, iface);\r
-\r
-  return IFont_AddRef(this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_GetClassID (IPersistStream)\r
- *\r
- * See Windows documentation for more details on IPersistStream methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_GetClassID(\r
-  IPersistStream* iface,\r
-  CLSID*                pClassID)\r
-{\r
-  TRACE("(%p,%p)\n",iface,pClassID);\r
-  if (pClassID==0)\r
-    return E_POINTER;\r
-\r
-  memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IsDirty (IPersistStream)\r
- *\r
- * See Windows documentation for more details on IPersistStream methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IsDirty(\r
-  IPersistStream*  iface)\r
-{\r
-  TRACE("(%p)\n",iface);\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Load (IPersistStream)\r
- *\r
- * See Windows documentation for more details on IPersistStream methods.\r
- *\r
- * This is the format of the standard font serialization as far as I\r
- * know\r
- *\r
- * Offset   Type   Value           Comment\r
- * 0x0000   Byte   Unknown         Probably a version number, contains 0x01\r
- * 0x0001   Short  Charset         Charset value from the FONTDESC structure\r
- * 0x0003   Byte   Attributes      Flags defined as follows:\r
- *                                     00000010 - Italic\r
- *                                     00000100 - Underline\r
- *                                     00001000 - Strikethrough\r
- * 0x0004   Short  Weight          Weight value from FONTDESC structure\r
- * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC\r
- *                                 structure/\r
- * 0x000A   Byte   name length     Length of the font name string (no null character)\r
- * 0x000B   String name            Name of the font (ASCII, no nul character)\r
- */\r
-static HRESULT WINAPI OLEFontImpl_Load(\r
-  IPersistStream*  iface,\r
-  IStream*         pLoadStream)\r
-{\r
-  char  readBuffer[0x100];\r
-  ULONG cbRead;\r
-  BYTE  bVersion;\r
-  BYTE  bAttributes;\r
-  BYTE  bStringSize;\r
-  INT len;\r
-\r
-  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);\r
-\r
-  /*\r
-   * Read the version byte\r
-   */\r
-  IStream_Read(pLoadStream, &bVersion, 1, &cbRead);\r
-\r
-  if ( (cbRead!=1) ||\r
-       (bVersion!=0x01) )\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Charset\r
-   */\r
-  IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);\r
-\r
-  if (cbRead!=2)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Attributes\r
-   */\r
-  IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);\r
-\r
-  if (cbRead!=1)\r
-    return E_FAIL;\r
-\r
-  this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;\r
-  this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;\r
-  this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;\r
-\r
-  /*\r
-   * Weight\r
-   */\r
-  IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);\r
-\r
-  if (cbRead!=2)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Size\r
-   */\r
-  IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);\r
-\r
-  if (cbRead!=4)\r
-    return E_FAIL;\r
-\r
-  this->description.cySize.s.Hi = 0;\r
-\r
-  /*\r
-   * FontName\r
-   */\r
-  IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);\r
-\r
-  if (cbRead!=1)\r
-    return E_FAIL;\r
-\r
-  IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);\r
-\r
-  if (cbRead!=bStringSize)\r
-    return E_FAIL;\r
-\r
-  HeapFree(GetProcessHeap(), 0, this->description.lpstrName);\r
-\r
-  len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );\r
-  this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );\r
-  MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );\r
-  this->description.lpstrName[len] = 0;\r
-\r
-  /* Ensure use of this font causes a new one to be created @@@@ */\r
-  DeleteObject(this->gdiFont);\r
-  this->gdiFont = 0;\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_Save (IPersistStream)\r
- *\r
- * See Windows documentation for more details on IPersistStream methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_Save(\r
-  IPersistStream*  iface,\r
-  IStream*         pOutStream,\r
-  BOOL             fClearDirty)\r
-{\r
-  char* writeBuffer = NULL;\r
-  ULONG cbWritten;\r
-  BYTE  bVersion = 0x01;\r
-  BYTE  bAttributes;\r
-  BYTE  bStringSize;\r
-\r
-  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);\r
-\r
-  /*\r
-   * Read the version byte\r
-   */\r
-  IStream_Write(pOutStream, &bVersion, 1, &cbWritten);\r
-\r
-  if (cbWritten!=1)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Charset\r
-   */\r
-  IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);\r
-\r
-  if (cbWritten!=2)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Attributes\r
-   */\r
-  bAttributes = 0;\r
-\r
-  if (this->description.fItalic)\r
-    bAttributes |= FONTPERSIST_ITALIC;\r
-\r
-  if (this->description.fStrikethrough)\r
-    bAttributes |= FONTPERSIST_STRIKETHROUGH;\r
-\r
-  if (this->description.fUnderline)\r
-    bAttributes |= FONTPERSIST_UNDERLINE;\r
-\r
-  IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);\r
-\r
-  if (cbWritten!=1)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Weight\r
-   */\r
-  IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);\r
-\r
-  if (cbWritten!=2)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * Size\r
-   */\r
-  IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);\r
-\r
-  if (cbWritten!=4)\r
-    return E_FAIL;\r
-\r
-  /*\r
-   * FontName\r
-   */\r
-  if (this->description.lpstrName!=0)\r
-    bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,\r
-                                       strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );\r
-  else\r
-    bStringSize = 0;\r
-\r
-  IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);\r
-\r
-  if (cbWritten!=1)\r
-    return E_FAIL;\r
-\r
-  if (bStringSize!=0)\r
-  {\r
-      if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;\r
-      WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,\r
-                           strlenW(this->description.lpstrName),\r
-                           writeBuffer, bStringSize, NULL, NULL );\r
-\r
-    IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);\r
-    HeapFree(GetProcessHeap(), 0, writeBuffer);\r
-\r
-    if (cbWritten!=bStringSize)\r
-      return E_FAIL;\r
-  }\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_GetSizeMax (IPersistStream)\r
- *\r
- * See Windows documentation for more details on IPersistStream methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_GetSizeMax(\r
-  IPersistStream*  iface,\r
-  ULARGE_INTEGER*  pcbSize)\r
-{\r
-  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);\r
-\r
-  if (pcbSize==NULL)\r
-    return E_POINTER;\r
-\r
-  pcbSize->u.HighPart = 0;\r
-  pcbSize->u.LowPart = 0;\r
-\r
-  pcbSize->u.LowPart += sizeof(BYTE);  /* Version */\r
-  pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */\r
-  pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */\r
-  pcbSize->u.LowPart += sizeof(WORD);  /* Weight */\r
-  pcbSize->u.LowPart += sizeof(DWORD); /* Size */\r
-  pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */\r
-\r
-  if (this->description.lpstrName!=0)\r
-    pcbSize->u.LowPart += lstrlenW(this->description.lpstrName);\r
-\r
-  return S_OK;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(\r
-  IConnectionPointContainer* iface,\r
-  REFIID     riid,\r
-  VOID**     ppvoid)\r
-{\r
-  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);\r
-\r
-  return IFont_QueryInterface((IFont*)this, riid, ppvoid);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(\r
-  IConnectionPointContainer* iface)\r
-{\r
-  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);\r
-\r
-  return IFont_Release((IFont*)this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)\r
- *\r
- * See Windows documentation for more details on IUnknown methods.\r
- */\r
-static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(\r
-  IConnectionPointContainer* iface)\r
-{\r
-  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);\r
-\r
-  return IFont_AddRef((IFont*)this);\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)\r
- *\r
- * See Windows documentation for more details on IConnectionPointContainer\r
- * methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(\r
-  IConnectionPointContainer* iface,\r
-  IEnumConnectionPoints **ppEnum)\r
-{\r
-  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);\r
-\r
-  FIXME("(%p)->(%p): stub\n", this, ppEnum);\r
-  return E_NOTIMPL;\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)\r
- *\r
- * See Windows documentation for more details on IConnectionPointContainer\r
- * methods.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(\r
-   IConnectionPointContainer* iface,\r
-   REFIID riid,\r
-   IConnectionPoint **ppCp)\r
-{\r
-  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);\r
-  TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);\r
-\r
-  if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) {\r
-    return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint,\r
-                                          (LPVOID)ppCp);\r
-  } else {\r
-    FIXME("Tried to find connection point on %s\n", debugstr_guid(riid));\r
-    return E_NOINTERFACE;\r
-  }\r
-}\r
-\r
-/************************************************************************\r
- * OLEFontImpl implementation of IPersistPropertyBag.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(\r
-   IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj\r
-) {\r
-  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);\r
-  return IFont_QueryInterface(this,riid,ppvObj);\r
-}\r
-\r
-static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(\r
-   IPersistPropertyBag *iface\r
-) {\r
-  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);\r
-  return IFont_AddRef(this);\r
-}\r
-\r
-static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(\r
-   IPersistPropertyBag *iface\r
-) {\r
-  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);\r
-  return IFont_Release(this);\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(\r
-   IPersistPropertyBag *iface, CLSID *classid\r
-) {\r
-  FIXME("(%p,%p), stub!\n", iface, classid);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(\r
-   IPersistPropertyBag *iface\r
-) {\r
-  FIXME("(%p), stub!\n", iface);\r
-  return S_OK;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(\r
-   IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog\r
-) {\r
-/* (from Visual Basic 6 property bag)\r
-         Name            =   "MS Sans Serif"\r
-         Size            =   13.8\r
-         Charset         =   0\r
-         Weight          =   400\r
-         Underline       =   0   'False\r
-         Italic          =   0   'False\r
-         Strikethrough   =   0   'False\r
-*/\r
-    static const WCHAR sAttrName[] = {'N','a','m','e',0};\r
-    static const WCHAR sAttrSize[] = {'S','i','z','e',0};\r
-    static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};\r
-    static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};\r
-    static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};\r
-    static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};\r
-    static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};\r
-    VARIANT rawAttr;\r
-    VARIANT valueAttr;\r
-    HRESULT iRes = S_OK;\r
-    _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);\r
-\r
-    VariantInit(&rawAttr);\r
-    VariantInit(&valueAttr);\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Name(this, V_BSTR(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Size(this, V_CY(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Charset(this, V_I2(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Weight(this, V_I2(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Underline(this, V_BOOL(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);\r
-            if (iRes == S_OK)\r
-                iRes = IFont_put_Italic(this, V_BOOL(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (iRes == S_OK) {\r
-        iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);\r
-        if (iRes == S_OK)\r
-        {\r
-            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);\r
-            if (iRes == S_OK)\r
-                IFont_put_Strikethrough(this, V_BOOL(&valueAttr));\r
-        }\r
-        else if (iRes == E_INVALIDARG)\r
-            iRes = S_OK;\r
-        VariantClear(&rawAttr);\r
-        VariantClear(&valueAttr);\r
-    }\r
-\r
-    if (FAILED(iRes))\r
-        WARN("-- 0x%08lx\n", iRes);\r
-    return iRes;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(\r
-   IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,\r
-   BOOL fSaveAllProperties\r
-) {\r
-  FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);\r
-  return E_FAIL;\r
-}\r
-\r
-static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = \r
-{\r
-  OLEFontImpl_IPersistPropertyBag_QueryInterface,\r
-  OLEFontImpl_IPersistPropertyBag_AddRef,\r
-  OLEFontImpl_IPersistPropertyBag_Release,\r
-\r
-  OLEFontImpl_IPersistPropertyBag_GetClassID,\r
-  OLEFontImpl_IPersistPropertyBag_InitNew,\r
-  OLEFontImpl_IPersistPropertyBag_Load,\r
-  OLEFontImpl_IPersistPropertyBag_Save\r
-};\r
-\r
-/************************************************************************\r
- * OLEFontImpl implementation of IPersistStreamInit.\r
- */\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(\r
-   IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj\r
-) {\r
-  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);\r
-  return IFont_QueryInterface(this,riid,ppvObj);\r
-}\r
-\r
-static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(\r
-   IPersistStreamInit *iface\r
-) {\r
-  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);\r
-  return IFont_AddRef(this);\r
-}\r
-\r
-static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(\r
-   IPersistStreamInit *iface\r
-) {\r
-  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);\r
-  return IFont_Release(this);\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(\r
-   IPersistStreamInit *iface, CLSID *classid\r
-) {\r
-  FIXME("(%p,%p), stub!\n", iface, classid);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(\r
-   IPersistStreamInit *iface\r
-) {\r
-  FIXME("(%p), stub!\n", iface);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(\r
-   IPersistStreamInit *iface, LPSTREAM pStm\r
-) {\r
-  FIXME("(%p,%p), stub!\n", iface, pStm);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(\r
-   IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty\r
-) {\r
-  FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(\r
-   IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize\r
-) {\r
-  FIXME("(%p,%p), stub!\n", iface, pcbSize);\r
-  return E_FAIL;\r
-}\r
-\r
-static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(\r
-   IPersistStreamInit *iface\r
-) {\r
-  FIXME("(%p), stub!\n", iface);\r
-  return S_OK;\r
-}\r
-\r
-static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = \r
-{\r
-  OLEFontImpl_IPersistStreamInit_QueryInterface,\r
-  OLEFontImpl_IPersistStreamInit_AddRef,\r
-  OLEFontImpl_IPersistStreamInit_Release,\r
-\r
-  OLEFontImpl_IPersistStreamInit_GetClassID,\r
-  OLEFontImpl_IPersistStreamInit_IsDirty,\r
-  OLEFontImpl_IPersistStreamInit_Load,\r
-  OLEFontImpl_IPersistStreamInit_Save,\r
-  OLEFontImpl_IPersistStreamInit_GetSizeMax,\r
-  OLEFontImpl_IPersistStreamInit_InitNew\r
-};\r
-\r
-/*******************************************************************************\r
- * StdFont ClassFactory\r
- */\r
-typedef struct\r
-{\r
-    /* IUnknown fields */\r
-    IClassFactoryVtbl          *lpVtbl;\r
-    DWORD                       ref;\r
-} IClassFactoryImpl;\r
-\r
-static HRESULT WINAPI\r
-SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-\r
-       FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);\r
-       return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI\r
-SFCF_AddRef(LPCLASSFACTORY iface) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       return InterlockedIncrement(&This->ref);\r
-}\r
-\r
-static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       /* static class, won't be  freed */\r
-       return InterlockedDecrement(&This->ref);\r
-}\r
-\r
-static HRESULT WINAPI SFCF_CreateInstance(\r
-       LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj\r
-) {\r
-       return OleCreateFontIndirect(NULL,riid,ppobj);\r
-\r
-}\r
-\r
-static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {\r
-       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;\r
-       FIXME("(%p)->(%d),stub!\n",This,dolock);\r
-       return S_OK;\r
-}\r
-\r
-static IClassFactoryVtbl SFCF_Vtbl = {\r
-       SFCF_QueryInterface,\r
-       SFCF_AddRef,\r
-       SFCF_Release,\r
-       SFCF_CreateInstance,\r
-       SFCF_LockServer\r
-};\r
-static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };\r
-\r
-void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }\r
+/*
+ * OLE Font encapsulation implementation
+ *
+ * This file contains an implementation of the IFont
+ * interface and the OleCreateFontIndirect API call.
+ *
+ * Copyright 1999 Francis Beaudet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "wine/unicode.h"
+#include "objbase.h"
+#include "oleauto.h"    /* for SysAllocString(....) */
+#include "ole2.h"
+#include "olectl.h"
+#include "wine/debug.h"
+#include "connpt.h" /* for CreateConnectionPoint */
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+
+/***********************************************************************
+ * Declaration of constants used when serializing the font object.
+ */
+#define FONTPERSIST_ITALIC        0x02
+#define FONTPERSIST_UNDERLINE     0x04
+#define FONTPERSIST_STRIKETHROUGH 0x08
+
+/***********************************************************************
+ * Declaration of the implementation class for the IFont interface
+ */
+typedef struct OLEFontImpl OLEFontImpl;
+
+struct OLEFontImpl
+{
+  /*
+   * This class supports many interfaces. IUnknown, IFont,
+   * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
+   * The first two are supported by the first vtable, the next two are
+   * supported by the second table and the last two have their own.
+   */
+  IFontVtbl*                           lpvtbl1;
+  IDispatchVtbl*                       lpvtbl2;
+  IPersistStreamVtbl*                  lpvtbl3;
+  IConnectionPointContainerVtbl*       lpvtbl4;
+  IPersistPropertyBagVtbl*             lpvtbl5;
+  IPersistStreamInitVtbl*              lpvtbl6;
+  /*
+   * Reference count for that instance of the class.
+   */
+  ULONG ref;
+
+  /*
+   * This structure contains the description of the class.
+   */
+  FONTDESC description;
+
+  /*
+   * Contain the font associated with this object.
+   */
+  HFONT gdiFont;
+
+  /*
+   * Font lock count.
+   */
+  DWORD fontLock;
+
+  /*
+   * Size ratio
+   */
+  long cyLogical;
+  long cyHimetric;
+
+  IConnectionPoint *pCP;
+};
+
+/*
+ * Here, I define utility macros to help with the casting of the
+ * "this" parameter.
+ * There is a version to accommodate all of the VTables implemented
+ * by this object.
+ */
+#define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*))
+#define _ICOM_THIS_From_IPersistStream(class, name) class* this = (class*)(((char*)name)-2*sizeof(void*))
+#define _ICOM_THIS_From_IConnectionPointContainer(class, name) class* this = (class*)(((char*)name)-3*sizeof(void*))
+#define _ICOM_THIS_From_IPersistPropertyBag(class, name) class* this = (class*)(((char*)name)-4*sizeof(void*))
+#define _ICOM_THIS_From_IPersistStreamInit(class, name) class* this = (class*)(((char*)name)-5*sizeof(void*))
+
+
+/***********************************************************************
+ * Prototypes for the implementation functions for the IFont
+ * interface
+ */
+static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc);
+static void         OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
+static HRESULT      WINAPI OLEFontImpl_QueryInterface(IFont* iface, REFIID riid, VOID** ppvoid);
+static ULONG        WINAPI OLEFontImpl_AddRef(IFont* iface);
+static ULONG        WINAPI OLEFontImpl_Release(IFont* iface);
+static HRESULT      WINAPI OLEFontImpl_get_Name(IFont* iface, BSTR* pname);
+static HRESULT      WINAPI OLEFontImpl_put_Name(IFont* iface, BSTR name);
+static HRESULT      WINAPI OLEFontImpl_get_Size(IFont* iface, CY* psize);
+static HRESULT      WINAPI OLEFontImpl_put_Size(IFont* iface, CY size);
+static HRESULT      WINAPI OLEFontImpl_get_Bold(IFont* iface, BOOL* pbold);
+static HRESULT      WINAPI OLEFontImpl_put_Bold(IFont* iface, BOOL bold);
+static HRESULT      WINAPI OLEFontImpl_get_Italic(IFont* iface, BOOL* pitalic);
+static HRESULT      WINAPI OLEFontImpl_put_Italic(IFont* iface, BOOL italic);
+static HRESULT      WINAPI OLEFontImpl_get_Underline(IFont* iface, BOOL* punderline);
+static HRESULT      WINAPI OLEFontImpl_put_Underline(IFont* iface, BOOL underline);
+static HRESULT      WINAPI OLEFontImpl_get_Strikethrough(IFont* iface, BOOL* pstrikethrough);
+static HRESULT      WINAPI OLEFontImpl_put_Strikethrough(IFont* iface, BOOL strikethrough);
+static HRESULT      WINAPI OLEFontImpl_get_Weight(IFont* iface, short* pweight);
+static HRESULT      WINAPI OLEFontImpl_put_Weight(IFont* iface, short weight);
+static HRESULT      WINAPI OLEFontImpl_get_Charset(IFont* iface, short* pcharset);
+static HRESULT      WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset);
+static HRESULT      WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont);
+static HRESULT      WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont);
+static HRESULT      WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther);
+static HRESULT      WINAPI OLEFontImpl_SetRatio(IFont* iface, LONG cyLogical, LONG cyHimetric);
+static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm);
+static HRESULT      WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont);
+static HRESULT      WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont);
+static HRESULT      WINAPI OLEFontImpl_SetHdc(IFont* iface, HDC hdc);
+
+/***********************************************************************
+ * Prototypes for the implementation functions for the IDispatch
+ * interface
+ */
+static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(IDispatch* iface,
+                                                   REFIID     riid,
+                                                   VOID**     ppvoid);
+static ULONG   WINAPI OLEFontImpl_IDispatch_AddRef(IDispatch* iface);
+static ULONG   WINAPI OLEFontImpl_IDispatch_Release(IDispatch* iface);
+static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(IDispatch*    iface,
+                                                  unsigned int* pctinfo);
+static HRESULT WINAPI OLEFontImpl_GetTypeInfo(IDispatch*  iface,
+                                             UINT      iTInfo,
+                                             LCID        lcid,
+                                             ITypeInfo** ppTInfo);
+static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(IDispatch*  iface,
+                                               REFIID      riid,
+                                               LPOLESTR* rgszNames,
+                                               UINT      cNames,
+                                               LCID        lcid,
+                                               DISPID*     rgDispId);
+static HRESULT WINAPI OLEFontImpl_Invoke(IDispatch*  iface,
+                                        DISPID      dispIdMember,
+                                        REFIID      riid,
+                                        LCID        lcid,
+                                        WORD        wFlags,
+                                        DISPPARAMS* pDispParams,
+                                        VARIANT*    pVarResult,
+                                        EXCEPINFO*  pExepInfo,
+                                        UINT*     puArgErr);
+
+/***********************************************************************
+ * Prototypes for the implementation functions for the IPersistStream
+ * interface
+ */
+static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(IPersistStream* iface,
+                                                   REFIID     riid,
+                                                   VOID**     ppvoid);
+static ULONG   WINAPI OLEFontImpl_IPersistStream_AddRef(IPersistStream* iface);
+static ULONG   WINAPI OLEFontImpl_IPersistStream_Release(IPersistStream* iface);
+static HRESULT WINAPI OLEFontImpl_GetClassID(IPersistStream* iface,
+                                            CLSID*                pClassID);
+static HRESULT WINAPI OLEFontImpl_IsDirty(IPersistStream*  iface);
+static HRESULT WINAPI OLEFontImpl_Load(IPersistStream*  iface,
+                                      IStream*         pLoadStream);
+static HRESULT WINAPI OLEFontImpl_Save(IPersistStream*  iface,
+                                      IStream*         pOutStream,
+                                      BOOL             fClearDirty);
+static HRESULT WINAPI OLEFontImpl_GetSizeMax(IPersistStream*  iface,
+                                            ULARGE_INTEGER*  pcbSize);
+
+/***********************************************************************
+ * Prototypes for the implementation functions for the
+ * IConnectionPointContainer interface
+ */
+static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
+                                           IConnectionPointContainer* iface,
+                                           REFIID     riid,
+                                           VOID**     ppvoid);
+static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
+                                           IConnectionPointContainer* iface);
+static ULONG   WINAPI OLEFontImpl_IConnectionPointContainer_Release(
+                                           IConnectionPointContainer* iface);
+static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
+                                           IConnectionPointContainer* iface,
+                                           IEnumConnectionPoints **ppEnum);
+static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
+                                           IConnectionPointContainer* iface,
+                                           REFIID riid,
+                                           IConnectionPoint **ppCp);
+
+/*
+ * Virtual function tables for the OLEFontImpl class.
+ */
+static IFontVtbl OLEFontImpl_VTable =
+{
+  OLEFontImpl_QueryInterface,
+  OLEFontImpl_AddRef,
+  OLEFontImpl_Release,
+  OLEFontImpl_get_Name,
+  OLEFontImpl_put_Name,
+  OLEFontImpl_get_Size,
+  OLEFontImpl_put_Size,
+  OLEFontImpl_get_Bold,
+  OLEFontImpl_put_Bold,
+  OLEFontImpl_get_Italic,
+  OLEFontImpl_put_Italic,
+  OLEFontImpl_get_Underline,
+  OLEFontImpl_put_Underline,
+  OLEFontImpl_get_Strikethrough,
+  OLEFontImpl_put_Strikethrough,
+  OLEFontImpl_get_Weight,
+  OLEFontImpl_put_Weight,
+  OLEFontImpl_get_Charset,
+  OLEFontImpl_put_Charset,
+  OLEFontImpl_get_hFont,
+  OLEFontImpl_Clone,
+  OLEFontImpl_IsEqual,
+  OLEFontImpl_SetRatio,
+  OLEFontImpl_QueryTextMetrics,
+  OLEFontImpl_AddRefHfont,
+  OLEFontImpl_ReleaseHfont,
+  OLEFontImpl_SetHdc
+};
+
+static IDispatchVtbl OLEFontImpl_IDispatch_VTable =
+{
+  OLEFontImpl_IDispatch_QueryInterface,
+  OLEFontImpl_IDispatch_AddRef,
+  OLEFontImpl_IDispatch_Release,
+  OLEFontImpl_GetTypeInfoCount,
+  OLEFontImpl_GetTypeInfo,
+  OLEFontImpl_GetIDsOfNames,
+  OLEFontImpl_Invoke
+};
+
+static IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
+{
+  OLEFontImpl_IPersistStream_QueryInterface,
+  OLEFontImpl_IPersistStream_AddRef,
+  OLEFontImpl_IPersistStream_Release,
+  OLEFontImpl_GetClassID,
+  OLEFontImpl_IsDirty,
+  OLEFontImpl_Load,
+  OLEFontImpl_Save,
+  OLEFontImpl_GetSizeMax
+};
+
+static IConnectionPointContainerVtbl
+     OLEFontImpl_IConnectionPointContainer_VTable =
+{
+  OLEFontImpl_IConnectionPointContainer_QueryInterface,
+  OLEFontImpl_IConnectionPointContainer_AddRef,
+  OLEFontImpl_IConnectionPointContainer_Release,
+  OLEFontImpl_EnumConnectionPoints,
+  OLEFontImpl_FindConnectionPoint
+};
+
+static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable;
+static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable;
+/******************************************************************************
+ *             OleCreateFontIndirect   [OLEAUT32.420]
+ */
+HRESULT WINAPI OleCreateFontIndirect(
+  LPFONTDESC lpFontDesc,
+  REFIID     riid,
+  LPVOID*     ppvObj)
+{
+  OLEFontImpl* newFont = 0;
+  HRESULT      hr      = S_OK;
+
+  TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
+  /*
+   * Sanity check
+   */
+  if (ppvObj==0)
+    return E_POINTER;
+
+  *ppvObj = 0;
+
+  if (!lpFontDesc) {
+    FONTDESC fd;
+
+    static const WCHAR fname[] = { 'S','y','s','t','e','m',0 };
+
+    fd.cbSizeofstruct = sizeof(fd);
+    fd.lpstrName      = (WCHAR*)fname;
+    fd.cySize.s.Lo    = 80000;
+    fd.cySize.s.Hi    = 0;
+    fd.sWeight               = 0;
+    fd.sCharset       = 0;
+    fd.fItalic       = 0;
+    fd.fUnderline     = 0;
+    fd.fStrikethrough = 0;
+    lpFontDesc = &fd;
+  }
+
+  /*
+   * Try to construct a new instance of the class.
+   */
+  newFont = OLEFontImpl_Construct(lpFontDesc);
+
+  if (newFont == 0)
+    return E_OUTOFMEMORY;
+
+  /*
+   * Make sure it supports the interface required by the caller.
+   */
+  hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
+
+  /*
+   * Release the reference obtained in the constructor. If
+   * the QueryInterface was unsuccessful, it will free the class.
+   */
+  IFont_Release((IFont*)newFont);
+
+  return hr;
+}
+
+
+/***********************************************************************
+ * Implementation of the OLEFontImpl class.
+ */
+
+/***********************************************************************
+ *    OLEFont_SendNotify (internal)
+ *
+ * Sends notification messages of changed properties to any interested
+ * connections.
+ */
+static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
+{
+  IEnumConnections *pEnum;
+  CONNECTDATA CD;
+  HRESULT hres;
+
+  hres = IConnectionPoint_EnumConnections(this->pCP, &pEnum);
+  if (FAILED(hres)) /* When we have 0 connections. */
+    return;
+
+  while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
+    IPropertyNotifySink *sink;
+
+    IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
+    IPropertyNotifySink_OnChanged(sink, dispID);
+    IPropertyNotifySink_Release(sink);
+    IUnknown_Release(CD.pUnk);
+  }
+  IEnumConnections_Release(pEnum);
+  return;
+}
+
+/************************************************************************
+ * OLEFontImpl_Construct
+ *
+ * This method will construct a new instance of the OLEFontImpl
+ * class.
+ *
+ * The caller of this method must release the object when it's
+ * done with it.
+ */
+static OLEFontImpl* OLEFontImpl_Construct(LPFONTDESC fontDesc)
+{
+  OLEFontImpl* newObject = 0;
+
+  /*
+   * Allocate space for the object.
+   */
+  newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
+
+  if (newObject==0)
+    return newObject;
+
+  /*
+   * Initialize the virtual function table.
+   */
+  newObject->lpvtbl1 = &OLEFontImpl_VTable;
+  newObject->lpvtbl2 = &OLEFontImpl_IDispatch_VTable;
+  newObject->lpvtbl3 = &OLEFontImpl_IPersistStream_VTable;
+  newObject->lpvtbl4 = &OLEFontImpl_IConnectionPointContainer_VTable;
+  newObject->lpvtbl5 = &OLEFontImpl_IPersistPropertyBag_VTable;
+  newObject->lpvtbl6 = &OLEFontImpl_IPersistStreamInit_VTable;
+
+  /*
+   * Start with one reference count. The caller of this function
+   * must release the interface pointer when it is done.
+   */
+  newObject->ref = 1;
+
+  /*
+   * Copy the description of the font in the object.
+   */
+  assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
+
+  newObject->description.cbSizeofstruct = sizeof(FONTDESC);
+  newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
+                                              0,
+                                              (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
+  strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
+  newObject->description.cySize         = fontDesc->cySize;
+  newObject->description.sWeight        = fontDesc->sWeight;
+  newObject->description.sCharset       = fontDesc->sCharset;
+  newObject->description.fItalic        = fontDesc->fItalic;
+  newObject->description.fUnderline     = fontDesc->fUnderline;
+  newObject->description.fStrikethrough = fontDesc->fStrikethrough;
+
+  /*
+   * Initializing all the other members.
+   */
+  newObject->gdiFont  = 0;
+  newObject->fontLock = 0;
+  newObject->cyLogical  = 72L;
+  newObject->cyHimetric = 2540L;
+  CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pCP);
+  TRACE("returning %p\n", newObject);
+  return newObject;
+}
+
+/************************************************************************
+ * OLEFontImpl_Destroy
+ *
+ * This method is called by the Release method when the reference
+ * count goes down to 0. It will free all resources used by
+ * this object.
+ */
+static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
+{
+  TRACE("(%p)\n", fontDesc);
+
+  HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
+
+  if (fontDesc->gdiFont!=0)
+    DeleteObject(fontDesc->gdiFont);
+
+  HeapFree(GetProcessHeap(), 0, fontDesc);
+}
+
+/************************************************************************
+ * OLEFontImpl_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+HRESULT WINAPI OLEFontImpl_QueryInterface(
+  IFont*  iface,
+  REFIID  riid,
+  void**  ppvObject)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
+
+  /*
+   * Perform a sanity check on the parameters.
+   */
+  if ( (this==0) || (ppvObject==0) )
+    return E_INVALIDARG;
+
+  /*
+   * Initialize the return parameter.
+   */
+  *ppvObject = 0;
+
+  /*
+   * Compare the riid with the interface IDs implemented by this object.
+   */
+  if (IsEqualGUID(&IID_IUnknown, riid))
+    *ppvObject = (IFont*)this;
+  if (IsEqualGUID(&IID_IFont, riid))
+    *ppvObject = (IFont*)this;
+  if (IsEqualGUID(&IID_IDispatch, riid))
+    *ppvObject = (IDispatch*)&(this->lpvtbl2);
+  if (IsEqualGUID(&IID_IFontDisp, riid))
+    *ppvObject = (IDispatch*)&(this->lpvtbl2);
+  if (IsEqualGUID(&IID_IPersistStream, riid))
+    *ppvObject = (IPersistStream*)&(this->lpvtbl3);
+  if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
+    *ppvObject = (IConnectionPointContainer*)&(this->lpvtbl4);
+  if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
+    *ppvObject = (IPersistPropertyBag*)&(this->lpvtbl5);
+  if (IsEqualGUID(&IID_IPersistStreamInit, riid))
+    *ppvObject = (IPersistStreamInit*)&(this->lpvtbl6);
+
+  /*
+   * Check that we obtained an interface.
+   */
+  if ((*ppvObject)==0)
+  {
+    FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
+    return E_NOINTERFACE;
+  }
+  OLEFontImpl_AddRef((IFont*)this);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+ULONG WINAPI OLEFontImpl_AddRef(
+  IFont* iface)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(ref=%ld)\n", this, this->ref);
+  return InterlockedIncrement(&this->ref);
+}
+
+/************************************************************************
+ * OLEFontImpl_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+ULONG WINAPI OLEFontImpl_Release(
+      IFont* iface)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  ULONG ret;
+  TRACE("(%p)->(ref=%ld)\n", this, this->ref);
+
+  /*
+   * Decrease the reference count on this object.
+   */
+  ret = InterlockedDecrement(&this->ref);
+
+  /*
+   * If the reference count goes down to 0, perform suicide.
+   */
+  if (ret==0) OLEFontImpl_Destroy(this);
+
+  return ret;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Name (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Name(
+  IFont*  iface,
+  BSTR* pname)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pname);
+  /*
+   * Sanity check.
+   */
+  if (pname==0)
+    return E_POINTER;
+
+  if (this->description.lpstrName!=0)
+    *pname = SysAllocString(this->description.lpstrName);
+  else
+    *pname = 0;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Name (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Name(
+  IFont* iface,
+  BSTR name)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, name);
+
+  if (this->description.lpstrName==0)
+  {
+    this->description.lpstrName = HeapAlloc(GetProcessHeap(),
+                                           0,
+                                           (lstrlenW(name)+1) * sizeof(WCHAR));
+  }
+  else
+  {
+    this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
+                                             0,
+                                             this->description.lpstrName,
+                                             (lstrlenW(name)+1) * sizeof(WCHAR));
+  }
+
+  if (this->description.lpstrName==0)
+    return E_OUTOFMEMORY;
+
+  strcpyW(this->description.lpstrName, name);
+  TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
+  OLEFont_SendNotify(this, DISPID_FONT_NAME);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Size (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Size(
+  IFont* iface,
+  CY*    psize)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, psize);
+
+  /*
+   * Sanity check
+   */
+  if (psize==0)
+    return E_POINTER;
+
+  psize->s.Hi = 0;
+  psize->s.Lo = this->description.cySize.s.Lo;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Size (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Size(
+  IFont* iface,
+  CY     size)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%ld)\n", this, size.s.Lo);
+  this->description.cySize.s.Hi = 0;
+  this->description.cySize.s.Lo = size.s.Lo;
+  OLEFont_SendNotify(this, DISPID_FONT_SIZE);
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Bold (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Bold(
+  IFont*  iface,
+  BOOL* pbold)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pbold);
+  /*
+   * Sanity check
+   */
+  if (pbold==0)
+    return E_POINTER;
+
+  *pbold = this->description.sWeight > 550;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Bold (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Bold(
+  IFont* iface,
+  BOOL bold)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, bold);
+  this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
+  OLEFont_SendNotify(this, DISPID_FONT_BOLD);
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Italic (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Italic(
+  IFont*  iface,
+  BOOL* pitalic)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pitalic);
+  /*
+   * Sanity check
+   */
+  if (pitalic==0)
+    return E_POINTER;
+
+  *pitalic = this->description.fItalic;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Italic (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Italic(
+  IFont* iface,
+  BOOL italic)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, italic);
+
+  this->description.fItalic = italic;
+
+  OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Underline (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Underline(
+  IFont*  iface,
+  BOOL* punderline)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, punderline);
+
+  /*
+   * Sanity check
+   */
+  if (punderline==0)
+    return E_POINTER;
+
+  *punderline = this->description.fUnderline;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Underline (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Underline(
+  IFont* iface,
+  BOOL underline)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, underline);
+
+  this->description.fUnderline = underline;
+
+  OLEFont_SendNotify(this, DISPID_FONT_UNDER);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Strikethrough (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
+  IFont*  iface,
+  BOOL* pstrikethrough)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pstrikethrough);
+
+  /*
+   * Sanity check
+   */
+  if (pstrikethrough==0)
+    return E_POINTER;
+
+  *pstrikethrough = this->description.fStrikethrough;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Strikethrough (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
+ IFont* iface,
+ BOOL strikethrough)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, strikethrough);
+
+  this->description.fStrikethrough = strikethrough;
+  OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Weight (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Weight(
+  IFont* iface,
+  short* pweight)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pweight);
+
+  /*
+   * Sanity check
+   */
+  if (pweight==0)
+    return E_POINTER;
+
+  *pweight = this->description.sWeight;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Weight (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Weight(
+  IFont* iface,
+  short  weight)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, weight);
+
+  this->description.sWeight = weight;
+
+  OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_Charset (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_Charset(
+  IFont* iface,
+  short* pcharset)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, pcharset);
+
+  /*
+   * Sanity check
+   */
+  if (pcharset==0)
+    return E_POINTER;
+
+  *pcharset = this->description.sCharset;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_put_Charset (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_put_Charset(
+  IFont* iface,
+  short charset)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%d)\n", this, charset);
+
+  this->description.sCharset = charset;
+  OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_get_hFont (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_get_hFont(
+  IFont*   iface,
+  HFONT* phfont)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, phfont);
+  if (phfont==NULL)
+    return E_POINTER;
+
+  /*
+   * Realize the font if necessary
+ */
+  if (this->gdiFont==0)
+{
+    LOGFONTW logFont;
+    INT      fontHeight;
+    CY       cySize;
+
+    /*
+     * The height of the font returned by the get_Size property is the
+     * height of the font in points multiplied by 10000... Using some
+     * simple conversions and the ratio given by the application, it can
+     * be converted to a height in pixels.
+     */
+    IFont_get_Size(iface, &cySize);
+
+    fontHeight = MulDiv( cySize.s.Lo, this->cyLogical, this->cyHimetric );
+
+    memset(&logFont, 0, sizeof(LOGFONTW));
+
+    logFont.lfHeight          = ((fontHeight%10000L)>5000L) ?  (-fontHeight/10000L)-1 :
+                                                               (-fontHeight/10000L);
+    logFont.lfItalic          = this->description.fItalic;
+    logFont.lfUnderline       = this->description.fUnderline;
+    logFont.lfStrikeOut       = this->description.fStrikethrough;
+    logFont.lfWeight          = this->description.sWeight;
+    logFont.lfCharSet         = this->description.sCharset;
+    logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
+    logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
+    logFont.lfQuality         = DEFAULT_QUALITY;
+    logFont.lfPitchAndFamily  = DEFAULT_PITCH;
+    strcpyW(logFont.lfFaceName,this->description.lpstrName);
+
+    this->gdiFont = CreateFontIndirectW(&logFont);
+  }
+
+  *phfont = this->gdiFont;
+  TRACE("Returning %p\n", *phfont);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_Clone (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_Clone(
+  IFont*  iface,
+  IFont** ppfont)
+{
+  OLEFontImpl* newObject = 0;
+  LOGFONTW logFont;
+  INT      fontHeight;
+  CY       cySize;
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p)\n", this, ppfont);
+
+  if (ppfont == NULL)
+    return E_POINTER;
+
+  *ppfont = NULL;
+
+  /*
+   * Allocate space for the object.
+   */
+  newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
+
+  if (newObject==NULL)
+    return E_OUTOFMEMORY;
+
+  *newObject = *this;
+
+  /* We need to alloc new memory for the string, otherwise
+   * we free memory twice.
+   */
+  newObject->description.lpstrName = HeapAlloc(
+       GetProcessHeap(),0,
+       (1+strlenW(this->description.lpstrName))*2
+  );
+  strcpyW(newObject->description.lpstrName, this->description.lpstrName);
+  /* We need to clone the HFONT too. This is just cut & paste from above */
+  IFont_get_Size(iface, &cySize);
+
+  fontHeight = MulDiv(cySize.s.Lo, this->cyLogical,this->cyHimetric);
+
+  memset(&logFont, 0, sizeof(LOGFONTW));
+
+  logFont.lfHeight          = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L)-1 :
+                                                           (-fontHeight/10000L);
+  logFont.lfItalic          = this->description.fItalic;
+  logFont.lfUnderline       = this->description.fUnderline;
+  logFont.lfStrikeOut       = this->description.fStrikethrough;
+  logFont.lfWeight          = this->description.sWeight;
+  logFont.lfCharSet         = this->description.sCharset;
+  logFont.lfOutPrecision    = OUT_CHARACTER_PRECIS;
+  logFont.lfClipPrecision   = CLIP_DEFAULT_PRECIS;
+  logFont.lfQuality         = DEFAULT_QUALITY;
+  logFont.lfPitchAndFamily  = DEFAULT_PITCH;
+  strcpyW(logFont.lfFaceName,this->description.lpstrName);
+
+  newObject->gdiFont = CreateFontIndirectW(&logFont);
+
+
+  /* The cloned object starts with a reference count of 1 */
+  newObject->ref          = 1;
+
+  *ppfont = (IFont*)newObject;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_IsEqual (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_IsEqual(
+  IFont* iface,
+  IFont* pFontOther)
+{
+  FIXME("(%p, %p), stub!\n",iface,pFontOther);
+  return E_NOTIMPL;
+}
+
+/************************************************************************
+ * OLEFontImpl_SetRatio (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_SetRatio(
+  IFont* iface,
+  LONG   cyLogical,
+  LONG   cyHimetric)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric);
+
+  this->cyLogical  = cyLogical;
+  this->cyHimetric = cyHimetric;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_QueryTextMetrics (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT      WINAPI OLEFontImpl_QueryTextMetrics(
+  IFont*         iface,
+  TEXTMETRICOLE* ptm)
+{
+  HDC hdcRef;
+  HFONT hOldFont, hNewFont;
+
+  hdcRef = GetDC(0);
+  OLEFontImpl_get_hFont(iface, &hNewFont);
+  hOldFont = SelectObject(hdcRef, hNewFont);
+  GetTextMetricsW(hdcRef, ptm);
+  SelectObject(hdcRef, hOldFont);
+  ReleaseDC(0, hdcRef);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_AddRefHfont (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_AddRefHfont(
+  IFont*  iface,
+  HFONT hfont)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
+
+  if ( (hfont == 0) ||
+       (hfont != this->gdiFont) )
+    return E_INVALIDARG;
+
+  this->fontLock++;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_ReleaseHfont (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
+  IFont*  iface,
+  HFONT hfont)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  TRACE("(%p)->(%p) (lock=%ld)\n", this, hfont, this->fontLock);
+
+  if ( (hfont == 0) ||
+       (hfont != this->gdiFont) )
+    return E_INVALIDARG;
+
+  this->fontLock--;
+
+  /*
+   * If we just released our last font reference, destroy it.
+   */
+  if (this->fontLock==0)
+  {
+    DeleteObject(this->gdiFont);
+    this->gdiFont = 0;
+  }
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_SetHdc (IFont)
+ *
+ * See Windows documentation for more details on IFont methods.
+ */
+static HRESULT WINAPI OLEFontImpl_SetHdc(
+  IFont* iface,
+  HDC  hdc)
+{
+  OLEFontImpl *this = (OLEFontImpl *)iface;
+  FIXME("(%p)->(%p): Stub\n", this, hdc);
+  return E_NOTIMPL;
+}
+
+/************************************************************************
+ * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
+  IDispatch* iface,
+  REFIID     riid,
+  VOID**     ppvoid)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+
+  return IFont_QueryInterface(this, riid, ppvoid);
+}
+
+/************************************************************************
+ * OLEFontImpl_IDispatch_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IDispatch_Release(
+  IDispatch* iface)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+
+  return IFont_Release(this);
+}
+
+/************************************************************************
+ * OLEFontImpl_IDispatch_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
+  IDispatch* iface)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+
+  return IFont_AddRef(this);
+}
+
+/************************************************************************
+ * OLEFontImpl_GetTypeInfoCount (IDispatch)
+ *
+ * See Windows documentation for more details on IDispatch methods.
+ */
+static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
+  IDispatch*    iface,
+  unsigned int* pctinfo)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+  FIXME("(%p)->(%p): Stub\n", this, pctinfo);
+
+  return E_NOTIMPL;
+}
+
+/************************************************************************
+ * OLEFontImpl_GetTypeInfo (IDispatch)
+ *
+ * See Windows documentation for more details on IDispatch methods.
+ */
+static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
+  IDispatch*  iface,
+  UINT      iTInfo,
+  LCID        lcid,
+  ITypeInfo** ppTInfo)
+{
+  static const WCHAR stdole32tlb[] = {'s','t','d','o','l','e','3','2','.','t','l','b',0};
+  ITypeLib *tl;
+  HRESULT hres;
+
+  _ICOM_THIS_From_IDispatch(OLEFontImpl, iface);
+  TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
+  if (iTInfo != 0)
+    return E_FAIL;
+  hres = LoadTypeLib(stdole32tlb, &tl);
+  if (FAILED(hres)) {
+    ERR("Could not load the stdole32.tlb?\n");
+    return hres;
+  }
+  hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IDispatch, ppTInfo);
+  if (FAILED(hres)) {
+    FIXME("Did not IDispatch typeinfo from typelib, hres %lx\n",hres);
+  }
+  return hres;
+}
+
+/************************************************************************
+ * OLEFontImpl_GetIDsOfNames (IDispatch)
+ *
+ * See Windows documentation for more details on IDispatch methods.
+ */
+static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
+  IDispatch*  iface,
+  REFIID      riid,
+  LPOLESTR* rgszNames,
+  UINT      cNames,
+  LCID        lcid,
+  DISPID*     rgDispId)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+  FIXME("(%p,%s,%p,%d,%04x,%p), stub!\n", this, debugstr_guid(riid), rgszNames,
+       cNames, (int)lcid, rgDispId
+  );
+  return E_NOTIMPL;
+}
+
+/************************************************************************
+ * OLEFontImpl_Invoke (IDispatch)
+ *
+ * See Windows documentation for more details on IDispatch methods.
+ * 
+ * Note: Do not call _put_Xxx methods, since setting things here
+ * should not call notify functions as I found out debugging the generic
+ * MS VB5 installer.
+ */
+static HRESULT WINAPI OLEFontImpl_Invoke(
+  IDispatch*  iface,
+  DISPID      dispIdMember,
+  REFIID      riid,
+  LCID        lcid,
+  WORD        wFlags,
+  DISPPARAMS* pDispParams,
+  VARIANT*    pVarResult,
+  EXCEPINFO*  pExepInfo,
+  UINT*     puArgErr)
+{
+  _ICOM_THIS_From_IDispatch(IFont, iface);
+  OLEFontImpl *xthis = (OLEFontImpl*)this;
+
+  switch (dispIdMember) {
+  case DISPID_FONT_NAME:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_BSTR;
+      return OLEFontImpl_get_Name(this, &V_BSTR(pVarResult));
+    case DISPATCH_PROPERTYPUT: {
+      BSTR name;
+      BOOL freename;
+      
+      if (V_VT(&pDispParams->rgvarg[0]) == VT_DISPATCH) {
+        IFont *font;
+        HRESULT hr = S_OK;
+        
+        hr = IUnknown_QueryInterface(V_DISPATCH(&pDispParams->rgvarg[0]), &IID_IFont, (void **) &font);
+        if (FAILED(hr))
+        {
+            FIXME("dispatch value for name property is not an OleFont, returning hr=0x%lx\n", hr);
+            return hr;
+        }
+
+        hr = IFont_get_Name(font, &name); /* this allocates a new BSTR so free it later */
+        if (FAILED(hr)) return hr;
+
+        IUnknown_Release(font);
+        
+        freename = TRUE;
+      } else if (V_VT(&pDispParams->rgvarg[0]) == VT_BSTR) {
+        name = V_BSTR(&pDispParams->rgvarg[0]);
+        freename = FALSE;
+      } else {
+        FIXME("app is trying to set name property with a non BSTR, non dispatch value. returning E_FAIL\n");
+        return E_FAIL;
+      }
+
+      TRACE("name is %s\n", debugstr_w(name));
+      
+      if (!xthis->description.lpstrName)
+       xthis->description.lpstrName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1) * sizeof(WCHAR));
+      else
+       xthis->description.lpstrName = HeapReAlloc(GetProcessHeap(), 0, xthis->description.lpstrName, (lstrlenW(name)+1) * sizeof(WCHAR));
+
+      if (xthis->description.lpstrName==0)
+       return E_OUTOFMEMORY;
+      strcpyW(xthis->description.lpstrName, name);
+
+      if (freename) SysFreeString(name);
+      
+      return S_OK;
+    }
+    }
+    break;
+  case DISPID_FONT_BOLD:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_BOOL;
+      return OLEFontImpl_get_Bold(this, (BOOL*)&V_BOOL(pVarResult));
+    case DISPATCH_PROPERTYPUT:
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
+       FIXME("DISPID_FONT_BOLD/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
+       return E_FAIL;
+      } else {
+        xthis->description.sWeight = V_BOOL(&pDispParams->rgvarg[0]) ? FW_BOLD : FW_NORMAL;
+       return S_OK;
+      }
+    }
+    break;
+  case DISPID_FONT_ITALIC:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_BOOL;
+      return OLEFontImpl_get_Italic(this, (BOOL*)&V_BOOL(pVarResult));
+    case DISPATCH_PROPERTYPUT:
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
+       FIXME("DISPID_FONT_ITALIC/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
+       return E_FAIL;
+      } else {
+        xthis->description.fItalic = V_BOOL(&pDispParams->rgvarg[0]);
+       return S_OK;
+      }
+    }
+    break;
+  case DISPID_FONT_UNDER:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_BOOL;
+      return OLEFontImpl_get_Underline(this, (BOOL*)&V_BOOL(pVarResult));
+    case DISPATCH_PROPERTYPUT:
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
+       FIXME("DISPID_FONT_UNDER/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
+       return E_FAIL;
+      } else {
+        xthis->description.fUnderline = V_BOOL(&pDispParams->rgvarg[0]);
+       return S_OK;
+      }
+    }
+    break;
+  case DISPID_FONT_STRIKE:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_BOOL;
+      return OLEFontImpl_get_Strikethrough(this, (BOOL*)&V_BOOL(pVarResult));
+    case DISPATCH_PROPERTYPUT:
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_BOOL) {
+       FIXME("DISPID_FONT_STRIKE/put, vt is %d, not VT_BOOL.\n",V_VT(&pDispParams->rgvarg[0]));
+       return E_FAIL;
+      } else {
+        xthis->description.fStrikethrough = V_BOOL(&pDispParams->rgvarg[0]);
+       return S_OK;
+      }
+    }
+    break;
+  case DISPID_FONT_SIZE:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYPUT: {
+      assert (pDispParams->cArgs == 1);
+      xthis->description.cySize.s.Hi = 0;
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_CY) {
+        if (V_VT(&pDispParams->rgvarg[0]) == VT_I2) {
+         xthis->description.cySize.s.Lo = V_I2(&pDispParams->rgvarg[0]) * 10000;
+       } else {
+         FIXME("property put for Size with vt %d unsupported!\n",V_VT(&pDispParams->rgvarg[0]));
+       }
+      } else {
+        xthis->description.cySize.s.Lo = V_CY(&pDispParams->rgvarg[0]).s.Lo;
+      }
+      return S_OK;
+    }
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_CY;
+      return OLEFontImpl_get_Size(this, &V_CY(pVarResult));
+    }
+    break;
+  case DISPID_FONT_CHARSET:
+    switch (wFlags) {
+    case DISPATCH_PROPERTYPUT:
+      assert (pDispParams->cArgs == 1);
+      if (V_VT(&pDispParams->rgvarg[0]) != VT_I2)
+       FIXME("varg of first disparg is not VT_I2, but %d\n",V_VT(&pDispParams->rgvarg[0]));
+      xthis->description.sCharset = V_I2(&pDispParams->rgvarg[0]);
+      return S_OK;
+    case DISPATCH_PROPERTYGET:
+    case DISPATCH_PROPERTYGET|DISPATCH_METHOD:
+      V_VT(pVarResult) = VT_I2;
+      return OLEFontImpl_get_Charset(this, &V_I2(pVarResult));
+    }
+    break;
+  }
+  FIXME("%p->(%ld,%s,%lx,%x,%p,%p,%p,%p), unhandled dispid/flag!\n",
+    this,dispIdMember,debugstr_guid(riid),lcid,
+    wFlags,pDispParams,pVarResult,pExepInfo,puArgErr
+  );
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
+  IPersistStream* iface,
+  REFIID     riid,
+  VOID**     ppvoid)
+{
+  _ICOM_THIS_From_IPersistStream(IFont, iface);
+
+  return IFont_QueryInterface(this, riid, ppvoid);
+}
+
+/************************************************************************
+ * OLEFontImpl_IPersistStream_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
+  IPersistStream* iface)
+{
+  _ICOM_THIS_From_IPersistStream(IFont, iface);
+
+  return IFont_Release(this);
+}
+
+/************************************************************************
+ * OLEFontImpl_IPersistStream_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
+  IPersistStream* iface)
+{
+  _ICOM_THIS_From_IPersistStream(IFont, iface);
+
+  return IFont_AddRef(this);
+}
+
+/************************************************************************
+ * OLEFontImpl_GetClassID (IPersistStream)
+ *
+ * See Windows documentation for more details on IPersistStream methods.
+ */
+static HRESULT WINAPI OLEFontImpl_GetClassID(
+  IPersistStream* iface,
+  CLSID*                pClassID)
+{
+  TRACE("(%p,%p)\n",iface,pClassID);
+  if (pClassID==0)
+    return E_POINTER;
+
+  memcpy(pClassID, &CLSID_StdFont, sizeof(CLSID_StdFont));
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_IsDirty (IPersistStream)
+ *
+ * See Windows documentation for more details on IPersistStream methods.
+ */
+static HRESULT WINAPI OLEFontImpl_IsDirty(
+  IPersistStream*  iface)
+{
+  TRACE("(%p)\n",iface);
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_Load (IPersistStream)
+ *
+ * See Windows documentation for more details on IPersistStream methods.
+ *
+ * This is the format of the standard font serialization as far as I
+ * know
+ *
+ * Offset   Type   Value           Comment
+ * 0x0000   Byte   Unknown         Probably a version number, contains 0x01
+ * 0x0001   Short  Charset         Charset value from the FONTDESC structure
+ * 0x0003   Byte   Attributes      Flags defined as follows:
+ *                                     00000010 - Italic
+ *                                     00000100 - Underline
+ *                                     00001000 - Strikethrough
+ * 0x0004   Short  Weight          Weight value from FONTDESC structure
+ * 0x0006   DWORD  size            "Low" portion of the cySize member of the FONTDESC
+ *                                 structure/
+ * 0x000A   Byte   name length     Length of the font name string (no null character)
+ * 0x000B   String name            Name of the font (ASCII, no nul character)
+ */
+static HRESULT WINAPI OLEFontImpl_Load(
+  IPersistStream*  iface,
+  IStream*         pLoadStream)
+{
+  char  readBuffer[0x100];
+  ULONG cbRead;
+  BYTE  bVersion;
+  BYTE  bAttributes;
+  BYTE  bStringSize;
+  INT len;
+
+  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
+
+  /*
+   * Read the version byte
+   */
+  IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
+
+  if ( (cbRead!=1) ||
+       (bVersion!=0x01) )
+    return E_FAIL;
+
+  /*
+   * Charset
+   */
+  IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
+
+  if (cbRead!=2)
+    return E_FAIL;
+
+  /*
+   * Attributes
+   */
+  IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
+
+  if (cbRead!=1)
+    return E_FAIL;
+
+  this->description.fItalic        = (bAttributes & FONTPERSIST_ITALIC) != 0;
+  this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
+  this->description.fUnderline     = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
+
+  /*
+   * Weight
+   */
+  IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
+
+  if (cbRead!=2)
+    return E_FAIL;
+
+  /*
+   * Size
+   */
+  IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
+
+  if (cbRead!=4)
+    return E_FAIL;
+
+  this->description.cySize.s.Hi = 0;
+
+  /*
+   * FontName
+   */
+  IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
+
+  if (cbRead!=1)
+    return E_FAIL;
+
+  IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
+
+  if (cbRead!=bStringSize)
+    return E_FAIL;
+
+  HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
+
+  len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
+  this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
+  MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
+  this->description.lpstrName[len] = 0;
+
+  /* Ensure use of this font causes a new one to be created @@@@ */
+  DeleteObject(this->gdiFont);
+  this->gdiFont = 0;
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_Save (IPersistStream)
+ *
+ * See Windows documentation for more details on IPersistStream methods.
+ */
+static HRESULT WINAPI OLEFontImpl_Save(
+  IPersistStream*  iface,
+  IStream*         pOutStream,
+  BOOL             fClearDirty)
+{
+  char* writeBuffer = NULL;
+  ULONG cbWritten;
+  BYTE  bVersion = 0x01;
+  BYTE  bAttributes;
+  BYTE  bStringSize;
+
+  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
+
+  /*
+   * Read the version byte
+   */
+  IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
+
+  if (cbWritten!=1)
+    return E_FAIL;
+
+  /*
+   * Charset
+   */
+  IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
+
+  if (cbWritten!=2)
+    return E_FAIL;
+
+  /*
+   * Attributes
+   */
+  bAttributes = 0;
+
+  if (this->description.fItalic)
+    bAttributes |= FONTPERSIST_ITALIC;
+
+  if (this->description.fStrikethrough)
+    bAttributes |= FONTPERSIST_STRIKETHROUGH;
+
+  if (this->description.fUnderline)
+    bAttributes |= FONTPERSIST_UNDERLINE;
+
+  IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
+
+  if (cbWritten!=1)
+    return E_FAIL;
+
+  /*
+   * Weight
+   */
+  IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
+
+  if (cbWritten!=2)
+    return E_FAIL;
+
+  /*
+   * Size
+   */
+  IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
+
+  if (cbWritten!=4)
+    return E_FAIL;
+
+  /*
+   * FontName
+   */
+  if (this->description.lpstrName!=0)
+    bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
+                                       strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
+  else
+    bStringSize = 0;
+
+  IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
+
+  if (cbWritten!=1)
+    return E_FAIL;
+
+  if (bStringSize!=0)
+  {
+      if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
+      WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
+                           strlenW(this->description.lpstrName),
+                           writeBuffer, bStringSize, NULL, NULL );
+
+    IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
+    HeapFree(GetProcessHeap(), 0, writeBuffer);
+
+    if (cbWritten!=bStringSize)
+      return E_FAIL;
+  }
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_GetSizeMax (IPersistStream)
+ *
+ * See Windows documentation for more details on IPersistStream methods.
+ */
+static HRESULT WINAPI OLEFontImpl_GetSizeMax(
+  IPersistStream*  iface,
+  ULARGE_INTEGER*  pcbSize)
+{
+  _ICOM_THIS_From_IPersistStream(OLEFontImpl, iface);
+
+  if (pcbSize==NULL)
+    return E_POINTER;
+
+  pcbSize->u.HighPart = 0;
+  pcbSize->u.LowPart = 0;
+
+  pcbSize->u.LowPart += sizeof(BYTE);  /* Version */
+  pcbSize->u.LowPart += sizeof(WORD);  /* Lang code */
+  pcbSize->u.LowPart += sizeof(BYTE);  /* Flags */
+  pcbSize->u.LowPart += sizeof(WORD);  /* Weight */
+  pcbSize->u.LowPart += sizeof(DWORD); /* Size */
+  pcbSize->u.LowPart += sizeof(BYTE);  /* StrLength */
+
+  if (this->description.lpstrName!=0)
+    pcbSize->u.LowPart += lstrlenW(this->description.lpstrName);
+
+  return S_OK;
+}
+
+/************************************************************************
+ * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
+  IConnectionPointContainer* iface,
+  REFIID     riid,
+  VOID**     ppvoid)
+{
+  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
+
+  return IFont_QueryInterface((IFont*)this, riid, ppvoid);
+}
+
+/************************************************************************
+ * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
+  IConnectionPointContainer* iface)
+{
+  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
+
+  return IFont_Release((IFont*)this);
+}
+
+/************************************************************************
+ * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
+ *
+ * See Windows documentation for more details on IUnknown methods.
+ */
+static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
+  IConnectionPointContainer* iface)
+{
+  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
+
+  return IFont_AddRef((IFont*)this);
+}
+
+/************************************************************************
+ * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
+ *
+ * See Windows documentation for more details on IConnectionPointContainer
+ * methods.
+ */
+static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
+  IConnectionPointContainer* iface,
+  IEnumConnectionPoints **ppEnum)
+{
+  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
+
+  FIXME("(%p)->(%p): stub\n", this, ppEnum);
+  return E_NOTIMPL;
+}
+
+/************************************************************************
+ * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
+ *
+ * See Windows documentation for more details on IConnectionPointContainer
+ * methods.
+ */
+static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
+   IConnectionPointContainer* iface,
+   REFIID riid,
+   IConnectionPoint **ppCp)
+{
+  _ICOM_THIS_From_IConnectionPointContainer(OLEFontImpl, iface);
+  TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp);
+
+  if(memcmp(riid, &IID_IPropertyNotifySink, sizeof(IID_IPropertyNotifySink)) == 0) {
+    return IConnectionPoint_QueryInterface(this->pCP, &IID_IConnectionPoint,
+                                          (LPVOID)ppCp);
+  } else {
+    FIXME("Tried to find connection point on %s\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+  }
+}
+
+/************************************************************************
+ * OLEFontImpl implementation of IPersistPropertyBag.
+ */
+static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
+   IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
+) {
+  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
+  return IFont_QueryInterface(this,riid,ppvObj);
+}
+
+static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
+   IPersistPropertyBag *iface
+) {
+  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
+  return IFont_AddRef(this);
+}
+
+static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
+   IPersistPropertyBag *iface
+) {
+  _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
+  return IFont_Release(this);
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
+   IPersistPropertyBag *iface, CLSID *classid
+) {
+  FIXME("(%p,%p), stub!\n", iface, classid);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
+   IPersistPropertyBag *iface
+) {
+  FIXME("(%p), stub!\n", iface);
+  return S_OK;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
+   IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
+) {
+/* (from Visual Basic 6 property bag)
+         Name            =   "MS Sans Serif"
+         Size            =   13.8
+         Charset         =   0
+         Weight          =   400
+         Underline       =   0   'False
+         Italic          =   0   'False
+         Strikethrough   =   0   'False
+*/
+    static const WCHAR sAttrName[] = {'N','a','m','e',0};
+    static const WCHAR sAttrSize[] = {'S','i','z','e',0};
+    static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
+    static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
+    static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
+    static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
+    static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
+    VARIANT rawAttr;
+    VARIANT valueAttr;
+    HRESULT iRes = S_OK;
+    _ICOM_THIS_From_IPersistPropertyBag(IFont, iface);
+
+    VariantInit(&rawAttr);
+    VariantInit(&valueAttr);
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
+            if (iRes == S_OK)
+                iRes = IFont_put_Name(this, V_BSTR(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
+            if (iRes == S_OK)
+                iRes = IFont_put_Size(this, V_CY(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
+            if (iRes == S_OK)
+                iRes = IFont_put_Charset(this, V_I2(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
+            if (iRes == S_OK)
+                iRes = IFont_put_Weight(this, V_I2(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
+            if (iRes == S_OK)
+                iRes = IFont_put_Underline(this, V_BOOL(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
+            if (iRes == S_OK)
+                iRes = IFont_put_Italic(this, V_BOOL(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (iRes == S_OK) {
+        iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
+        if (iRes == S_OK)
+        {
+            iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
+            if (iRes == S_OK)
+                IFont_put_Strikethrough(this, V_BOOL(&valueAttr));
+        }
+        else if (iRes == E_INVALIDARG)
+            iRes = S_OK;
+        VariantClear(&rawAttr);
+        VariantClear(&valueAttr);
+    }
+
+    if (FAILED(iRes))
+        WARN("-- 0x%08lx\n", iRes);
+    return iRes;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
+   IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
+   BOOL fSaveAllProperties
+) {
+  FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
+  return E_FAIL;
+}
+
+static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
+{
+  OLEFontImpl_IPersistPropertyBag_QueryInterface,
+  OLEFontImpl_IPersistPropertyBag_AddRef,
+  OLEFontImpl_IPersistPropertyBag_Release,
+
+  OLEFontImpl_IPersistPropertyBag_GetClassID,
+  OLEFontImpl_IPersistPropertyBag_InitNew,
+  OLEFontImpl_IPersistPropertyBag_Load,
+  OLEFontImpl_IPersistPropertyBag_Save
+};
+
+/************************************************************************
+ * OLEFontImpl implementation of IPersistStreamInit.
+ */
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
+   IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
+) {
+  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
+  return IFont_QueryInterface(this,riid,ppvObj);
+}
+
+static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
+   IPersistStreamInit *iface
+) {
+  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
+  return IFont_AddRef(this);
+}
+
+static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
+   IPersistStreamInit *iface
+) {
+  _ICOM_THIS_From_IPersistStreamInit(IFont, iface);
+  return IFont_Release(this);
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
+   IPersistStreamInit *iface, CLSID *classid
+) {
+  FIXME("(%p,%p), stub!\n", iface, classid);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
+   IPersistStreamInit *iface
+) {
+  FIXME("(%p), stub!\n", iface);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
+   IPersistStreamInit *iface, LPSTREAM pStm
+) {
+  FIXME("(%p,%p), stub!\n", iface, pStm);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
+   IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
+) {
+  FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
+   IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
+) {
+  FIXME("(%p,%p), stub!\n", iface, pcbSize);
+  return E_FAIL;
+}
+
+static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
+   IPersistStreamInit *iface
+) {
+  FIXME("(%p), stub!\n", iface);
+  return S_OK;
+}
+
+static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
+{
+  OLEFontImpl_IPersistStreamInit_QueryInterface,
+  OLEFontImpl_IPersistStreamInit_AddRef,
+  OLEFontImpl_IPersistStreamInit_Release,
+
+  OLEFontImpl_IPersistStreamInit_GetClassID,
+  OLEFontImpl_IPersistStreamInit_IsDirty,
+  OLEFontImpl_IPersistStreamInit_Load,
+  OLEFontImpl_IPersistStreamInit_Save,
+  OLEFontImpl_IPersistStreamInit_GetSizeMax,
+  OLEFontImpl_IPersistStreamInit_InitNew
+};
+
+/*******************************************************************************
+ * StdFont ClassFactory
+ */
+typedef struct
+{
+    /* IUnknown fields */
+    IClassFactoryVtbl          *lpVtbl;
+    DWORD                       ref;
+} IClassFactoryImpl;
+
+static HRESULT WINAPI
+SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
+       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+       FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
+       return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+SFCF_AddRef(LPCLASSFACTORY iface) {
+       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+       return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
+       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+       /* static class, won't be  freed */
+       return InterlockedDecrement(&This->ref);
+}
+
+static HRESULT WINAPI SFCF_CreateInstance(
+       LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
+) {
+       return OleCreateFontIndirect(NULL,riid,ppobj);
+
+}
+
+static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
+       IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+       FIXME("(%p)->(%d),stub!\n",This,dolock);
+       return S_OK;
+}
+
+static IClassFactoryVtbl SFCF_Vtbl = {
+       SFCF_QueryInterface,
+       SFCF_AddRef,
+       SFCF_Release,
+       SFCF_CreateInstance,
+       SFCF_LockServer
+};
+static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
+
+void _get_STDFONT_CF(LPVOID *ppv) { *ppv = (LPVOID)&STDFONT_CF; }