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