ReactOS 0.4.16-dev-1311-g81a4d83
documentmgr.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS CTF
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Implementation of ITfDocumentMgr and IEnumTfContexts
5 * COPYRIGHT: Copyright 2009 Aric Stewart, CodeWeavers
6 * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
7 */
8
9#include <initguid.h>
10#include <windef.h>
11#include <winbase.h>
12#include <oleauto.h>
13#include <msctf.h>
14#include <msctf_undoc.h>
15#include <wine/list.h>
16
17// Cicero
18#include <cicbase.h>
19
20#include "documentmgr.h"
21#include "msctf_internal.h"
22
23#include <wine/debug.h>
25
28
30// CDocumentMgr
31
33 : m_cRefs(1)
34 , m_pCompartmentMgr(NULL)
35 , m_pThreadMgrSink(threadMgrSink)
36{
38
40
41 ITfDocumentMgr *pDocMgr = static_cast<ITfDocumentMgr *>(this);
42 ITfCompartmentMgr **ppCompMgr = static_cast<ITfCompartmentMgr **>(&m_pCompartmentMgr);
43 CompartmentMgr_Constructor(pDocMgr, IID_IUnknown, reinterpret_cast<IUnknown **>(ppCompMgr));
44}
45
47{
48 TRACE("destroying %p\n", this);
49
52 if (tm)
53 {
55 tm->Release();
56 }
57
58 if (m_contextStack[0])
59 {
62 }
63
64 if (m_contextStack[1])
65 {
68 }
69
71
73 {
76 }
77}
78
81 _In_ ITfThreadMgrEventSink *pThreadMgrSink,
82 _Out_ ITfDocumentMgr **ppOut)
83{
84 if (!ppOut)
85 {
86 ERR("!ppOut\n");
87 return E_POINTER;
88 }
89
90 if (!pThreadMgrSink)
91 {
92 ERR("!pThreadMgrSink\n");
93 return E_INVALIDARG;
94 }
95
96 CDocumentMgr *This = new(cicNoThrow) CDocumentMgr(pThreadMgrSink);
97 if (!This)
98 {
99 ERR("E_OUTOFMEMORY\n");
100 return E_OUTOFMEMORY;
101 }
102
103 *ppOut = static_cast<ITfDocumentMgr *>(This);
104 TRACE("returning %p\n", *ppOut);
105 return S_OK;
106}
107
109{
110 TRACE("%p -> (%s, %p)\n", this, wine_dbgstr_guid(&iid), ppvObject);
111 *ppvObject = NULL;
112
113 if (iid == IID_IUnknown || iid == IID_ITfDocumentMgr)
114 *ppvObject = static_cast<ITfDocumentMgr *>(this);
115 else if (iid == IID_ITfSource)
116 *ppvObject = static_cast<ITfSource *>(this);
117 else if (iid == IID_ITfCompartmentMgr)
119
120 if (*ppvObject)
121 {
122 AddRef();
123 return S_OK;
124 }
125
126 ERR("E_NOINTERFACE: %s\n", wine_dbgstr_guid(&iid));
127 return E_NOINTERFACE;
128}
129
131{
132 TRACE("%p -> ()\n", this);
133 return ::InterlockedIncrement(&m_cRefs);
134}
135
137{
138 TRACE("%p -> ()\n", this);
140 if (!ret)
141 delete this;
142 return ret;
143}
144
147 TfClientId tidOwner,
149 IUnknown *punk,
150 ITfContext **ppic,
151 TfEditCookie *pecTextStore)
152{
153 TRACE("%p -> (%d, 0x%lX, %p, %p, %p)\n", this, tidOwner, dwFlags, punk, ppic, pecTextStore);
154 return Context_Constructor(tidOwner, punk, this, ppic, pecTextStore);
155}
156
158{
159 TRACE("%p -> (%p)\n", this, pic);
160
161 if (m_contextStack[1]) /* Full */
162 {
163 ERR("TF_E_STACKFULL\n");
164 return TF_E_STACKFULL;
165 }
166
167 if (!pic)
168 {
169 ERR("!pic\n");
170 return E_INVALIDARG;
171 }
172
174 HRESULT hr = pic->QueryInterface(IID_ITfContext, reinterpret_cast<LPVOID *>(&check));
175 if (FAILED(hr))
176 {
177 ERR("hr: 0x%lX\n", hr);
178 return E_INVALIDARG;
179 }
180
181 if (!m_contextStack[0])
183
186
189
190 return S_OK;
191}
192
194{
195 TRACE("%p -> (0x%lX)\n", this, dwFlags);
196
197 if (dwFlags == TF_POPF_ALL)
198 {
199 for (SIZE_T i = 0; i < _countof(m_contextStack); i++)
200 {
201 if (!m_contextStack[i])
202 continue;
203
208 }
209
211 return S_OK;
212 }
213
214 if (dwFlags)
215 {
216 ERR("E_INVALIDARG: 0x%lX\n", dwFlags);
217 return E_INVALIDARG;
218 }
219
220 if (!m_contextStack[1]) // Cannot pop last context
221 {
222 ERR("!m_contextStack[1]\n");
223 return E_FAIL;
224 }
225
228
229 if (m_contextStack[0])
231
233 m_contextStack[1] = NULL;
234
235 if (!m_contextStack[0])
237
238 return S_OK;
239}
240
242{
243 TRACE("%p -> (%p)\n", this, ppic);
244
245 if (!ppic)
246 {
247 ERR("!ppic\n");
248 return E_INVALIDARG;
249 }
250
251 if (m_contextStack[0])
253
254 *ppic = m_contextStack[0];
255 return S_OK;
256}
257
259{
260 TRACE("%p -> (%p)\n", this, ppic);
261
262 if (!ppic)
263 {
264 ERR("!ppic\n");
265 return E_INVALIDARG;
266 }
267
269 *ppic = target;
270 if (target)
271 target->AddRef();
272 return S_OK;
273}
274
276{
277 TRACE("%p -> (%p)\n", this, ppEnum);
278 return EnumTfContext_Constructor(this, ppEnum);
279}
280
282{
283 TRACE("%p -> (%s, %p, %p)\n", this, wine_dbgstr_guid(&riid), punk, pdwCookie);
284
285 if (!punk || !pdwCookie)
286 return E_INVALIDARG;
287
288 if (riid != IID_ITfTransitoryExtensionSink)
289 {
290 FIXME("E_NOTIMPL: %s\n", wine_dbgstr_guid(&riid));
291 return E_NOTIMPL;
292 }
293
294 return advise_sink(&m_transitoryExtensionSink, IID_ITfTransitoryExtensionSink,
295 COOKIE_MAGIC_DMSINK, punk, pdwCookie);
296
297}
298
300{
301 TRACE("%p -> (%p)\n", this, pdwCookie);
302
303 if (get_Cookie_magic(pdwCookie) != COOKIE_MAGIC_DMSINK)
304 return E_INVALIDARG;
305
306 return unadvise_sink(pdwCookie);
307}
308
310// CEnumTfContext
311
313 : m_cRefs(1)
314 , m_index(0)
315 , m_pDocMgr(mgr)
316{
317 if (mgr)
318 mgr->AddRef();
319}
320
322{
323 if (m_pDocMgr)
324 {
326 m_pDocMgr = NULL;
327 }
328}
329
331{
332 if (!ppOut)
333 {
334 ERR("!ppOut\n");
335 return E_POINTER;
336 }
337
339 if (This == NULL)
340 {
341 ERR("E_OUTOFMEMORY\n");
342 return E_OUTOFMEMORY;
343 }
344
345 *ppOut = static_cast<IEnumTfContexts *>(This);
346 TRACE("returning %p\n", *ppOut);
347 return S_OK;
348}
349
351{
352 TRACE("%p -> (%s, %p)\n", this, wine_dbgstr_guid(&iid), ppvObject);
353
354 *ppvObject = NULL;
355
356 if (iid == IID_IUnknown || iid == IID_IEnumTfContexts)
357 *ppvObject = static_cast<IEnumTfContexts *>(this);
358
359 if (*ppvObject)
360 {
361 AddRef();
362 return S_OK;
363 }
364
365 WARN("E_NOINTERFACE: %s\n", wine_dbgstr_guid(&iid));
366 return E_NOINTERFACE;
367}
368
370{
371 TRACE("%p -> ()\n", this);
372 return ::InterlockedIncrement(&m_cRefs);
373}
374
376{
377 TRACE("%p -> ()\n", this);
379 if (!ret)
380 delete this;
381 return ret;
382}
383
384STDMETHODIMP CEnumTfContext::Next(ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched)
385{
386 TRACE("%p -> (%lu, %p, %p)\n",this, ulCount, rgContext, pcFetched);
387
388 if (!rgContext)
389 {
390 ERR("!rgContext\n");
391 return E_POINTER;
392 }
393
394 ULONG fetched;
395 for (fetched = 0; fetched < ulCount; ++fetched, ++m_index, ++rgContext)
396 {
398 break;
399
401 break;
402
403 *rgContext = m_pDocMgr->m_contextStack[m_index];
404 (*rgContext)->AddRef();
405 }
406
407 if (pcFetched)
408 *pcFetched = fetched;
409
410 return (fetched == ulCount) ? S_OK : S_FALSE;
411}
412
414{
415 TRACE("%p -> (%lu)\n", this, celt);
416 m_index += celt;
417 return S_OK;
418}
419
421{
422 TRACE("%p -> ()\n", this);
423 m_index = 0;
424 return S_OK;
425}
426
428{
429 TRACE("%p -> (%p)\n", this, ppenum);
430
431 if (!ppenum)
432 {
433 ERR("!ppenum\n");
434 return E_POINTER;
435 }
436
438 if (!This)
439 {
440 ERR("E_OUTOFMEMORY\n");
441 return E_OUTOFMEMORY;
442 }
443
444 This->m_index = m_index;
445 *ppenum = This;
446 return S_OK;
447}
448
450
453{
454 return CDocumentMgr::CreateInstance(pThreadMgrSink, ppOut);
455}
456
459{
460 return CEnumTfContext::CreateInstance(mgr, ppOut);
461}
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
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 void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define EXTERN_C
Definition: basetyps.h:12
#define STDMETHODIMP
Definition: basetyps.h:43
#define STDMETHODIMP_(t)
Definition: basetyps.h:44
const GUID IID_IUnknown
#define cicNoThrow
Definition: cicbase.h:34
STDMETHODIMP Push(ITfContext *pic) override
struct list m_transitoryExtensionSink
Definition: documentmgr.h:56
STDMETHODIMP CreateContext(TfClientId tidOwner, DWORD dwFlags, IUnknown *punk, ITfContext **ppic, TfEditCookie *pecTextStore) override
STDMETHODIMP Pop(DWORD dwFlags) override
STDMETHODIMP UnadviseSink(DWORD pdwCookie) override
STDMETHODIMP GetTop(ITfContext **ppic) override
static HRESULT CreateInstance(_In_ ITfThreadMgrEventSink *pThreadMgrSink, _Out_ ITfDocumentMgr **ppOut)
Definition: documentmgr.cpp:80
STDMETHODIMP EnumContexts(IEnumTfContexts **ppEnum) override
ITfThreadMgrEventSink * m_pThreadMgrSink
Definition: documentmgr.h:55
STDMETHODIMP GetBase(ITfContext **ppic) override
STDMETHODIMP QueryInterface(REFIID iid, LPVOID *ppvObject) override
CDocumentMgr(ITfThreadMgrEventSink *threadMgrSink)
Definition: documentmgr.cpp:32
ITfCompartmentMgr * m_pCompartmentMgr
Definition: documentmgr.h:53
STDMETHODIMP AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie) override
ITfContext * m_contextStack[2]
Definition: documentmgr.h:54
virtual ~CDocumentMgr()
Definition: documentmgr.cpp:46
STDMETHODIMP QueryInterface(REFIID iid, LPVOID *ppvObject) override
CDocumentMgr * m_pDocMgr
Definition: documentmgr.h:85
STDMETHODIMP Reset() override
static HRESULT CreateInstance(_In_opt_ CDocumentMgr *mgr, _Out_ IEnumTfContexts **ppOut)
virtual ~CEnumTfContext()
CEnumTfContext(_In_opt_ CDocumentMgr *mgr)
STDMETHODIMP Next(ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched) override
STDMETHODIMP Skip(ULONG celt) override
STDMETHODIMP Clone(IEnumTfContexts **ppenum) override
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
EXTERN_C HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink *pThreadMgrSink, ITfDocumentMgr **ppOut)
EXTERN_C HRESULT EnumTfContext_Constructor(CDocumentMgr *mgr, IEnumTfContexts **ppOut)
#define check(expected, result)
Definition: dplayx.c:32
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum target
Definition: glext.h:7315
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
const DWORD TF_POPF_ALL
Definition: msctf.idl:281
HRESULT OnUninitDocumentMgr([in] ITfDocumentMgr *pdim)
HRESULT OnPopContext([in] ITfContext *pic)
HRESULT OnInitDocumentMgr([in] ITfDocumentMgr *pdim)
HRESULT OnPushContext([in] ITfContext *pic)
ULONG AddRef()
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
ULONG Release()
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
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:630
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:87
DWORD TfEditCookie
Definition: msctf.idl:86
#define COOKIE_MAGIC_DMSINK
void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr) DECLSPEC_HIDDEN
Definition: threadmgr.c:1537
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define REFIID
Definition: guiddef.h:118
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
HRESULT hr
Definition: shlfolder.c:183
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
Definition: time.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59
int ret
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_POINTER
Definition: winerror.h:2365