[OLEAUT32]
[reactos.git] / reactos / dll / win32 / oleaut32 / olefont.c
1 /*
2 * OLE Font encapsulation implementation
3 *
4 * This file contains an implementation of the IFont
5 * interface and the OleCreateFontIndirect API call.
6 *
7 * Copyright 1999 Francis Beaudet
8 * Copyright 2006 (Google) Benjamin Arai
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <string.h>
27
28 #define COBJMACROS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31
32 #include "winerror.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "winuser.h"
37 #include "wine/list.h"
38 #include "wine/unicode.h"
39 #include "objbase.h"
40 #include "oleauto.h" /* for SysAllocString(....) */
41 #include "ole2.h"
42 #include "olectl.h"
43 #include "wine/debug.h"
44 #include "connpt.h" /* for CreateConnectionPoint */
45 #include "oaidl.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48
49 /***********************************************************************
50 * Declaration of constants used when serializing the font object.
51 */
52 #define FONTPERSIST_ITALIC 0x02
53 #define FONTPERSIST_UNDERLINE 0x04
54 #define FONTPERSIST_STRIKETHROUGH 0x08
55
56 static HDC olefont_hdc;
57
58 /***********************************************************************
59 * List of the HFONTs it has given out, with each one having a separate
60 * ref count.
61 */
62 typedef struct _HFONTItem
63 {
64 struct list entry;
65
66 /* Reference count of any IFont objects that own this hfont */
67 LONG int_refs;
68
69 /* Total reference count of any refs held by the application obtained by AddRefHfont plus any internal refs */
70 LONG total_refs;
71
72 /* The font associated with this object. */
73 HFONT gdiFont;
74
75 } HFONTItem, *PHFONTItem;
76
77 static struct list OLEFontImpl_hFontList = LIST_INIT(OLEFontImpl_hFontList);
78
79 /* Counts how many fonts contain at least one lock */
80 static LONG ifont_cnt = 0;
81
82 /***********************************************************************
83 * Critical section for OLEFontImpl_hFontList
84 */
85 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST;
86 static CRITICAL_SECTION_DEBUG OLEFontImpl_csHFONTLIST_debug =
87 {
88 0, 0, &OLEFontImpl_csHFONTLIST,
89 { &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList,
90 &OLEFontImpl_csHFONTLIST_debug.ProcessLocksList },
91 0, 0, { (DWORD_PTR)(__FILE__ ": OLEFontImpl_csHFONTLIST") }
92 };
93 static CRITICAL_SECTION OLEFontImpl_csHFONTLIST = { &OLEFontImpl_csHFONTLIST_debug, -1, 0, 0, 0, 0 };
94
95 static HDC get_dc(void)
96 {
97 HDC hdc;
98 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
99 if(!olefont_hdc)
100 olefont_hdc = CreateCompatibleDC(NULL);
101 hdc = olefont_hdc;
102 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
103 return hdc;
104 }
105
106 static void delete_dc(void)
107 {
108 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
109 if(olefont_hdc)
110 {
111 DeleteDC(olefont_hdc);
112 olefont_hdc = NULL;
113 }
114 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
115 }
116
117 static void HFONTItem_Delete(PHFONTItem item)
118 {
119 DeleteObject(item->gdiFont);
120 list_remove(&item->entry);
121 HeapFree(GetProcessHeap(), 0, item);
122 }
123
124 /* Find hfont item entry in the list. Should be called while holding the crit sect */
125 static HFONTItem *find_hfontitem(HFONT hfont)
126 {
127 HFONTItem *item;
128
129 LIST_FOR_EACH_ENTRY(item, &OLEFontImpl_hFontList, HFONTItem, entry)
130 {
131 if (item->gdiFont == hfont)
132 return item;
133 }
134 return NULL;
135 }
136
137 /* Add an item to the list with one internal reference */
138 static HRESULT add_hfontitem(HFONT hfont)
139 {
140 HFONTItem *new_item = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_item));
141
142 if(!new_item) return E_OUTOFMEMORY;
143
144 new_item->int_refs = 1;
145 new_item->total_refs = 1;
146 new_item->gdiFont = hfont;
147 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
148 list_add_tail(&OLEFontImpl_hFontList,&new_item->entry);
149 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
150 return S_OK;
151 }
152
153 static HRESULT inc_int_ref(HFONT hfont)
154 {
155 HFONTItem *item;
156 HRESULT hr = S_FALSE;
157
158 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
159 item = find_hfontitem(hfont);
160
161 if(item)
162 {
163 item->int_refs++;
164 item->total_refs++;
165 hr = S_OK;
166 }
167 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
168
169 return hr;
170 }
171
172 /* decrements the internal ref of a hfont item. If both refs are zero it'll
173 remove the item from the list and delete the hfont */
174 static HRESULT dec_int_ref(HFONT hfont)
175 {
176 HFONTItem *item;
177 HRESULT hr = S_FALSE;
178
179 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
180 item = find_hfontitem(hfont);
181
182 if(item)
183 {
184 item->int_refs--;
185 item->total_refs--;
186 if(item->int_refs == 0 && item->total_refs == 0)
187 HFONTItem_Delete(item);
188 hr = S_OK;
189 }
190 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
191
192 return hr;
193 }
194
195 static HRESULT inc_ext_ref(HFONT hfont)
196 {
197 HFONTItem *item;
198 HRESULT hr = S_FALSE;
199
200 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
201
202 item = find_hfontitem(hfont);
203 if(item)
204 {
205 item->total_refs++;
206 hr = S_OK;
207 }
208 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
209
210 return hr;
211 }
212
213 static HRESULT dec_ext_ref(HFONT hfont)
214 {
215 HFONTItem *item;
216 HRESULT hr = S_FALSE;
217
218 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
219
220 item = find_hfontitem(hfont);
221 if(item)
222 {
223 if(--item->total_refs >= 0) hr = S_OK;
224 }
225 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
226
227 return hr;
228 }
229
230 static WCHAR *strdupW(const WCHAR* str)
231 {
232 WCHAR *ret;
233 DWORD size = (strlenW(str) + 1) * sizeof(WCHAR);
234
235 ret = HeapAlloc(GetProcessHeap(), 0, size);
236 if(ret)
237 memcpy(ret, str, size);
238 return ret;
239 }
240
241 /***********************************************************************
242 * Declaration of the implementation class for the IFont interface
243 */
244 typedef struct OLEFontImpl OLEFontImpl;
245
246 struct OLEFontImpl
247 {
248 /*
249 * This class supports many interfaces. IUnknown, IFont,
250 * IDispatch, IDispFont IPersistStream and IConnectionPointContainer.
251 * The first two are supported by the first vtable, the next two are
252 * supported by the second table and the last two have their own.
253 */
254 const IFontVtbl* lpVtbl;
255 const IDispatchVtbl* lpvtblIDispatch;
256 const IPersistStreamVtbl* lpvtblIPersistStream;
257 const IConnectionPointContainerVtbl* lpvtblIConnectionPointContainer;
258 const IPersistPropertyBagVtbl* lpvtblIPersistPropertyBag;
259 const IPersistStreamInitVtbl* lpvtblIPersistStreamInit;
260 /*
261 * Reference count for that instance of the class.
262 */
263 LONG ref;
264
265 /*
266 * This structure contains the description of the class.
267 */
268 FONTDESC description;
269
270 /*
271 * Contain the font associated with this object.
272 */
273 HFONT gdiFont;
274 BOOL dirty;
275 /*
276 * Size ratio
277 */
278 LONG cyLogical;
279 LONG cyHimetric;
280
281 IConnectionPoint *pPropertyNotifyCP;
282 IConnectionPoint *pFontEventsCP;
283 };
284
285 /*
286 * Here, I define utility macros to help with the casting of the
287 * "this" parameter.
288 * There is a version to accommodate all of the VTables implemented
289 * by this object.
290 */
291
292 static inline OLEFontImpl *impl_from_IDispatch( IDispatch *iface )
293 {
294 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIDispatch));
295 }
296
297 static inline OLEFontImpl *impl_from_IPersistStream( IPersistStream *iface )
298 {
299 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStream));
300 }
301
302 static inline OLEFontImpl *impl_from_IConnectionPointContainer( IConnectionPointContainer *iface )
303 {
304 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIConnectionPointContainer));
305 }
306
307 static inline OLEFontImpl *impl_from_IPersistPropertyBag( IPersistPropertyBag *iface )
308 {
309 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistPropertyBag));
310 }
311
312 static inline OLEFontImpl *impl_from_IPersistStreamInit( IPersistStreamInit *iface )
313 {
314 return (OLEFontImpl *)((char*)iface - FIELD_OFFSET(OLEFontImpl, lpvtblIPersistStreamInit));
315 }
316
317
318 /***********************************************************************
319 * Prototypes for the implementation functions for the IFont
320 * interface
321 */
322 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc);
323 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc);
324 static ULONG WINAPI OLEFontImpl_AddRef(IFont* iface);
325
326 /******************************************************************************
327 * OleCreateFontIndirect [OLEAUT32.420]
328 */
329 HRESULT WINAPI OleCreateFontIndirect(
330 LPFONTDESC lpFontDesc,
331 REFIID riid,
332 LPVOID* ppvObj)
333 {
334 OLEFontImpl* newFont = 0;
335 HRESULT hr = S_OK;
336
337 TRACE("(%p, %s, %p)\n", lpFontDesc, debugstr_guid(riid), ppvObj);
338 /*
339 * Sanity check
340 */
341 if (ppvObj==0)
342 return E_POINTER;
343
344 *ppvObj = 0;
345
346 if (!lpFontDesc) {
347 FONTDESC fd;
348
349 static WCHAR fname[] = { 'S','y','s','t','e','m',0 };
350
351 fd.cbSizeofstruct = sizeof(fd);
352 fd.lpstrName = fname;
353 fd.cySize.s.Lo = 80000;
354 fd.cySize.s.Hi = 0;
355 fd.sWeight = 0;
356 fd.sCharset = 0;
357 fd.fItalic = 0;
358 fd.fUnderline = 0;
359 fd.fStrikethrough = 0;
360 lpFontDesc = &fd;
361 }
362
363 /*
364 * Try to construct a new instance of the class.
365 */
366 newFont = OLEFontImpl_Construct(lpFontDesc);
367
368 if (newFont == 0)
369 return E_OUTOFMEMORY;
370
371 /*
372 * Make sure it supports the interface required by the caller.
373 */
374 hr = IFont_QueryInterface((IFont*)newFont, riid, ppvObj);
375
376 /*
377 * Release the reference obtained in the constructor. If
378 * the QueryInterface was unsuccessful, it will free the class.
379 */
380 IFont_Release((IFont*)newFont);
381
382 return hr;
383 }
384
385
386 /***********************************************************************
387 * Implementation of the OLEFontImpl class.
388 */
389
390 /***********************************************************************
391 * OLEFont_SendNotify (internal)
392 *
393 * Sends notification messages of changed properties to any interested
394 * connections.
395 */
396 static void OLEFont_SendNotify(OLEFontImpl* this, DISPID dispID)
397 {
398 static const WCHAR wszName[] = {'N','a','m','e',0};
399 static const WCHAR wszSize[] = {'S','i','z','e',0};
400 static const WCHAR wszBold[] = {'B','o','l','d',0};
401 static const WCHAR wszItalic[] = {'I','t','a','l','i','c',0};
402 static const WCHAR wszUnder[] = {'U','n','d','e','r','l','i','n','e',0};
403 static const WCHAR wszStrike[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
404 static const WCHAR wszWeight[] = {'W','e','i','g','h','t',0};
405 static const WCHAR wszCharset[] = {'C','h','a','r','s','s','e','t',0};
406 static const LPCWSTR dispid_mapping[] =
407 {
408 wszName,
409 NULL,
410 wszSize,
411 wszBold,
412 wszItalic,
413 wszUnder,
414 wszStrike,
415 wszWeight,
416 wszCharset
417 };
418
419 IEnumConnections *pEnum;
420 CONNECTDATA CD;
421 HRESULT hres;
422
423 this->dirty = TRUE;
424
425 hres = IConnectionPoint_EnumConnections(this->pPropertyNotifyCP, &pEnum);
426 if (SUCCEEDED(hres))
427 {
428 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
429 IPropertyNotifySink *sink;
430
431 IUnknown_QueryInterface(CD.pUnk, &IID_IPropertyNotifySink, (LPVOID)&sink);
432 IPropertyNotifySink_OnChanged(sink, dispID);
433 IPropertyNotifySink_Release(sink);
434 IUnknown_Release(CD.pUnk);
435 }
436 IEnumConnections_Release(pEnum);
437 }
438
439 hres = IConnectionPoint_EnumConnections(this->pFontEventsCP, &pEnum);
440 if (SUCCEEDED(hres))
441 {
442 DISPPARAMS dispparams;
443 VARIANTARG vararg;
444
445 VariantInit(&vararg);
446 V_VT(&vararg) = VT_BSTR;
447 V_BSTR(&vararg) = SysAllocString(dispid_mapping[dispID]);
448
449 dispparams.cArgs = 1;
450 dispparams.cNamedArgs = 0;
451 dispparams.rgdispidNamedArgs = NULL;
452 dispparams.rgvarg = &vararg;
453
454 while(IEnumConnections_Next(pEnum, 1, &CD, NULL) == S_OK) {
455 IFontEventsDisp *disp;
456
457 IUnknown_QueryInterface(CD.pUnk, &IID_IFontEventsDisp, (LPVOID)&disp);
458 IDispatch_Invoke(disp, DISPID_FONT_CHANGED, &IID_NULL,
459 LOCALE_NEUTRAL, INVOKE_FUNC, &dispparams, NULL,
460 NULL, NULL);
461
462 IDispatch_Release(disp);
463 IUnknown_Release(CD.pUnk);
464 }
465 VariantClear(&vararg);
466 IEnumConnections_Release(pEnum);
467 }
468 }
469
470 /************************************************************************
471 * OLEFontImpl_QueryInterface (IUnknown)
472 *
473 * See Windows documentation for more details on IUnknown methods.
474 */
475 static HRESULT WINAPI OLEFontImpl_QueryInterface(
476 IFont* iface,
477 REFIID riid,
478 void** ppvObject)
479 {
480 OLEFontImpl *this = (OLEFontImpl *)iface;
481 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppvObject);
482
483 /*
484 * Perform a sanity check on the parameters.
485 */
486 if ( (this==0) || (ppvObject==0) )
487 return E_INVALIDARG;
488
489 /*
490 * Initialize the return parameter.
491 */
492 *ppvObject = 0;
493
494 /*
495 * Compare the riid with the interface IDs implemented by this object.
496 */
497 if (IsEqualGUID(&IID_IUnknown, riid))
498 *ppvObject = this;
499 if (IsEqualGUID(&IID_IFont, riid))
500 *ppvObject = this;
501 if (IsEqualGUID(&IID_IDispatch, riid))
502 *ppvObject = &this->lpvtblIDispatch;
503 if (IsEqualGUID(&IID_IFontDisp, riid))
504 *ppvObject = &this->lpvtblIDispatch;
505 if (IsEqualIID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistStream, riid))
506 *ppvObject = &this->lpvtblIPersistStream;
507 if (IsEqualGUID(&IID_IConnectionPointContainer, riid))
508 *ppvObject = &this->lpvtblIConnectionPointContainer;
509 if (IsEqualGUID(&IID_IPersistPropertyBag, riid))
510 *ppvObject = &this->lpvtblIPersistPropertyBag;
511 if (IsEqualGUID(&IID_IPersistStreamInit, riid))
512 *ppvObject = &this->lpvtblIPersistStreamInit;
513
514 /*
515 * Check that we obtained an interface.
516 */
517 if ((*ppvObject)==0)
518 {
519 FIXME("() : asking for unsupported interface %s\n",debugstr_guid(riid));
520 return E_NOINTERFACE;
521 }
522 OLEFontImpl_AddRef((IFont*)this);
523 return S_OK;
524 }
525
526 /************************************************************************
527 * OLEFontImpl_AddRef (IUnknown)
528 *
529 * See Windows documentation for more details on IUnknown methods.
530 */
531 static ULONG WINAPI OLEFontImpl_AddRef(
532 IFont* iface)
533 {
534 OLEFontImpl *this = (OLEFontImpl *)iface;
535 TRACE("(%p)->(ref=%d)\n", this, this->ref);
536 return InterlockedIncrement(&this->ref);
537 }
538
539 /************************************************************************
540 * OLEFontImpl_Release (IUnknown)
541 *
542 * See Windows documentation for more details on IUnknown methods.
543 */
544 static ULONG WINAPI OLEFontImpl_Release(
545 IFont* iface)
546 {
547 OLEFontImpl *this = (OLEFontImpl *)iface;
548 ULONG ret;
549 TRACE("(%p)->(ref=%d)\n", this, this->ref);
550
551 /* Decrease the reference count for current interface */
552 ret = InterlockedDecrement(&this->ref);
553
554 /* If the reference count goes down to 0, destroy. */
555 if (ret == 0)
556 {
557 ULONG fontlist_refs = InterlockedDecrement(&ifont_cnt);
558
559 /* Final IFont object so destroy font cache */
560 if (fontlist_refs == 0)
561 {
562 HFONTItem *item, *cursor2;
563
564 EnterCriticalSection(&OLEFontImpl_csHFONTLIST);
565 LIST_FOR_EACH_ENTRY_SAFE(item, cursor2, &OLEFontImpl_hFontList, HFONTItem, entry)
566 HFONTItem_Delete(item);
567 LeaveCriticalSection(&OLEFontImpl_csHFONTLIST);
568 delete_dc();
569 }
570 else
571 {
572 dec_int_ref(this->gdiFont);
573 }
574 OLEFontImpl_Destroy(this);
575 }
576
577 return ret;
578 }
579
580 typedef struct
581 {
582 short orig_cs;
583 short avail_cs;
584 } enum_data;
585
586 static int CALLBACK font_enum_proc(const LOGFONTW *elf, const TEXTMETRICW *ntm, DWORD type, LPARAM lp)
587 {
588 enum_data *data = (enum_data*)lp;
589
590 if(elf->lfCharSet == data->orig_cs)
591 {
592 data->avail_cs = data->orig_cs;
593 return 0;
594 }
595 if(data->avail_cs == -1) data->avail_cs = elf->lfCharSet;
596 return 1;
597 }
598
599 static void realize_font(OLEFontImpl *This)
600 {
601 if (This->dirty)
602 {
603 LOGFONTW logFont;
604 INT fontHeight;
605 WCHAR text_face[LF_FACESIZE];
606 HDC hdc = get_dc();
607 HFONT old_font;
608 TEXTMETRICW tm;
609
610 text_face[0] = 0;
611
612 if(This->gdiFont)
613 {
614 old_font = SelectObject(hdc, This->gdiFont);
615 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
616 SelectObject(hdc, old_font);
617 dec_int_ref(This->gdiFont);
618 This->gdiFont = 0;
619 }
620
621 memset(&logFont, 0, sizeof(LOGFONTW));
622
623 lstrcpynW(logFont.lfFaceName, This->description.lpstrName, LF_FACESIZE);
624 logFont.lfCharSet = This->description.sCharset;
625
626 /* If the font name has been changed then enumerate all charsets
627 and pick one that'll result in the font specified being selected */
628 if(text_face[0] && lstrcmpiW(text_face, This->description.lpstrName))
629 {
630 enum_data data;
631 data.orig_cs = This->description.sCharset;
632 data.avail_cs = -1;
633 logFont.lfCharSet = DEFAULT_CHARSET;
634 EnumFontFamiliesExW(get_dc(), &logFont, font_enum_proc, (LPARAM)&data, 0);
635 if(data.avail_cs != -1) logFont.lfCharSet = data.avail_cs;
636 }
637
638
639 /*
640 * The height of the font returned by the get_Size property is the
641 * height of the font in points multiplied by 10000... Using some
642 * simple conversions and the ratio given by the application, it can
643 * be converted to a height in pixels.
644 *
645 * Standard ratio is 72 / 2540, or 18 / 635 in lowest terms.
646 * Ratio is applied here relative to the standard.
647 */
648
649 fontHeight = MulDiv( This->description.cySize.s.Lo, This->cyLogical*635, This->cyHimetric*18 );
650
651
652 logFont.lfHeight = ((fontHeight%10000L)>5000L) ? (-fontHeight/10000L) - 1 :
653 (-fontHeight/10000L);
654 logFont.lfItalic = This->description.fItalic;
655 logFont.lfUnderline = This->description.fUnderline;
656 logFont.lfStrikeOut = This->description.fStrikethrough;
657 logFont.lfWeight = This->description.sWeight;
658 logFont.lfOutPrecision = OUT_CHARACTER_PRECIS;
659 logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
660 logFont.lfQuality = DEFAULT_QUALITY;
661 logFont.lfPitchAndFamily = DEFAULT_PITCH;
662
663 This->gdiFont = CreateFontIndirectW(&logFont);
664 This->dirty = FALSE;
665
666 add_hfontitem(This->gdiFont);
667
668 /* Fixup the name and charset properties so that they match the
669 selected font */
670 old_font = SelectObject(get_dc(), This->gdiFont);
671 GetTextFaceW(hdc, sizeof(text_face) / sizeof(text_face[0]), text_face);
672 if(lstrcmpiW(text_face, This->description.lpstrName))
673 {
674 HeapFree(GetProcessHeap(), 0, This->description.lpstrName);
675 This->description.lpstrName = strdupW(text_face);
676 }
677 GetTextMetricsW(hdc, &tm);
678 This->description.sCharset = tm.tmCharSet;
679 SelectObject(hdc, old_font);
680 }
681 }
682
683 /************************************************************************
684 * OLEFontImpl_get_Name (IFont)
685 *
686 * See Windows documentation for more details on IFont methods.
687 */
688 static HRESULT WINAPI OLEFontImpl_get_Name(
689 IFont* iface,
690 BSTR* pname)
691 {
692 OLEFontImpl *this = (OLEFontImpl *)iface;
693 TRACE("(%p)->(%p)\n", this, pname);
694 /*
695 * Sanity check.
696 */
697 if (pname==0)
698 return E_POINTER;
699
700 if(this->dirty) realize_font(this);
701
702 if (this->description.lpstrName!=0)
703 *pname = SysAllocString(this->description.lpstrName);
704 else
705 *pname = 0;
706
707 return S_OK;
708 }
709
710 /************************************************************************
711 * OLEFontImpl_put_Name (IFont)
712 *
713 * See Windows documentation for more details on IFont methods.
714 */
715 static HRESULT WINAPI OLEFontImpl_put_Name(
716 IFont* iface,
717 BSTR name)
718 {
719 OLEFontImpl *this = (OLEFontImpl *)iface;
720 TRACE("(%p)->(%p)\n", this, name);
721
722 if (!name)
723 return CTL_E_INVALIDPROPERTYVALUE;
724
725 if (this->description.lpstrName==0)
726 {
727 this->description.lpstrName = HeapAlloc(GetProcessHeap(),
728 0,
729 (lstrlenW(name)+1) * sizeof(WCHAR));
730 }
731 else
732 {
733 this->description.lpstrName = HeapReAlloc(GetProcessHeap(),
734 0,
735 this->description.lpstrName,
736 (lstrlenW(name)+1) * sizeof(WCHAR));
737 }
738
739 if (this->description.lpstrName==0)
740 return E_OUTOFMEMORY;
741
742 strcpyW(this->description.lpstrName, name);
743 TRACE("new name %s\n", debugstr_w(this->description.lpstrName));
744 OLEFont_SendNotify(this, DISPID_FONT_NAME);
745 return S_OK;
746 }
747
748 /************************************************************************
749 * OLEFontImpl_get_Size (IFont)
750 *
751 * See Windows documentation for more details on IFont methods.
752 */
753 static HRESULT WINAPI OLEFontImpl_get_Size(
754 IFont* iface,
755 CY* psize)
756 {
757 OLEFontImpl *this = (OLEFontImpl *)iface;
758 TRACE("(%p)->(%p)\n", this, psize);
759
760 /*
761 * Sanity check
762 */
763 if (psize==0)
764 return E_POINTER;
765
766 if(this->dirty) realize_font(this);
767
768 psize->s.Hi = 0;
769 psize->s.Lo = this->description.cySize.s.Lo;
770
771 return S_OK;
772 }
773
774 /************************************************************************
775 * OLEFontImpl_put_Size (IFont)
776 *
777 * See Windows documentation for more details on IFont methods.
778 */
779 static HRESULT WINAPI OLEFontImpl_put_Size(
780 IFont* iface,
781 CY size)
782 {
783 OLEFontImpl *this = (OLEFontImpl *)iface;
784 TRACE("(%p)->(%d)\n", this, size.s.Lo);
785 this->description.cySize.s.Hi = 0;
786 this->description.cySize.s.Lo = size.s.Lo;
787 OLEFont_SendNotify(this, DISPID_FONT_SIZE);
788
789 return S_OK;
790 }
791
792 /************************************************************************
793 * OLEFontImpl_get_Bold (IFont)
794 *
795 * See Windows documentation for more details on IFont methods.
796 */
797 static HRESULT WINAPI OLEFontImpl_get_Bold(
798 IFont* iface,
799 BOOL* pbold)
800 {
801 OLEFontImpl *this = (OLEFontImpl *)iface;
802 TRACE("(%p)->(%p)\n", this, pbold);
803 /*
804 * Sanity check
805 */
806 if (pbold==0)
807 return E_POINTER;
808
809 if(this->dirty) realize_font(this);
810
811 *pbold = this->description.sWeight > 550;
812
813 return S_OK;
814 }
815
816 /************************************************************************
817 * OLEFontImpl_put_Bold (IFont)
818 *
819 * See Windows documentation for more details on IFont methods.
820 */
821 static HRESULT WINAPI OLEFontImpl_put_Bold(
822 IFont* iface,
823 BOOL bold)
824 {
825 OLEFontImpl *this = (OLEFontImpl *)iface;
826 TRACE("(%p)->(%d)\n", this, bold);
827 this->description.sWeight = bold ? FW_BOLD : FW_NORMAL;
828 OLEFont_SendNotify(this, DISPID_FONT_BOLD);
829
830 return S_OK;
831 }
832
833 /************************************************************************
834 * OLEFontImpl_get_Italic (IFont)
835 *
836 * See Windows documentation for more details on IFont methods.
837 */
838 static HRESULT WINAPI OLEFontImpl_get_Italic(
839 IFont* iface,
840 BOOL* pitalic)
841 {
842 OLEFontImpl *this = (OLEFontImpl *)iface;
843 TRACE("(%p)->(%p)\n", this, pitalic);
844 /*
845 * Sanity check
846 */
847 if (pitalic==0)
848 return E_POINTER;
849
850 if(this->dirty) realize_font(this);
851
852 *pitalic = this->description.fItalic;
853
854 return S_OK;
855 }
856
857 /************************************************************************
858 * OLEFontImpl_put_Italic (IFont)
859 *
860 * See Windows documentation for more details on IFont methods.
861 */
862 static HRESULT WINAPI OLEFontImpl_put_Italic(
863 IFont* iface,
864 BOOL italic)
865 {
866 OLEFontImpl *this = (OLEFontImpl *)iface;
867 TRACE("(%p)->(%d)\n", this, italic);
868
869 this->description.fItalic = italic;
870
871 OLEFont_SendNotify(this, DISPID_FONT_ITALIC);
872 return S_OK;
873 }
874
875 /************************************************************************
876 * OLEFontImpl_get_Underline (IFont)
877 *
878 * See Windows documentation for more details on IFont methods.
879 */
880 static HRESULT WINAPI OLEFontImpl_get_Underline(
881 IFont* iface,
882 BOOL* punderline)
883 {
884 OLEFontImpl *this = (OLEFontImpl *)iface;
885 TRACE("(%p)->(%p)\n", this, punderline);
886
887 /*
888 * Sanity check
889 */
890 if (punderline==0)
891 return E_POINTER;
892
893 if(this->dirty) realize_font(this);
894
895 *punderline = this->description.fUnderline;
896
897 return S_OK;
898 }
899
900 /************************************************************************
901 * OLEFontImpl_put_Underline (IFont)
902 *
903 * See Windows documentation for more details on IFont methods.
904 */
905 static HRESULT WINAPI OLEFontImpl_put_Underline(
906 IFont* iface,
907 BOOL underline)
908 {
909 OLEFontImpl *this = (OLEFontImpl *)iface;
910 TRACE("(%p)->(%d)\n", this, underline);
911
912 this->description.fUnderline = underline;
913
914 OLEFont_SendNotify(this, DISPID_FONT_UNDER);
915 return S_OK;
916 }
917
918 /************************************************************************
919 * OLEFontImpl_get_Strikethrough (IFont)
920 *
921 * See Windows documentation for more details on IFont methods.
922 */
923 static HRESULT WINAPI OLEFontImpl_get_Strikethrough(
924 IFont* iface,
925 BOOL* pstrikethrough)
926 {
927 OLEFontImpl *this = (OLEFontImpl *)iface;
928 TRACE("(%p)->(%p)\n", this, pstrikethrough);
929
930 /*
931 * Sanity check
932 */
933 if (pstrikethrough==0)
934 return E_POINTER;
935
936 if(this->dirty) realize_font(this);
937
938 *pstrikethrough = this->description.fStrikethrough;
939
940 return S_OK;
941 }
942
943 /************************************************************************
944 * OLEFontImpl_put_Strikethrough (IFont)
945 *
946 * See Windows documentation for more details on IFont methods.
947 */
948 static HRESULT WINAPI OLEFontImpl_put_Strikethrough(
949 IFont* iface,
950 BOOL strikethrough)
951 {
952 OLEFontImpl *this = (OLEFontImpl *)iface;
953 TRACE("(%p)->(%d)\n", this, strikethrough);
954
955 this->description.fStrikethrough = strikethrough;
956 OLEFont_SendNotify(this, DISPID_FONT_STRIKE);
957
958 return S_OK;
959 }
960
961 /************************************************************************
962 * OLEFontImpl_get_Weight (IFont)
963 *
964 * See Windows documentation for more details on IFont methods.
965 */
966 static HRESULT WINAPI OLEFontImpl_get_Weight(
967 IFont* iface,
968 short* pweight)
969 {
970 OLEFontImpl *this = (OLEFontImpl *)iface;
971 TRACE("(%p)->(%p)\n", this, pweight);
972
973 /*
974 * Sanity check
975 */
976 if (pweight==0)
977 return E_POINTER;
978
979 if(this->dirty) realize_font(this);
980
981 *pweight = this->description.sWeight;
982
983 return S_OK;
984 }
985
986 /************************************************************************
987 * OLEFontImpl_put_Weight (IFont)
988 *
989 * See Windows documentation for more details on IFont methods.
990 */
991 static HRESULT WINAPI OLEFontImpl_put_Weight(
992 IFont* iface,
993 short weight)
994 {
995 OLEFontImpl *this = (OLEFontImpl *)iface;
996 TRACE("(%p)->(%d)\n", this, weight);
997
998 this->description.sWeight = weight;
999
1000 OLEFont_SendNotify(this, DISPID_FONT_WEIGHT);
1001 return S_OK;
1002 }
1003
1004 /************************************************************************
1005 * OLEFontImpl_get_Charset (IFont)
1006 *
1007 * See Windows documentation for more details on IFont methods.
1008 */
1009 static HRESULT WINAPI OLEFontImpl_get_Charset(
1010 IFont* iface,
1011 short* pcharset)
1012 {
1013 OLEFontImpl *this = (OLEFontImpl *)iface;
1014 TRACE("(%p)->(%p)\n", this, pcharset);
1015
1016 /*
1017 * Sanity check
1018 */
1019 if (pcharset==0)
1020 return E_POINTER;
1021
1022 if(this->dirty) realize_font(this);
1023
1024 *pcharset = this->description.sCharset;
1025
1026 return S_OK;
1027 }
1028
1029 /************************************************************************
1030 * OLEFontImpl_put_Charset (IFont)
1031 *
1032 * See Windows documentation for more details on IFont methods.
1033 */
1034 static HRESULT WINAPI OLEFontImpl_put_Charset(
1035 IFont* iface,
1036 short charset)
1037 {
1038 OLEFontImpl *this = (OLEFontImpl *)iface;
1039 TRACE("(%p)->(%d)\n", this, charset);
1040
1041 this->description.sCharset = charset;
1042 OLEFont_SendNotify(this, DISPID_FONT_CHARSET);
1043
1044 return S_OK;
1045 }
1046
1047 /************************************************************************
1048 * OLEFontImpl_get_hFont (IFont)
1049 *
1050 * See Windows documentation for more details on IFont methods.
1051 */
1052 static HRESULT WINAPI OLEFontImpl_get_hFont(
1053 IFont* iface,
1054 HFONT* phfont)
1055 {
1056 OLEFontImpl *this = (OLEFontImpl *)iface;
1057 TRACE("(%p)->(%p)\n", this, phfont);
1058 if (phfont==NULL)
1059 return E_POINTER;
1060
1061 if(this->dirty) realize_font(this);
1062
1063 *phfont = this->gdiFont;
1064 TRACE("Returning %p\n", *phfont);
1065 return S_OK;
1066 }
1067
1068 /************************************************************************
1069 * OLEFontImpl_Clone (IFont)
1070 *
1071 * See Windows documentation for more details on IFont methods.
1072 */
1073 static HRESULT WINAPI OLEFontImpl_Clone(
1074 IFont* iface,
1075 IFont** ppfont)
1076 {
1077 OLEFontImpl* newObject = 0;
1078 OLEFontImpl *this = (OLEFontImpl *)iface;
1079
1080 TRACE("(%p)->(%p)\n", this, ppfont);
1081
1082 if (ppfont == NULL)
1083 return E_POINTER;
1084
1085 *ppfont = NULL;
1086
1087 /*
1088 * Allocate space for the object.
1089 */
1090 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
1091
1092 if (newObject==NULL)
1093 return E_OUTOFMEMORY;
1094
1095 *newObject = *this;
1096
1097 /* We need to alloc new memory for the string, otherwise
1098 * we free memory twice.
1099 */
1100 newObject->description.lpstrName = HeapAlloc(
1101 GetProcessHeap(),0,
1102 (1+strlenW(this->description.lpstrName))*2
1103 );
1104 strcpyW(newObject->description.lpstrName, this->description.lpstrName);
1105
1106
1107 /* Increment internal ref in hfont item list */
1108 if(newObject->gdiFont) inc_int_ref(newObject->gdiFont);
1109
1110 InterlockedIncrement(&ifont_cnt);
1111
1112 /* create new connection points */
1113 newObject->pPropertyNotifyCP = NULL;
1114 newObject->pFontEventsCP = NULL;
1115 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
1116 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
1117
1118 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
1119 {
1120 OLEFontImpl_Destroy(newObject);
1121 return E_OUTOFMEMORY;
1122 }
1123
1124 /* The cloned object starts with a reference count of 1 */
1125 newObject->ref = 1;
1126
1127 *ppfont = (IFont*)newObject;
1128
1129 return S_OK;
1130 }
1131
1132 /************************************************************************
1133 * OLEFontImpl_IsEqual (IFont)
1134 *
1135 * See Windows documentation for more details on IFont methods.
1136 */
1137 static HRESULT WINAPI OLEFontImpl_IsEqual(
1138 IFont* iface,
1139 IFont* pFontOther)
1140 {
1141 OLEFontImpl *left = (OLEFontImpl *)iface;
1142 OLEFontImpl *right = (OLEFontImpl *)pFontOther;
1143 INT ret;
1144 INT left_len,right_len;
1145
1146 if((iface == NULL) || (pFontOther == NULL))
1147 return E_POINTER;
1148 else if (left->description.cySize.s.Lo != right->description.cySize.s.Lo)
1149 return S_FALSE;
1150 else if (left->description.cySize.s.Hi != right->description.cySize.s.Hi)
1151 return S_FALSE;
1152 else if (left->description.sWeight != right->description.sWeight)
1153 return S_FALSE;
1154 else if (left->description.sCharset != right->description.sCharset)
1155 return S_FALSE;
1156 else if (left->description.fItalic != right->description.fItalic)
1157 return S_FALSE;
1158 else if (left->description.fUnderline != right->description.fUnderline)
1159 return S_FALSE;
1160 else if (left->description.fStrikethrough != right->description.fStrikethrough)
1161 return S_FALSE;
1162
1163 /* Check from string */
1164 left_len = strlenW(left->description.lpstrName);
1165 right_len = strlenW(right->description.lpstrName);
1166 ret = CompareStringW(0,0,left->description.lpstrName, left_len,
1167 right->description.lpstrName, right_len);
1168 if (ret != CSTR_EQUAL)
1169 return S_FALSE;
1170
1171 return S_OK;
1172 }
1173
1174 /************************************************************************
1175 * OLEFontImpl_SetRatio (IFont)
1176 *
1177 * See Windows documentation for more details on IFont methods.
1178 */
1179 static HRESULT WINAPI OLEFontImpl_SetRatio(
1180 IFont* iface,
1181 LONG cyLogical,
1182 LONG cyHimetric)
1183 {
1184 OLEFontImpl *this = (OLEFontImpl *)iface;
1185 TRACE("(%p)->(%d, %d)\n", this, cyLogical, cyHimetric);
1186
1187 this->cyLogical = cyLogical;
1188 this->cyHimetric = cyHimetric;
1189
1190 return S_OK;
1191 }
1192
1193 /************************************************************************
1194 * OLEFontImpl_QueryTextMetrics (IFont)
1195 *
1196 * See Windows documentation for more details on IFont methods.
1197 */
1198 static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(
1199 IFont* iface,
1200 TEXTMETRICOLE* ptm)
1201 {
1202 HDC hdcRef;
1203 HFONT hOldFont, hNewFont;
1204
1205 hdcRef = GetDC(0);
1206 OLEFontImpl_get_hFont(iface, &hNewFont);
1207 hOldFont = SelectObject(hdcRef, hNewFont);
1208 GetTextMetricsW(hdcRef, ptm);
1209 SelectObject(hdcRef, hOldFont);
1210 ReleaseDC(0, hdcRef);
1211 return S_OK;
1212 }
1213
1214 /************************************************************************
1215 * OLEFontImpl_AddRefHfont (IFont)
1216 *
1217 * See Windows documentation for more details on IFont methods.
1218 */
1219 static HRESULT WINAPI OLEFontImpl_AddRefHfont(
1220 IFont* iface,
1221 HFONT hfont)
1222 {
1223 OLEFontImpl *this = (OLEFontImpl *)iface;
1224
1225 TRACE("(%p)->(%p)\n", this, hfont);
1226
1227 if (!hfont) return E_INVALIDARG;
1228
1229 return inc_ext_ref(hfont);
1230 }
1231
1232 /************************************************************************
1233 * OLEFontImpl_ReleaseHfont (IFont)
1234 *
1235 * See Windows documentation for more details on IFont methods.
1236 */
1237 static HRESULT WINAPI OLEFontImpl_ReleaseHfont(
1238 IFont* iface,
1239 HFONT hfont)
1240 {
1241 OLEFontImpl *this = (OLEFontImpl *)iface;
1242
1243 TRACE("(%p)->(%p)\n", this, hfont);
1244
1245 if (!hfont) return E_INVALIDARG;
1246
1247 return dec_ext_ref(hfont);
1248 }
1249
1250 /************************************************************************
1251 * OLEFontImpl_SetHdc (IFont)
1252 *
1253 * See Windows documentation for more details on IFont methods.
1254 */
1255 static HRESULT WINAPI OLEFontImpl_SetHdc(
1256 IFont* iface,
1257 HDC hdc)
1258 {
1259 OLEFontImpl *this = (OLEFontImpl *)iface;
1260 FIXME("(%p)->(%p): Stub\n", this, hdc);
1261 return E_NOTIMPL;
1262 }
1263
1264 /*
1265 * Virtual function tables for the OLEFontImpl class.
1266 */
1267 static const IFontVtbl OLEFontImpl_VTable =
1268 {
1269 OLEFontImpl_QueryInterface,
1270 OLEFontImpl_AddRef,
1271 OLEFontImpl_Release,
1272 OLEFontImpl_get_Name,
1273 OLEFontImpl_put_Name,
1274 OLEFontImpl_get_Size,
1275 OLEFontImpl_put_Size,
1276 OLEFontImpl_get_Bold,
1277 OLEFontImpl_put_Bold,
1278 OLEFontImpl_get_Italic,
1279 OLEFontImpl_put_Italic,
1280 OLEFontImpl_get_Underline,
1281 OLEFontImpl_put_Underline,
1282 OLEFontImpl_get_Strikethrough,
1283 OLEFontImpl_put_Strikethrough,
1284 OLEFontImpl_get_Weight,
1285 OLEFontImpl_put_Weight,
1286 OLEFontImpl_get_Charset,
1287 OLEFontImpl_put_Charset,
1288 OLEFontImpl_get_hFont,
1289 OLEFontImpl_Clone,
1290 OLEFontImpl_IsEqual,
1291 OLEFontImpl_SetRatio,
1292 OLEFontImpl_QueryTextMetrics,
1293 OLEFontImpl_AddRefHfont,
1294 OLEFontImpl_ReleaseHfont,
1295 OLEFontImpl_SetHdc
1296 };
1297
1298 /************************************************************************
1299 * OLEFontImpl_IDispatch_QueryInterface (IUnknown)
1300 *
1301 * See Windows documentation for more details on IUnknown methods.
1302 */
1303 static HRESULT WINAPI OLEFontImpl_IDispatch_QueryInterface(
1304 IDispatch* iface,
1305 REFIID riid,
1306 VOID** ppvoid)
1307 {
1308 OLEFontImpl *this = impl_from_IDispatch(iface);
1309
1310 return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1311 }
1312
1313 /************************************************************************
1314 * OLEFontImpl_IDispatch_Release (IUnknown)
1315 *
1316 * See Windows documentation for more details on IUnknown methods.
1317 */
1318 static ULONG WINAPI OLEFontImpl_IDispatch_Release(
1319 IDispatch* iface)
1320 {
1321 OLEFontImpl *this = impl_from_IDispatch(iface);
1322
1323 return IFont_Release((IFont *)this);
1324 }
1325
1326 /************************************************************************
1327 * OLEFontImpl_IDispatch_AddRef (IUnknown)
1328 *
1329 * See Windows documentation for more details on IUnknown methods.
1330 */
1331 static ULONG WINAPI OLEFontImpl_IDispatch_AddRef(
1332 IDispatch* iface)
1333 {
1334 OLEFontImpl *this = impl_from_IDispatch(iface);
1335
1336 return IFont_AddRef((IFont *)this);
1337 }
1338
1339 /************************************************************************
1340 * OLEFontImpl_GetTypeInfoCount (IDispatch)
1341 *
1342 * See Windows documentation for more details on IDispatch methods.
1343 */
1344 static HRESULT WINAPI OLEFontImpl_GetTypeInfoCount(
1345 IDispatch* iface,
1346 unsigned int* pctinfo)
1347 {
1348 OLEFontImpl *this = impl_from_IDispatch(iface);
1349 TRACE("(%p)->(%p)\n", this, pctinfo);
1350 *pctinfo = 1;
1351
1352 return S_OK;
1353 }
1354
1355 /************************************************************************
1356 * OLEFontImpl_GetTypeInfo (IDispatch)
1357 *
1358 * See Windows documentation for more details on IDispatch methods.
1359 */
1360 static HRESULT WINAPI OLEFontImpl_GetTypeInfo(
1361 IDispatch* iface,
1362 UINT iTInfo,
1363 LCID lcid,
1364 ITypeInfo** ppTInfo)
1365 {
1366 static const WCHAR stdole2tlb[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
1367 ITypeLib *tl;
1368 HRESULT hres;
1369
1370 OLEFontImpl *this = impl_from_IDispatch(iface);
1371 TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo);
1372 if (iTInfo != 0)
1373 return E_FAIL;
1374 hres = LoadTypeLib(stdole2tlb, &tl);
1375 if (FAILED(hres)) {
1376 ERR("Could not load the stdole2.tlb?\n");
1377 return hres;
1378 }
1379 hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo);
1380 ITypeLib_Release(tl);
1381 if (FAILED(hres)) {
1382 FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres);
1383 }
1384 return hres;
1385 }
1386
1387 /************************************************************************
1388 * OLEFontImpl_GetIDsOfNames (IDispatch)
1389 *
1390 * See Windows documentation for more details on IDispatch methods.
1391 */
1392 static HRESULT WINAPI OLEFontImpl_GetIDsOfNames(
1393 IDispatch* iface,
1394 REFIID riid,
1395 LPOLESTR* rgszNames,
1396 UINT cNames,
1397 LCID lcid,
1398 DISPID* rgDispId)
1399 {
1400 ITypeInfo * pTInfo;
1401 HRESULT hres;
1402
1403 OLEFontImpl *this = impl_from_IDispatch(iface);
1404
1405 TRACE("(%p,%s,%p,cNames=%d,lcid=%04x,%p)\n", this, debugstr_guid(riid),
1406 rgszNames, cNames, (int)lcid, rgDispId);
1407
1408 if (cNames == 0)
1409 {
1410 return E_INVALIDARG;
1411 }
1412 else
1413 {
1414 /* retrieve type information */
1415 hres = OLEFontImpl_GetTypeInfo(iface, 0, lcid, &pTInfo);
1416
1417 if (FAILED(hres))
1418 {
1419 ERR("GetTypeInfo failed.\n");
1420 return hres;
1421 }
1422
1423 /* convert names to DISPIDs */
1424 hres = DispGetIDsOfNames (pTInfo, rgszNames, cNames, rgDispId);
1425 ITypeInfo_Release(pTInfo);
1426
1427 return hres;
1428 }
1429 }
1430
1431 /************************************************************************
1432 * OLEFontImpl_Invoke (IDispatch)
1433 *
1434 * See Windows documentation for more details on IDispatch methods.
1435 *
1436 * Note: Do not call _put_Xxx methods, since setting things here
1437 * should not call notify functions as I found out debugging the generic
1438 * MS VB5 installer.
1439 */
1440 static HRESULT WINAPI OLEFontImpl_Invoke(
1441 IDispatch* iface,
1442 DISPID dispIdMember,
1443 REFIID riid,
1444 LCID lcid,
1445 WORD wFlags,
1446 DISPPARAMS* pDispParams,
1447 VARIANT* pVarResult,
1448 EXCEPINFO* pExepInfo,
1449 UINT* puArgErr)
1450 {
1451 OLEFontImpl *this = impl_from_IDispatch(iface);
1452 HRESULT hr;
1453
1454 TRACE("%p->(%d,%s,0x%x,0x%x,%p,%p,%p,%p)\n", this, dispIdMember,
1455 debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExepInfo,
1456 puArgErr);
1457
1458 /* validate parameters */
1459
1460 if (!IsEqualIID(riid, &IID_NULL))
1461 {
1462 ERR("riid was %s instead of IID_NULL\n", debugstr_guid(riid));
1463 return DISP_E_UNKNOWNINTERFACE;
1464 }
1465
1466 if (wFlags & DISPATCH_PROPERTYGET)
1467 {
1468 if (!pVarResult)
1469 {
1470 ERR("null pVarResult not allowed when DISPATCH_PROPERTYGET specified\n");
1471 return DISP_E_PARAMNOTOPTIONAL;
1472 }
1473 }
1474 else if (wFlags & DISPATCH_PROPERTYPUT)
1475 {
1476 if (!pDispParams)
1477 {
1478 ERR("null pDispParams not allowed when DISPATCH_PROPERTYPUT specified\n");
1479 return DISP_E_PARAMNOTOPTIONAL;
1480 }
1481 if (pDispParams->cArgs != 1)
1482 {
1483 ERR("param count for DISPATCH_PROPERTYPUT was %d instead of 1\n", pDispParams->cArgs);
1484 return DISP_E_BADPARAMCOUNT;
1485 }
1486 }
1487 else
1488 {
1489 ERR("one of DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT must be specified\n");
1490 return DISP_E_MEMBERNOTFOUND;
1491 }
1492
1493 switch (dispIdMember) {
1494 case DISPID_FONT_NAME:
1495 if (wFlags & DISPATCH_PROPERTYGET) {
1496 V_VT(pVarResult) = VT_BSTR;
1497 return IFont_get_Name((IFont *)this, &V_BSTR(pVarResult));
1498 } else {
1499 VARIANTARG vararg;
1500
1501 VariantInit(&vararg);
1502 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BSTR);
1503 if (FAILED(hr))
1504 return hr;
1505
1506 hr = IFont_put_Name((IFont *)this, V_BSTR(&vararg));
1507
1508 VariantClear(&vararg);
1509 return hr;
1510 }
1511 break;
1512 case DISPID_FONT_BOLD:
1513 if (wFlags & DISPATCH_PROPERTYGET) {
1514 BOOL value;
1515 hr = IFont_get_Bold((IFont *)this, &value);
1516 V_VT(pVarResult) = VT_BOOL;
1517 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1518 return hr;
1519 } else {
1520 VARIANTARG vararg;
1521
1522 VariantInit(&vararg);
1523 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1524 if (FAILED(hr))
1525 return hr;
1526
1527 hr = IFont_put_Bold((IFont *)this, V_BOOL(&vararg));
1528
1529 VariantClear(&vararg);
1530 return hr;
1531 }
1532 break;
1533 case DISPID_FONT_ITALIC:
1534 if (wFlags & DISPATCH_PROPERTYGET) {
1535 BOOL value;
1536 hr = IFont_get_Italic((IFont *)this, &value);
1537 V_VT(pVarResult) = VT_BOOL;
1538 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1539 return hr;
1540 } else {
1541 VARIANTARG vararg;
1542
1543 VariantInit(&vararg);
1544 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1545 if (FAILED(hr))
1546 return hr;
1547
1548 hr = IFont_put_Italic((IFont *)this, V_BOOL(&vararg));
1549
1550 VariantClear(&vararg);
1551 return hr;
1552 }
1553 break;
1554 case DISPID_FONT_UNDER:
1555 if (wFlags & DISPATCH_PROPERTYGET) {
1556 BOOL value;
1557 hr = IFont_get_Underline((IFont *)this, &value);
1558 V_VT(pVarResult) = VT_BOOL;
1559 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1560 return hr;
1561 } else {
1562 VARIANTARG vararg;
1563
1564 VariantInit(&vararg);
1565 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1566 if (FAILED(hr))
1567 return hr;
1568
1569 hr = IFont_put_Underline((IFont *)this, V_BOOL(&vararg));
1570
1571 VariantClear(&vararg);
1572 return hr;
1573 }
1574 break;
1575 case DISPID_FONT_STRIKE:
1576 if (wFlags & DISPATCH_PROPERTYGET) {
1577 BOOL value;
1578 hr = IFont_get_Strikethrough((IFont *)this, &value);
1579 V_VT(pVarResult) = VT_BOOL;
1580 V_BOOL(pVarResult) = value ? VARIANT_TRUE : VARIANT_FALSE;
1581 return hr;
1582 } else {
1583 VARIANTARG vararg;
1584
1585 VariantInit(&vararg);
1586 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_BOOL);
1587 if (FAILED(hr))
1588 return hr;
1589
1590 hr = IFont_put_Strikethrough((IFont *)this, V_BOOL(&vararg));
1591
1592 VariantClear(&vararg);
1593 return hr;
1594 }
1595 break;
1596 case DISPID_FONT_SIZE:
1597 if (wFlags & DISPATCH_PROPERTYGET) {
1598 V_VT(pVarResult) = VT_CY;
1599 return OLEFontImpl_get_Size((IFont *)this, &V_CY(pVarResult));
1600 } else {
1601 VARIANTARG vararg;
1602
1603 VariantInit(&vararg);
1604 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_CY);
1605 if (FAILED(hr))
1606 return hr;
1607
1608 hr = IFont_put_Size((IFont *)this, V_CY(&vararg));
1609
1610 VariantClear(&vararg);
1611 return hr;
1612 }
1613 break;
1614 case DISPID_FONT_WEIGHT:
1615 if (wFlags & DISPATCH_PROPERTYGET) {
1616 V_VT(pVarResult) = VT_I2;
1617 return OLEFontImpl_get_Weight((IFont *)this, &V_I2(pVarResult));
1618 } else {
1619 VARIANTARG vararg;
1620
1621 VariantInit(&vararg);
1622 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1623 if (FAILED(hr))
1624 return hr;
1625
1626 hr = IFont_put_Weight((IFont *)this, V_I2(&vararg));
1627
1628 VariantClear(&vararg);
1629 return hr;
1630 }
1631 break;
1632 case DISPID_FONT_CHARSET:
1633 if (wFlags & DISPATCH_PROPERTYGET) {
1634 V_VT(pVarResult) = VT_I2;
1635 return OLEFontImpl_get_Charset((IFont *)this, &V_I2(pVarResult));
1636 } else {
1637 VARIANTARG vararg;
1638
1639 VariantInit(&vararg);
1640 hr = VariantChangeTypeEx(&vararg, &pDispParams->rgvarg[0], lcid, 0, VT_I2);
1641 if (FAILED(hr))
1642 return hr;
1643
1644 hr = IFont_put_Charset((IFont *)this, V_I2(&vararg));
1645
1646 VariantClear(&vararg);
1647 return hr;
1648 }
1649 break;
1650 default:
1651 ERR("member not found for dispid 0x%x\n", dispIdMember);
1652 return DISP_E_MEMBERNOTFOUND;
1653 }
1654 }
1655
1656 static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
1657 {
1658 OLEFontImpl_IDispatch_QueryInterface,
1659 OLEFontImpl_IDispatch_AddRef,
1660 OLEFontImpl_IDispatch_Release,
1661 OLEFontImpl_GetTypeInfoCount,
1662 OLEFontImpl_GetTypeInfo,
1663 OLEFontImpl_GetIDsOfNames,
1664 OLEFontImpl_Invoke
1665 };
1666
1667 /************************************************************************
1668 * OLEFontImpl_IPersistStream_QueryInterface (IUnknown)
1669 *
1670 * See Windows documentation for more details on IUnknown methods.
1671 */
1672 static HRESULT WINAPI OLEFontImpl_IPersistStream_QueryInterface(
1673 IPersistStream* iface,
1674 REFIID riid,
1675 VOID** ppvoid)
1676 {
1677 OLEFontImpl *this = impl_from_IPersistStream(iface);
1678
1679 return IFont_QueryInterface((IFont *)this, riid, ppvoid);
1680 }
1681
1682 /************************************************************************
1683 * OLEFontImpl_IPersistStream_Release (IUnknown)
1684 *
1685 * See Windows documentation for more details on IUnknown methods.
1686 */
1687 static ULONG WINAPI OLEFontImpl_IPersistStream_Release(
1688 IPersistStream* iface)
1689 {
1690 OLEFontImpl *this = impl_from_IPersistStream(iface);
1691
1692 return IFont_Release((IFont *)this);
1693 }
1694
1695 /************************************************************************
1696 * OLEFontImpl_IPersistStream_AddRef (IUnknown)
1697 *
1698 * See Windows documentation for more details on IUnknown methods.
1699 */
1700 static ULONG WINAPI OLEFontImpl_IPersistStream_AddRef(
1701 IPersistStream* iface)
1702 {
1703 OLEFontImpl *this = impl_from_IPersistStream(iface);
1704
1705 return IFont_AddRef((IFont *)this);
1706 }
1707
1708 /************************************************************************
1709 * OLEFontImpl_GetClassID (IPersistStream)
1710 *
1711 * See Windows documentation for more details on IPersistStream methods.
1712 */
1713 static HRESULT WINAPI OLEFontImpl_GetClassID(
1714 IPersistStream* iface,
1715 CLSID* pClassID)
1716 {
1717 TRACE("(%p,%p)\n",iface,pClassID);
1718 if (pClassID==0)
1719 return E_POINTER;
1720
1721 *pClassID = CLSID_StdFont;
1722
1723 return S_OK;
1724 }
1725
1726 /************************************************************************
1727 * OLEFontImpl_IsDirty (IPersistStream)
1728 *
1729 * See Windows documentation for more details on IPersistStream methods.
1730 */
1731 static HRESULT WINAPI OLEFontImpl_IsDirty(
1732 IPersistStream* iface)
1733 {
1734 TRACE("(%p)\n",iface);
1735 return S_OK;
1736 }
1737
1738 /************************************************************************
1739 * OLEFontImpl_Load (IPersistStream)
1740 *
1741 * See Windows documentation for more details on IPersistStream methods.
1742 *
1743 * This is the format of the standard font serialization as far as I
1744 * know
1745 *
1746 * Offset Type Value Comment
1747 * 0x0000 Byte Unknown Probably a version number, contains 0x01
1748 * 0x0001 Short Charset Charset value from the FONTDESC structure
1749 * 0x0003 Byte Attributes Flags defined as follows:
1750 * 00000010 - Italic
1751 * 00000100 - Underline
1752 * 00001000 - Strikethrough
1753 * 0x0004 Short Weight Weight value from FONTDESC structure
1754 * 0x0006 DWORD size "Low" portion of the cySize member of the FONTDESC
1755 * structure/
1756 * 0x000A Byte name length Length of the font name string (no null character)
1757 * 0x000B String name Name of the font (ASCII, no nul character)
1758 */
1759 static HRESULT WINAPI OLEFontImpl_Load(
1760 IPersistStream* iface,
1761 IStream* pLoadStream)
1762 {
1763 char readBuffer[0x100];
1764 ULONG cbRead;
1765 BYTE bVersion;
1766 BYTE bAttributes;
1767 BYTE bStringSize;
1768 INT len;
1769
1770 OLEFontImpl *this = impl_from_IPersistStream(iface);
1771
1772 /*
1773 * Read the version byte
1774 */
1775 IStream_Read(pLoadStream, &bVersion, 1, &cbRead);
1776
1777 if ( (cbRead!=1) ||
1778 (bVersion!=0x01) )
1779 return E_FAIL;
1780
1781 /*
1782 * Charset
1783 */
1784 IStream_Read(pLoadStream, &this->description.sCharset, 2, &cbRead);
1785
1786 if (cbRead!=2)
1787 return E_FAIL;
1788
1789 /*
1790 * Attributes
1791 */
1792 IStream_Read(pLoadStream, &bAttributes, 1, &cbRead);
1793
1794 if (cbRead!=1)
1795 return E_FAIL;
1796
1797 this->description.fItalic = (bAttributes & FONTPERSIST_ITALIC) != 0;
1798 this->description.fStrikethrough = (bAttributes & FONTPERSIST_STRIKETHROUGH) != 0;
1799 this->description.fUnderline = (bAttributes & FONTPERSIST_UNDERLINE) != 0;
1800
1801 /*
1802 * Weight
1803 */
1804 IStream_Read(pLoadStream, &this->description.sWeight, 2, &cbRead);
1805
1806 if (cbRead!=2)
1807 return E_FAIL;
1808
1809 /*
1810 * Size
1811 */
1812 IStream_Read(pLoadStream, &this->description.cySize.s.Lo, 4, &cbRead);
1813
1814 if (cbRead!=4)
1815 return E_FAIL;
1816
1817 this->description.cySize.s.Hi = 0;
1818
1819 /*
1820 * FontName
1821 */
1822 IStream_Read(pLoadStream, &bStringSize, 1, &cbRead);
1823
1824 if (cbRead!=1)
1825 return E_FAIL;
1826
1827 IStream_Read(pLoadStream, readBuffer, bStringSize, &cbRead);
1828
1829 if (cbRead!=bStringSize)
1830 return E_FAIL;
1831
1832 HeapFree(GetProcessHeap(), 0, this->description.lpstrName);
1833
1834 len = MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, NULL, 0 );
1835 this->description.lpstrName = HeapAlloc( GetProcessHeap(), 0, (len+1) * sizeof(WCHAR) );
1836 MultiByteToWideChar( CP_ACP, 0, readBuffer, bStringSize, this->description.lpstrName, len );
1837 this->description.lpstrName[len] = 0;
1838
1839 /* Ensure use of this font causes a new one to be created @@@@ */
1840 dec_int_ref(this->gdiFont);
1841 this->gdiFont = 0;
1842
1843 return S_OK;
1844 }
1845
1846 /************************************************************************
1847 * OLEFontImpl_Save (IPersistStream)
1848 *
1849 * See Windows documentation for more details on IPersistStream methods.
1850 */
1851 static HRESULT WINAPI OLEFontImpl_Save(
1852 IPersistStream* iface,
1853 IStream* pOutStream,
1854 BOOL fClearDirty)
1855 {
1856 char* writeBuffer = NULL;
1857 ULONG cbWritten;
1858 BYTE bVersion = 0x01;
1859 BYTE bAttributes;
1860 BYTE bStringSize;
1861
1862 OLEFontImpl *this = impl_from_IPersistStream(iface);
1863
1864 /*
1865 * Read the version byte
1866 */
1867 IStream_Write(pOutStream, &bVersion, 1, &cbWritten);
1868
1869 if (cbWritten!=1)
1870 return E_FAIL;
1871
1872 /*
1873 * Charset
1874 */
1875 IStream_Write(pOutStream, &this->description.sCharset, 2, &cbWritten);
1876
1877 if (cbWritten!=2)
1878 return E_FAIL;
1879
1880 /*
1881 * Attributes
1882 */
1883 bAttributes = 0;
1884
1885 if (this->description.fItalic)
1886 bAttributes |= FONTPERSIST_ITALIC;
1887
1888 if (this->description.fStrikethrough)
1889 bAttributes |= FONTPERSIST_STRIKETHROUGH;
1890
1891 if (this->description.fUnderline)
1892 bAttributes |= FONTPERSIST_UNDERLINE;
1893
1894 IStream_Write(pOutStream, &bAttributes, 1, &cbWritten);
1895
1896 if (cbWritten!=1)
1897 return E_FAIL;
1898
1899 /*
1900 * Weight
1901 */
1902 IStream_Write(pOutStream, &this->description.sWeight, 2, &cbWritten);
1903
1904 if (cbWritten!=2)
1905 return E_FAIL;
1906
1907 /*
1908 * Size
1909 */
1910 IStream_Write(pOutStream, &this->description.cySize.s.Lo, 4, &cbWritten);
1911
1912 if (cbWritten!=4)
1913 return E_FAIL;
1914
1915 /*
1916 * FontName
1917 */
1918 if (this->description.lpstrName!=0)
1919 bStringSize = WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1920 strlenW(this->description.lpstrName), NULL, 0, NULL, NULL );
1921 else
1922 bStringSize = 0;
1923
1924 IStream_Write(pOutStream, &bStringSize, 1, &cbWritten);
1925
1926 if (cbWritten!=1)
1927 return E_FAIL;
1928
1929 if (bStringSize!=0)
1930 {
1931 if (!(writeBuffer = HeapAlloc( GetProcessHeap(), 0, bStringSize ))) return E_OUTOFMEMORY;
1932 WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1933 strlenW(this->description.lpstrName),
1934 writeBuffer, bStringSize, NULL, NULL );
1935
1936 IStream_Write(pOutStream, writeBuffer, bStringSize, &cbWritten);
1937 HeapFree(GetProcessHeap(), 0, writeBuffer);
1938
1939 if (cbWritten!=bStringSize)
1940 return E_FAIL;
1941 }
1942
1943 return S_OK;
1944 }
1945
1946 /************************************************************************
1947 * OLEFontImpl_GetSizeMax (IPersistStream)
1948 *
1949 * See Windows documentation for more details on IPersistStream methods.
1950 */
1951 static HRESULT WINAPI OLEFontImpl_GetSizeMax(
1952 IPersistStream* iface,
1953 ULARGE_INTEGER* pcbSize)
1954 {
1955 OLEFontImpl *this = impl_from_IPersistStream(iface);
1956
1957 if (pcbSize==NULL)
1958 return E_POINTER;
1959
1960 pcbSize->u.HighPart = 0;
1961 pcbSize->u.LowPart = 0;
1962
1963 pcbSize->u.LowPart += sizeof(BYTE); /* Version */
1964 pcbSize->u.LowPart += sizeof(WORD); /* Lang code */
1965 pcbSize->u.LowPart += sizeof(BYTE); /* Flags */
1966 pcbSize->u.LowPart += sizeof(WORD); /* Weight */
1967 pcbSize->u.LowPart += sizeof(DWORD); /* Size */
1968 pcbSize->u.LowPart += sizeof(BYTE); /* StrLength */
1969
1970 if (this->description.lpstrName!=0)
1971 pcbSize->u.LowPart += WideCharToMultiByte( CP_ACP, 0, this->description.lpstrName,
1972 strlenW(this->description.lpstrName),
1973 NULL, 0, NULL, NULL );
1974
1975 return S_OK;
1976 }
1977
1978 static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
1979 {
1980 OLEFontImpl_IPersistStream_QueryInterface,
1981 OLEFontImpl_IPersistStream_AddRef,
1982 OLEFontImpl_IPersistStream_Release,
1983 OLEFontImpl_GetClassID,
1984 OLEFontImpl_IsDirty,
1985 OLEFontImpl_Load,
1986 OLEFontImpl_Save,
1987 OLEFontImpl_GetSizeMax
1988 };
1989
1990 /************************************************************************
1991 * OLEFontImpl_IConnectionPointContainer_QueryInterface (IUnknown)
1992 *
1993 * See Windows documentation for more details on IUnknown methods.
1994 */
1995 static HRESULT WINAPI OLEFontImpl_IConnectionPointContainer_QueryInterface(
1996 IConnectionPointContainer* iface,
1997 REFIID riid,
1998 VOID** ppvoid)
1999 {
2000 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2001
2002 return IFont_QueryInterface((IFont*)this, riid, ppvoid);
2003 }
2004
2005 /************************************************************************
2006 * OLEFontImpl_IConnectionPointContainer_Release (IUnknown)
2007 *
2008 * See Windows documentation for more details on IUnknown methods.
2009 */
2010 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_Release(
2011 IConnectionPointContainer* iface)
2012 {
2013 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2014
2015 return IFont_Release((IFont*)this);
2016 }
2017
2018 /************************************************************************
2019 * OLEFontImpl_IConnectionPointContainer_AddRef (IUnknown)
2020 *
2021 * See Windows documentation for more details on IUnknown methods.
2022 */
2023 static ULONG WINAPI OLEFontImpl_IConnectionPointContainer_AddRef(
2024 IConnectionPointContainer* iface)
2025 {
2026 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2027
2028 return IFont_AddRef((IFont*)this);
2029 }
2030
2031 /************************************************************************
2032 * OLEFontImpl_EnumConnectionPoints (IConnectionPointContainer)
2033 *
2034 * See Windows documentation for more details on IConnectionPointContainer
2035 * methods.
2036 */
2037 static HRESULT WINAPI OLEFontImpl_EnumConnectionPoints(
2038 IConnectionPointContainer* iface,
2039 IEnumConnectionPoints **ppEnum)
2040 {
2041 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2042
2043 FIXME("(%p)->(%p): stub\n", this, ppEnum);
2044 return E_NOTIMPL;
2045 }
2046
2047 /************************************************************************
2048 * OLEFontImpl_FindConnectionPoint (IConnectionPointContainer)
2049 *
2050 * See Windows documentation for more details on IConnectionPointContainer
2051 * methods.
2052 */
2053 static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
2054 IConnectionPointContainer* iface,
2055 REFIID riid,
2056 IConnectionPoint **ppCp)
2057 {
2058 OLEFontImpl *this = impl_from_IConnectionPointContainer(iface);
2059 TRACE("(%p)->(%s, %p)\n", this, debugstr_guid(riid), ppCp);
2060
2061 if(IsEqualIID(riid, &IID_IPropertyNotifySink)) {
2062 return IConnectionPoint_QueryInterface(this->pPropertyNotifyCP,
2063 &IID_IConnectionPoint,
2064 (LPVOID)ppCp);
2065 } else if(IsEqualIID(riid, &IID_IFontEventsDisp)) {
2066 return IConnectionPoint_QueryInterface(this->pFontEventsCP,
2067 &IID_IConnectionPoint,
2068 (LPVOID)ppCp);
2069 } else {
2070 FIXME("no connection point for %s\n", debugstr_guid(riid));
2071 return CONNECT_E_NOCONNECTION;
2072 }
2073 }
2074
2075 static const IConnectionPointContainerVtbl
2076 OLEFontImpl_IConnectionPointContainer_VTable =
2077 {
2078 OLEFontImpl_IConnectionPointContainer_QueryInterface,
2079 OLEFontImpl_IConnectionPointContainer_AddRef,
2080 OLEFontImpl_IConnectionPointContainer_Release,
2081 OLEFontImpl_EnumConnectionPoints,
2082 OLEFontImpl_FindConnectionPoint
2083 };
2084
2085 /************************************************************************
2086 * OLEFontImpl implementation of IPersistPropertyBag.
2087 */
2088 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_QueryInterface(
2089 IPersistPropertyBag *iface, REFIID riid, LPVOID *ppvObj
2090 ) {
2091 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2092 return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2093 }
2094
2095 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_AddRef(
2096 IPersistPropertyBag *iface
2097 ) {
2098 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2099 return IFont_AddRef((IFont *)this);
2100 }
2101
2102 static ULONG WINAPI OLEFontImpl_IPersistPropertyBag_Release(
2103 IPersistPropertyBag *iface
2104 ) {
2105 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2106 return IFont_Release((IFont *)this);
2107 }
2108
2109 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_GetClassID(
2110 IPersistPropertyBag *iface, CLSID *classid
2111 ) {
2112 FIXME("(%p,%p), stub!\n", iface, classid);
2113 return E_FAIL;
2114 }
2115
2116 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_InitNew(
2117 IPersistPropertyBag *iface
2118 ) {
2119 FIXME("(%p), stub!\n", iface);
2120 return S_OK;
2121 }
2122
2123 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Load(
2124 IPersistPropertyBag *iface, IPropertyBag* pPropBag, IErrorLog* pErrorLog
2125 ) {
2126 /* (from Visual Basic 6 property bag)
2127 Name = "MS Sans Serif"
2128 Size = 13.8
2129 Charset = 0
2130 Weight = 400
2131 Underline = 0 'False
2132 Italic = 0 'False
2133 Strikethrough = 0 'False
2134 */
2135 static const WCHAR sAttrName[] = {'N','a','m','e',0};
2136 static const WCHAR sAttrSize[] = {'S','i','z','e',0};
2137 static const WCHAR sAttrCharset[] = {'C','h','a','r','s','e','t',0};
2138 static const WCHAR sAttrWeight[] = {'W','e','i','g','h','t',0};
2139 static const WCHAR sAttrUnderline[] = {'U','n','d','e','r','l','i','n','e',0};
2140 static const WCHAR sAttrItalic[] = {'I','t','a','l','i','c',0};
2141 static const WCHAR sAttrStrikethrough[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
2142 VARIANT rawAttr;
2143 VARIANT valueAttr;
2144 HRESULT iRes = S_OK;
2145 OLEFontImpl *this = impl_from_IPersistPropertyBag(iface);
2146
2147 VariantInit(&rawAttr);
2148 VariantInit(&valueAttr);
2149
2150 if (iRes == S_OK) {
2151 iRes = IPropertyBag_Read(pPropBag, sAttrName, &rawAttr, pErrorLog);
2152 if (iRes == S_OK)
2153 {
2154 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BSTR);
2155 if (iRes == S_OK)
2156 iRes = IFont_put_Name((IFont *)this, V_BSTR(&valueAttr));
2157 }
2158 else if (iRes == E_INVALIDARG)
2159 iRes = S_OK;
2160 VariantClear(&rawAttr);
2161 VariantClear(&valueAttr);
2162 }
2163
2164 if (iRes == S_OK) {
2165 iRes = IPropertyBag_Read(pPropBag, sAttrSize, &rawAttr, pErrorLog);
2166 if (iRes == S_OK)
2167 {
2168 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_CY);
2169 if (iRes == S_OK)
2170 iRes = IFont_put_Size((IFont *)this, V_CY(&valueAttr));
2171 }
2172 else if (iRes == E_INVALIDARG)
2173 iRes = S_OK;
2174 VariantClear(&rawAttr);
2175 VariantClear(&valueAttr);
2176 }
2177
2178 if (iRes == S_OK) {
2179 iRes = IPropertyBag_Read(pPropBag, sAttrCharset, &rawAttr, pErrorLog);
2180 if (iRes == S_OK)
2181 {
2182 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2183 if (iRes == S_OK)
2184 iRes = IFont_put_Charset((IFont *)this, V_I2(&valueAttr));
2185 }
2186 else if (iRes == E_INVALIDARG)
2187 iRes = S_OK;
2188 VariantClear(&rawAttr);
2189 VariantClear(&valueAttr);
2190 }
2191
2192 if (iRes == S_OK) {
2193 iRes = IPropertyBag_Read(pPropBag, sAttrWeight, &rawAttr, pErrorLog);
2194 if (iRes == S_OK)
2195 {
2196 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_I2);
2197 if (iRes == S_OK)
2198 iRes = IFont_put_Weight((IFont *)this, V_I2(&valueAttr));
2199 }
2200 else if (iRes == E_INVALIDARG)
2201 iRes = S_OK;
2202 VariantClear(&rawAttr);
2203 VariantClear(&valueAttr);
2204
2205 }
2206
2207 if (iRes == S_OK) {
2208 iRes = IPropertyBag_Read(pPropBag, sAttrUnderline, &rawAttr, pErrorLog);
2209 if (iRes == S_OK)
2210 {
2211 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2212 if (iRes == S_OK)
2213 iRes = IFont_put_Underline((IFont *)this, V_BOOL(&valueAttr));
2214 }
2215 else if (iRes == E_INVALIDARG)
2216 iRes = S_OK;
2217 VariantClear(&rawAttr);
2218 VariantClear(&valueAttr);
2219 }
2220
2221 if (iRes == S_OK) {
2222 iRes = IPropertyBag_Read(pPropBag, sAttrItalic, &rawAttr, pErrorLog);
2223 if (iRes == S_OK)
2224 {
2225 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2226 if (iRes == S_OK)
2227 iRes = IFont_put_Italic((IFont *)this, V_BOOL(&valueAttr));
2228 }
2229 else if (iRes == E_INVALIDARG)
2230 iRes = S_OK;
2231 VariantClear(&rawAttr);
2232 VariantClear(&valueAttr);
2233 }
2234
2235 if (iRes == S_OK) {
2236 iRes = IPropertyBag_Read(pPropBag, sAttrStrikethrough, &rawAttr, pErrorLog);
2237 if (iRes == S_OK)
2238 {
2239 iRes = VariantChangeType(&rawAttr, &valueAttr, 0, VT_BOOL);
2240 if (iRes == S_OK)
2241 IFont_put_Strikethrough((IFont *)this, V_BOOL(&valueAttr));
2242 }
2243 else if (iRes == E_INVALIDARG)
2244 iRes = S_OK;
2245 VariantClear(&rawAttr);
2246 VariantClear(&valueAttr);
2247 }
2248
2249 if (FAILED(iRes))
2250 WARN("-- 0x%08x\n", iRes);
2251 return iRes;
2252 }
2253
2254 static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
2255 IPersistPropertyBag *iface, IPropertyBag* pPropBag, BOOL fClearDirty,
2256 BOOL fSaveAllProperties
2257 ) {
2258 FIXME("(%p,%p,%d,%d), stub!\n", iface, pPropBag, fClearDirty, fSaveAllProperties);
2259 return E_FAIL;
2260 }
2261
2262 static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable =
2263 {
2264 OLEFontImpl_IPersistPropertyBag_QueryInterface,
2265 OLEFontImpl_IPersistPropertyBag_AddRef,
2266 OLEFontImpl_IPersistPropertyBag_Release,
2267
2268 OLEFontImpl_IPersistPropertyBag_GetClassID,
2269 OLEFontImpl_IPersistPropertyBag_InitNew,
2270 OLEFontImpl_IPersistPropertyBag_Load,
2271 OLEFontImpl_IPersistPropertyBag_Save
2272 };
2273
2274 /************************************************************************
2275 * OLEFontImpl implementation of IPersistStreamInit.
2276 */
2277 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_QueryInterface(
2278 IPersistStreamInit *iface, REFIID riid, LPVOID *ppvObj
2279 ) {
2280 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2281 return IFont_QueryInterface((IFont *)this,riid,ppvObj);
2282 }
2283
2284 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_AddRef(
2285 IPersistStreamInit *iface
2286 ) {
2287 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2288 return IFont_AddRef((IFont *)this);
2289 }
2290
2291 static ULONG WINAPI OLEFontImpl_IPersistStreamInit_Release(
2292 IPersistStreamInit *iface
2293 ) {
2294 OLEFontImpl *this = impl_from_IPersistStreamInit(iface);
2295 return IFont_Release((IFont *)this);
2296 }
2297
2298 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetClassID(
2299 IPersistStreamInit *iface, CLSID *classid
2300 ) {
2301 FIXME("(%p,%p), stub!\n", iface, classid);
2302 return E_FAIL;
2303 }
2304
2305 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_IsDirty(
2306 IPersistStreamInit *iface
2307 ) {
2308 FIXME("(%p), stub!\n", iface);
2309 return E_FAIL;
2310 }
2311
2312 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Load(
2313 IPersistStreamInit *iface, LPSTREAM pStm
2314 ) {
2315 FIXME("(%p,%p), stub!\n", iface, pStm);
2316 return E_FAIL;
2317 }
2318
2319 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_Save(
2320 IPersistStreamInit *iface, LPSTREAM pStm, BOOL fClearDirty
2321 ) {
2322 FIXME("(%p,%p,%d), stub!\n", iface, pStm, fClearDirty);
2323 return E_FAIL;
2324 }
2325
2326 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_GetSizeMax(
2327 IPersistStreamInit *iface, ULARGE_INTEGER *pcbSize
2328 ) {
2329 FIXME("(%p,%p), stub!\n", iface, pcbSize);
2330 return E_FAIL;
2331 }
2332
2333 static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
2334 IPersistStreamInit *iface
2335 ) {
2336 FIXME("(%p), stub!\n", iface);
2337 return S_OK;
2338 }
2339
2340 static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable =
2341 {
2342 OLEFontImpl_IPersistStreamInit_QueryInterface,
2343 OLEFontImpl_IPersistStreamInit_AddRef,
2344 OLEFontImpl_IPersistStreamInit_Release,
2345
2346 OLEFontImpl_IPersistStreamInit_GetClassID,
2347 OLEFontImpl_IPersistStreamInit_IsDirty,
2348 OLEFontImpl_IPersistStreamInit_Load,
2349 OLEFontImpl_IPersistStreamInit_Save,
2350 OLEFontImpl_IPersistStreamInit_GetSizeMax,
2351 OLEFontImpl_IPersistStreamInit_InitNew
2352 };
2353
2354 /************************************************************************
2355 * OLEFontImpl_Construct
2356 *
2357 * This method will construct a new instance of the OLEFontImpl
2358 * class.
2359 *
2360 * The caller of this method must release the object when it's
2361 * done with it.
2362 */
2363 static OLEFontImpl* OLEFontImpl_Construct(const FONTDESC *fontDesc)
2364 {
2365 OLEFontImpl* newObject = 0;
2366
2367 /*
2368 * Allocate space for the object.
2369 */
2370 newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(OLEFontImpl));
2371
2372 if (newObject==0)
2373 return newObject;
2374
2375 /*
2376 * Initialize the virtual function table.
2377 */
2378 newObject->lpVtbl = &OLEFontImpl_VTable;
2379 newObject->lpvtblIDispatch = &OLEFontImpl_IDispatch_VTable;
2380 newObject->lpvtblIPersistStream = &OLEFontImpl_IPersistStream_VTable;
2381 newObject->lpvtblIConnectionPointContainer = &OLEFontImpl_IConnectionPointContainer_VTable;
2382 newObject->lpvtblIPersistPropertyBag = &OLEFontImpl_IPersistPropertyBag_VTable;
2383 newObject->lpvtblIPersistStreamInit = &OLEFontImpl_IPersistStreamInit_VTable;
2384
2385 /*
2386 * Start with one reference count. The caller of this function
2387 * must release the interface pointer when it is done.
2388 */
2389 newObject->ref = 1;
2390
2391 /*
2392 * Copy the description of the font in the object.
2393 */
2394 assert(fontDesc->cbSizeofstruct >= sizeof(FONTDESC));
2395
2396 newObject->description.cbSizeofstruct = sizeof(FONTDESC);
2397 newObject->description.lpstrName = HeapAlloc(GetProcessHeap(),
2398 0,
2399 (lstrlenW(fontDesc->lpstrName)+1) * sizeof(WCHAR));
2400 strcpyW(newObject->description.lpstrName, fontDesc->lpstrName);
2401 newObject->description.cySize = fontDesc->cySize;
2402 newObject->description.sWeight = fontDesc->sWeight;
2403 newObject->description.sCharset = fontDesc->sCharset;
2404 newObject->description.fItalic = fontDesc->fItalic;
2405 newObject->description.fUnderline = fontDesc->fUnderline;
2406 newObject->description.fStrikethrough = fontDesc->fStrikethrough;
2407
2408 /*
2409 * Initializing all the other members.
2410 */
2411 newObject->gdiFont = 0;
2412 newObject->dirty = TRUE;
2413 newObject->cyLogical = 72L;
2414 newObject->cyHimetric = 2540L;
2415 newObject->pPropertyNotifyCP = NULL;
2416 newObject->pFontEventsCP = NULL;
2417
2418 CreateConnectionPoint((IUnknown*)newObject, &IID_IPropertyNotifySink, &newObject->pPropertyNotifyCP);
2419 CreateConnectionPoint((IUnknown*)newObject, &IID_IFontEventsDisp, &newObject->pFontEventsCP);
2420
2421 if (!newObject->pPropertyNotifyCP || !newObject->pFontEventsCP)
2422 {
2423 OLEFontImpl_Destroy(newObject);
2424 return NULL;
2425 }
2426
2427 InterlockedIncrement(&ifont_cnt);
2428
2429 TRACE("returning %p\n", newObject);
2430 return newObject;
2431 }
2432
2433 /************************************************************************
2434 * OLEFontImpl_Destroy
2435 *
2436 * This method is called by the Release method when the reference
2437 * count goes down to 0. It will free all resources used by
2438 * this object.
2439 */
2440 static void OLEFontImpl_Destroy(OLEFontImpl* fontDesc)
2441 {
2442 TRACE("(%p)\n", fontDesc);
2443
2444 HeapFree(GetProcessHeap(), 0, fontDesc->description.lpstrName);
2445
2446 if (fontDesc->pPropertyNotifyCP)
2447 IConnectionPoint_Release(fontDesc->pPropertyNotifyCP);
2448 if (fontDesc->pFontEventsCP)
2449 IConnectionPoint_Release(fontDesc->pFontEventsCP);
2450
2451 HeapFree(GetProcessHeap(), 0, fontDesc);
2452 }
2453
2454 /*******************************************************************************
2455 * StdFont ClassFactory
2456 */
2457 typedef struct
2458 {
2459 /* IUnknown fields */
2460 const IClassFactoryVtbl *lpVtbl;
2461 LONG ref;
2462 } IClassFactoryImpl;
2463
2464 static HRESULT WINAPI
2465 SFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
2466 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2467
2468 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
2469 return E_NOINTERFACE;
2470 }
2471
2472 static ULONG WINAPI
2473 SFCF_AddRef(LPCLASSFACTORY iface) {
2474 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2475 return InterlockedIncrement(&This->ref);
2476 }
2477
2478 static ULONG WINAPI SFCF_Release(LPCLASSFACTORY iface) {
2479 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2480 /* static class, won't be freed */
2481 return InterlockedDecrement(&This->ref);
2482 }
2483
2484 static HRESULT WINAPI SFCF_CreateInstance(
2485 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
2486 ) {
2487 return OleCreateFontIndirect(NULL,riid,ppobj);
2488
2489 }
2490
2491 static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
2492 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
2493 FIXME("(%p)->(%d),stub!\n",This,dolock);
2494 return S_OK;
2495 }
2496
2497 static const IClassFactoryVtbl SFCF_Vtbl = {
2498 SFCF_QueryInterface,
2499 SFCF_AddRef,
2500 SFCF_Release,
2501 SFCF_CreateInstance,
2502 SFCF_LockServer
2503 };
2504 static IClassFactoryImpl STDFONT_CF = {&SFCF_Vtbl, 1 };
2505
2506 void _get_STDFONT_CF(LPVOID *ppv) { *ppv = &STDFONT_CF; }