2 * ITfCompartmentMgr implementation
4 * Copyright 2009 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "msctf_internal.h"
25 typedef struct tagCompartmentValue
{
29 ITfCompartment
*compartment
;
32 typedef struct tagCompartmentMgr
{
33 ITfCompartmentMgr ITfCompartmentMgr_iface
;
41 typedef struct tagCompartmentEnumGuid
{
42 IEnumGUID IEnumGUID_iface
;
47 } CompartmentEnumGuid
;
49 typedef struct tagCompartment
{
50 ITfCompartment ITfCompartment_iface
;
51 ITfSource ITfSource_iface
;
54 /* Only VT_I4, VT_UNKNOWN and VT_BSTR data types are allowed */
56 CompartmentValue
*valueData
;
57 struct list CompartmentEventSink
;
60 static HRESULT
CompartmentEnumGuid_Constructor(struct list
* values
, IEnumGUID
**ppOut
);
61 static HRESULT
Compartment_Constructor(CompartmentValue
*value
, ITfCompartment
**ppOut
);
63 static inline CompartmentMgr
*impl_from_ITfCompartmentMgr(ITfCompartmentMgr
*iface
)
65 return CONTAINING_RECORD(iface
, CompartmentMgr
, ITfCompartmentMgr_iface
);
68 static inline Compartment
*impl_from_ITfCompartment(ITfCompartment
*iface
)
70 return CONTAINING_RECORD(iface
, Compartment
, ITfCompartment_iface
);
73 static inline Compartment
*impl_from_ITfSource(ITfSource
*iface
)
75 return CONTAINING_RECORD(iface
, Compartment
, ITfSource_iface
);
78 static inline CompartmentEnumGuid
*impl_from_IEnumGUID(IEnumGUID
*iface
)
80 return CONTAINING_RECORD(iface
, CompartmentEnumGuid
, IEnumGUID_iface
);
83 HRESULT
CompartmentMgr_Destructor(ITfCompartmentMgr
*iface
)
85 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
86 struct list
*cursor
, *cursor2
;
88 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->values
)
90 CompartmentValue
* value
= LIST_ENTRY(cursor
,CompartmentValue
,entry
);
92 ITfCompartment_Release(value
->compartment
);
93 HeapFree(GetProcessHeap(),0,value
);
96 HeapFree(GetProcessHeap(),0,This
);
100 /*****************************************************
101 * ITfCompartmentMgr functions
102 *****************************************************/
103 static HRESULT WINAPI
CompartmentMgr_QueryInterface(ITfCompartmentMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
105 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
107 return IUnknown_QueryInterface(This
->pUnkOuter
, iid
, ppvOut
);
112 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
114 *ppvOut
= &This
->ITfCompartmentMgr_iface
;
119 ITfCompartmentMgr_AddRef(iface
);
123 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
124 return E_NOINTERFACE
;
128 static ULONG WINAPI
CompartmentMgr_AddRef(ITfCompartmentMgr
*iface
)
130 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
132 return IUnknown_AddRef(This
->pUnkOuter
);
134 return InterlockedIncrement(&This
->refCount
);
137 static ULONG WINAPI
CompartmentMgr_Release(ITfCompartmentMgr
*iface
)
139 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
141 return IUnknown_Release(This
->pUnkOuter
);
146 ret
= InterlockedDecrement(&This
->refCount
);
148 CompartmentMgr_Destructor(iface
);
153 static HRESULT WINAPI
CompartmentMgr_GetCompartment(ITfCompartmentMgr
*iface
,
154 REFGUID rguid
, ITfCompartment
**ppcomp
)
156 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
157 CompartmentValue
* value
;
161 TRACE("(%p) %s %p\n",This
,debugstr_guid(rguid
),ppcomp
);
163 LIST_FOR_EACH(cursor
, &This
->values
)
165 value
= LIST_ENTRY(cursor
,CompartmentValue
,entry
);
166 if (IsEqualGUID(rguid
,&value
->guid
))
168 ITfCompartment_AddRef(value
->compartment
);
169 *ppcomp
= value
->compartment
;
174 value
= HeapAlloc(GetProcessHeap(),0,sizeof(CompartmentValue
));
175 value
->guid
= *rguid
;
177 hr
= Compartment_Constructor(value
,&value
->compartment
);
180 list_add_head(&This
->values
,&value
->entry
);
181 ITfCompartment_AddRef(value
->compartment
);
182 *ppcomp
= value
->compartment
;
186 HeapFree(GetProcessHeap(),0,value
);
192 static HRESULT WINAPI
CompartmentMgr_ClearCompartment(ITfCompartmentMgr
*iface
,
193 TfClientId tid
, REFGUID rguid
)
195 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
198 TRACE("(%p) %i %s\n",This
,tid
,debugstr_guid(rguid
));
200 LIST_FOR_EACH(cursor
, &This
->values
)
202 CompartmentValue
* value
= LIST_ENTRY(cursor
,CompartmentValue
,entry
);
203 if (IsEqualGUID(rguid
,&value
->guid
))
205 if (value
->owner
&& tid
!= value
->owner
)
208 ITfCompartment_Release(value
->compartment
);
209 HeapFree(GetProcessHeap(),0,value
);
214 return CONNECT_E_NOCONNECTION
;
217 static HRESULT WINAPI
CompartmentMgr_EnumCompartments(ITfCompartmentMgr
*iface
,
220 CompartmentMgr
*This
= impl_from_ITfCompartmentMgr(iface
);
222 TRACE("(%p) %p\n",This
,ppEnum
);
225 return CompartmentEnumGuid_Constructor(&This
->values
, ppEnum
);
228 static const ITfCompartmentMgrVtbl CompartmentMgrVtbl
=
230 CompartmentMgr_QueryInterface
,
231 CompartmentMgr_AddRef
,
232 CompartmentMgr_Release
,
233 CompartmentMgr_GetCompartment
,
234 CompartmentMgr_ClearCompartment
,
235 CompartmentMgr_EnumCompartments
238 HRESULT
CompartmentMgr_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, IUnknown
**ppOut
)
240 CompartmentMgr
*This
;
245 if (pUnkOuter
&& !IsEqualIID (riid
, &IID_IUnknown
))
246 return CLASS_E_NOAGGREGATION
;
248 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(CompartmentMgr
));
250 return E_OUTOFMEMORY
;
252 This
->ITfCompartmentMgr_iface
.lpVtbl
= &CompartmentMgrVtbl
;
253 This
->pUnkOuter
= pUnkOuter
;
254 list_init(&This
->values
);
258 *ppOut
= (IUnknown
*)&This
->ITfCompartmentMgr_iface
;
259 TRACE("returning %p\n", *ppOut
);
265 hr
= ITfCompartmentMgr_QueryInterface(&This
->ITfCompartmentMgr_iface
, riid
, (void**)ppOut
);
267 HeapFree(GetProcessHeap(),0,This
);
272 /**************************************************
273 * IEnumGUID implementation for ITfCompartmentMgr::EnumCompartments
274 **************************************************/
275 static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid
*This
)
277 TRACE("destroying %p\n", This
);
278 HeapFree(GetProcessHeap(),0,This
);
281 static HRESULT WINAPI
CompartmentEnumGuid_QueryInterface(IEnumGUID
*iface
, REFIID iid
, LPVOID
*ppvOut
)
283 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
286 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumGUID
))
288 *ppvOut
= &This
->IEnumGUID_iface
;
293 IEnumGUID_AddRef(iface
);
297 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
298 return E_NOINTERFACE
;
301 static ULONG WINAPI
CompartmentEnumGuid_AddRef(IEnumGUID
*iface
)
303 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
304 return InterlockedIncrement(&This
->refCount
);
307 static ULONG WINAPI
CompartmentEnumGuid_Release(IEnumGUID
*iface
)
309 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
312 ret
= InterlockedDecrement(&This
->refCount
);
314 CompartmentEnumGuid_Destructor(This
);
318 /*****************************************************
319 * IEnumGuid functions
320 *****************************************************/
321 static HRESULT WINAPI
CompartmentEnumGuid_Next(IEnumGUID
*iface
,
322 ULONG celt
, GUID
*rgelt
, ULONG
*pceltFetched
)
324 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
327 TRACE("(%p)\n",This
);
329 if (rgelt
== NULL
) return E_POINTER
;
331 while (fetched
< celt
&& This
->cursor
)
333 CompartmentValue
* value
= LIST_ENTRY(This
->cursor
,CompartmentValue
,entry
);
337 This
->cursor
= list_next(This
->values
,This
->cursor
);
338 *rgelt
= value
->guid
;
344 if (pceltFetched
) *pceltFetched
= fetched
;
345 return fetched
== celt
? S_OK
: S_FALSE
;
348 static HRESULT WINAPI
CompartmentEnumGuid_Skip(IEnumGUID
*iface
, ULONG celt
)
350 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
351 TRACE("(%p)\n",This
);
353 This
->cursor
= list_next(This
->values
,This
->cursor
);
357 static HRESULT WINAPI
CompartmentEnumGuid_Reset(IEnumGUID
*iface
)
359 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
360 TRACE("(%p)\n",This
);
361 This
->cursor
= list_head(This
->values
);
365 static HRESULT WINAPI
CompartmentEnumGuid_Clone(IEnumGUID
*iface
,
368 CompartmentEnumGuid
*This
= impl_from_IEnumGUID(iface
);
371 TRACE("(%p)\n",This
);
373 if (ppenum
== NULL
) return E_POINTER
;
375 res
= CompartmentEnumGuid_Constructor(This
->values
, ppenum
);
378 CompartmentEnumGuid
*new_This
= impl_from_IEnumGUID(*ppenum
);
379 new_This
->cursor
= This
->cursor
;
384 static const IEnumGUIDVtbl EnumGUIDVtbl
=
386 CompartmentEnumGuid_QueryInterface
,
387 CompartmentEnumGuid_AddRef
,
388 CompartmentEnumGuid_Release
,
389 CompartmentEnumGuid_Next
,
390 CompartmentEnumGuid_Skip
,
391 CompartmentEnumGuid_Reset
,
392 CompartmentEnumGuid_Clone
395 static HRESULT
CompartmentEnumGuid_Constructor(struct list
*values
, IEnumGUID
**ppOut
)
397 CompartmentEnumGuid
*This
;
399 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(CompartmentEnumGuid
));
401 return E_OUTOFMEMORY
;
403 This
->IEnumGUID_iface
.lpVtbl
= &EnumGUIDVtbl
;
406 This
->values
= values
;
407 This
->cursor
= list_head(values
);
409 *ppOut
= &This
->IEnumGUID_iface
;
410 TRACE("returning %p\n", *ppOut
);
414 /**************************************************
416 **************************************************/
417 static void Compartment_Destructor(Compartment
*This
)
419 TRACE("destroying %p\n", This
);
420 VariantClear(&This
->variant
);
421 free_sinks(&This
->CompartmentEventSink
);
422 HeapFree(GetProcessHeap(),0,This
);
425 static HRESULT WINAPI
Compartment_QueryInterface(ITfCompartment
*iface
, REFIID iid
, LPVOID
*ppvOut
)
427 Compartment
*This
= impl_from_ITfCompartment(iface
);
431 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfCompartment
))
433 *ppvOut
= &This
->ITfCompartment_iface
;
435 else if (IsEqualIID(iid
, &IID_ITfSource
))
437 *ppvOut
= &This
->ITfSource_iface
;
442 ITfCompartment_AddRef(iface
);
446 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
447 return E_NOINTERFACE
;
450 static ULONG WINAPI
Compartment_AddRef(ITfCompartment
*iface
)
452 Compartment
*This
= impl_from_ITfCompartment(iface
);
453 return InterlockedIncrement(&This
->refCount
);
456 static ULONG WINAPI
Compartment_Release(ITfCompartment
*iface
)
458 Compartment
*This
= impl_from_ITfCompartment(iface
);
461 ret
= InterlockedDecrement(&This
->refCount
);
463 Compartment_Destructor(This
);
467 static HRESULT WINAPI
Compartment_SetValue(ITfCompartment
*iface
,
468 TfClientId tid
, const VARIANT
*pvarValue
)
470 Compartment
*This
= impl_from_ITfCompartment(iface
);
471 ITfCompartmentEventSink
*sink
;
474 TRACE("(%p) %i %p\n",This
,tid
,pvarValue
);
479 if (!(V_VT(pvarValue
) == VT_BSTR
|| V_VT(pvarValue
) == VT_I4
||
480 V_VT(pvarValue
) == VT_UNKNOWN
))
483 if (!This
->valueData
->owner
)
484 This
->valueData
->owner
= tid
;
486 VariantClear(&This
->variant
);
488 /* Shallow copy of value and type */
489 This
->variant
= *pvarValue
;
491 if (V_VT(pvarValue
) == VT_BSTR
)
492 V_BSTR(&This
->variant
) = SysAllocStringByteLen((char*)V_BSTR(pvarValue
),
493 SysStringByteLen(V_BSTR(pvarValue
)));
494 else if (V_VT(pvarValue
) == VT_UNKNOWN
)
495 IUnknown_AddRef(V_UNKNOWN(&This
->variant
));
497 SINK_FOR_EACH(cursor
, &This
->CompartmentEventSink
, ITfCompartmentEventSink
, sink
)
499 ITfCompartmentEventSink_OnChange(sink
, &This
->valueData
->guid
);
505 static HRESULT WINAPI
Compartment_GetValue(ITfCompartment
*iface
,
508 Compartment
*This
= impl_from_ITfCompartment(iface
);
509 TRACE("(%p) %p\n",This
, pvarValue
);
514 VariantInit(pvarValue
);
515 if (V_VT(&This
->variant
) == VT_EMPTY
) return S_FALSE
;
516 return VariantCopy(pvarValue
,&This
->variant
);
519 static const ITfCompartmentVtbl CompartmentVtbl
=
521 Compartment_QueryInterface
,
524 Compartment_SetValue
,
528 /*****************************************************
529 * ITfSource functions
530 *****************************************************/
532 static HRESULT WINAPI
CompartmentSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
534 Compartment
*This
= impl_from_ITfSource(iface
);
535 return ITfCompartment_QueryInterface(&This
->ITfCompartment_iface
, iid
, ppvOut
);
538 static ULONG WINAPI
CompartmentSource_AddRef(ITfSource
*iface
)
540 Compartment
*This
= impl_from_ITfSource(iface
);
541 return ITfCompartment_AddRef(&This
->ITfCompartment_iface
);
544 static ULONG WINAPI
CompartmentSource_Release(ITfSource
*iface
)
546 Compartment
*This
= impl_from_ITfSource(iface
);
547 return ITfCompartment_Release(&This
->ITfCompartment_iface
);
550 static HRESULT WINAPI
CompartmentSource_AdviseSink(ITfSource
*iface
,
551 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
553 Compartment
*This
= impl_from_ITfSource(iface
);
555 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
557 if (!riid
|| !punk
|| !pdwCookie
)
560 if (IsEqualIID(riid
, &IID_ITfCompartmentEventSink
))
561 return advise_sink(&This
->CompartmentEventSink
, &IID_ITfCompartmentEventSink
,
562 COOKIE_MAGIC_COMPARTMENTSINK
, punk
, pdwCookie
);
564 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
568 static HRESULT WINAPI
CompartmentSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
570 Compartment
*This
= impl_from_ITfSource(iface
);
572 TRACE("(%p) %x\n",This
,pdwCookie
);
574 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_COMPARTMENTSINK
)
577 return unadvise_sink(pdwCookie
);
580 static const ITfSourceVtbl CompartmentSourceVtbl
=
582 CompartmentSource_QueryInterface
,
583 CompartmentSource_AddRef
,
584 CompartmentSource_Release
,
585 CompartmentSource_AdviseSink
,
586 CompartmentSource_UnadviseSink
,
589 static HRESULT
Compartment_Constructor(CompartmentValue
*valueData
, ITfCompartment
**ppOut
)
593 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Compartment
));
595 return E_OUTOFMEMORY
;
597 This
->ITfCompartment_iface
.lpVtbl
= &CompartmentVtbl
;
598 This
->ITfSource_iface
.lpVtbl
= &CompartmentSourceVtbl
;
601 This
->valueData
= valueData
;
602 VariantInit(&This
->variant
);
604 list_init(&This
->CompartmentEventSink
);
606 *ppOut
= &This
->ITfCompartment_iface
;
607 TRACE("returning %p\n", *ppOut
);