/* * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #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 */ #include "oaidl.h" 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. */ const IFontVtbl* lpVtbl; const IDispatchVtbl* lpvtblIDispatch; const IPersistStreamVtbl* lpvtblIPersistStream; const IConnectionPointContainerVtbl* lpvtblIConnectionPointContainer; const IPersistPropertyBagVtbl* lpvtblIPersistPropertyBag; const IPersistStreamInitVtbl* lpvtblIPersistStreamInit; /* * Reference count for that instance of the class. */ LONG 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 *pPropertyNotifyCP; IConnectionPoint *pFontEventsCP; }; /* * 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. */ static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface ) { return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIDispatch)); } static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface ) { return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStream)); } static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface ) { return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIConnectionPointContainer)); } static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface ) { return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistPropertyBag)); } static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface ) { return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStreamInit)); } /*********************************************************************** * 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 const 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 const IDispatchVtbl OLEFontImpl_IDispatch_VTable = { OLEFontImpl_IDispatch_QueryInterface, OLEFontImpl_IDispatch_AddRef, OLEFontImpl_IDispatch_Release, OLEFontImpl_GetTypeInfoCount, OLEFontImpl_GetTypeInfo, OLEFontImpl_GetIDsOfNames, OLEFontImpl_Invoke }; static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable = { OLEFontImpl_IPersistStream_QueryInterface, OLEFontImpl_IPersistStream_AddRef, OLEFontImpl_IPersistStream_Release, OLEFontImpl_GetClassID, OLEFontImpl_IsDirty, OLEFontImpl_Load, OLEFontImpl_Save, OLEFontImpl_GetSizeMax }; static const IConnectionPointContainerVtbl OLEFontImpl_IConnectionPointContainer_VTable = { OLEFontImpl_IConnectionPointContainer_QueryInterface, OLEFontImpl_IConnectionPointContainer_AddRef, OLEFontImpl_IConnectionPointContainer_Release, OLEFontImpl_EnumConnectionPoints, OLEFontImpl_FindConnectionPoint }; static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable; static const 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) { static const WCHAR wszName[] = {'N','a','m','e',0}; static const WCHAR wszSize[] = {'S','i','z','e',0}; static const WCHAR wszBold[] = {'B','o','l','d',0}; static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0}; static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0}; static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0}; static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0}; static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0}; static const LPCWSTR dispid_mapping[] = { wszName, NULL, wszSize, wszBold, wszItalic, wszUnder, wszStrike, wszWeight, wszCharset }; IEnumConnections *pEnum; CONNECTDATA CD; HRESULT hres; hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum); if (SUCCEEDED(hres)) { 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); } hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum); if (SUCCEEDED(hres)) { DISPPARAMS dispparams; VARIANTARG vararg; VariantInit(&vararg); V_VT(&vararg) = VT_BSTR; V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]); dispparams.cArgs = 1; dispparams.cNamedArgs = 0; dispparams.rgdispidNamedArgs = NULL; dispparams.rgvarg = &vararg; while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) { IFontEventsDisp *disp; IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp); IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL, LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL, NULL, NULL); IDispatch_Release(disp); IUnknown_Release(CD.pUnk); } VariantClear(&vararg); IEnumConnections_Release(pEnum); } } /************************************************************************ * 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->lpVtbl = &OLEFontImpl_VTable; newObject->lpvtblIDispatch = &OLEFontImpl_IDispatch_VTable; newObject->lpvtblIPersistStream = &OLEFontImpl_IPersistStream_VTable; newObject->lpvtblIConnectionPointContainer = &OLEFontImpl_IConnectionPointContainer_VTable; newObject->lpvtblIPersistPropertyBag = &OLEFontImpl_IPersistPropertyBag_VTable; newObject->lpvtblIPersistStreamInit = &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; newObject->pPropertyNotifyCP = NULL; newObject->pFontEventsCP = NULL; CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP); CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP); if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) { OLEFontImpl_Destroy(newObject); return NULL; } 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); if (fontDesc->pPropertyNotifyCP) IConnectionPoint_Release(fontDesc->pPropertyNotifyCP); if (fontDesc->pFontEventsCP) IConnectionPoint_Release(fontDesc->pFontEventsCP); 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->lpvtblIDispatch); if (IsEqualGUID(&IID_IFontDisp, riid)) *ppvObject = (IDispatch*)&(this->lpvtblIDispatch); if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid)) *ppvObject = (IPersistStream*)&(this->lpvtblIPersistStream); if (IsEqualGUID(&IID_IConnectionPointContainer, riid)) *ppvObject = (IConnectionPointContainer*)&(this->lpvtblIConnectionPointContainer); if (IsEqualGUID(&IID_IPersistPropertyBag, riid)) *ppvObject = (IPersistPropertyBag*)&(this->lpvtblIPersistPropertyBag); if (IsEqualGUID(&IID_IPersistStreamInit, riid)) *ppvObject = (IPersistStreamInit*)&(this->lpvtblIPersistStreamInit); /* * 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); /* Standard ratio is 72 / 2540, or 18 / 635 in lowest terms. */ /* Ratio is applied here relative to the standard. */ fontHeight = MulDiv( cySize.s.Lo, this->cyLogical*635, this->cyHimetric*18 ); 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*635,this->cyHimetric*18); 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); /* create new connection points */ newObject->pPropertyNotifyCP = NULL; newObject->pFontEventsCP = NULL; CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP); CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP); if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP) { OLEFontImpl_Destroy(newObject); return E_OUTOFMEMORY; } /* 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) { OLEFontImpl *this = impl_from_IDispatch(iface); return IFont_QueryInterface((IFont *)this, riid, ppvoid); } /************************************************************************ * OLEFontImpl_IDispatch_Release (IUnknown) * * See Windows documentation for more details on IUnknown methods. */ static ULONG WINAPI OLEFontImpl_IDispatch_Release( IDispatch* iface) { OLEFontImpl *this = impl_from_IDispatch(iface); return IFont_Release((IFont *)this); } /************************************************************************ * OLEFontImpl_IDispatch_AddRef (IUnknown) * * See Windows documentation for more details on IUnknown methods. */ static ULONG WINAPI OLEFontImpl_IDispatch_AddRef( IDispatch* iface) { OLEFontImpl *this = impl_from_IDispatch(iface); return IFont_AddRef((IFont *)this); } /************************************************************************ * OLEFontImpl_GetTypeInfoCount (IDispatch) * * See Windows documentation for more details on IDispatch methods. */ static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount( IDispatch* iface, unsigned int* pctinfo) { OLEFontImpl *this = impl_from_IDispatch(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 stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0}; ITypeLib *tl; HRESULT hres; OLEFontImpl *this = impl_from_IDispatch(iface); TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo); if (iTInfo != 0) return E_FAIL; hres = LoadTypeLib(stdole2tlb, &tl); if (FAILED(hres)) { ERR("Could not load the stdole2.tlb?\n"); return hres; } hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, 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) { OLEFontImpl *this = impl_from_IDispatch(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) { OLEFontImpl *this = impl_from_IDispatch(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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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) { OLEFontImpl *this = impl_from_IPersistStream(iface); return IFont_QueryInterface((IFont *)this, riid, ppvoid); } /************************************************************************ * OLEFontImpl_IPersistStream_Release (IUnknown) * * See Windows documentation for more details on IUnknown methods. */ static ULONG WINAPI OLEFontImpl_IPersistStream_Release( IPersistStream* iface) { OLEFontImpl *this = impl_from_IPersistStream(iface); return IFont_Release((IFont *)this); } /************************************************************************ * OLEFontImpl_IPersistStream_AddRef (IUnknown) * * See Windows documentation for more details on IUnknown methods. */ static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef( IPersistStream* iface) { OLEFontImpl *this = impl_from_IPersistStream(iface); return IFont_AddRef((IFont *)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; OLEFontImpl *this = impl_from_IPersistStream(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; OLEFontImpl *this = impl_from_IPersistStream(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) { OLEFontImpl *this = impl_from_IPersistStream(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) { OLEFontImpl *this = impl_from_IConnectionPointContainer(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) { OLEFontImpl *this = impl_from_IConnectionPointContainer(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) { OLEFontImpl *this = impl_from_IConnectionPointContainer(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) { OLEFontImpl *this = impl_from_IConnectionPointContainer(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) { OLEFontImpl *this = impl_from_IConnectionPointContainer(iface); TRACE("(%p)->(%s, %p): stub\n", this, debugstr_guid(riid), ppCp); if(IsEqualIID(riid, &IID_IPropertyNotifySink)) { return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP, &IID_IConnectionPoint, (LPVOID)ppCp); } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) { return IConnectionPoint_QueryInterface(this->pFontEventsCP, &IID_IConnectionPoint, (LPVOID)ppCp); } else { FIXME("no connection point for %s\n", debugstr_guid(riid)); return CONNECT_E_NOCONNECTION; } } /************************************************************************ * OLEFontImpl implementation of IPersistPropertyBag. */ static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface( IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj ) { OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); return IFont_QueryInterface((IFont *)this,riid,ppvObj); } static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef( IPersistPropertyBag *iface ) { OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); return IFont_AddRef((IFont *)this); } static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release( IPersistPropertyBag *iface ) { OLEFontImpl *this = impl_from_IPersistPropertyBag(iface); return IFont_Release((IFont *)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; OLEFontImpl *this = impl_from_IPersistPropertyBag(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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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((IFont *)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 const 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 ) { OLEFontImpl *this = impl_from_IPersistStreamInit(iface); return IFont_QueryInterface((IFont *)this,riid,ppvObj); } static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef( IPersistStreamInit *iface ) { OLEFontImpl *this = impl_from_IPersistStreamInit(iface); return IFont_AddRef((IFont *)this); } static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release( IPersistStreamInit *iface ) { OLEFontImpl *this = impl_from_IPersistStreamInit(iface); return IFont_Release((IFont *)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 const 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 */ const IClassFactoryVtbl *lpVtbl; LONG 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 const 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; }