File: Core\CSharp\System\Windows\Input\DefaultTextStoreTextComposition.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//---------------------------------------------------------------------------
//
// <copyright file=DefaultTextStoreTextComposition.cs company=Microsoft>
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
// 
// Description: DefaultTextStoreTextComposition class is the composition 
//              object for the input in DefaultTextStore.
//              Cicero's composition injected to DefaulteTextStore is
//              represent by this DefaultTextStoreTextComposition.
//              This has custom Complete method to control
//              Cicero's composiiton.
//
// History:  
//  04/01/2004 : yutakas created
//
//---------------------------------------------------------------------------
 
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Threading;
using System.Windows;
using System.Security; 
 
using MS.Win32;
 
namespace System.Windows.Input
{
 
    /// <summary>
    ///     DefaultTextStoreTextComposition class implements Complete for 
    ///     the composition in DefaultTextStore.
    /// </summary>
    internal class DefaultTextStoreTextComposition : TextComposition
    {
 
        //------------------------------------------------------
        //
        //  ctor
        //
        //------------------------------------------------------
 
        /// <summary>
        ///     ctor
        /// </summary>
        ///<SecurityNote>
        ///     Critical - calls base ctor - which in turn stores the inputmanager that's critical. 
        ///</SecurityNote> 
        [SecurityCritical]
        internal DefaultTextStoreTextComposition(InputManager inputManager, IInputElement source, string text, TextCompositionAutoComplete autoComplete) : base(inputManager, source, text, autoComplete)
        {
        }
 
        //------------------------------------------------------
        //
        //  Public Interface Methods 
        //
        //------------------------------------------------------
 
        /// <summary>
        ///     Finalize the composition.
        ///     This does not call base.Complete() because TextComposition.Complete()
        ///     will call TextServicesManager.CompleteComposition() directly to generate TextCompositionEvent.
        ///     We finalize Cicero's composition and DefaultTextStore will automatically
        ///     generate the proper TextComposition events.
        /// </summary>
        /// <SecurityNote>
        ///   Critical: This completes the composition and in doing so calls GetTransitionaryContext which gives it ITfContext
        ///   TreatAsSafe: The context is not exposed, neither are the other members
        /// </SecurityNote>
        [SecurityCritical,SecurityTreatAsSafe]
        public override void Complete()
        {
//             VerifyAccess();
 
            UnsafeNativeMethods.ITfContext context = GetTransitoryContext();
            UnsafeNativeMethods.ITfContextOwnerCompositionServices compositionService = context as UnsafeNativeMethods.ITfContextOwnerCompositionServices;
            UnsafeNativeMethods.ITfCompositionView composition = GetComposition(context);
            
            if (composition != null)
            {
                // Terminate composition if there is a composition view.
                compositionService.TerminateComposition(composition);
                Marshal.ReleaseComObject(composition);
            }
 
            Marshal.ReleaseComObject(context);
 
        }
 
        //------------------------------------------------------
        //
        //  private Methods 
        //
        //------------------------------------------------------
 
        /// <summary>
        ///     Get the base ITfContext of the transitory document.
        /// </summary>
        /// <SecurityNote>
        ///   Critical: This exposes ITfContext which has unsecure methods
        /// </SecurityNote>
        [SecurityCritical]
        private UnsafeNativeMethods.ITfContext GetTransitoryContext()
        {
            DefaultTextStore defaultTextStore = DefaultTextStore.Current;
            UnsafeNativeMethods.ITfDocumentMgr doc = defaultTextStore.TransitoryDocumentManager;
            UnsafeNativeMethods.ITfContext context;
 
            doc.GetBase(out context);
 
            Marshal.ReleaseComObject(doc);
            return context;
        }
 
        /// <summary>
        ///     Get ITfContextView of the context.
        /// </summary>
        ///<SecurityNote>
        ///     Critical: calls Marshal.ReleaseComObject which has a LinkDemand
        ///	TreatAsSafe: can't pass in arbitrary COM object to release
        ///</SecurityNote> 
        [SecurityCritical, SecurityTreatAsSafe]
        private UnsafeNativeMethods.ITfCompositionView GetComposition(UnsafeNativeMethods.ITfContext context)
        {
            UnsafeNativeMethods.ITfContextComposition contextComposition;
            UnsafeNativeMethods.IEnumITfCompositionView enumCompositionView;
            UnsafeNativeMethods.ITfCompositionView[] compositionViews = new UnsafeNativeMethods.ITfCompositionView[1];
            int fetched;
          
            contextComposition = (UnsafeNativeMethods.ITfContextComposition)context;
            contextComposition.EnumCompositions(out enumCompositionView);
 
            enumCompositionView.Next(1, compositionViews, out fetched);
 
            Marshal.ReleaseComObject(enumCompositionView);
            return compositionViews[0];
 
        }
    }
}