wine/dlls/oleaut32/olefont.c

2350 lines
65 KiB
C

/*
* OLE Font encapsulation implementation
*
* This file contains an implementation of the IFont
* interface and the OleCreateFontIndirect API call.
*
* Copyright 1999 Francis Beaudet
* Copyright 2006 (Google) Benjamin Arai
*
* 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 <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/list.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
/***********************************************************************
* List of the HFONTs it has given out, with each one having a separate
* ref count.
*/
typedef struct _HFONTItem
{
struct list entry;
/* Reference count for that instance of the class. */
LONG ref;
/* Contain the font associated with this object. */
HFONT gdiFont;
} HFONTItem, *PHFONTItem;
static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
/* Counts how many fonts contain at least one lock */
static LONG ifont_cnt = 0;
/***********************************************************************
* Critical section for OLEFontImpl_hFontList
*/
static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
{
0, 0, &OLEFontImpl_csHFONTLIST,
{ &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
&OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
};
static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
static void HFONTItem_Delete(PHFONTItem item)
{
DeleteObject(item->gdiFont);
list_remove(&item->entry);
HeapFree(GetProcessHeap(), 0, item);
}
/***********************************************************************
* 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;
/*
* 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 ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
/******************************************************************************
* 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 WCHAR fname[] = { 'S','y','s','t','e','m',0 };
fd.cbSizeofstruct = sizeof(fd);
fd.lpstrName = 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;
this->gdiFont = 0;
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_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=%d)\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;
PHFONTItem ptr, next;
TRACE("(%p)->(ref=%d)\n", this, this->ref);
/* Decrease the reference count for current interface */
ret = InterlockedDecrement(&this->ref);
/* If the reference count goes down to 0, destroy. */
if (ret == 0)
{
ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
/* Check if all HFONT list refs are zero */
if (fontlist_refs == 0)
{
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &OLEFontImpl_hFontList, HFONTItem, entry)
HFONTItem_Delete(ptr);
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
}
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)->(%d)\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;
PHFONTItem newEntry;
/*
* 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);
/* Add font to the cache */
newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(HFONTItem));
newEntry->ref = 1;
newEntry->gdiFont = this->gdiFont;
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
list_add_tail(&OLEFontImpl_hFontList,&newEntry->entry);
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
}
*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;
PHFONTItem newEntry;
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);
/* Add font to the cache */
InterlockedIncrement(&ifont_cnt);
newEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(HFONTItem));
newEntry->ref = 1;
newEntry->gdiFont = newObject->gdiFont;
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
list_add_tail(&OLEFontImpl_hFontList,&newEntry->entry);
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
/* 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)
{
OLEFontImpl *left = (OLEFontImpl *)iface;
OLEFontImpl *right = (OLEFontImpl *)pFontOther;
HRESULT hres;
INT left_len,right_len;
if((iface == NULL) || (pFontOther == NULL))
return E_POINTER;
else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
return S_FALSE;
else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
return S_FALSE;
else if (left->description.sWeight != right->description.sWeight)
return S_FALSE;
else if (left->description.sCharset != right->description.sCharset)
return S_FALSE;
else if (left->description.fItalic != right->description.fItalic)
return S_FALSE;
else if (left->description.fUnderline != right->description.fUnderline)
return S_FALSE;
else if (left->description.fStrikethrough != right->description.fStrikethrough)
return S_FALSE;
/* Check from string */
left_len = strlenW(left->description.lpstrName);
right_len = strlenW(right->description.lpstrName);
hres = CompareStringW(0,0,left->description.lpstrName, left_len,
right->description.lpstrName, right_len);
if (hres != CSTR_EQUAL)
return S_FALSE;
return S_OK;
}
/************************************************************************
* 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)->(%d, %d)\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;
PHFONTItem ptr, next;
HRESULT hres = S_FALSE; /* assume not present */
TRACE("(%p)->(%p)\n", this, hfont);
if (!hfont)
return E_INVALIDARG;
/* Check of the hFont is already in the list */
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &OLEFontImpl_hFontList, HFONTItem, entry)
{
if (ptr->gdiFont == hfont)
{
ptr->ref++;
hres = S_OK;
break;
}
}
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
return hres;
}
/************************************************************************
* 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;
PHFONTItem ptr, next;
HRESULT hres = S_FALSE; /* assume not present */
TRACE("(%p)->(%p)\n", this, hfont);
if (!hfont)
return E_INVALIDARG;
/* Check of the hFont is already in the list */
EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &OLEFontImpl_hFontList, HFONTItem, entry)
{
if ((ptr->gdiFont == hfont) && ptr->ref)
{
/* Remove from cache and delete object if not referenced */
if (!--ptr->ref)
{
if (ptr->gdiFont == this->gdiFont)
this->gdiFont = NULL;
}
hres = S_OK;
break;
}
}
LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
return hres;
}
/************************************************************************
* 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;
}
/*
* 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
};
/************************************************************************
* 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);
TRACE("(%p)->(%p)\n", this, pctinfo);
*pctinfo = 1;
return S_OK;
}
/************************************************************************
* 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 %x\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)
{
ITypeInfo * pTInfo;
HRESULT hres;
OLEFontImpl *this = impl_from_IDispatch(iface);
TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
rgszNames, cNames, (int)lcid, rgDispId);
if (cNames == 0)
{
return E_INVALIDARG;
}
else
{
/* retrieve type information */
hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
if (FAILED(hres))
{
ERR("GetTypeInfo failed.\n");
return hres;
}
/* convert names to DISPIDs */
hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
ITypeInfo_Release(pTInfo);
return hres;
}
}
/************************************************************************
* 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);
HRESULT hr;
TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
puArgErr);
/* validate parameters */
if (!IsEqualIID(riid, &IID_NULL))
{
ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
return DISP_E_UNKNOWNINTERFACE;
}
if (wFlags & DISPATCH_PROPERTYGET)
{
if (!pVarResult)
{
ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
return DISP_E_PARAMNOTOPTIONAL;
}
}
else if (wFlags & DISPATCH_PROPERTYPUT)
{
if (!pDispParams)
{
ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
return DISP_E_PARAMNOTOPTIONAL;
}
if (pDispParams->cArgs != 1)
{
ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
return DISP_E_BADPARAMCOUNT;
}
}
else
{
ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
return DISP_E_MEMBERNOTFOUND;
}
switch (dispIdMember) {
case DISPID_FONT_NAME:
if (wFlags & DISPATCH_PROPERTYGET) {
V_VT(pVarResult) = VT_BSTR;
return IFont_get_Name((IFont *)this, &V_BSTR(pVarResult));
} else {
VARIANTARG vararg;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
if (FAILED(hr))
return hr;
hr = IFont_put_Name((IFont *)this, V_BSTR(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_BOLD:
if (wFlags & DISPATCH_PROPERTYGET) {
BOOL value;
hr = IFont_get_Bold((IFont *)this, &value);
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
return hr;
} else {
VARIANTARG vararg;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
if (FAILED(hr))
return hr;
hr = IFont_put_Bold((IFont *)this, V_BOOL(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_ITALIC:
if (wFlags & DISPATCH_PROPERTYGET) {
BOOL value;
hr = IFont_get_Italic((IFont *)this, &value);
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
return hr;
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
if (FAILED(hr))
return hr;
hr = IFont_put_Italic((IFont *)this, V_BOOL(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_UNDER:
if (wFlags & DISPATCH_PROPERTYGET) {
BOOL value;
hr = IFont_get_Underline((IFont *)this, &value);
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
return hr;
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
if (FAILED(hr))
return hr;
hr = IFont_put_Underline((IFont *)this, V_BOOL(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_STRIKE:
if (wFlags & DISPATCH_PROPERTYGET) {
BOOL value;
hr = IFont_get_Strikethrough((IFont *)this, &value);
V_VT(pVarResult) = VT_BOOL;
V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
return hr;
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
if (FAILED(hr))
return hr;
hr = IFont_put_Strikethrough((IFont *)this, V_BOOL(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_SIZE:
if (wFlags & DISPATCH_PROPERTYGET) {
V_VT(pVarResult) = VT_CY;
return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
if (FAILED(hr))
return hr;
hr = IFont_put_Size((IFont *)this, V_CY(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_WEIGHT:
if (wFlags & DISPATCH_PROPERTYGET) {
V_VT(pVarResult) = VT_I2;
return OLEFontImpl_get_Weight((IFont *)this, &V_I2(pVarResult));
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
if (FAILED(hr))
return hr;
hr = IFont_put_Weight((IFont *)this, V_I2(&vararg));
VariantClear(&vararg);
return hr;
}
break;
case DISPID_FONT_CHARSET:
if (wFlags & DISPATCH_PROPERTYGET) {
V_VT(pVarResult) = VT_I2;
return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
} else {
VARIANTARG vararg;
HRESULT hr;
VariantInit(&vararg);
hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
if (FAILED(hr))
return hr;
hr = IFont_put_Charset((IFont *)this, V_I2(&vararg));
VariantClear(&vararg);
return hr;
}
break;
default:
ERR("member not found for dispid 0x%x\n", dispIdMember);
return DISP_E_MEMBERNOTFOUND;
}
}
static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
{
OLEFontImpl_IDispatch_QueryInterface,
OLEFontImpl_IDispatch_AddRef,
OLEFontImpl_IDispatch_Release,
OLEFontImpl_GetTypeInfoCount,
OLEFontImpl_GetTypeInfo,
OLEFontImpl_GetIDsOfNames,
OLEFontImpl_Invoke
};
/************************************************************************
* 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;
}
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
};
/************************************************************************
* 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)\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;
}
}
static const IConnectionPointContainerVtbl
OLEFontImpl_IConnectionPointContainer_VTable =
{
OLEFontImpl_IConnectionPointContainer_QueryInterface,
OLEFontImpl_IConnectionPointContainer_AddRef,
OLEFontImpl_IConnectionPointContainer_Release,
OLEFontImpl_EnumConnectionPoints,
OLEFontImpl_FindConnectionPoint
};
/************************************************************************
* 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%08x\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
};
/************************************************************************
* 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->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;
}
InterlockedIncrement(&ifont_cnt);
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);
}
/*******************************************************************************
* 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; }