File: Core\CSharp\System\Windows\Input\TextServicesCompartmentContext.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//---------------------------------------------------------------------------
//
// <copyright file=TextServicesCompartmentContext.cs company=Microsoft>
//    Copyright (C) Microsoft Corporation.  All rights reserved.
// </copyright>
// 
// Description: Manages Text Services Compartment.
//
// History:  
//  07/30/2003 : yutakas - Ported from .net tree.
//
//---------------------------------------------------------------------------
 
using System;
using System.Runtime.InteropServices;
using System.Windows.Threading;
 
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;
using System.Collections;
using MS.Internal;
using MS.Utility;
using MS.Win32;
 
namespace System.Windows.Input 
{
    //------------------------------------------------------
    //
    //  TextServicesCompartmentContext class
    //
    //------------------------------------------------------
 
    internal class TextServicesCompartmentContext
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        /// <summary>
        ///  private constructer to avoid from creating instance outside.
        /// </summary>
        private TextServicesCompartmentContext()
        {
        }
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        /// <summary>
        ///  Get the compartment of the given input method state.
        /// </summary>
        /// <SecurityNote>
        /// Critical - retrieves message pump/input manager wrapper class
        /// TreatAsSafe - returns safe wrapper for property request
        /// </SecurityNote>
        [SecurityCritical, SecurityTreatAsSafe]
        internal TextServicesCompartment GetCompartment(InputMethodStateType statetype)
        {
             for (int i = 0; i < InputMethodEventTypeInfo.InfoList.Length; i++)
             {
                 InputMethodEventTypeInfo iminfo = InputMethodEventTypeInfo.InfoList[i];
 
                 if (iminfo.Type  == statetype)
                 {
                     if (iminfo.Scope == CompartmentScope.Thread)
                         return GetThreadCompartment(iminfo.Guid);
                     else if (iminfo.Scope == CompartmentScope.Global)
                         return GetGlobalCompartment(iminfo.Guid);
                 }
             }
             return null;
        }
 
        /// <summary>
        ///  Get the thread compartment of the Guid.
        /// </summary>
        /// <SecurityNote>
        /// Critical - manipulates input manager/message pump
        /// </SecurityNote>
        [SecurityCritical]
        internal TextServicesCompartment GetThreadCompartment(Guid guid)
        {
            // No TextServices are installed so that the compartment won't work.
            if (!TextServicesLoader.ServicesInstalled ||
                TextServicesContext.DispatcherCurrent == null)
                return null;
 
            UnsafeNativeMethods.ITfThreadMgr threadmgr = TextServicesContext.DispatcherCurrent.ThreadManager;
            if (threadmgr == null)
                return null;
 
            if (_compartmentTable == null)
                _compartmentTable = new Hashtable();
 
            TextServicesCompartment compartment;
 
            compartment = _compartmentTable[guid] as TextServicesCompartment;
            if (compartment == null)
            {
                compartment = new TextServicesCompartment(guid, 
                                                          threadmgr as UnsafeNativeMethods.ITfCompartmentMgr);
                _compartmentTable[guid] = compartment;
            }
 
            return compartment;
        }
 
        /// <summary>
        ///  Get the global compartment of the Guid.
        /// </summary>
        /// <SecurityNote>
        /// Critical - access input manager directly
        /// </SecurityNote>
        [SecurityCritical]
        internal TextServicesCompartment GetGlobalCompartment(Guid guid)
        {
            // No TextServices are installed so that the compartment won't work.
            if (!TextServicesLoader.ServicesInstalled ||
                TextServicesContext.DispatcherCurrent == null)
                return null;
 
            if (_globalcompartmentTable == null)
                _globalcompartmentTable = new Hashtable();
 
            if (_globalcompartmentmanager == null)
            {
                UnsafeNativeMethods.ITfThreadMgr threadmgr = TextServicesContext.DispatcherCurrent.ThreadManager;
 
                if (threadmgr == null)
                    return null;
 
                threadmgr.GetGlobalCompartment(out _globalcompartmentmanager);
            }
 
            TextServicesCompartment compartment = null;
 
            compartment = _globalcompartmentTable[guid] as TextServicesCompartment;
            if (compartment == null)
            {
                compartment = new TextServicesCompartment(guid, _globalcompartmentmanager);
                _globalcompartmentTable[guid] = compartment;
            }
 
            return compartment;
        }
 
        #endregion Internal Methods
 
        //------------------------------------------------------
        //
        //  Internal Properties
        //
        //------------------------------------------------------
 
        /// <summary>
        ///  Create and get thread local compartment context.
        /// </summary>
        internal static TextServicesCompartmentContext Current
        {
            get
            {
                // TextServicesCompartmentContext for the current Dispatcher is stored in InputMethod of
                // the current Dispatcher.
                if (InputMethod.Current.TextServicesCompartmentContext == null)
                    InputMethod.Current.TextServicesCompartmentContext = new TextServicesCompartmentContext();
 
                return InputMethod.Current.TextServicesCompartmentContext;
            }
        }
 
 
        //------------------------------------------------------
        //
        //  Private Fields
        //
        //------------------------------------------------------
                
        // cache of ITfCompartments
        private Hashtable _compartmentTable;
        private Hashtable _globalcompartmentTable;
 
        // cache of the global compartment manager
        /// <SecurityNote>
        ///  Critical :  Field for critical type
        /// </SecurityNote>
        [SecurityCritical]
        private UnsafeNativeMethods.ITfCompartmentMgr  _globalcompartmentmanager;
 
 
    }
}