d3d8/tests: Fix some tests (logical || with non-zero constant).
[wine] / dlls / msctf / compartmentmgr.c
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 "config.h"
22
23 #include <stdarg.h>
24
25 #define COBJMACROS
26
27 #include "wine/debug.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "shlwapi.h"
33 #include "winerror.h"
34 #include "objbase.h"
35 #include "oleauto.h"
36 #include "olectl.h"
37
38 #include "wine/unicode.h"
39 #include "wine/list.h"
40
41 #include "msctf.h"
42 #include "msctf_internal.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
45
46 typedef struct tagCompartmentValue {
47     struct list entry;
48     GUID guid;
49     TfClientId owner;
50     ITfCompartment *compartment;
51 } CompartmentValue;
52
53 typedef struct tagCompartmentMgr {
54     const ITfCompartmentMgrVtbl *CompartmentMgrVtbl;
55     LONG refCount;
56
57     IUnknown *pUnkOuter;
58
59     struct list values;
60 } CompartmentMgr;
61
62 typedef struct tagCompartmentEnumGuid {
63     const IEnumGUIDVtbl *Vtbl;
64     LONG refCount;
65
66     struct list *values;
67     struct list *cursor;
68 } CompartmentEnumGuid;
69
70 static HRESULT CompartmentEnumGuid_Constructor(struct list* values, IEnumGUID **ppOut);
71
72 HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface)
73 {
74     CompartmentMgr *This = (CompartmentMgr *)iface;
75     struct list *cursor, *cursor2;
76
77     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->values)
78     {
79         CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry);
80         list_remove(cursor);
81         ITfCompartment_Release(value->compartment);
82         HeapFree(GetProcessHeap(),0,value);
83     }
84
85     HeapFree(GetProcessHeap(),0,This);
86     return S_OK;
87 }
88
89 /*****************************************************
90  * ITfCompartmentMgr functions
91  *****************************************************/
92 static HRESULT WINAPI CompartmentMgr_QueryInterface(ITfCompartmentMgr *iface, REFIID iid, LPVOID *ppvOut)
93 {
94     CompartmentMgr *This = (CompartmentMgr *)iface;
95     if (This->pUnkOuter)
96         return IUnknown_QueryInterface(This->pUnkOuter, iid, *ppvOut);
97     else
98     {
99         *ppvOut = NULL;
100
101         if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCompartmentMgr))
102         {
103             *ppvOut = This;
104         }
105
106         if (*ppvOut)
107         {
108             IUnknown_AddRef(iface);
109             return S_OK;
110         }
111
112         WARN("unsupported interface: %s\n", debugstr_guid(iid));
113         return E_NOINTERFACE;
114     }
115 }
116
117 static ULONG WINAPI CompartmentMgr_AddRef(ITfCompartmentMgr *iface)
118 {
119     CompartmentMgr *This = (CompartmentMgr *)iface;
120     if (This->pUnkOuter)
121         return IUnknown_AddRef(This->pUnkOuter);
122     else
123         return InterlockedIncrement(&This->refCount);
124 }
125
126 static ULONG WINAPI CompartmentMgr_Release(ITfCompartmentMgr *iface)
127 {
128     CompartmentMgr *This = (CompartmentMgr *)iface;
129     if (This->pUnkOuter)
130         return IUnknown_Release(This->pUnkOuter);
131     else
132     {
133         ULONG ret;
134
135         ret = InterlockedDecrement(&This->refCount);
136         if (ret == 0)
137             CompartmentMgr_Destructor(iface);
138         return ret;
139     }
140 }
141
142 static HRESULT WINAPI CompartmentMgr_GetCompartment(ITfCompartmentMgr *iface,
143         REFGUID rguid, ITfCompartment **ppcomp)
144 {
145     CompartmentMgr *This = (CompartmentMgr *)iface;
146     FIXME("STUB:(%p)\n",This);
147     return E_NOTIMPL;
148 }
149
150 static HRESULT WINAPI CompartmentMgr_ClearCompartment(ITfCompartmentMgr *iface,
151     TfClientId tid, REFGUID rguid)
152 {
153     struct list *cursor;
154     CompartmentMgr *This = (CompartmentMgr *)iface;
155     TRACE("(%p) %i %s\n",This,tid,debugstr_guid(rguid));
156
157     LIST_FOR_EACH(cursor, &This->values)
158     {
159         CompartmentValue* value = LIST_ENTRY(cursor,CompartmentValue,entry);
160         if (IsEqualGUID(rguid,&value->guid))
161         {
162             if (value->owner && tid != value->owner)
163                 return E_UNEXPECTED;
164             list_remove(cursor);
165             ITfCompartment_Release(value->compartment);
166             HeapFree(GetProcessHeap(),0,value);
167             return S_OK;
168         }
169     }
170
171     return CONNECT_E_NOCONNECTION;
172 }
173
174 static HRESULT WINAPI CompartmentMgr_EnumCompartments(ITfCompartmentMgr *iface,
175  IEnumGUID **ppEnum)
176 {
177     CompartmentMgr *This = (CompartmentMgr *)iface;
178     TRACE("(%p) %p\n",This,ppEnum);
179     if (!ppEnum)
180         return E_INVALIDARG;
181     return CompartmentEnumGuid_Constructor(&This->values, ppEnum);
182 }
183
184 static const ITfCompartmentMgrVtbl CompartmentMgr_CompartmentMgrVtbl =
185 {
186     CompartmentMgr_QueryInterface,
187     CompartmentMgr_AddRef,
188     CompartmentMgr_Release,
189
190     CompartmentMgr_GetCompartment,
191     CompartmentMgr_ClearCompartment,
192     CompartmentMgr_EnumCompartments
193 };
194
195 HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut)
196 {
197     CompartmentMgr *This;
198
199     if (!ppOut)
200         return E_POINTER;
201
202     if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
203         return CLASS_E_NOAGGREGATION;
204
205     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentMgr));
206     if (This == NULL)
207         return E_OUTOFMEMORY;
208
209     This->CompartmentMgrVtbl = &CompartmentMgr_CompartmentMgrVtbl;
210     This->pUnkOuter = pUnkOuter;
211     list_init(&This->values);
212
213     if (pUnkOuter)
214     {
215         TRACE("returning %p\n", This);
216         *ppOut = (IUnknown*)This;
217         return S_OK;
218     }
219     else
220     {
221         HRESULT hr;
222         hr = IUnknown_QueryInterface((IUnknown*)This, riid, (LPVOID*)ppOut);
223         if (FAILED(hr))
224             HeapFree(GetProcessHeap(),0,This);
225         return hr;
226     }
227 }
228
229 /**************************************************
230  * IEnumGUID implementaion for ITfCompartmentMgr::EnumCompartments
231  **************************************************/
232 static void CompartmentEnumGuid_Destructor(CompartmentEnumGuid *This)
233 {
234     TRACE("destroying %p\n", This);
235     HeapFree(GetProcessHeap(),0,This);
236 }
237
238 static HRESULT WINAPI CompartmentEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
239 {
240     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
241     *ppvOut = NULL;
242
243     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
244     {
245         *ppvOut = This;
246     }
247
248     if (*ppvOut)
249     {
250         IUnknown_AddRef(iface);
251         return S_OK;
252     }
253
254     WARN("unsupported interface: %s\n", debugstr_guid(iid));
255     return E_NOINTERFACE;
256 }
257
258 static ULONG WINAPI CompartmentEnumGuid_AddRef(IEnumGUID *iface)
259 {
260     CompartmentEnumGuid *This = (CompartmentEnumGuid*)iface;
261     return InterlockedIncrement(&This->refCount);
262 }
263
264 static ULONG WINAPI CompartmentEnumGuid_Release(IEnumGUID *iface)
265 {
266     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
267     ULONG ret;
268
269     ret = InterlockedDecrement(&This->refCount);
270     if (ret == 0)
271         CompartmentEnumGuid_Destructor(This);
272     return ret;
273 }
274
275 /*****************************************************
276  * IEnumGuid functions
277  *****************************************************/
278 static HRESULT WINAPI CompartmentEnumGuid_Next( LPENUMGUID iface,
279     ULONG celt, GUID *rgelt, ULONG *pceltFetched)
280 {
281     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
282     ULONG fetched = 0;
283
284     TRACE("(%p)\n",This);
285
286     if (rgelt == NULL) return E_POINTER;
287
288     while (fetched < celt && This->cursor)
289     {
290         CompartmentValue* value = LIST_ENTRY(This->cursor,CompartmentValue,entry);
291         if (!value)
292             break;
293
294         This->cursor = list_next(This->values,This->cursor);
295         *rgelt = value->guid;
296
297         ++fetched;
298         ++rgelt;
299     }
300
301     if (pceltFetched) *pceltFetched = fetched;
302     return fetched == celt ? S_OK : S_FALSE;
303 }
304
305 static HRESULT WINAPI CompartmentEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
306 {
307     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
308     TRACE("(%p)\n",This);
309
310     This->cursor = list_next(This->values,This->cursor);
311     return S_OK;
312 }
313
314 static HRESULT WINAPI CompartmentEnumGuid_Reset( LPENUMGUID iface)
315 {
316     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
317     TRACE("(%p)\n",This);
318     This->cursor = list_head(This->values);
319     return S_OK;
320 }
321
322 static HRESULT WINAPI CompartmentEnumGuid_Clone( LPENUMGUID iface,
323     IEnumGUID **ppenum)
324 {
325     CompartmentEnumGuid *This = (CompartmentEnumGuid *)iface;
326     HRESULT res;
327
328     TRACE("(%p)\n",This);
329
330     if (ppenum == NULL) return E_POINTER;
331
332     res = CompartmentEnumGuid_Constructor(This->values, ppenum);
333     if (SUCCEEDED(res))
334     {
335         CompartmentEnumGuid *new_This = (CompartmentEnumGuid *)*ppenum;
336         new_This->cursor = This->cursor;
337     }
338     return res;
339 }
340
341 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
342     CompartmentEnumGuid_QueryInterface,
343     CompartmentEnumGuid_AddRef,
344     CompartmentEnumGuid_Release,
345
346     CompartmentEnumGuid_Next,
347     CompartmentEnumGuid_Skip,
348     CompartmentEnumGuid_Reset,
349     CompartmentEnumGuid_Clone
350 };
351
352 static HRESULT CompartmentEnumGuid_Constructor(struct list *values, IEnumGUID **ppOut)
353 {
354     CompartmentEnumGuid *This;
355
356     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CompartmentEnumGuid));
357     if (This == NULL)
358         return E_OUTOFMEMORY;
359
360     This->Vtbl= &IEnumGUID_Vtbl;
361     This->refCount = 1;
362
363     This->values = values;
364     This->cursor = list_head(values);
365
366     TRACE("returning %p\n", This);
367     *ppOut = (IEnumGUID*)This;
368     return S_OK;
369 }