ReactOS 0.4.15-dev-8227-g32d615f
compartmentmgr.c
Go to the documentation of this file.
1/*
2 * ITfCompartmentMgr implementation
3 *
4 * Copyright 2009 Aric Stewart, CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21#include <stdarg.h>
22
23#define COBJMACROS
24
25#include "wine/debug.h"
26#include "windef.h"
27#include "winbase.h"
28#include "winreg.h"
29#include "winuser.h"
30#include "shlwapi.h"
31#include "winerror.h"
32#include "objbase.h"
33#include "oleauto.h"
34#include "olectl.h"
35
36#include "msctf.h"
37#include "msctf_internal.h"
38
40
41typedef struct tagCompartmentValue {
42 struct list entry;
47
48typedef struct tagCompartmentMgr {
51
53
54 struct list values;
56
57typedef struct tagCompartmentEnumGuid {
60
61 struct list *values;
62 struct list *cursor;
64
65typedef struct tagCompartment {
69
70 /* Only VT_I4, VT_UNKNOWN and VT_BSTR data types are allowed */
75
78
80{
81 return CONTAINING_RECORD(iface, CompartmentMgr, ITfCompartmentMgr_iface);
82}
83
85{
86 return CONTAINING_RECORD(iface, Compartment, ITfCompartment_iface);
87}
88
90{
91 return CONTAINING_RECORD(iface, Compartment, ITfSource_iface);
92}
93
95{
96 return CONTAINING_RECORD(iface, CompartmentEnumGuid, IEnumGUID_iface);
97}
98
100{
102 struct list *cursor, *cursor2;
103
104 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->values)
105 {
108 ITfCompartment_Release(value->compartment);
110 }
111
113 return S_OK;
114}
115
116/*****************************************************
117 * ITfCompartmentMgr functions
118 *****************************************************/
120{
122 if (This->pUnkOuter)
123 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvOut);
124 else
125 {
126 *ppvOut = NULL;
127
128 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartmentMgr))
129 {
130 *ppvOut = &This->ITfCompartmentMgr_iface;
131 }
132
133 if (*ppvOut)
134 {
135 ITfCompartmentMgr_AddRef(iface);
136 return S_OK;
137 }
138
139 WARN("unsupported interface: %s\n", debugstr_guid(iid));
140 return E_NOINTERFACE;
141 }
142}
143
145{
147 if (This->pUnkOuter)
148 return IUnknown_AddRef(This->pUnkOuter);
149 else
150 return InterlockedIncrement(&This->refCount);
151}
152
154{
156 if (This->pUnkOuter)
157 return IUnknown_Release(This->pUnkOuter);
158 else
159 {
160 ULONG ret;
161
162 ret = InterlockedDecrement(&This->refCount);
163 if (ret == 0)
165 return ret;
166 }
167}
168
170 REFGUID rguid, ITfCompartment **ppcomp)
171{
174 struct list *cursor;
175 HRESULT hr;
176
177 TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),ppcomp);
178
179 LIST_FOR_EACH(cursor, &This->values)
180 {
182 if (IsEqualGUID(rguid,&value->guid))
183 {
184 ITfCompartment_AddRef(value->compartment);
185 *ppcomp = value->compartment;
186 return S_OK;
187 }
188 }
189
191 value->guid = *rguid;
192 value->owner = 0;
193 hr = Compartment_Constructor(value,&value->compartment);
194 if (SUCCEEDED(hr))
195 {
196 list_add_head(&This->values,&value->entry);
197 ITfCompartment_AddRef(value->compartment);
198 *ppcomp = value->compartment;
199 }
200 else
201 {
203 *ppcomp = NULL;
204 }
205 return hr;
206}
207
209 TfClientId tid, REFGUID rguid)
210{
212 struct list *cursor;
213
214 TRACE("(%p) %i %s\n",This,tid,debugstr_guid(rguid));
215
216 LIST_FOR_EACH(cursor, &This->values)
217 {
219 if (IsEqualGUID(rguid,&value->guid))
220 {
221 if (value->owner && tid != value->owner)
222 return E_UNEXPECTED;
224 ITfCompartment_Release(value->compartment);
226 return S_OK;
227 }
228 }
229
231}
232
234 IEnumGUID **ppEnum)
235{
237
238 TRACE("(%p) %p\n",This,ppEnum);
239 if (!ppEnum)
240 return E_INVALIDARG;
241 return CompartmentEnumGuid_Constructor(&This->values, ppEnum);
242}
243
244static const ITfCompartmentMgrVtbl CompartmentMgrVtbl =
245{
252};
253
255{
257
258 if (!ppOut)
259 return E_POINTER;
260
261 if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
263
265 if (This == NULL)
266 return E_OUTOFMEMORY;
267
268 This->ITfCompartmentMgr_iface.lpVtbl = &CompartmentMgrVtbl;
269 This->pUnkOuter = pUnkOuter;
270 list_init(&This->values);
271
272 if (pUnkOuter)
273 {
274 *ppOut = (IUnknown*)&This->ITfCompartmentMgr_iface;
275 TRACE("returning %p\n", *ppOut);
276 return S_OK;
277 }
278 else
279 {
280 HRESULT hr;
281 hr = ITfCompartmentMgr_QueryInterface(&This->ITfCompartmentMgr_iface, riid, (void**)ppOut);
282 if (FAILED(hr))
284 return hr;
285 }
286}
287
288/**************************************************
289 * IEnumGUID implementation for ITfCompartmentMgr::EnumCompartments
290 **************************************************/
292{
293 TRACE("destroying %p\n", This);
295}
296
298{
300 *ppvOut = NULL;
301
302 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
303 {
304 *ppvOut = &This->IEnumGUID_iface;
305 }
306
307 if (*ppvOut)
308 {
309 IEnumGUID_AddRef(iface);
310 return S_OK;
311 }
312
313 WARN("unsupported interface: %s\n", debugstr_guid(iid));
314 return E_NOINTERFACE;
315}
316
318{
320 return InterlockedIncrement(&This->refCount);
321}
322
324{
326 ULONG ret;
327
328 ret = InterlockedDecrement(&This->refCount);
329 if (ret == 0)
331 return ret;
332}
333
334/*****************************************************
335 * IEnumGuid functions
336 *****************************************************/
338 ULONG celt, GUID *rgelt, ULONG *pceltFetched)
339{
341 ULONG fetched = 0;
342
343 TRACE("(%p)\n",This);
344
345 if (rgelt == NULL) return E_POINTER;
346
347 while (fetched < celt && This->cursor)
348 {
350 if (!value)
351 break;
352
353 This->cursor = list_next(This->values,This->cursor);
354 *rgelt = value->guid;
355
356 ++fetched;
357 ++rgelt;
358 }
359
360 if (pceltFetched) *pceltFetched = fetched;
361 return fetched == celt ? S_OK : S_FALSE;
362}
363
365{
367 TRACE("(%p)\n",This);
368
369 This->cursor = list_next(This->values,This->cursor);
370 return S_OK;
371}
372
374{
376 TRACE("(%p)\n",This);
377 This->cursor = list_head(This->values);
378 return S_OK;
379}
380
382 IEnumGUID **ppenum)
383{
385 HRESULT res;
386
387 TRACE("(%p)\n",This);
388
389 if (ppenum == NULL) return E_POINTER;
390
391 res = CompartmentEnumGuid_Constructor(This->values, ppenum);
392 if (SUCCEEDED(res))
393 {
394 CompartmentEnumGuid *new_This = impl_from_IEnumGUID(*ppenum);
395 new_This->cursor = This->cursor;
396 }
397 return res;
398}
399
400static const IEnumGUIDVtbl EnumGUIDVtbl =
401{
409};
410
412{
414
416 if (This == NULL)
417 return E_OUTOFMEMORY;
418
419 This->IEnumGUID_iface.lpVtbl= &EnumGUIDVtbl;
420 This->refCount = 1;
421
422 This->values = values;
423 This->cursor = list_head(values);
424
425 *ppOut = &This->IEnumGUID_iface;
426 TRACE("returning %p\n", *ppOut);
427 return S_OK;
428}
429
430/**************************************************
431 * ITfCompartment
432 **************************************************/
434{
435 TRACE("destroying %p\n", This);
436 VariantClear(&This->variant);
437 free_sinks(&This->CompartmentEventSink);
439}
440
442{
444
445 *ppvOut = NULL;
446
447 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartment))
448 {
449 *ppvOut = &This->ITfCompartment_iface;
450 }
451 else if (IsEqualIID(iid, &IID_ITfSource))
452 {
453 *ppvOut = &This->ITfSource_iface;
454 }
455
456 if (*ppvOut)
457 {
458 ITfCompartment_AddRef(iface);
459 return S_OK;
460 }
461
462 WARN("unsupported interface: %s\n", debugstr_guid(iid));
463 return E_NOINTERFACE;
464}
465
467{
469 return InterlockedIncrement(&This->refCount);
470}
471
473{
475 ULONG ret;
476
477 ret = InterlockedDecrement(&This->refCount);
478 if (ret == 0)
480 return ret;
481}
482
484 TfClientId tid, const VARIANT *pvarValue)
485{
488 struct list *cursor;
489
490 TRACE("(%p) %i %p\n",This,tid,pvarValue);
491
492 if (!pvarValue)
493 return E_INVALIDARG;
494
495 if (!(V_VT(pvarValue) == VT_BSTR || V_VT(pvarValue) == VT_I4 ||
496 V_VT(pvarValue) == VT_UNKNOWN))
497 return E_INVALIDARG;
498
499 if (!This->valueData->owner)
500 This->valueData->owner = tid;
501
502 VariantClear(&This->variant);
503
504 /* Shallow copy of value and type */
505 This->variant = *pvarValue;
506
507 if (V_VT(pvarValue) == VT_BSTR)
508 V_BSTR(&This->variant) = SysAllocStringByteLen((char*)V_BSTR(pvarValue),
509 SysStringByteLen(V_BSTR(pvarValue)));
510 else if (V_VT(pvarValue) == VT_UNKNOWN)
511 IUnknown_AddRef(V_UNKNOWN(&This->variant));
512
513 SINK_FOR_EACH(cursor, &This->CompartmentEventSink, ITfCompartmentEventSink, sink)
514 {
515 ITfCompartmentEventSink_OnChange(sink, &This->valueData->guid);
516 }
517
518 return S_OK;
519}
520
522 VARIANT *pvarValue)
523{
525 TRACE("(%p) %p\n",This, pvarValue);
526
527 if (!pvarValue)
528 return E_INVALIDARG;
529
530 VariantInit(pvarValue);
531 if (V_VT(&This->variant) == VT_EMPTY) return S_FALSE;
532 return VariantCopy(pvarValue,&This->variant);
533}
534
535static const ITfCompartmentVtbl CompartmentVtbl =
536{
542};
543
544/*****************************************************
545 * ITfSource functions
546 *****************************************************/
547
549{
551 return ITfCompartment_QueryInterface(&This->ITfCompartment_iface, iid, ppvOut);
552}
553
555{
557 return ITfCompartment_AddRef(&This->ITfCompartment_iface);
558}
559
561{
563 return ITfCompartment_Release(&This->ITfCompartment_iface);
564}
565
567 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
568{
570
571 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
572
573 if (!riid || !punk || !pdwCookie)
574 return E_INVALIDARG;
575
576 if (IsEqualIID(riid, &IID_ITfCompartmentEventSink))
577 return advise_sink(&This->CompartmentEventSink, &IID_ITfCompartmentEventSink,
578 COOKIE_MAGIC_COMPARTMENTSINK, punk, pdwCookie);
579
580 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
581 return E_NOTIMPL;
582}
583
585{
587
588 TRACE("(%p) %x\n",This,pdwCookie);
589
591 return E_INVALIDARG;
592
593 return unadvise_sink(pdwCookie);
594}
595
596static const ITfSourceVtbl CompartmentSourceVtbl =
597{
603};
604
606{
608
610 if (This == NULL)
611 return E_OUTOFMEMORY;
612
613 This->ITfCompartment_iface.lpVtbl= &CompartmentVtbl;
614 This->ITfSource_iface.lpVtbl = &CompartmentSourceVtbl;
615 This->refCount = 1;
616
617 This->valueData = valueData;
618 VariantInit(&This->variant);
619
620 list_init(&This->CompartmentEventSink);
621
622 *ppOut = &This->ITfCompartment_iface;
623 TRACE("returning %p\n", *ppOut);
624 return S_OK;
625}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:114
#define WARN(fmt,...)
Definition: debug.h:115
Definition: list.h:37
static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid *This)
struct tagCompartmentMgr CompartmentMgr
static HRESULT WINAPI CompartmentEnumGuid_Reset(IEnumGUID *iface)
static HRESULT WINAPI CompartmentMgr_QueryInterface(ITfCompartmentMgr *iface, REFIID iid, LPVOID *ppvOut)
static ULONG WINAPI CompartmentSource_AddRef(ITfSource *iface)
static CompartmentMgr * impl_from_ITfCompartmentMgr(ITfCompartmentMgr *iface)
static void Compartment_Destructor(Compartment *This)
static HRESULT WINAPI CompartmentEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
static HRESULT WINAPI CompartmentSource_AdviseSink(ITfSource *iface, REFIID riid, IUnknown *punk, DWORD *pdwCookie)
static HRESULT WINAPI Compartment_QueryInterface(ITfCompartment *iface, REFIID iid, LPVOID *ppvOut)
static HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface, REFGUID rguid, ITfCompartment **ppcomp)
static HRESULT WINAPI Compartment_SetValue(ITfCompartment *iface, TfClientId tid, const VARIANT *pvarValue)
HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface)
static Compartment * impl_from_ITfSource(ITfSource *iface)
static HRESULT WINAPI Compartment_GetValue(ITfCompartment *iface, VARIANT *pvarValue)
static ULONG WINAPI CompartmentEnumGuid_AddRef(IEnumGUID *iface)
static HRESULT WINAPI CompartmentSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
static Compartment * impl_from_ITfCompartment(ITfCompartment *iface)
static const ITfCompartmentVtbl CompartmentVtbl
static ULONG WINAPI CompartmentMgr_AddRef(ITfCompartmentMgr *iface)
static CompartmentEnumGuid * impl_from_IEnumGUID(IEnumGUID *iface)
static HRESULT CompartmentEnumGuid_Constructor(struct list *values, IEnumGUID **ppOut)
static HRESULT Compartment_Constructor(CompartmentValue *value, ITfCompartment **ppOut)
struct tagCompartmentEnumGuid CompartmentEnumGuid
static HRESULT WINAPI CompartmentSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
static ULONG WINAPI CompartmentMgr_Release(ITfCompartmentMgr *iface)
HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut)
static HRESULT WINAPI CompartmentEnumGuid_Skip(IEnumGUID *iface, ULONG celt)
static const IEnumGUIDVtbl EnumGUIDVtbl
static ULONG WINAPI CompartmentEnumGuid_Release(IEnumGUID *iface)
static ULONG WINAPI CompartmentSource_Release(ITfSource *iface)
static const ITfSourceVtbl CompartmentSourceVtbl
static HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface, IEnumGUID **ppEnum)
static ULONG WINAPI Compartment_AddRef(ITfCompartment *iface)
static HRESULT WINAPI CompartmentEnumGuid_Clone(IEnumGUID *iface, IEnumGUID **ppenum)
static ULONG WINAPI Compartment_Release(ITfCompartment *iface)
static HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface, TfClientId tid, REFGUID rguid)
struct tagCompartment Compartment
static HRESULT WINAPI CompartmentEnumGuid_Next(IEnumGUID *iface, ULONG celt, GUID *rgelt, ULONG *pceltFetched)
static const ITfCompartmentMgrVtbl CompartmentMgrVtbl
struct tagCompartmentValue CompartmentValue
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
@ VT_BSTR
Definition: compat.h:2303
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_I4
Definition: compat.h:2298
@ VT_EMPTY
Definition: compat.h:2295
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLsizei GLenum GLboolean sink
Definition: glext.h:5672
const char cursor[]
Definition: icontest.c:13
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_guid
Definition: kernel32.h:35
static TfClientId tid
DWORD get_Cookie_magic(DWORD id)
Definition: msctf.c:233
HRESULT unadvise_sink(DWORD cookie)
Definition: msctf.c:312
void free_sinks(struct list *sink_list)
Definition: msctf.c:324
HRESULT advise_sink(struct list *sink_list, REFIID riid, DWORD cookie_magic, IUnknown *unk, DWORD *cookie)
Definition: msctf.c:285
DWORD TfClientId
Definition: msctf.idl:105
#define SINK_FOR_EACH(cursor, list, type, elem)
#define COOKIE_MAGIC_COMPARTMENTSINK
UINT WINAPI SysStringByteLen(BSTR str)
Definition: oleaut.c:215
BSTR WINAPI DECLSPEC_HOTPATCH SysAllocStringByteLen(LPCSTR str, UINT len)
Definition: oleaut.c:428
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define CONNECT_E_NOCONNECTION
Definition: olectl.h:251
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:115
#define LIST_FOR_EACH(cursor, list)
Definition: list.h:188
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list)
Definition: list.h:192
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
Definition: scsiwmi.h:51
Definition: list.h:15
IUnknown * pUnkOuter
ITfCompartmentMgr ITfCompartmentMgr_iface
ITfCompartment * compartment
ITfCompartment ITfCompartment_iface
ITfSource ITfSource_iface
CompartmentValue * valueData
struct list CompartmentEventSink
#define LIST_ENTRY(type)
Definition: queue.h:175
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
Definition: pdh_main.c:94
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
int ret
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
#define E_UNEXPECTED
Definition: winerror.h:2456
#define E_POINTER
Definition: winerror.h:2365