TextServicesLoader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Shared / MS / Internal / TextServicesLoader.cs / 1 / TextServicesLoader.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Creates ITfThreadMgr instances, the root object of the Text 
//              Services Framework.
// 
// History:
//  07/16/2003 : [....] - ported from dotnet tree.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Runtime.InteropServices; 
using System.Security.Permissions;
using System.Security; 
using System.Threading;
using MS.Internal;
using Microsoft.Win32;
using MS.Win32; 
using System.Diagnostics;
 
#if WINDOWS_BASE 
    using MS.Internal.WindowsBase;
#elif PRESENTATION_CORE 
    using MS.Internal.PresentationCore;
#elif PRESENTATIONFRAMEWORK
    using MS.Internal.PresentationFramework;
#elif DRT 
    using MS.Internal.Drt;
#else 
#error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. 
using MS.Internal.YourAssemblyName;
#endif 

namespace MS.Internal
{
    // Creates ITfThreadMgr instances, the root object of the Text Services 
    // Framework.
    [FriendAccessAllowed] 
    internal class TextServicesLoader 
    {
        //----------------------------------------------------- 
        //
        //  Constructors
        //
        //----------------------------------------------------- 

        #region Constructors 
 
        // Private ctor to prevent anyone from instantiating this static class.
        private TextServicesLoader() {} 

        #endregion Constructors

        //------------------------------------------------------ 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
 
        //------------------------------------------------------
        //
        //  Public Properties
        // 
        //------------------------------------------------------
 
        //----------------------------------------------------- 
        //
        //  Public Events 
        //
        //------------------------------------------------------

        //----------------------------------------------------- 
        //
        //  Protected Methods 
        // 
        //-----------------------------------------------------
 
        //-----------------------------------------------------
        //
        //  Internal Methods
        // 
        //------------------------------------------------------
 
        //----------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //------------------------------------------------------

        #region Internal Properties 

        ///  
        /// Loads an instance of the Text Services Framework. 
        /// 
        ///  
        /// May return null if no text services are available.
        /// 
        /// 
        /// SecurityCritical: As this causes elevation of privilige 
        /// 
        [SecurityCritical] 
        internal static UnsafeNativeMethods.ITfThreadMgr Load() 
        {
            UnsafeNativeMethods.ITfThreadMgr threadManager; 

            Invariant.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "Load called on MTA thread!");

            if (ServicesInstalled) 
            {
                // NB: a COMException here means something went wrong initialzing Cicero. 
                // Cicero will throw an exception if it doesn't think it should have been 
                // loaded (no TIPs to run), you can check that in msctf.dll's NoTipsInstalled
                // which lives in nt\windows\advcore\ctf\lib\immxutil.cpp.  If that's the 
                // problem, ServicesInstalled is out of sync with Cicero's thinking.
                if (UnsafeNativeMethods.TF_CreateThreadMgr(out threadManager) == NativeMethods.S_OK)
                {
                    return threadManager; 
                }
            } 
 
            return null;
        } 

        /// 
        /// Informs the caller if text services are installed for the current user.
        ///  
        /// 
        /// true if one or more text services are installed for the current user, otherwise false. 
        ///  
        /// 
        /// If this method returns false, TextServicesLoader.Load is guarenteed to return null. 
        /// Callers can use this information to avoid overhead that would otherwise be
        /// required to support text services.
        /// 
        internal static bool ServicesInstalled 
        {
            get 
            { 
                lock (s_servicesInstalledLock)
                { 
                    if (s_servicesInstalled == InstallState.Unknown)
                    {
                        s_servicesInstalled = TIPsWantToRun() ? InstallState.Installed : InstallState.NotInstalled;
                    } 
                }
 
                return (s_servicesInstalled == InstallState.Installed); 
            }
        } 

        #endregion Internal Properties

        //------------------------------------------------------ 
        //
        //  Internal Events 
        // 
        //-----------------------------------------------------
 
        //------------------------------------------------------
        //
        //  Private Methods
        // 
        //-----------------------------------------------------
 
        #region Private Methods 

        // 
        // This method tries to stop Avalon from loading Cicero when there are no TIPs to run.
        // The perf tradeoff is a typically small number of registry checks versus loading and
        // initializing cicero.
        // 
        // The Algorithm:
        // 
        // Do a quick check vs. the global disable flag, return false if it is set. 
        // For each key under HKLM\SOFTWARE\Microsoft\CTF\TIP (a TIP or category clsid)
        //  If the the key has a LanguageProfile subkey (it's a TIP clsid) 
        //      Iterate under the matching TIP entry in HKCU.
        //          For each key under the LanguageProfile (a particular LANGID)
        //              For each key under the LANGID (an assembly GUID)
        //                  Try to read the Enable value. 
        //                  If the value is set non-zero, then stop all processing and return true.
        //                  If the value is set zero, continue. 
        //                  If the value does not exist, continue (default is disabled). 
        //      If any Enable values were found under HKCU for the TIP, then stop all processing and return false.
        //      Else, no Enable values have been found thus far and we keep going to investigate HKLM. 
        //      Iterate under the TIP entry in HKLM.
        //          For each key under the LanguageProfile (a particular LANGID)
        //              For each key under the LANGID (an assembly GUID)
        //                  Try to read the Enable value. 
        //                  If the value is set non-zero, then stop all processing and return true.
        //                  If the value does not exist, then stop all processing and return true (default is enabled). 
        //                  If the value is set zero, continue. 
        // If we finish iterating all entries under HKLM without returning true, return false.
        // 

        ///
        ///  Safe - no critical state stored, disclosure that Tips wanting to run is safe
        ///  Critical - critical because we do an assert 
        ///
        [SecurityTreatAsSafe, SecurityCritical] 
        private static bool TIPsWantToRun() 
        {
            object obj; 
            RegistryKey key;
            bool tipsWantToRun = false;

            PermissionSet ps = new PermissionSet(PermissionState.None); 
            ps.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\CTF"));
            ps.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, "HKEY_CURRENT_USER\\Software\\Microsoft\\CTF")); 
            ps.Assert(); // BlessedAssert: 
            try
            { 
                key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\CTF", false);

                // Is cicero disabled completely for the current user?
                if (key != null) 
                {
                    obj = key.GetValue("Disable Thread Input Manager"); 
 
                    if (obj is int && (int)obj != 0)
                        return false; 
                }

                // Loop through all the TIP entries for machine and current user.
                tipsWantToRun = IterateSubKeys(Registry.LocalMachine, "SOFTWARE\\Microsoft\\CTF\\TIP",new IterateHandler(SingleTIPWantsToRun), true) == EnableState.Enabled; 
            }
            finally 
            { 
                CodeAccessPermission.RevertAssert();
            } 

            return tipsWantToRun;
        }
 
        // Returns EnableState.Enabled if one or more TIPs are installed and
        // enabled for the current user. 
        private static EnableState SingleTIPWantsToRun(RegistryKey keyLocalMachine, string subKeyName, bool localMachine) 
        {
            EnableState result; 

            if (subKeyName.Length != CLSIDLength)
                return EnableState.Disabled;
 
            // We want subkey\LanguageProfile key.
            // Loop through all the langid entries for TIP. 
 
            // First, check current user.
            result = IterateSubKeys(Registry.CurrentUser, "SOFTWARE\\Microsoft\\CTF\\TIP\\" + subKeyName + "\\LanguageProfile", new IterateHandler(IsLangidEnabled), false); 

            // Any explicit value short circuits the process.
            // Otherwise check local machine.
            if (result == EnableState.None || result == EnableState.Error) 
            {
                result = IterateSubKeys(keyLocalMachine, subKeyName + "\\LanguageProfile", new IterateHandler(IsLangidEnabled), true); 
 
                if (result == EnableState.None)
                { 
                    result = EnableState.Enabled;
                }
            }
 
            return result;
        } 
 
        // Returns EnableState.Enabled if the supplied subkey is a valid LANGID key with enabled
        // cicero assembly. 
        private static EnableState IsLangidEnabled(RegistryKey key, string subKeyName, bool localMachine)
        {
            if (subKeyName.Length != LANGIDLength)
                return EnableState.Error; 

            // Loop through all the assembly entries for the langid 
            return IterateSubKeys(key, subKeyName, new IterateHandler(IsAssemblyEnabled), localMachine); 
        }
 
        // Returns EnableState.Enabled if the supplied assembly key is enabled.
        private static EnableState IsAssemblyEnabled(RegistryKey key, string subKeyName, bool localMachine)
        {
            RegistryKey subKey; 
            object obj;
 
            if (subKeyName.Length != CLSIDLength) 
                return EnableState.Error;
 
            // Open the local machine assembly key.
            subKey = key.OpenSubKey(subKeyName);

            if (subKey == null) 
                return EnableState.Error;
 
            // Try to read the "Enable" value. 
            obj = subKey.GetValue("Enable");
 
            if (obj is int)
            {
                return ((int)obj == 0) ? EnableState.Disabled : EnableState.Enabled;
            } 

            return EnableState.None; 
        } 

        // Calls the supplied delegate on each of the children of keyBase. 
        private static EnableState IterateSubKeys(RegistryKey keyBase, string subKey, IterateHandler handler, bool localMachine)
        {
            RegistryKey key;
            string[] subKeyNames; 
            EnableState state;
 
            key = keyBase.OpenSubKey(subKey, false); 

            if (key == null) 
                return EnableState.Error;

            subKeyNames = key.GetSubKeyNames();
            state = EnableState.Error; 

            foreach (string name in subKeyNames) 
            { 
                switch (handler(key, name, localMachine))
                { 
                    case EnableState.Error:
                        break;
                    case EnableState.None:
                        if (localMachine) // For lm, want to return here right away. 
                            return EnableState.None;
 
                        // For current user, remember that we found no Enable value. 
                        if (state == EnableState.Error)
                        { 
                            state = EnableState.None;
                        }
                        break;
                    case EnableState.Disabled: 
                        state = EnableState.Disabled;
                        break; 
                    case EnableState.Enabled: 
                        return EnableState.Enabled;
                } 
            }

            return state;
        } 

        #endregion Private Methods 
 
        //-----------------------------------------------------
        // 
        //  Private Properties
        //
        //-----------------------------------------------------
 
        //------------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // String consts used to validate registry entires. 
        private const int CLSIDLength = 38;  // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
        private const int LANGIDLength = 10; // 0x12345678 
 
        // Status of a TIP assembly.
        private enum EnableState 
        {
            Error,      // Invalid entry.
            None,       // No explicit Enable entry on the assembly.
            Enabled,    // Assembly is enabled. 
            Disabled    // Assembly is disabled.
        }; 
 
        // Callback delegate for the IterateSubKeys method.
        private delegate EnableState IterateHandler(RegistryKey key, string subKeyName, bool localMachine); 

        // Install state.
        private enum InstallState
        { 
            Unknown,        // Haven't checked to see if any TIPs are installed yet.
            Installed,      // Checked and installed. 
            NotInstalled    // Checked and not installed. 
        }
 
        // Cached install state value.
        // Writes are not thread safe, but we don't mind the neglible perf hit
        // of potentially writing it twice.
        private static InstallState s_servicesInstalled = InstallState.Unknown; 
        private static object s_servicesInstalledLock = new object();
 
        #endregion Private Fields 
    }
} 

// 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