fusion: CompareAssemblyIdentity() and GetAssemblyIdentityFromFile() are unused stubs...
[wine] / dlls / msctf / context.c
1 /*
2  *  ITfContext 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 "olectl.h"
36
37 #include "wine/unicode.h"
38 #include "wine/list.h"
39
40 #include "msctf.h"
41 #include "msctf_internal.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
44
45 typedef struct tagContextSink {
46     struct list         entry;
47     union {
48         /* Context Sinks */
49         IUnknown            *pIUnknown;
50         /* ITfContextKeyEventSink  *pITfContextKeyEventSink; */
51         /* ITfEditTransactionSink  *pITfEditTransactionSink; */
52         /* ITfStatusSink           *pITfStatusSink; */
53         ITfTextEditSink     *pITfTextEditSink;
54         /* ITfTextLayoutSink       *pITfTextLayoutSink; */
55     } interfaces;
56 } ContextSink;
57
58 typedef struct tagContext {
59     const ITfContextVtbl *ContextVtbl;
60     const ITfSourceVtbl *SourceVtbl;
61     /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
62     /* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
63     /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
64     /* const ITfInsertAtSelectionVtbl *InsertAtSelectionVtbl; */
65     /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
66     /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
67     /* const ITfSourceSingleVtbl *SourceSingleVtbl; */
68     LONG refCount;
69
70     TfClientId tidOwner;
71
72     ITextStoreACP   *pITextStoreACP;
73     ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
74
75     ITextStoreACPSink *pITextStoreACPSink;
76
77     /* kept as separate lists to reduce unnecessary iterations */
78     struct list     pContextKeyEventSink;
79     struct list     pEditTransactionSink;
80     struct list     pStatusSink;
81     struct list     pTextEditSink;
82     struct list     pTextLayoutSink;
83
84 } Context;
85
86
87 typedef struct tagTextStoreACPSink {
88     const ITextStoreACPSinkVtbl *TextStoreACPSinkVtbl;
89     /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
90     LONG refCount;
91
92     Context *pContext;
93 } TextStoreACPSink;
94
95
96 static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext);
97
98 static inline Context *impl_from_ITfSourceVtbl(ITfSource *iface)
99 {
100     return (Context *)((char *)iface - FIELD_OFFSET(Context,SourceVtbl));
101 }
102
103 static void free_sink(ContextSink *sink)
104 {
105         IUnknown_Release(sink->interfaces.pIUnknown);
106         HeapFree(GetProcessHeap(),0,sink);
107 }
108
109 static void Context_Destructor(Context *This)
110 {
111     struct list *cursor, *cursor2;
112     TRACE("destroying %p\n", This);
113
114     if (This->pITextStoreACPSink)
115     {
116         ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink);
117         ITextStoreACPSink_Release(This->pITextStoreACPSink);
118     }
119
120     if (This->pITextStoreACP)
121         ITextStoreACPSink_Release(This->pITextStoreACP);
122
123     if (This->pITfContextOwnerCompositionSink)
124         ITextStoreACPSink_Release(This->pITfContextOwnerCompositionSink);
125
126     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink)
127     {
128         ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
129         list_remove(cursor);
130         free_sink(sink);
131     }
132     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pEditTransactionSink)
133     {
134         ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
135         list_remove(cursor);
136         free_sink(sink);
137     }
138     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pStatusSink)
139     {
140         ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
141         list_remove(cursor);
142         free_sink(sink);
143     }
144     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextEditSink)
145     {
146         ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
147         list_remove(cursor);
148         free_sink(sink);
149     }
150     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextLayoutSink)
151     {
152         ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
153         list_remove(cursor);
154         free_sink(sink);
155     }
156
157     HeapFree(GetProcessHeap(),0,This);
158 }
159
160 static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut)
161 {
162     Context *This = (Context *)iface;
163     *ppvOut = NULL;
164
165     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext))
166     {
167         *ppvOut = This;
168     }
169     else if (IsEqualIID(iid, &IID_ITfSource))
170     {
171         *ppvOut = &This->SourceVtbl;
172     }
173
174     if (*ppvOut)
175     {
176         IUnknown_AddRef(iface);
177         return S_OK;
178     }
179
180     WARN("unsupported interface: %s\n", debugstr_guid(iid));
181     return E_NOINTERFACE;
182 }
183
184 static ULONG WINAPI Context_AddRef(ITfContext *iface)
185 {
186     Context *This = (Context *)iface;
187     return InterlockedIncrement(&This->refCount);
188 }
189
190 static ULONG WINAPI Context_Release(ITfContext *iface)
191 {
192     Context *This = (Context *)iface;
193     ULONG ret;
194
195     ret = InterlockedDecrement(&This->refCount);
196     if (ret == 0)
197         Context_Destructor(This);
198     return ret;
199 }
200
201 /*****************************************************
202  * ITfContext functions
203  *****************************************************/
204 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
205         TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
206         HRESULT *phrSession)
207 {
208     Context *This = (Context *)iface;
209     FIXME("STUB:(%p)\n",This);
210     return E_NOTIMPL;
211 }
212
213 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
214          TfClientId tid,
215          BOOL *pfWriteSession)
216 {
217     Context *This = (Context *)iface;
218     FIXME("STUB:(%p)\n",This);
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI Context_GetSelection (ITfContext *iface,
223         TfEditCookie ec, ULONG ulIndex, ULONG ulCount,
224         TF_SELECTION *pSelection, ULONG *pcFetched)
225 {
226     Context *This = (Context *)iface;
227     FIXME("STUB:(%p)\n",This);
228     return E_NOTIMPL;
229 }
230
231 static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
232         TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection)
233 {
234     Context *This = (Context *)iface;
235     FIXME("STUB:(%p)\n",This);
236     return E_NOTIMPL;
237 }
238
239 static HRESULT WINAPI Context_GetStart (ITfContext *iface,
240         TfEditCookie ec, ITfRange **ppStart)
241 {
242     Context *This = (Context *)iface;
243     FIXME("STUB:(%p)\n",This);
244     return E_NOTIMPL;
245 }
246
247 static HRESULT WINAPI Context_GetEnd (ITfContext *iface,
248         TfEditCookie ec, ITfRange **ppEnd)
249 {
250     Context *This = (Context *)iface;
251     FIXME("STUB:(%p)\n",This);
252     return E_NOTIMPL;
253 }
254
255 static HRESULT WINAPI Context_GetActiveView (ITfContext *iface,
256   ITfContextView **ppView)
257 {
258     Context *This = (Context *)iface;
259     FIXME("STUB:(%p)\n",This);
260     return E_NOTIMPL;
261 }
262
263 static HRESULT WINAPI Context_EnumViews (ITfContext *iface,
264         IEnumTfContextViews **ppEnum)
265 {
266     Context *This = (Context *)iface;
267     FIXME("STUB:(%p)\n",This);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI Context_GetStatus (ITfContext *iface,
272         TF_STATUS *pdcs)
273 {
274     Context *This = (Context *)iface;
275     FIXME("STUB:(%p)\n",This);
276     return E_NOTIMPL;
277 }
278
279 static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
280         REFGUID guidProp, ITfProperty **ppProp)
281 {
282     Context *This = (Context *)iface;
283     FIXME("STUB:(%p)\n",This);
284     return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface,
288         REFGUID guidProp, ITfReadOnlyProperty **ppProp)
289 {
290     Context *This = (Context *)iface;
291     FIXME("STUB:(%p)\n",This);
292     return E_NOTIMPL;
293 }
294
295 static HRESULT WINAPI Context_TrackProperties (ITfContext *iface,
296         const GUID **prgProp, ULONG cProp, const GUID **prgAppProp,
297         ULONG cAppProp, ITfReadOnlyProperty **ppProperty)
298 {
299     Context *This = (Context *)iface;
300     FIXME("STUB:(%p)\n",This);
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface,
305         IEnumTfProperties **ppEnum)
306 {
307     Context *This = (Context *)iface;
308     FIXME("STUB:(%p)\n",This);
309     return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface,
313         ITfDocumentMgr **ppDm)
314 {
315     Context *This = (Context *)iface;
316     FIXME("STUB:(%p)\n",This);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface,
321         TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup)
322 {
323     Context *This = (Context *)iface;
324     FIXME("STUB:(%p)\n",This);
325     return E_NOTIMPL;
326 }
327
328 static const ITfContextVtbl Context_ContextVtbl =
329 {
330     Context_QueryInterface,
331     Context_AddRef,
332     Context_Release,
333
334     Context_RequestEditSession,
335     Context_InWriteSession,
336     Context_GetSelection,
337     Context_SetSelection,
338     Context_GetStart,
339     Context_GetEnd,
340     Context_GetActiveView,
341     Context_EnumViews,
342     Context_GetStatus,
343     Context_GetProperty,
344     Context_GetAppProperty,
345     Context_TrackProperties,
346     Context_EnumProperties,
347     Context_GetDocumentMgr,
348     Context_CreateRangeBackup
349 };
350
351 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
352 {
353     Context *This = impl_from_ITfSourceVtbl(iface);
354     return Context_QueryInterface((ITfContext *)This, iid, *ppvOut);
355 }
356
357 static ULONG WINAPI Source_AddRef(ITfSource *iface)
358 {
359     Context *This = impl_from_ITfSourceVtbl(iface);
360     return Context_AddRef((ITfContext *)This);
361 }
362
363 static ULONG WINAPI Source_Release(ITfSource *iface)
364 {
365     Context *This = impl_from_ITfSourceVtbl(iface);
366     return Context_Release((ITfContext *)This);
367 }
368
369 /*****************************************************
370  * ITfSource functions
371  *****************************************************/
372 static WINAPI HRESULT ContextSource_AdviseSink(ITfSource *iface,
373         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
374 {
375     ContextSink *es;
376     Context *This = impl_from_ITfSourceVtbl(iface);
377     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
378
379     if (!riid || !punk || !pdwCookie)
380         return E_INVALIDARG;
381
382     if (IsEqualIID(riid, &IID_ITfTextEditSink))
383     {
384         es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink));
385         if (!es)
386             return E_OUTOFMEMORY;
387         if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&es->interfaces.pITfTextEditSink)))
388         {
389             HeapFree(GetProcessHeap(),0,es);
390             return CONNECT_E_CANNOTCONNECT;
391         }
392         list_add_head(&This->pTextEditSink ,&es->entry);
393         *pdwCookie = generate_Cookie(COOKIE_MAGIC_CONTEXTSINK, es);
394     }
395     else
396     {
397         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
398         return E_NOTIMPL;
399     }
400
401     TRACE("cookie %x\n",*pdwCookie);
402     return S_OK;
403 }
404
405 static WINAPI HRESULT ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
406 {
407     ContextSink *sink;
408     Context *This = impl_from_ITfSourceVtbl(iface);
409
410     TRACE("(%p) %x\n",This,pdwCookie);
411
412     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK)
413         return E_INVALIDARG;
414
415     sink = (ContextSink*)remove_Cookie(pdwCookie);
416     if (!sink)
417         return CONNECT_E_NOCONNECTION;
418
419     list_remove(&sink->entry);
420     free_sink(sink);
421
422     return S_OK;
423 }
424
425 static const ITfSourceVtbl Context_SourceVtbl =
426 {
427     Source_QueryInterface,
428     Source_AddRef,
429     Source_Release,
430
431     ContextSource_AdviseSink,
432     ContextSource_UnadviseSink,
433 };
434
435 HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore)
436 {
437     Context *This;
438
439     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context));
440     if (This == NULL)
441         return E_OUTOFMEMORY;
442
443     TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
444
445     This->ContextVtbl= &Context_ContextVtbl;
446     This->SourceVtbl = &Context_SourceVtbl;
447     This->refCount = 1;
448     This->tidOwner = tidOwner;
449
450     if (punk)
451     {
452         if (SUCCEEDED(IUnknown_QueryInterface(punk, &IID_ITextStoreACP,
453                           (LPVOID*)&This->pITextStoreACP)))
454         {
455             if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This)))
456                 ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink,
457                                         (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS);
458         }
459
460         IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink,
461                                 (LPVOID*)&This->pITfContextOwnerCompositionSink);
462
463         if (!This->pITextStoreACP && !This->pITfContextOwnerCompositionSink)
464             FIXME("Unhandled pUnk\n");
465     }
466
467     TRACE("returning %p\n", This);
468     *ppOut = (ITfContext*)This;
469     /* FIXME */
470     *pecTextStore = 0xdeaddead;
471
472     list_init(&This->pContextKeyEventSink);
473     list_init(&This->pEditTransactionSink);
474     list_init(&This->pStatusSink);
475     list_init(&This->pTextEditSink);
476     list_init(&This->pTextLayoutSink);
477
478     return S_OK;
479 }
480
481 /**************************************************************************
482  *  ITextStoreACPSink
483  **************************************************************************/
484
485 static void TextStoreACPSink_Destructor(TextStoreACPSink *This)
486 {
487     TRACE("destroying %p\n", This);
488     HeapFree(GetProcessHeap(),0,This);
489 }
490
491 static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut)
492 {
493     TextStoreACPSink *This = (TextStoreACPSink *)iface;
494     *ppvOut = NULL;
495
496     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink))
497     {
498         *ppvOut = This;
499     }
500
501     if (*ppvOut)
502     {
503         IUnknown_AddRef(iface);
504         return S_OK;
505     }
506
507     WARN("unsupported interface: %s\n", debugstr_guid(iid));
508     return E_NOINTERFACE;
509 }
510
511 static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface)
512 {
513     TextStoreACPSink *This = (TextStoreACPSink *)iface;
514     return InterlockedIncrement(&This->refCount);
515 }
516
517 static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface)
518 {
519     TextStoreACPSink *This = (TextStoreACPSink *)iface;
520     ULONG ret;
521
522     ret = InterlockedDecrement(&This->refCount);
523     if (ret == 0)
524         TextStoreACPSink_Destructor(This);
525     return ret;
526 }
527
528 /*****************************************************
529  * ITextStoreACPSink functions
530  *****************************************************/
531
532 static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface,
533         DWORD dwFlags, const TS_TEXTCHANGE *pChange)
534 {
535     TextStoreACPSink *This = (TextStoreACPSink *)iface;
536     FIXME("STUB:(%p)\n",This);
537     return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface)
541 {
542     TextStoreACPSink *This = (TextStoreACPSink *)iface;
543     FIXME("STUB:(%p)\n",This);
544     return E_NOTIMPL;
545 }
546
547 static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface,
548     TsLayoutCode lcode, TsViewCookie vcView)
549 {
550     TextStoreACPSink *This = (TextStoreACPSink *)iface;
551     FIXME("STUB:(%p)\n",This);
552     return E_NOTIMPL;
553 }
554
555 static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface,
556         DWORD dwFlags)
557 {
558     TextStoreACPSink *This = (TextStoreACPSink *)iface;
559     FIXME("STUB:(%p)\n",This);
560     return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface,
564         LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs)
565 {
566     TextStoreACPSink *This = (TextStoreACPSink *)iface;
567     FIXME("STUB:(%p)\n",This);
568     return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface,
572         DWORD dwLockFlags)
573 {
574     TextStoreACPSink *This = (TextStoreACPSink *)iface;
575     FIXME("STUB:(%p)\n",This);
576     return E_NOTIMPL;
577 }
578
579 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
580 {
581     TextStoreACPSink *This = (TextStoreACPSink *)iface;
582     FIXME("STUB:(%p)\n",This);
583     return E_NOTIMPL;
584 }
585
586 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface)
587 {
588     TextStoreACPSink *This = (TextStoreACPSink *)iface;
589     FIXME("STUB:(%p)\n",This);
590     return E_NOTIMPL;
591 }
592
593 static const ITextStoreACPSinkVtbl TextStoreACPSink_TextStoreACPSinkVtbl =
594 {
595     TextStoreACPSink_QueryInterface,
596     TextStoreACPSink_AddRef,
597     TextStoreACPSink_Release,
598
599     TextStoreACPSink_OnTextChange,
600     TextStoreACPSink_OnSelectionChange,
601     TextStoreACPSink_OnLayoutChange,
602     TextStoreACPSink_OnStatusChange,
603     TextStoreACPSink_OnAttrsChange,
604     TextStoreACPSink_OnLockGranted,
605     TextStoreACPSink_OnStartEditTransaction,
606     TextStoreACPSink_OnEndEditTransaction
607 };
608
609 static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext)
610 {
611     TextStoreACPSink *This;
612
613     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextStoreACPSink));
614     if (This == NULL)
615         return E_OUTOFMEMORY;
616
617     This->TextStoreACPSinkVtbl= &TextStoreACPSink_TextStoreACPSinkVtbl;
618     This->refCount = 1;
619
620     This->pContext = pContext;
621
622     TRACE("returning %p\n", This);
623     *ppOut = (ITextStoreACPSink*)This;
624     return S_OK;
625 }