user32/tests: Fix some window test failures on various Windows platforms.
[wine] / dlls / msctf / threadmgr.c
1 /*
2  *  ITfThreadMgr implementation
3  *
4  *  Copyright 2008 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
36 #include "wine/unicode.h"
37
38 #include "msctf.h"
39 #include "msctf_internal.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
42
43 typedef struct tagACLMulti {
44     const ITfThreadMgrVtbl *ThreadMgrVtbl;
45     const ITfSourceVtbl *SourceVtbl;
46     LONG refCount;
47
48     ITfDocumentMgr *focus;
49 } ThreadMgr;
50
51 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
52 {
53     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
54 }
55
56 static void ThreadMgr_Destructor(ThreadMgr *This)
57 {
58     TlsSetValue(tlsIndex,NULL);
59     TRACE("destroying %p\n", This);
60     if (This->focus)
61         ITfDocumentMgr_Release(This->focus);
62     HeapFree(GetProcessHeap(),0,This);
63 }
64
65 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
66 {
67     ThreadMgr *This = (ThreadMgr *)iface;
68     *ppvOut = NULL;
69
70     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
71     {
72         *ppvOut = This;
73     }
74     else if (IsEqualIID(iid, &IID_ITfSource))
75     {
76         *ppvOut = &This->SourceVtbl;
77     }
78
79     if (*ppvOut)
80     {
81         IUnknown_AddRef(iface);
82         return S_OK;
83     }
84
85     WARN("unsupported interface: %s\n", debugstr_guid(iid));
86     return E_NOINTERFACE;
87 }
88
89 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
90 {
91     ThreadMgr *This = (ThreadMgr *)iface;
92     return InterlockedIncrement(&This->refCount);
93 }
94
95 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
96 {
97     ThreadMgr *This = (ThreadMgr *)iface;
98     ULONG ret;
99
100     ret = InterlockedDecrement(&This->refCount);
101     if (ret == 0)
102         ThreadMgr_Destructor(This);
103     return ret;
104 }
105
106 /*****************************************************
107  * ITfThreadMgr functions
108  *****************************************************/
109
110 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
111 {
112     ThreadMgr *This = (ThreadMgr *)iface;
113     FIXME("STUB:(%p)\n",This);
114     return E_NOTIMPL;
115 }
116
117 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
118 {
119     ThreadMgr *This = (ThreadMgr *)iface;
120     FIXME("STUB:(%p)\n",This);
121     return E_NOTIMPL;
122 }
123
124 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
125 **ppdim)
126 {
127     TRACE("(%p)\n",iface);
128     return DocumentMgr_Constructor(ppdim);
129 }
130
131 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
132 **ppEnum)
133 {
134     ThreadMgr *This = (ThreadMgr *)iface;
135     FIXME("STUB:(%p)\n",This);
136     return E_NOTIMPL;
137 }
138
139 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
140 **ppdimFocus)
141 {
142     ThreadMgr *This = (ThreadMgr *)iface;
143     TRACE("(%p)\n",This);
144
145     if (!ppdimFocus)
146         return E_INVALIDARG;
147
148     *ppdimFocus = This->focus;
149
150     TRACE("->%p\n",This->focus);
151
152     if (This->focus == NULL)
153         return S_FALSE;
154
155     ITfDocumentMgr_AddRef(This->focus);
156
157     return S_OK;
158 }
159
160 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
161 {
162     ITfDocumentMgr *check;
163     ThreadMgr *This = (ThreadMgr *)iface;
164
165     TRACE("(%p) %p\n",This,pdimFocus);
166
167     if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
168         return E_INVALIDARG;
169
170     if (This->focus)
171         ITfDocumentMgr_Release(This->focus);
172
173     This->focus = check;
174     return S_OK;
175 }
176
177 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
178 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
179 {
180     ThreadMgr *This = (ThreadMgr *)iface;
181     FIXME("STUB:(%p)\n",This);
182     return E_NOTIMPL;
183 }
184
185 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
186 {
187     ThreadMgr *This = (ThreadMgr *)iface;
188     FIXME("STUB:(%p)\n",This);
189     return E_NOTIMPL;
190 }
191
192 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
193 ITfFunctionProvider **ppFuncProv)
194 {
195     ThreadMgr *This = (ThreadMgr *)iface;
196     FIXME("STUB:(%p)\n",This);
197     return E_NOTIMPL;
198 }
199
200 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
201 IEnumTfFunctionProviders **ppEnum)
202 {
203     ThreadMgr *This = (ThreadMgr *)iface;
204     FIXME("STUB:(%p)\n",This);
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
209 ITfCompartmentMgr **ppCompMgr)
210 {
211     ThreadMgr *This = (ThreadMgr *)iface;
212     FIXME("STUB:(%p)\n",This);
213     return E_NOTIMPL;
214 }
215
216 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
217 {
218     ThreadMgr_QueryInterface,
219     ThreadMgr_AddRef,
220     ThreadMgr_Release,
221
222     ThreadMgr_fnActivate,
223     ThreadMgr_fnDeactivate,
224     ThreadMgr_CreateDocumentMgr,
225     ThreadMgr_EnumDocumentMgrs,
226     ThreadMgr_GetFocus,
227     ThreadMgr_SetFocus,
228     ThreadMgr_AssociateFocus,
229     ThreadMgr_IsThreadFocus,
230     ThreadMgr_GetFunctionProvider,
231     ThreadMgr_EnumFunctionProviders,
232     ThreadMgr_GetGlobalCompartment
233 };
234
235
236 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
237 {
238     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
239     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
240 }
241
242 static ULONG WINAPI Source_AddRef(ITfSource *iface)
243 {
244     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
245     return ThreadMgr_AddRef((ITfThreadMgr*)This);
246 }
247
248 static ULONG WINAPI Source_Release(ITfSource *iface)
249 {
250     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
251     return ThreadMgr_Release((ITfThreadMgr *)This);
252 }
253
254 /*****************************************************
255  * ITfSource functions
256  *****************************************************/
257 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
258         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
259 {
260     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
261     FIXME("STUB:(%p)\n",This);
262     return E_NOTIMPL;
263 }
264
265 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
266 {
267     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
268     FIXME("STUB:(%p)\n",This);
269     return E_NOTIMPL;
270 }
271
272 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
273 {
274     Source_QueryInterface,
275     Source_AddRef,
276     Source_Release,
277
278     ThreadMgrSource_AdviseSink,
279     ThreadMgrSource_UnadviseSink,
280 };
281
282 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
283 {
284     ThreadMgr *This;
285     if (pUnkOuter)
286         return CLASS_E_NOAGGREGATION;
287
288     /* Only 1 ThreadMgr is created per thread */
289     This = TlsGetValue(tlsIndex);
290     if (This)
291     {
292         ThreadMgr_AddRef((ITfThreadMgr*)This);
293         *ppOut = (IUnknown*)This;
294         return S_OK;
295     }
296
297     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
298     if (This == NULL)
299         return E_OUTOFMEMORY;
300
301     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
302     This->SourceVtbl = &ThreadMgr_SourceVtbl;
303     This->refCount = 1;
304     TlsSetValue(tlsIndex,This);
305
306     TRACE("returning %p\n", This);
307     *ppOut = (IUnknown *)This;
308     return S_OK;
309 }