TextServicesContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Input / TextServicesContext.cs / 1 / TextServicesContext.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Manages Text Services Framework state. 
// 
// History:
//  07/16/2003 : benwest - Ported from .net tree. 
//
//---------------------------------------------------------------------------

using System; 
using System.Runtime.InteropServices;
using System.Threading; 
using System.Windows.Threading; 
using System.Security;
using System.Security.Permissions; 
using System.Diagnostics;
using System.Collections;
using MS.Utility;
using MS.Win32; 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper 
 
namespace System.Windows.Input
{ 

    //-----------------------------------------------------
    //
    //  TextServicesContext class 
    //
    //----------------------------------------------------- 
 
    /// 
    /// This class manages the ITfThreadMgr, EmptyDim and the reference to 
    /// the default TextStore.
    /// The instance of TextServicesContext class is created per Dispatcher.
    /// 
    ///  
    /// 
    internal class TextServicesContext 
    { 
        //------------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Instantiates a TextServicesContext.
        ///  
        /// 
        /// Critical - accesses AppDomain.DomainUnload event.
        /// SecurityTreatAsSafe - does not accept or reveal any information.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private TextServicesContext() 
        { 
            Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "SetDispatcherThreaad on MTA thread");
            TextServicesContextShutDownListener listener; 

            // Add Dispatcher.Shutdown event handler. We will clean up Cicero's resource
            // when Dispatcher is terminated.
            listener = new TextServicesContextShutDownListener(this, ShutDownEvents.DispatcherShutdown); 

            // Add an event handler for AppDomain unload. 
            // When an AppDomain is unloaded, we won't get the Dispatcher shutdown, 
            // and we'll be called back on a worker thread.
            listener = new TextServicesContextShutDownListener(this, ShutDownEvents.DomainUnload); 
        }

        #endregion Constructors
 
        //------------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 

        #region Internal Methods

        ///  
        /// Releases all unmanaged resources allocated by the
        /// TextServicesContext. 
        ///  
        /// 
        /// if appDomainShutdown == false, this method must be called on the 
        /// Dispatcher thread.  Otherwise, the caller is an AppDomain.Shutdown
        /// listener, and is calling from a worker thread.
        /// 
        ///  
        /// Critical - access thread manager directly
        /// TreatAsSafe - uninitializing would only result in input being dead for the app 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Uninitialize(bool appDomainShutdown) 
        {
            // Unregister DefaultTextStore.
            if (_defaultTextStore != null)
            { 
                StopTransitoryExtension();
                if (_defaultTextStore.DocumentManager != null) 
                { 
                    _defaultTextStore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL);
                    Marshal.ReleaseComObject(_defaultTextStore.DocumentManager); 
                    _defaultTextStore.DocumentManager = null;
                }

                // We can't use tls during AppDomainShutdown -- we're called on 
                // a worker thread.  But we don't need to cleanup in that case
                // either. 
                if (!appDomainShutdown) 
                {
                    InputMethod.Current.DefaultTextStore = null; 
                }

                _defaultTextStore = null;
            } 

            // Free up any remaining textstores. 
            if (_istimactivated == true) 
            {
                // Shut down the thread manager when the last TextStore goes away. 
                // On XP, if we're called on a worker thread (during AppDomain shutdown)
                // we can't call call any methods on _threadManager.  The problem is
                // that there's no proxy registered for ITfThreadMgr on OS versions
                // previous to Vista.  Not calling Deactivate will leak the IMEs, but 
                // in practice (1) they're singletons, so it's not unbounded; and (2)
                // most applications will share the thread with other AppDomains that 
                // have a UI, in which case the IME won't be released until the process 
                // shuts down in any case.  In theory we could also work around this
                // problem by creating our own XP proxy/stub implementation, which would 
                // be added to WPF setup....
                if (!appDomainShutdown || System.Environment.OSVersion.Version.Major >= 6)
                {
                    _threadManager.Value.Deactivate(); 
                }
                _istimactivated = false; 
            } 

            // Release the empty dim. 
            if (_dimEmpty != null)
            {
                if (_dimEmpty.Value != null)
                { 
                    Marshal.ReleaseComObject(_dimEmpty.Value);
                } 
                _dimEmpty = null; 
            }
 
            // Release the ThreadManager.
            // We don't do this in UnregisterTextStore because someone may have
            // called get_ThreadManager after the last TextStore was unregistered.
            if (_threadManager != null) 
            {
                if (_threadManager.Value != null) 
                { 
                    Marshal.ReleaseComObject(_threadManager.Value);
                } 
                _threadManager = null;
            }
        }
 
        /// 
        /// Feeds a keystroke to the Text Services Framework, wrapper for 
        /// ITfKeystrokeMgr::TestKeyUp/TestKeyDown/KeyUp/KeyDown. 
        /// 
        ///  
        /// Must be called on the main dispatcher thread.
        /// 
        /// 
        /// true if the keystroke will be eaten by the Text Services Framework, 
        /// false otherwise.
        /// Callers should stop further processing of the keystroke on true, 
        /// continue otherwise. 
        /// 
        ///  
        /// Critical - directly access thread manager, and pushes keystrokes into the input pipeline
        /// 
        [SecurityCritical]
        internal bool Keystroke(int wParam, int lParam, KeyOp op) 
        {
            bool fConsume; 
            UnsafeNativeMethods.ITfKeystrokeMgr keystrokeMgr; 

            // We delay load cicero until someone creates an ITextStore. 
            // Or this thread may not have a ThreadMgr.
            if ((_threadManager == null) || (_threadManager.Value == null))
                return false;
 
            keystrokeMgr = _threadManager.Value as UnsafeNativeMethods.ITfKeystrokeMgr;
 
            switch (op) 
            {
                case KeyOp.TestUp: 
                    keystrokeMgr.TestKeyUp(wParam, lParam, out fConsume);
                    break;
                case KeyOp.TestDown:
                    keystrokeMgr.TestKeyDown(wParam, lParam, out fConsume); 
                    break;
                case KeyOp.Up: 
                    keystrokeMgr.KeyUp(wParam, lParam, out fConsume); 
                    break;
                case KeyOp.Down: 
                    keystrokeMgr.KeyDown(wParam, lParam, out fConsume);
                    break;
                default:
                    fConsume = false; 
                    break;
            } 
 
            return fConsume;
        } 

        // Called by framework's TextStore class.  This method registers a
        // document with TSF.  The TextServicesContext must maintain this list
        // to ensure all native resources are released after gc or uninitialization. 
        /// 
        ///     Critical - directly manipulates input/message pump It also calls into Cicero 
        ///     to extract ThreadManager, clientID and DocumentManager all of which are not safe to 
        ///     expose.
        ///  
        [SecurityCritical]
        internal void RegisterTextStore(DefaultTextStore defaultTextStore)
        {
            // We must cache the DefaultTextStore because we'll need it from 
            // a worker thread if the AppDomain is torn down before the Dispatcher
            // is shutdown. 
            _defaultTextStore = defaultTextStore; 

            UnsafeNativeMethods.ITfThreadMgr threadManager = ThreadManager; 

            if (threadManager != null)
            {
                UnsafeNativeMethods.ITfDocumentMgr doc; 
                UnsafeNativeMethods.ITfContext context;
                int editCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; 
 
                // Activate TSF on this thread if this is the first TextStore.
                if (_istimactivated == false) 
                {
                    //temp variable created to retrieve the value
                    // which is then stored in the critical data.
                    int clientIdTemp; 
                    threadManager.Activate(out clientIdTemp);
                    _clientId = new SecurityCriticalData(clientIdTemp); 
                    _istimactivated = true; 
                }
 
                // Create a TSF document.
                threadManager.CreateDocumentMgr(out doc);
                doc.CreateContext(_clientId.Value, 0 /* flags */, _defaultTextStore, out context, out editCookie);
                doc.Push(context); 

                // Release any native resources we're done with. 
                Marshal.ReleaseComObject(context); 

                // Same DocumentManager and EditCookie in _defaultTextStore. 
                _defaultTextStore.DocumentManager = doc;
                _defaultTextStore.EditCookie = editCookie;

                // Start the transitory extenstion so we can have Level 1 composition window from Cicero. 
                StartTransitoryExtension();
            } 
        } 

 
        // Cal ITfThreadMgr.SetFocus() with the dim for the default text store
        /// 
        ///     Critical    - access DocumentManager of the current DefaultTextStore.
        ///     TreatAsSafe - This is a safe since it does not expose ITfDocumentMgr. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        internal void SetFocusOnDefaultTextStore() 
        {
            SetFocusOnDim(DefaultTextStore.Current.DocumentManager); 
        }

        // Cal ITfThreadMgr.SetFocus() with the empty dim.
        ///  
        ///     Critical    - access ITfDocumentMgr for empty dim.
        ///     TreatAsSafe - This is a safe since it does not expose ITfDocumentMgr. 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        internal void SetFocusOnEmptyDim() 
        {
            SetFocusOnDim(EmptyDocumentManager);
        }
 

        #endregion Internal Methods 
 
        //-----------------------------------------------------
        // 
        //  Internal Properties
        //
        //------------------------------------------------------
 

        // Get TextServicesContext that is linked to the current Dispatcher. 
        // return NULL if the default text store is not registered yet. 
        internal static TextServicesContext DispatcherCurrent
        { 
            get
            {
                // Create TextServicesContext on demand.
                if (InputMethod.Current.TextServicesContext == null) 
                {
                    InputMethod.Current.TextServicesContext = new TextServicesContext(); 
                } 

                return InputMethod.Current.TextServicesContext; 
            }
        }

        ///  
        /// This is an internal, link demand protected method.
        ///  
        ///  
        /// Critical - returns the thread manager (input and message pump)
        ///  
        internal UnsafeNativeMethods.ITfThreadMgr ThreadManager
        {
            // The ITfThreadMgr for this thread.
            [SecurityCritical] 
            get
            { 
                if (_threadManager == null) 
                {
                    _threadManager = new SecurityCriticalDataClass(TextServicesLoader.Load()); 
                }

                return _threadManager.Value;
            } 
        }
 
        //----------------------------------------------------- 
        //
        //  Internal Events 
        //
        //-----------------------------------------------------

        //----------------------------------------------------- 
        //
        //  Internal Enums 
        // 
        //------------------------------------------------------
 
        #region Internal Enums

        /// 
        /// Specifies the type of keystroke operation to perform in the 
        /// TextServicesContext.Keystroke method.
        ///  
        internal enum KeyOp 
        {
            ///  
            /// ITfKeystrokeMgr::TestKeyUp
            /// 
            TestUp,
 
            /// 
            /// ITfKeystrokeMgr::TestKeyDown 
            ///  
            TestDown,
 
            /// 
            /// ITfKeystrokeMgr::KeyUp
            /// 
            Up, 

            ///  
            /// ITfKeystrokeMgr::KeyDown 
            /// 
            Down 
        };

        #endregion Internal Enums
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 

        // Cal ITfThreadMgr.SetFocus() with dim
        /// 
        ///     Critical: This code calls into critical code threadmgr.SetFocus 
        ///     TreatAsSafe: This does not expose any critical data and SetFocus is safe to expose
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void SetFocusOnDim(UnsafeNativeMethods.ITfDocumentMgr dim)
        { 
            UnsafeNativeMethods.ITfThreadMgr threadmgr = ThreadManager;

            if (threadmgr != null)
            { 
                threadmgr.SetFocus(dim);
            } 
        } 

        // Start the transitory extestion for Cicero Level1/Level2 composition window support. 
        /// 
        ///     Critical: Accesses unmanaged pointers (DocumentManager, CompartmentMgr,Compartment, Source)
        /// 
        [SecurityCritical] 
        private void StartTransitoryExtension()
        { 
            Guid guid; 
            Object var;
            UnsafeNativeMethods.ITfCompartmentMgr compmgr; 
            UnsafeNativeMethods.ITfCompartment comp;
            UnsafeNativeMethods.ITfSource source;
            int transitoryExtensionSinkCookie;
 
            // Start TransitryExtension
            compmgr = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; 
 
            // Set GUID_COMPARTMENT_TRANSITORYEXTENSION
            guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; 
            compmgr.GetCompartment(ref guid, out comp);
            var = (int)1;
            comp.SetValue(0, ref var);
 
            // Advise TransitoryExtension Sink and store the cookie.
            guid = UnsafeNativeMethods.IID_ITfTransitoryExtensionSink; 
            source = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfSource; 
            if (source != null)
            { 
                // DocumentManager only supports ITfSource on Longhorn, XP does not support it
                source.AdviseSink(ref guid, _defaultTextStore, out transitoryExtensionSinkCookie);
                _defaultTextStore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie;
            } 

            Marshal.ReleaseComObject(comp); 
        } 

        // Stop TransitoryExtesion 
        /// 
        ///     Critical: This code calls into ITfCompartmentMgr, ITfCompartment and ITfSource all
        ///    COM interop pointers
        ///     TreatAsSafe: This does not expose any critical data. 
        ///                  Stopping the transitory extenstion is a safe operation.
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void StopTransitoryExtension()
        { 
            // Unadvice the transitory extension sink.
            if (_defaultTextStore.TransitoryExtensionSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE)
            {
                UnsafeNativeMethods.ITfSource source; 
                source = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfSource;
                if (source != null) 
                { 
                    // DocumentManager only supports ITfSource on Longhorn, XP does not support it
                    source.UnadviseSink(_defaultTextStore.TransitoryExtensionSinkCookie); 
                }
                _defaultTextStore.TransitoryExtensionSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE;
            }
 
            // Reset GUID_COMPARTMENT_TRANSITORYEXTENSION
            UnsafeNativeMethods.ITfCompartmentMgr compmgr; 
            compmgr = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; 

            if (compmgr != null) 
            {
                Guid guid;
                Object var;
                UnsafeNativeMethods.ITfCompartment comp; 
                guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION;
                compmgr.GetCompartment(ref guid, out comp); 
 
                if (comp != null)
                { 
                    var = (int)0;
                    comp.SetValue(0, ref var);
                    Marshal.ReleaseComObject(comp);
                } 
            }
        } 
 
        //------------------------------------------------------
        // 
        //  Private Properties
        //
        //-----------------------------------------------------
 

        // Create an empty dim on demand. 
        ///  
        /// Critical - directly manipulates thread manager and expose ITfDocumentMgr
        ///  
        private UnsafeNativeMethods.ITfDocumentMgr EmptyDocumentManager
        {
            [SecurityCritical]
            get 
            {
                if (_dimEmpty == null) 
                { 
                    UnsafeNativeMethods.ITfThreadMgr threadManager = ThreadManager;
                    if (threadManager == null) 
                    {
                        return null;
                    }
                    //creating temp variable to retrieve from call and store in security critical data 
                    UnsafeNativeMethods.ITfDocumentMgr dimEmptyTemp;
                    // Create a TSF document. 
                    threadManager.CreateDocumentMgr(out dimEmptyTemp); 
                    _dimEmpty = new SecurityCriticalDataClass(dimEmptyTemp);
                } 
                return _dimEmpty.Value;
            }
        }
 
        //------------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // Cached Dispatcher default text store. 
        // We must cache the DefaultTextStore because we sometimes need it from
        // a worker thread if the AppDomain is torn down before the Dispatcher 
        // is shutdown. 
        private DefaultTextStore _defaultTextStore;
 
        // This is true if thread manager is activated.
        private bool _istimactivated;

        // The root TSF object, created on demand. 
        /// 
        ///     Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. 
        ///  
        private SecurityCriticalDataClass _threadManager;
 
        // TSF ClientId from Activate call.
        /// 
        ///     Critical: _clientId is an identifier for Cicero.
        ///  
        private SecurityCriticalData _clientId;
 
        // The empty dim for this thread. Created on demand. 
        /// 
        ///     Critical: UnsafeNativeMethods.ITfDocumentMgr has methods with SuppressUnmanagedCodeSecurity. 
        /// 
        private SecurityCriticalDataClass _dimEmpty;

        #endregion Private Fields 

        #region WeakEventTableShutDownListener 
 
        private sealed class TextServicesContextShutDownListener : ShutDownListener
        { 
            /// 
            ///     Critical: accesses AppDomain.DomainUnload event
            ///     TreatAsSafe: This code does not take any parameter or return state.
            ///                  It simply attaches private callbacks. 
            /// 
            [SecurityCritical,SecurityTreatAsSafe] 
            public TextServicesContextShutDownListener(TextServicesContext target, ShutDownEvents events) : base(target, events) 
            {
                _arg = (events == ShutDownEvents.DomainUnload); 
            }

            internal override void OnShutDown(object target)
            { 
                TextServicesContext textServicesContext = (TextServicesContext)target;
                textServicesContext.Uninitialize(_arg); 
            } 

            bool _arg; 
        }

        #endregion TextServicesContextShutDownListener
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Manages Text Services Framework state. 
// 
// History:
//  07/16/2003 : benwest - Ported from .net tree. 
//
//---------------------------------------------------------------------------

using System; 
using System.Runtime.InteropServices;
using System.Threading; 
using System.Windows.Threading; 
using System.Security;
using System.Security.Permissions; 
using System.Diagnostics;
using System.Collections;
using MS.Utility;
using MS.Win32; 
using MS.Internal;
using MS.Internal.PresentationCore;                        // SecurityHelper 
 
namespace System.Windows.Input
{ 

    //-----------------------------------------------------
    //
    //  TextServicesContext class 
    //
    //----------------------------------------------------- 
 
    /// 
    /// This class manages the ITfThreadMgr, EmptyDim and the reference to 
    /// the default TextStore.
    /// The instance of TextServicesContext class is created per Dispatcher.
    /// 
    ///  
    /// 
    internal class TextServicesContext 
    { 
        //------------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        #region Constructors
 
        ///  
        /// Instantiates a TextServicesContext.
        ///  
        /// 
        /// Critical - accesses AppDomain.DomainUnload event.
        /// SecurityTreatAsSafe - does not accept or reveal any information.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private TextServicesContext() 
        { 
            Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "SetDispatcherThreaad on MTA thread");
            TextServicesContextShutDownListener listener; 

            // Add Dispatcher.Shutdown event handler. We will clean up Cicero's resource
            // when Dispatcher is terminated.
            listener = new TextServicesContextShutDownListener(this, ShutDownEvents.DispatcherShutdown); 

            // Add an event handler for AppDomain unload. 
            // When an AppDomain is unloaded, we won't get the Dispatcher shutdown, 
            // and we'll be called back on a worker thread.
            listener = new TextServicesContextShutDownListener(this, ShutDownEvents.DomainUnload); 
        }

        #endregion Constructors
 
        //------------------------------------------------------
        // 
        //  Internal Methods 
        //
        //------------------------------------------------------ 

        #region Internal Methods

        ///  
        /// Releases all unmanaged resources allocated by the
        /// TextServicesContext. 
        ///  
        /// 
        /// if appDomainShutdown == false, this method must be called on the 
        /// Dispatcher thread.  Otherwise, the caller is an AppDomain.Shutdown
        /// listener, and is calling from a worker thread.
        /// 
        ///  
        /// Critical - access thread manager directly
        /// TreatAsSafe - uninitializing would only result in input being dead for the app 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Uninitialize(bool appDomainShutdown) 
        {
            // Unregister DefaultTextStore.
            if (_defaultTextStore != null)
            { 
                StopTransitoryExtension();
                if (_defaultTextStore.DocumentManager != null) 
                { 
                    _defaultTextStore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL);
                    Marshal.ReleaseComObject(_defaultTextStore.DocumentManager); 
                    _defaultTextStore.DocumentManager = null;
                }

                // We can't use tls during AppDomainShutdown -- we're called on 
                // a worker thread.  But we don't need to cleanup in that case
                // either. 
                if (!appDomainShutdown) 
                {
                    InputMethod.Current.DefaultTextStore = null; 
                }

                _defaultTextStore = null;
            } 

            // Free up any remaining textstores. 
            if (_istimactivated == true) 
            {
                // Shut down the thread manager when the last TextStore goes away. 
                // On XP, if we're called on a worker thread (during AppDomain shutdown)
                // we can't call call any methods on _threadManager.  The problem is
                // that there's no proxy registered for ITfThreadMgr on OS versions
                // previous to Vista.  Not calling Deactivate will leak the IMEs, but 
                // in practice (1) they're singletons, so it's not unbounded; and (2)
                // most applications will share the thread with other AppDomains that 
                // have a UI, in which case the IME won't be released until the process 
                // shuts down in any case.  In theory we could also work around this
                // problem by creating our own XP proxy/stub implementation, which would 
                // be added to WPF setup....
                if (!appDomainShutdown || System.Environment.OSVersion.Version.Major >= 6)
                {
                    _threadManager.Value.Deactivate(); 
                }
                _istimactivated = false; 
            } 

            // Release the empty dim. 
            if (_dimEmpty != null)
            {
                if (_dimEmpty.Value != null)
                { 
                    Marshal.ReleaseComObject(_dimEmpty.Value);
                } 
                _dimEmpty = null; 
            }
 
            // Release the ThreadManager.
            // We don't do this in UnregisterTextStore because someone may have
            // called get_ThreadManager after the last TextStore was unregistered.
            if (_threadManager != null) 
            {
                if (_threadManager.Value != null) 
                { 
                    Marshal.ReleaseComObject(_threadManager.Value);
                } 
                _threadManager = null;
            }
        }
 
        /// 
        /// Feeds a keystroke to the Text Services Framework, wrapper for 
        /// ITfKeystrokeMgr::TestKeyUp/TestKeyDown/KeyUp/KeyDown. 
        /// 
        ///  
        /// Must be called on the main dispatcher thread.
        /// 
        /// 
        /// true if the keystroke will be eaten by the Text Services Framework, 
        /// false otherwise.
        /// Callers should stop further processing of the keystroke on true, 
        /// continue otherwise. 
        /// 
        ///  
        /// Critical - directly access thread manager, and pushes keystrokes into the input pipeline
        /// 
        [SecurityCritical]
        internal bool Keystroke(int wParam, int lParam, KeyOp op) 
        {
            bool fConsume; 
            UnsafeNativeMethods.ITfKeystrokeMgr keystrokeMgr; 

            // We delay load cicero until someone creates an ITextStore. 
            // Or this thread may not have a ThreadMgr.
            if ((_threadManager == null) || (_threadManager.Value == null))
                return false;
 
            keystrokeMgr = _threadManager.Value as UnsafeNativeMethods.ITfKeystrokeMgr;
 
            switch (op) 
            {
                case KeyOp.TestUp: 
                    keystrokeMgr.TestKeyUp(wParam, lParam, out fConsume);
                    break;
                case KeyOp.TestDown:
                    keystrokeMgr.TestKeyDown(wParam, lParam, out fConsume); 
                    break;
                case KeyOp.Up: 
                    keystrokeMgr.KeyUp(wParam, lParam, out fConsume); 
                    break;
                case KeyOp.Down: 
                    keystrokeMgr.KeyDown(wParam, lParam, out fConsume);
                    break;
                default:
                    fConsume = false; 
                    break;
            } 
 
            return fConsume;
        } 

        // Called by framework's TextStore class.  This method registers a
        // document with TSF.  The TextServicesContext must maintain this list
        // to ensure all native resources are released after gc or uninitialization. 
        /// 
        ///     Critical - directly manipulates input/message pump It also calls into Cicero 
        ///     to extract ThreadManager, clientID and DocumentManager all of which are not safe to 
        ///     expose.
        ///  
        [SecurityCritical]
        internal void RegisterTextStore(DefaultTextStore defaultTextStore)
        {
            // We must cache the DefaultTextStore because we'll need it from 
            // a worker thread if the AppDomain is torn down before the Dispatcher
            // is shutdown. 
            _defaultTextStore = defaultTextStore; 

            UnsafeNativeMethods.ITfThreadMgr threadManager = ThreadManager; 

            if (threadManager != null)
            {
                UnsafeNativeMethods.ITfDocumentMgr doc; 
                UnsafeNativeMethods.ITfContext context;
                int editCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; 
 
                // Activate TSF on this thread if this is the first TextStore.
                if (_istimactivated == false) 
                {
                    //temp variable created to retrieve the value
                    // which is then stored in the critical data.
                    int clientIdTemp; 
                    threadManager.Activate(out clientIdTemp);
                    _clientId = new SecurityCriticalData(clientIdTemp); 
                    _istimactivated = true; 
                }
 
                // Create a TSF document.
                threadManager.CreateDocumentMgr(out doc);
                doc.CreateContext(_clientId.Value, 0 /* flags */, _defaultTextStore, out context, out editCookie);
                doc.Push(context); 

                // Release any native resources we're done with. 
                Marshal.ReleaseComObject(context); 

                // Same DocumentManager and EditCookie in _defaultTextStore. 
                _defaultTextStore.DocumentManager = doc;
                _defaultTextStore.EditCookie = editCookie;

                // Start the transitory extenstion so we can have Level 1 composition window from Cicero. 
                StartTransitoryExtension();
            } 
        } 

 
        // Cal ITfThreadMgr.SetFocus() with the dim for the default text store
        /// 
        ///     Critical    - access DocumentManager of the current DefaultTextStore.
        ///     TreatAsSafe - This is a safe since it does not expose ITfDocumentMgr. 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        internal void SetFocusOnDefaultTextStore() 
        {
            SetFocusOnDim(DefaultTextStore.Current.DocumentManager); 
        }

        // Cal ITfThreadMgr.SetFocus() with the empty dim.
        ///  
        ///     Critical    - access ITfDocumentMgr for empty dim.
        ///     TreatAsSafe - This is a safe since it does not expose ITfDocumentMgr. 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        internal void SetFocusOnEmptyDim() 
        {
            SetFocusOnDim(EmptyDocumentManager);
        }
 

        #endregion Internal Methods 
 
        //-----------------------------------------------------
        // 
        //  Internal Properties
        //
        //------------------------------------------------------
 

        // Get TextServicesContext that is linked to the current Dispatcher. 
        // return NULL if the default text store is not registered yet. 
        internal static TextServicesContext DispatcherCurrent
        { 
            get
            {
                // Create TextServicesContext on demand.
                if (InputMethod.Current.TextServicesContext == null) 
                {
                    InputMethod.Current.TextServicesContext = new TextServicesContext(); 
                } 

                return InputMethod.Current.TextServicesContext; 
            }
        }

        ///  
        /// This is an internal, link demand protected method.
        ///  
        ///  
        /// Critical - returns the thread manager (input and message pump)
        ///  
        internal UnsafeNativeMethods.ITfThreadMgr ThreadManager
        {
            // The ITfThreadMgr for this thread.
            [SecurityCritical] 
            get
            { 
                if (_threadManager == null) 
                {
                    _threadManager = new SecurityCriticalDataClass(TextServicesLoader.Load()); 
                }

                return _threadManager.Value;
            } 
        }
 
        //----------------------------------------------------- 
        //
        //  Internal Events 
        //
        //-----------------------------------------------------

        //----------------------------------------------------- 
        //
        //  Internal Enums 
        // 
        //------------------------------------------------------
 
        #region Internal Enums

        /// 
        /// Specifies the type of keystroke operation to perform in the 
        /// TextServicesContext.Keystroke method.
        ///  
        internal enum KeyOp 
        {
            ///  
            /// ITfKeystrokeMgr::TestKeyUp
            /// 
            TestUp,
 
            /// 
            /// ITfKeystrokeMgr::TestKeyDown 
            ///  
            TestDown,
 
            /// 
            /// ITfKeystrokeMgr::KeyUp
            /// 
            Up, 

            ///  
            /// ITfKeystrokeMgr::KeyDown 
            /// 
            Down 
        };

        #endregion Internal Enums
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 

        // Cal ITfThreadMgr.SetFocus() with dim
        /// 
        ///     Critical: This code calls into critical code threadmgr.SetFocus 
        ///     TreatAsSafe: This does not expose any critical data and SetFocus is safe to expose
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void SetFocusOnDim(UnsafeNativeMethods.ITfDocumentMgr dim)
        { 
            UnsafeNativeMethods.ITfThreadMgr threadmgr = ThreadManager;

            if (threadmgr != null)
            { 
                threadmgr.SetFocus(dim);
            } 
        } 

        // Start the transitory extestion for Cicero Level1/Level2 composition window support. 
        /// 
        ///     Critical: Accesses unmanaged pointers (DocumentManager, CompartmentMgr,Compartment, Source)
        /// 
        [SecurityCritical] 
        private void StartTransitoryExtension()
        { 
            Guid guid; 
            Object var;
            UnsafeNativeMethods.ITfCompartmentMgr compmgr; 
            UnsafeNativeMethods.ITfCompartment comp;
            UnsafeNativeMethods.ITfSource source;
            int transitoryExtensionSinkCookie;
 
            // Start TransitryExtension
            compmgr = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; 
 
            // Set GUID_COMPARTMENT_TRANSITORYEXTENSION
            guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; 
            compmgr.GetCompartment(ref guid, out comp);
            var = (int)1;
            comp.SetValue(0, ref var);
 
            // Advise TransitoryExtension Sink and store the cookie.
            guid = UnsafeNativeMethods.IID_ITfTransitoryExtensionSink; 
            source = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfSource; 
            if (source != null)
            { 
                // DocumentManager only supports ITfSource on Longhorn, XP does not support it
                source.AdviseSink(ref guid, _defaultTextStore, out transitoryExtensionSinkCookie);
                _defaultTextStore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie;
            } 

            Marshal.ReleaseComObject(comp); 
        } 

        // Stop TransitoryExtesion 
        /// 
        ///     Critical: This code calls into ITfCompartmentMgr, ITfCompartment and ITfSource all
        ///    COM interop pointers
        ///     TreatAsSafe: This does not expose any critical data. 
        ///                  Stopping the transitory extenstion is a safe operation.
        ///  
        [SecurityCritical,SecurityTreatAsSafe] 
        private void StopTransitoryExtension()
        { 
            // Unadvice the transitory extension sink.
            if (_defaultTextStore.TransitoryExtensionSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE)
            {
                UnsafeNativeMethods.ITfSource source; 
                source = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfSource;
                if (source != null) 
                { 
                    // DocumentManager only supports ITfSource on Longhorn, XP does not support it
                    source.UnadviseSink(_defaultTextStore.TransitoryExtensionSinkCookie); 
                }
                _defaultTextStore.TransitoryExtensionSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE;
            }
 
            // Reset GUID_COMPARTMENT_TRANSITORYEXTENSION
            UnsafeNativeMethods.ITfCompartmentMgr compmgr; 
            compmgr = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; 

            if (compmgr != null) 
            {
                Guid guid;
                Object var;
                UnsafeNativeMethods.ITfCompartment comp; 
                guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION;
                compmgr.GetCompartment(ref guid, out comp); 
 
                if (comp != null)
                { 
                    var = (int)0;
                    comp.SetValue(0, ref var);
                    Marshal.ReleaseComObject(comp);
                } 
            }
        } 
 
        //------------------------------------------------------
        // 
        //  Private Properties
        //
        //-----------------------------------------------------
 

        // Create an empty dim on demand. 
        ///  
        /// Critical - directly manipulates thread manager and expose ITfDocumentMgr
        ///  
        private UnsafeNativeMethods.ITfDocumentMgr EmptyDocumentManager
        {
            [SecurityCritical]
            get 
            {
                if (_dimEmpty == null) 
                { 
                    UnsafeNativeMethods.ITfThreadMgr threadManager = ThreadManager;
                    if (threadManager == null) 
                    {
                        return null;
                    }
                    //creating temp variable to retrieve from call and store in security critical data 
                    UnsafeNativeMethods.ITfDocumentMgr dimEmptyTemp;
                    // Create a TSF document. 
                    threadManager.CreateDocumentMgr(out dimEmptyTemp); 
                    _dimEmpty = new SecurityCriticalDataClass(dimEmptyTemp);
                } 
                return _dimEmpty.Value;
            }
        }
 
        //------------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // Cached Dispatcher default text store. 
        // We must cache the DefaultTextStore because we sometimes need it from
        // a worker thread if the AppDomain is torn down before the Dispatcher 
        // is shutdown. 
        private DefaultTextStore _defaultTextStore;
 
        // This is true if thread manager is activated.
        private bool _istimactivated;

        // The root TSF object, created on demand. 
        /// 
        ///     Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. 
        ///  
        private SecurityCriticalDataClass _threadManager;
 
        // TSF ClientId from Activate call.
        /// 
        ///     Critical: _clientId is an identifier for Cicero.
        ///  
        private SecurityCriticalData _clientId;
 
        // The empty dim for this thread. Created on demand. 
        /// 
        ///     Critical: UnsafeNativeMethods.ITfDocumentMgr has methods with SuppressUnmanagedCodeSecurity. 
        /// 
        private SecurityCriticalDataClass _dimEmpty;

        #endregion Private Fields 

        #region WeakEventTableShutDownListener 
 
        private sealed class TextServicesContextShutDownListener : ShutDownListener
        { 
            /// 
            ///     Critical: accesses AppDomain.DomainUnload event
            ///     TreatAsSafe: This code does not take any parameter or return state.
            ///                  It simply attaches private callbacks. 
            /// 
            [SecurityCritical,SecurityTreatAsSafe] 
            public TextServicesContextShutDownListener(TextServicesContext target, ShutDownEvents events) : base(target, events) 
            {
                _arg = (events == ShutDownEvents.DomainUnload); 
            }

            internal override void OnShutDown(object target)
            { 
                TextServicesContext textServicesContext = (TextServicesContext)target;
                textServicesContext.Uninitialize(_arg); 
            } 

            bool _arg; 
        }

        #endregion TextServicesContextShutDownListener
    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK