ReactOS 0.4.15-dev-7918-g2a2556c
documentmgr.c
Go to the documentation of this file.
1/*
2 * ITfDocumentMgr 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
34#include "msctf.h"
35#include "msctf_internal.h"
36
38
39typedef struct tagDocumentMgr {
43
44 /* Aggregation */
46
47 ITfContext* contextStack[2]; /* limit of 2 contexts */
49
52
53typedef struct tagEnumTfContext {
56
60
62
64{
65 return CONTAINING_RECORD(iface, DocumentMgr, ITfDocumentMgr_iface);
66}
67
69{
70 return CONTAINING_RECORD(iface, DocumentMgr, ITfSource_iface);
71}
72
74{
75 return CONTAINING_RECORD(iface, EnumTfContext, IEnumTfContexts_iface);
76}
77
79{
81 TRACE("destroying %p\n", This);
82
84 if (tm)
85 {
86 ThreadMgr_OnDocumentMgrDestruction(tm, &This->ITfDocumentMgr_iface);
87 ITfThreadMgr_Release(tm);
88 }
89
90 if (This->contextStack[0])
91 ITfContext_Release(This->contextStack[0]);
92 if (This->contextStack[1])
93 ITfContext_Release(This->contextStack[1]);
94 free_sinks(&This->TransitoryExtensionSink);
95 CompartmentMgr_Destructor(This->CompartmentMgr);
97}
98
100{
102 *ppvOut = NULL;
103
104 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfDocumentMgr))
105 {
106 *ppvOut = &This->ITfDocumentMgr_iface;
107 }
108 else if (IsEqualIID(iid, &IID_ITfSource))
109 {
110 *ppvOut = &This->ITfSource_iface;
111 }
112 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
113 {
114 *ppvOut = This->CompartmentMgr;
115 }
116
117 if (*ppvOut)
118 {
119 ITfDocumentMgr_AddRef(iface);
120 return S_OK;
121 }
122
123 WARN("unsupported interface: %s\n", debugstr_guid(iid));
124 return E_NOINTERFACE;
125}
126
128{
130 return InterlockedIncrement(&This->refCount);
131}
132
134{
136 ULONG ret;
137
138 ret = InterlockedDecrement(&This->refCount);
139 if (ret == 0)
141 return ret;
142}
143
144/*****************************************************
145 * ITfDocumentMgr functions
146 *****************************************************/
148 TfClientId tidOwner,
149 DWORD dwFlags, IUnknown *punk, ITfContext **ppic,
150 TfEditCookie *pecTextStore)
151{
153 TRACE("(%p) 0x%x 0x%x %p %p %p\n",This,tidOwner,dwFlags,punk,ppic,pecTextStore);
154 return Context_Constructor(tidOwner, punk, iface, ppic, pecTextStore);
155}
156
158{
161
162 TRACE("(%p) %p\n",This,pic);
163
164 if (This->contextStack[1]) /* FUll */
165 return TF_E_STACKFULL;
166
167 if (!pic || FAILED(ITfContext_QueryInterface(pic,&IID_ITfContext,(LPVOID*) &check)))
168 return E_INVALIDARG;
169
170 if (This->contextStack[0] == NULL)
171 ITfThreadMgrEventSink_OnInitDocumentMgr(This->ThreadMgrSink,iface);
172
173 This->contextStack[1] = This->contextStack[0];
174 This->contextStack[0] = check;
175
177 ITfThreadMgrEventSink_OnPushContext(This->ThreadMgrSink,check);
178
179 return S_OK;
180}
181
183{
185 TRACE("(%p) 0x%x\n",This,dwFlags);
186
187 if (dwFlags == TF_POPF_ALL)
188 {
189 int i;
190
191 for (i = 0; i < ARRAY_SIZE(This->contextStack); i++)
192 if (This->contextStack[i])
193 {
194 ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink, This->contextStack[i]);
195 Context_Uninitialize(This->contextStack[i]);
196 ITfContext_Release(This->contextStack[i]);
197 This->contextStack[i] = NULL;
198 }
199
200 ITfThreadMgrEventSink_OnUninitDocumentMgr(This->ThreadMgrSink, iface);
201 return S_OK;
202 }
203
204 if (dwFlags)
205 return E_INVALIDARG;
206
207 if (This->contextStack[1] == NULL) /* Cannot pop last context */
208 return E_FAIL;
209
210 ITfThreadMgrEventSink_OnPopContext(This->ThreadMgrSink,This->contextStack[0]);
211 Context_Uninitialize(This->contextStack[0]);
212 ITfContext_Release(This->contextStack[0]);
213 This->contextStack[0] = This->contextStack[1];
214 This->contextStack[1] = NULL;
215
216 if (This->contextStack[0] == NULL)
217 ITfThreadMgrEventSink_OnUninitDocumentMgr(This->ThreadMgrSink, iface);
218
219 return S_OK;
220}
221
223{
225 TRACE("(%p)\n",This);
226 if (!ppic)
227 return E_INVALIDARG;
228
229 if (This->contextStack[0])
230 ITfContext_AddRef(This->contextStack[0]);
231
232 *ppic = This->contextStack[0];
233
234 return S_OK;
235}
236
238{
240 ITfContext *tgt;
241
242 TRACE("(%p)\n",This);
243 if (!ppic)
244 return E_INVALIDARG;
245
246 if (This->contextStack[1])
247 tgt = This->contextStack[1];
248 else
249 tgt = This->contextStack[0];
250
251 if (tgt)
252 ITfContext_AddRef(tgt);
253
254 *ppic = tgt;
255
256 return S_OK;
257}
258
260{
262 TRACE("(%p) %p\n",This,ppEnum);
263 return EnumTfContext_Constructor(This, ppEnum);
264}
265
266static const ITfDocumentMgrVtbl DocumentMgrVtbl =
267{
277};
278
280{
282 return ITfDocumentMgr_QueryInterface(&This->ITfDocumentMgr_iface, iid, ppvOut);
283}
284
286{
288 return ITfDocumentMgr_AddRef(&This->ITfDocumentMgr_iface);
289}
290
292{
294 return ITfDocumentMgr_Release(&This->ITfDocumentMgr_iface);
295}
296
297/*****************************************************
298 * ITfSource functions
299 *****************************************************/
301 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
302{
304
305 TRACE("(%p) %s %p %p\n", This, debugstr_guid(riid), punk, pdwCookie);
306
307 if (!riid || !punk || !pdwCookie)
308 return E_INVALIDARG;
309
310 if (IsEqualIID(riid, &IID_ITfTransitoryExtensionSink))
311 {
312 WARN("semi-stub for ITfTransitoryExtensionSink: callback won't be used.\n");
313 return advise_sink(&This->TransitoryExtensionSink, &IID_ITfTransitoryExtensionSink,
314 COOKIE_MAGIC_DMSINK, punk, pdwCookie);
315 }
316
317 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
318 return E_NOTIMPL;
319}
320
322{
324
325 TRACE("(%p) %x\n",This,pdwCookie);
326
328 return E_INVALIDARG;
329
330 return unadvise_sink(pdwCookie);
331}
332
333static const ITfSourceVtbl DocumentMgrSourceVtbl =
334{
340};
341
343{
345
347 if (This == NULL)
348 return E_OUTOFMEMORY;
349
350 This->ITfDocumentMgr_iface.lpVtbl = &DocumentMgrVtbl;
351 This->ITfSource_iface.lpVtbl = &DocumentMgrSourceVtbl;
352 This->refCount = 1;
353 This->ThreadMgrSink = ThreadMgrSink;
354 list_init(&This->TransitoryExtensionSink);
355
356 CompartmentMgr_Constructor((IUnknown*)&This->ITfDocumentMgr_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
357
358 *ppOut = &This->ITfDocumentMgr_iface;
359 TRACE("returning %p\n", *ppOut);
360 return S_OK;
361}
362
363/**************************************************
364 * IEnumTfContexts implementation
365 **************************************************/
367{
368 TRACE("destroying %p\n", This);
370}
371
373{
375 *ppvOut = NULL;
376
377 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfContexts))
378 {
379 *ppvOut = &This->IEnumTfContexts_iface;
380 }
381
382 if (*ppvOut)
383 {
384 IEnumTfContexts_AddRef(iface);
385 return S_OK;
386 }
387
388 WARN("unsupported interface: %s\n", debugstr_guid(iid));
389 return E_NOINTERFACE;
390}
391
393{
395 return InterlockedIncrement(&This->refCount);
396}
397
399{
401 ULONG ret;
402
403 ret = InterlockedDecrement(&This->refCount);
404 if (ret == 0)
406 return ret;
407}
408
410 ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched)
411{
413 ULONG fetched = 0;
414
415 TRACE("(%p)\n",This);
416
417 if (rgContext == NULL) return E_POINTER;
418
419 while (fetched < ulCount)
420 {
421 if (This->index > 1)
422 break;
423
424 if (!This->docmgr->contextStack[This->index])
425 break;
426
427 *rgContext = This->docmgr->contextStack[This->index];
428 ITfContext_AddRef(*rgContext);
429
430 ++This->index;
431 ++fetched;
432 ++rgContext;
433 }
434
435 if (pcFetched) *pcFetched = fetched;
436 return fetched == ulCount ? S_OK : S_FALSE;
437}
438
440{
442 TRACE("(%p)\n",This);
443 This->index += celt;
444 return S_OK;
445}
446
448{
450 TRACE("(%p)\n",This);
451 This->index = 0;
452 return S_OK;
453}
454
456 IEnumTfContexts **ppenum)
457{
459 HRESULT res;
460
461 TRACE("(%p)\n",This);
462
463 if (ppenum == NULL) return E_POINTER;
464
465 res = EnumTfContext_Constructor(This->docmgr, ppenum);
466 if (SUCCEEDED(res))
467 {
468 EnumTfContext *new_This = impl_from_IEnumTfContexts(*ppenum);
469 new_This->index = This->index;
470 }
471 return res;
472}
473
474static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl ={
478
483};
484
486{
488
490 if (This == NULL)
491 return E_OUTOFMEMORY;
492
493 This->IEnumTfContexts_iface.lpVtbl = &IEnumTfContexts_Vtbl;
494 This->refCount = 1;
495 This->docmgr = mgr;
496
497 *ppOut = &This->IEnumTfContexts_iface;
498 TRACE("returning %p\n", *ppOut);
499 return S_OK;
500}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
static void list_init(struct list_entry *head)
Definition: list.h:51
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
Definition: list.h:37
HRESULT CompartmentMgr_Destructor(ITfCompartmentMgr *iface)
HRESULT CompartmentMgr_Constructor(IUnknown *pUnkOuter, REFIID riid, IUnknown **ppOut)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#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
HRESULT Context_Uninitialize(ITfContext *iface)
Definition: context.c:1121
HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore)
Definition: context.c:1047
HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager)
Definition: context.c:1109
static HRESULT WINAPI DocumentMgr_QueryInterface(ITfDocumentMgr *iface, REFIID iid, LPVOID *ppvOut)
Definition: documentmgr.c:99
static ULONG WINAPI DocumentMgr_Release(ITfDocumentMgr *iface)
Definition: documentmgr.c:133
static DocumentMgr * impl_from_ITfDocumentMgr(ITfDocumentMgr *iface)
Definition: documentmgr.c:63
static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic)
Definition: documentmgr.c:157
static HRESULT WINAPI DocumentMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
Definition: documentmgr.c:321
static HRESULT WINAPI DocumentMgrSource_AdviseSink(ITfSource *iface, REFIID riid, IUnknown *punk, DWORD *pdwCookie)
Definition: documentmgr.c:300
static ULONG WINAPI EnumTfContext_Release(IEnumTfContexts *iface)
Definition: documentmgr.c:398
static HRESULT WINAPI EnumTfContext_Next(IEnumTfContexts *iface, ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched)
Definition: documentmgr.c:409
static const ITfSourceVtbl DocumentMgrSourceVtbl
Definition: documentmgr.c:333
static HRESULT WINAPI DocumentMgr_EnumContexts(ITfDocumentMgr *iface, IEnumTfContexts **ppEnum)
Definition: documentmgr.c:259
static HRESULT WINAPI EnumTfContext_Reset(IEnumTfContexts *iface)
Definition: documentmgr.c:447
static DocumentMgr * impl_from_ITfSource(ITfSource *iface)
Definition: documentmgr.c:68
static const ITfDocumentMgrVtbl DocumentMgrVtbl
Definition: documentmgr.c:266
static ULONG WINAPI DocumentMgr_AddRef(ITfDocumentMgr *iface)
Definition: documentmgr.c:127
static HRESULT WINAPI DocumentMgr_CreateContext(ITfDocumentMgr *iface, TfClientId tidOwner, DWORD dwFlags, IUnknown *punk, ITfContext **ppic, TfEditCookie *pecTextStore)
Definition: documentmgr.c:147
static ULONG WINAPI DocumentMgrSource_AddRef(ITfSource *iface)
Definition: documentmgr.c:285
static ULONG WINAPI DocumentMgrSource_Release(ITfSource *iface)
Definition: documentmgr.c:291
static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl
Definition: documentmgr.c:474
static ULONG WINAPI EnumTfContext_AddRef(IEnumTfContexts *iface)
Definition: documentmgr.c:392
static HRESULT WINAPI DocumentMgr_GetBase(ITfDocumentMgr *iface, ITfContext **ppic)
Definition: documentmgr.c:237
static EnumTfContext * impl_from_IEnumTfContexts(IEnumTfContexts *iface)
Definition: documentmgr.c:73
struct tagDocumentMgr DocumentMgr
static HRESULT EnumTfContext_Constructor(DocumentMgr *mgr, IEnumTfContexts **ppOut)
Definition: documentmgr.c:485
static HRESULT WINAPI EnumTfContext_Skip(IEnumTfContexts *iface, ULONG celt)
Definition: documentmgr.c:439
struct tagEnumTfContext EnumTfContext
static HRESULT WINAPI EnumTfContext_Clone(IEnumTfContexts *iface, IEnumTfContexts **ppenum)
Definition: documentmgr.c:455
static HRESULT WINAPI DocumentMgrSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
Definition: documentmgr.c:279
HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink *ThreadMgrSink, ITfDocumentMgr **ppOut)
Definition: documentmgr.c:342
static HRESULT WINAPI EnumTfContext_QueryInterface(IEnumTfContexts *iface, REFIID iid, LPVOID *ppvOut)
Definition: documentmgr.c:372
static void EnumTfContext_Destructor(EnumTfContext *This)
Definition: documentmgr.c:366
static HRESULT WINAPI DocumentMgr_Pop(ITfDocumentMgr *iface, DWORD dwFlags)
Definition: documentmgr.c:182
static HRESULT WINAPI DocumentMgr_GetTop(ITfDocumentMgr *iface, ITfContext **ppic)
Definition: documentmgr.c:222
static void DocumentMgr_Destructor(DocumentMgr *This)
Definition: documentmgr.c:78
#define check(expected, result)
Definition: dplayx.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
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
#define debugstr_guid
Definition: kernel32.h:35
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 WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim)
Definition: msctf.c:628
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
DWORD TfEditCookie
Definition: msctf.idl:104
#define COOKIE_MAGIC_DMSINK
void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr) DECLSPEC_HIDDEN
Definition: threadmgr.c:1537
long LONG
Definition: pedump.c:60
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define TRACE(s)
Definition: solgame.cpp:4
ITfThreadMgrEventSink * ThreadMgrSink
Definition: documentmgr.c:48
ITfSource ITfSource_iface
Definition: documentmgr.c:41
ITfDocumentMgr ITfDocumentMgr_iface
Definition: documentmgr.c:40
ITfContext * contextStack[2]
Definition: documentmgr.c:47
struct list TransitoryExtensionSink
Definition: documentmgr.c:50
ITfCompartmentMgr * CompartmentMgr
Definition: documentmgr.c:45
IEnumTfContexts IEnumTfContexts_iface
Definition: documentmgr.c:54
DocumentMgr * docmgr
Definition: documentmgr.c:58
Definition: time.h:68
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
int ret
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_POINTER
Definition: winerror.h:2365