Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Documents / TextServicesHost.cs / 1 / TextServicesHost.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: TextServicesHost implementation. // // History: // 02/12/2004 : yutakas - created // //--------------------------------------------------------------------------- using System; using System.Runtime.InteropServices; using System.Windows.Threading; using System.Threading; using System.Collections; using System.Diagnostics; using System.Windows.Media; using System.Windows.Input; using System.Windows.Documents; using MS.Win32; using MS.Internal; using MS.Internal.PresentationFramework; // SecurityHelper using System.Security; using System.Security.Permissions; namespace System.Windows.Documents { //----------------------------------------------------- // // TextServicesHost class // //----------------------------------------------------- // // This class manages registration of TextStore. // The instance of this class is per Dispatcher and can be shared by // all TextStore in same Dispatcher. // The registration of TextStore does: // - create DocumentManger for each TextStore. // - advise ThreadFocusSink and EditSink. // // This activate ITfThreadMgr and keep the referrence of it. // When Dispatcher is finished, ITfThreadMgr is deactivated and released. // internal class TextServicesHost : DispatcherObject { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors // Creates a new TextServicesHost instance. internal TextServicesHost() { } #endregion Constructors //------------------------------------------------------ // // Internal Method // //------------------------------------------------------ // TextStore calls this to register it and advise sink. ////// Critical: This code accesses DocumentMgr,Source (inside of _RegisterTextStore) /// [SecurityCritical] internal void RegisterTextStore(TextStore textstore) { // VerifyAccess(); Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "OnRegisterTextStore must be called on STA thread"); // Register textstore and advise sinks. _RegisterTextStore((TextStore)textstore); _thread = Thread.CurrentThread; } // Free all resources associated with a TextStore. ////// Critical: This code invokes OnUnregisterTextStore which is a Critical method. /// [SecurityCritical] internal void UnregisterTextStore(TextStore textstore, bool finalizer) { if (!finalizer) { OnUnregisterTextStore(textstore); } else { // GC Finalizer is detaching TextStore and the dispatcher thread could be already // terminated or Dispatcher is already finished. if (!_isDispatcherShutdownFinished) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(OnUnregisterTextStore), textstore); } } } ////// Critical: This code calls into native code. /// [SecurityCritical] internal void RegisterWinEventSink(TextStore textstore) { // Start WinEvent hook to listen windows move/size event. // We need to call ITextStoreACPSink::OnLayoutChange() whenever the window is moved. if (_winEvent == null) { _winEvent = new MoveSizeWinEventHandler(); _winEvent.Start(); } _winEvent.RegisterTextStore(textstore); } ////// Critical: This code calls into native code. /// [SecurityCritical] internal void UnregisterWinEventSink(TextStore textstore) { _winEvent.UnregisterTextStore(textstore); // If the registerd text store count is 0, we don't need WinEvent hook any more. if (_winEvent.TextStoreCount == 0) { _winEvent.Stop(); _winEvent.Clear(); _winEvent = null; } } // Start the transitory extestion for Cicero Level1/Level2 composition window support. ////// Critical: This code calls into ITfCompartmentMgr and ItfCompartment both of which are critical /// [SecurityCritical] internal static void StartTransitoryExtension(TextStore textstore) { Guid guid; Object var; UnsafeNativeMethods.ITfCompartmentMgr compmgr; UnsafeNativeMethods.ITfCompartment comp; UnsafeNativeMethods.ITfSource source; int transitoryExtensionSinkCookie; // Start TransitryExtension compmgr = textstore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; // Set GUID_COMPARTMENT_TRANSITORYEXTENSION guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; compmgr.GetCompartment(ref guid, out comp); var = (int)2; // Use level 2 comp.SetValue(0, ref var); // Advise TransitoryExtension Sink and store the cookie. guid = UnsafeNativeMethods.IID_ITfTransitoryExtensionSink; source = textstore.DocumentManager as UnsafeNativeMethods.ITfSource; if (source != null) { // DocumentManager only supports ITfSource on Longhorn, XP does not support it source.AdviseSink(ref guid, textstore, out transitoryExtensionSinkCookie); textstore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie; } Marshal.ReleaseComObject(comp); } // Stop TransitoryExtesion ////// Critical: This code calls into ITfCompartmentMgr and ItfCompartment both of which are critical /// [SecurityCritical] internal static void StopTransitoryExtension(TextStore textstore) { Guid guid; Object var; UnsafeNativeMethods.ITfCompartmentMgr compmgr; UnsafeNativeMethods.ITfCompartment comp; compmgr = textstore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; // Unadvice the transitory extension sink. if (textstore.TransitoryExtensionSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { UnsafeNativeMethods.ITfSource source; source = textstore.DocumentManager as UnsafeNativeMethods.ITfSource; if (source != null) { // DocumentManager only supports ITfSource on Longhorn, XP does not support it source.UnadviseSink(textstore.TransitoryExtensionSinkCookie); } textstore.TransitoryExtensionSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } // Reset GUID_COMPARTMENT_TRANSITORYEXTENSION guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; compmgr.GetCompartment(ref guid, out comp); var = (int)0; comp.SetValue(0, ref var); Marshal.ReleaseComObject(comp); } //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ // Return the text services host associated with the current Dispatcher. internal static TextServicesHost Current { get { TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; if (threadLocalStore.TextServicesHost == null) { threadLocalStore.TextServicesHost = new TextServicesHost(); } return threadLocalStore.TextServicesHost; } } // Return ITfThreadMgr ////// Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. /// internal UnsafeNativeMethods.ITfThreadMgr ThreadManager { [SecurityCritical] get { if (_threadManager == null) { return null; } return _threadManager.Value; } } //----------------------------------------------------- // // Private Method // //----------------------------------------------------- #region Private Method // This is a callback in the dispacher thread to unregister TextStore. ////// Critical - As this calls methods on ITfContext, ItfSource and ITfDocumentMgr /// under elevation to unregister the text source. /// [SecurityCritical] private object OnUnregisterTextStore(object arg) { UnsafeNativeMethods.ITfContext context; UnsafeNativeMethods.ITfSource source; if ((_threadManager == null) || (_threadManager.Value == null)) { return null; } SecurityPermission secperm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); TextStore textstore = (TextStore)arg; // We don't have to release Dispatcher. // These Cicero COM calls could be marshalled when UnregisterTextStore is called from // TextEditor's Finalizer through TextStore.OnDetach. GC Thread does not take Dispatcher. if (textstore.ThreadFocusCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { source = _threadManager.Value as UnsafeNativeMethods.ITfSource; source.UnadviseSink(textstore.ThreadFocusCookie); textstore.ThreadFocusCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } textstore.DocumentManager.GetBase(out context); if (context != null) { if (textstore.EditSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { source = context as UnsafeNativeMethods.ITfSource; source.UnadviseSink(textstore.EditSinkCookie); textstore.EditSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } Marshal.ReleaseComObject(context); } secperm.Assert(); try { textstore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL); } finally { SecurityPermission.RevertAssert(); } Marshal.ReleaseComObject(textstore.DocumentManager); textstore.DocumentManager = null; Debug.Assert(_registeredtextstorecount > 0, "Overrelease TextStore!"); _registeredtextstorecount--; // If Dispatcher is finished and the last textstore // is unregistered, we don't need ThreadManager any more. Deactivate and release it. // We keep ThreadManager active as long as Dispatcher is alive even if // _registeredtextstorecount is 0. if (_isDispatcherShutdownFinished && (_registeredtextstorecount == 0)) { DeactivateThreadManager(); } return null; } // This is a callback when Dispatcher is finished. ////// Critical: This code diactivate thread manager. /// [SecurityCritical] private void OnDispatcherShutdownFinished(object sender, EventArgs args) { Debug.Assert(CheckAccess(), "OnDispatcherShutdownFinished called on bad thread!"); Debug.Assert(_isDispatcherShutdownFinished == false, "Was this dispather finished???"); // Remove the callback. Dispatcher.ShutdownFinished -= new EventHandler(OnDispatcherShutdownFinished); // Deactivate and release the ThreadManager if no more TextStore is registered. if (_registeredtextstorecount == 0) { DeactivateThreadManager(); } // We keep _dispatcherThread even Dispatcher is being finished. Because // this TextServicesHost won't be reused and we want to check if the thread is alive. _isDispatcherShutdownFinished = true; } // Activate TIM if it is not activated yet by this TextServicesHost. // And advise sinks for the given textstore. ////// Critical: This code accesses DocumentMgr,Source /// [SecurityCritical] private void _RegisterTextStore(TextStore textstore) { UnsafeNativeMethods.ITfDocumentMgr doc; UnsafeNativeMethods.ITfContext context; UnsafeNativeMethods.ITfSource source; int editCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; int threadFocusCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; int editSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; Guid guid; Debug.Assert(CheckAccess(), "RegisterTextStore called on bad thread!"); // Get ITfThreadMgr if (_threadManager == null) { Debug.Assert(_isDispatcherShutdownFinished == false, "Was this dispather finished?"); Debug.Assert(_registeredtextstorecount == 0, "TextStore was registered without ThreadMgr?"); // TextServicesLoader.Load() might return null if no text services are installed or enabled. _threadManager = new SecurityCriticalDataClass(TextServicesLoader.Load()); if (_threadManager.Value == null) { _threadManager = null; return; } // Activate TSF on this thread if this is the first TextStore. int clientIdTemp; _threadManager.Value.Activate(out clientIdTemp); _clientId = new SecurityCriticalData (clientIdTemp); // We want to get the notification when Dispatcher is finished. Dispatcher.ShutdownFinished += new EventHandler(OnDispatcherShutdownFinished); } // Create a TSF document. _threadManager.Value.CreateDocumentMgr(out doc); doc.CreateContext(_clientId.Value, 0 /* flags */, textstore, out context, out editCookie); doc.Push(context); // Attach a thread focus sink. if (textstore is UnsafeNativeMethods.ITfThreadFocusSink) { guid = UnsafeNativeMethods.IID_ITfThreadFocusSink; source = _threadManager.Value as UnsafeNativeMethods.ITfSource; source.AdviseSink(ref guid, textstore, out threadFocusCookie); } // Attach an edit sink. if (textstore is UnsafeNativeMethods.ITfTextEditSink) { guid = UnsafeNativeMethods.IID_ITfTextEditSink; source = context as UnsafeNativeMethods.ITfSource; source.AdviseSink(ref guid, textstore, out editSinkCookie); } // Release any native resources we're done with. Marshal.ReleaseComObject(context); textstore.DocumentManager = doc; textstore.ThreadFocusCookie = threadFocusCookie; textstore.EditSinkCookie = editSinkCookie; textstore.EditCookie = editCookie; // If Scope of this textstore already has a focus, we need to call SetFocus() // in order to put this DIM on Cicero's focus. TextStore.OnGotFocus() calls // ITfThreadMgr::SetFocus(); if (textstore.UiScope.IsKeyboardFocused) { textstore.OnGotFocus(); } _registeredtextstorecount++; } // Deactivate and release ThreadManager. /// /// Critical: This code deactivate ThreadManager by accessing ITfThreadMgr /// [SecurityCritical] private void DeactivateThreadManager() { if (_threadManager != null) { if (_threadManager.Value != null) { // 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 (_thread == Thread.CurrentThread || System.Environment.OSVersion.Version.Major >= 6) { _threadManager.Value.Deactivate(); } Marshal.ReleaseComObject(_threadManager.Value); } _threadManager = null; } // ThreadManager was deactivated. It is time to release this TextServicesHost. TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; threadLocalStore.TextServicesHost = null; } #endregion Private Method //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields // Number of the registered TextStore. private int _registeredtextstorecount; // TSF ClientId from Activate call. ////// Critical: _clientId is an identifier for Cicero. /// private SecurityCriticalData_clientId; // The root TSF object, created on demand. /// /// Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. /// private SecurityCriticalDataClass_threadManager; // This is true if Dispatcher is finished. private bool _isDispatcherShutdownFinished; // WinEvent handler for windows move/size. private MoveSizeWinEventHandler _winEvent; // Thread this host has affinity for. private Thread _thread; #endregion Private Fields } } // 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: TextServicesHost implementation. // // History: // 02/12/2004 : yutakas - created // //--------------------------------------------------------------------------- using System; using System.Runtime.InteropServices; using System.Windows.Threading; using System.Threading; using System.Collections; using System.Diagnostics; using System.Windows.Media; using System.Windows.Input; using System.Windows.Documents; using MS.Win32; using MS.Internal; using MS.Internal.PresentationFramework; // SecurityHelper using System.Security; using System.Security.Permissions; namespace System.Windows.Documents { //----------------------------------------------------- // // TextServicesHost class // //----------------------------------------------------- // // This class manages registration of TextStore. // The instance of this class is per Dispatcher and can be shared by // all TextStore in same Dispatcher. // The registration of TextStore does: // - create DocumentManger for each TextStore. // - advise ThreadFocusSink and EditSink. // // This activate ITfThreadMgr and keep the referrence of it. // When Dispatcher is finished, ITfThreadMgr is deactivated and released. // internal class TextServicesHost : DispatcherObject { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors // Creates a new TextServicesHost instance. internal TextServicesHost() { } #endregion Constructors //------------------------------------------------------ // // Internal Method // //------------------------------------------------------ // TextStore calls this to register it and advise sink. ////// Critical: This code accesses DocumentMgr,Source (inside of _RegisterTextStore) /// [SecurityCritical] internal void RegisterTextStore(TextStore textstore) { // VerifyAccess(); Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA, "OnRegisterTextStore must be called on STA thread"); // Register textstore and advise sinks. _RegisterTextStore((TextStore)textstore); _thread = Thread.CurrentThread; } // Free all resources associated with a TextStore. ////// Critical: This code invokes OnUnregisterTextStore which is a Critical method. /// [SecurityCritical] internal void UnregisterTextStore(TextStore textstore, bool finalizer) { if (!finalizer) { OnUnregisterTextStore(textstore); } else { // GC Finalizer is detaching TextStore and the dispatcher thread could be already // terminated or Dispatcher is already finished. if (!_isDispatcherShutdownFinished) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(OnUnregisterTextStore), textstore); } } } ////// Critical: This code calls into native code. /// [SecurityCritical] internal void RegisterWinEventSink(TextStore textstore) { // Start WinEvent hook to listen windows move/size event. // We need to call ITextStoreACPSink::OnLayoutChange() whenever the window is moved. if (_winEvent == null) { _winEvent = new MoveSizeWinEventHandler(); _winEvent.Start(); } _winEvent.RegisterTextStore(textstore); } ////// Critical: This code calls into native code. /// [SecurityCritical] internal void UnregisterWinEventSink(TextStore textstore) { _winEvent.UnregisterTextStore(textstore); // If the registerd text store count is 0, we don't need WinEvent hook any more. if (_winEvent.TextStoreCount == 0) { _winEvent.Stop(); _winEvent.Clear(); _winEvent = null; } } // Start the transitory extestion for Cicero Level1/Level2 composition window support. ////// Critical: This code calls into ITfCompartmentMgr and ItfCompartment both of which are critical /// [SecurityCritical] internal static void StartTransitoryExtension(TextStore textstore) { Guid guid; Object var; UnsafeNativeMethods.ITfCompartmentMgr compmgr; UnsafeNativeMethods.ITfCompartment comp; UnsafeNativeMethods.ITfSource source; int transitoryExtensionSinkCookie; // Start TransitryExtension compmgr = textstore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; // Set GUID_COMPARTMENT_TRANSITORYEXTENSION guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; compmgr.GetCompartment(ref guid, out comp); var = (int)2; // Use level 2 comp.SetValue(0, ref var); // Advise TransitoryExtension Sink and store the cookie. guid = UnsafeNativeMethods.IID_ITfTransitoryExtensionSink; source = textstore.DocumentManager as UnsafeNativeMethods.ITfSource; if (source != null) { // DocumentManager only supports ITfSource on Longhorn, XP does not support it source.AdviseSink(ref guid, textstore, out transitoryExtensionSinkCookie); textstore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie; } Marshal.ReleaseComObject(comp); } // Stop TransitoryExtesion ////// Critical: This code calls into ITfCompartmentMgr and ItfCompartment both of which are critical /// [SecurityCritical] internal static void StopTransitoryExtension(TextStore textstore) { Guid guid; Object var; UnsafeNativeMethods.ITfCompartmentMgr compmgr; UnsafeNativeMethods.ITfCompartment comp; compmgr = textstore.DocumentManager as UnsafeNativeMethods.ITfCompartmentMgr; // Unadvice the transitory extension sink. if (textstore.TransitoryExtensionSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { UnsafeNativeMethods.ITfSource source; source = textstore.DocumentManager as UnsafeNativeMethods.ITfSource; if (source != null) { // DocumentManager only supports ITfSource on Longhorn, XP does not support it source.UnadviseSink(textstore.TransitoryExtensionSinkCookie); } textstore.TransitoryExtensionSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } // Reset GUID_COMPARTMENT_TRANSITORYEXTENSION guid = UnsafeNativeMethods.GUID_COMPARTMENT_TRANSITORYEXTENSION; compmgr.GetCompartment(ref guid, out comp); var = (int)0; comp.SetValue(0, ref var); Marshal.ReleaseComObject(comp); } //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ // Return the text services host associated with the current Dispatcher. internal static TextServicesHost Current { get { TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; if (threadLocalStore.TextServicesHost == null) { threadLocalStore.TextServicesHost = new TextServicesHost(); } return threadLocalStore.TextServicesHost; } } // Return ITfThreadMgr ////// Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. /// internal UnsafeNativeMethods.ITfThreadMgr ThreadManager { [SecurityCritical] get { if (_threadManager == null) { return null; } return _threadManager.Value; } } //----------------------------------------------------- // // Private Method // //----------------------------------------------------- #region Private Method // This is a callback in the dispacher thread to unregister TextStore. ////// Critical - As this calls methods on ITfContext, ItfSource and ITfDocumentMgr /// under elevation to unregister the text source. /// [SecurityCritical] private object OnUnregisterTextStore(object arg) { UnsafeNativeMethods.ITfContext context; UnsafeNativeMethods.ITfSource source; if ((_threadManager == null) || (_threadManager.Value == null)) { return null; } SecurityPermission secperm = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); TextStore textstore = (TextStore)arg; // We don't have to release Dispatcher. // These Cicero COM calls could be marshalled when UnregisterTextStore is called from // TextEditor's Finalizer through TextStore.OnDetach. GC Thread does not take Dispatcher. if (textstore.ThreadFocusCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { source = _threadManager.Value as UnsafeNativeMethods.ITfSource; source.UnadviseSink(textstore.ThreadFocusCookie); textstore.ThreadFocusCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } textstore.DocumentManager.GetBase(out context); if (context != null) { if (textstore.EditSinkCookie != UnsafeNativeMethods.TF_INVALID_COOKIE) { source = context as UnsafeNativeMethods.ITfSource; source.UnadviseSink(textstore.EditSinkCookie); textstore.EditSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } Marshal.ReleaseComObject(context); } secperm.Assert(); try { textstore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL); } finally { SecurityPermission.RevertAssert(); } Marshal.ReleaseComObject(textstore.DocumentManager); textstore.DocumentManager = null; Debug.Assert(_registeredtextstorecount > 0, "Overrelease TextStore!"); _registeredtextstorecount--; // If Dispatcher is finished and the last textstore // is unregistered, we don't need ThreadManager any more. Deactivate and release it. // We keep ThreadManager active as long as Dispatcher is alive even if // _registeredtextstorecount is 0. if (_isDispatcherShutdownFinished && (_registeredtextstorecount == 0)) { DeactivateThreadManager(); } return null; } // This is a callback when Dispatcher is finished. ////// Critical: This code diactivate thread manager. /// [SecurityCritical] private void OnDispatcherShutdownFinished(object sender, EventArgs args) { Debug.Assert(CheckAccess(), "OnDispatcherShutdownFinished called on bad thread!"); Debug.Assert(_isDispatcherShutdownFinished == false, "Was this dispather finished???"); // Remove the callback. Dispatcher.ShutdownFinished -= new EventHandler(OnDispatcherShutdownFinished); // Deactivate and release the ThreadManager if no more TextStore is registered. if (_registeredtextstorecount == 0) { DeactivateThreadManager(); } // We keep _dispatcherThread even Dispatcher is being finished. Because // this TextServicesHost won't be reused and we want to check if the thread is alive. _isDispatcherShutdownFinished = true; } // Activate TIM if it is not activated yet by this TextServicesHost. // And advise sinks for the given textstore. ////// Critical: This code accesses DocumentMgr,Source /// [SecurityCritical] private void _RegisterTextStore(TextStore textstore) { UnsafeNativeMethods.ITfDocumentMgr doc; UnsafeNativeMethods.ITfContext context; UnsafeNativeMethods.ITfSource source; int editCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; int threadFocusCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; int editSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; Guid guid; Debug.Assert(CheckAccess(), "RegisterTextStore called on bad thread!"); // Get ITfThreadMgr if (_threadManager == null) { Debug.Assert(_isDispatcherShutdownFinished == false, "Was this dispather finished?"); Debug.Assert(_registeredtextstorecount == 0, "TextStore was registered without ThreadMgr?"); // TextServicesLoader.Load() might return null if no text services are installed or enabled. _threadManager = new SecurityCriticalDataClass(TextServicesLoader.Load()); if (_threadManager.Value == null) { _threadManager = null; return; } // Activate TSF on this thread if this is the first TextStore. int clientIdTemp; _threadManager.Value.Activate(out clientIdTemp); _clientId = new SecurityCriticalData (clientIdTemp); // We want to get the notification when Dispatcher is finished. Dispatcher.ShutdownFinished += new EventHandler(OnDispatcherShutdownFinished); } // Create a TSF document. _threadManager.Value.CreateDocumentMgr(out doc); doc.CreateContext(_clientId.Value, 0 /* flags */, textstore, out context, out editCookie); doc.Push(context); // Attach a thread focus sink. if (textstore is UnsafeNativeMethods.ITfThreadFocusSink) { guid = UnsafeNativeMethods.IID_ITfThreadFocusSink; source = _threadManager.Value as UnsafeNativeMethods.ITfSource; source.AdviseSink(ref guid, textstore, out threadFocusCookie); } // Attach an edit sink. if (textstore is UnsafeNativeMethods.ITfTextEditSink) { guid = UnsafeNativeMethods.IID_ITfTextEditSink; source = context as UnsafeNativeMethods.ITfSource; source.AdviseSink(ref guid, textstore, out editSinkCookie); } // Release any native resources we're done with. Marshal.ReleaseComObject(context); textstore.DocumentManager = doc; textstore.ThreadFocusCookie = threadFocusCookie; textstore.EditSinkCookie = editSinkCookie; textstore.EditCookie = editCookie; // If Scope of this textstore already has a focus, we need to call SetFocus() // in order to put this DIM on Cicero's focus. TextStore.OnGotFocus() calls // ITfThreadMgr::SetFocus(); if (textstore.UiScope.IsKeyboardFocused) { textstore.OnGotFocus(); } _registeredtextstorecount++; } // Deactivate and release ThreadManager. /// /// Critical: This code deactivate ThreadManager by accessing ITfThreadMgr /// [SecurityCritical] private void DeactivateThreadManager() { if (_threadManager != null) { if (_threadManager.Value != null) { // 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 (_thread == Thread.CurrentThread || System.Environment.OSVersion.Version.Major >= 6) { _threadManager.Value.Deactivate(); } Marshal.ReleaseComObject(_threadManager.Value); } _threadManager = null; } // ThreadManager was deactivated. It is time to release this TextServicesHost. TextEditorThreadLocalStore threadLocalStore = TextEditor._ThreadLocalStore; threadLocalStore.TextServicesHost = null; } #endregion Private Method //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields // Number of the registered TextStore. private int _registeredtextstorecount; // TSF ClientId from Activate call. ////// Critical: _clientId is an identifier for Cicero. /// private SecurityCriticalData_clientId; // The root TSF object, created on demand. /// /// Critical: UnsafeNativeMethods.ITfThreadMgr has methods with SuppressUnmanagedCodeSecurity. /// private SecurityCriticalDataClass_threadManager; // This is true if Dispatcher is finished. private bool _isDispatcherShutdownFinished; // WinEvent handler for windows move/size. private MoveSizeWinEventHandler _winEvent; // Thread this host has affinity for. private Thread _thread; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ICollection.cs
- DataSourceIDConverter.cs
- LinkConverter.cs
- HttpApplication.cs
- LoginViewDesigner.cs
- SettingsPropertyValue.cs
- DotNetATv1WindowsLogEntrySerializer.cs
- XmlReaderSettings.cs
- UrlPath.cs
- RegexCode.cs
- SqlRewriteScalarSubqueries.cs
- OpacityConverter.cs
- UnmanagedMemoryStream.cs
- ExpressionConverter.cs
- MonthChangedEventArgs.cs
- Point3DAnimationUsingKeyFrames.cs
- RelatedView.cs
- LockedBorderGlyph.cs
- StylusPointDescription.cs
- RsaSecurityKey.cs
- ResponseStream.cs
- ToolStripStatusLabel.cs
- IntranetCredentialPolicy.cs
- ProfileGroupSettingsCollection.cs
- _ScatterGatherBuffers.cs
- ModifierKeysValueSerializer.cs
- CroppedBitmap.cs
- Single.cs
- XmlIlTypeHelper.cs
- PageDeviceFont.cs
- UnsafeNativeMethods.cs
- TransactionManager.cs
- ImpersonationContext.cs
- Lease.cs
- CodeNamespace.cs
- mactripleDES.cs
- SchemaSetCompiler.cs
- TextHidden.cs
- DefaultTextStore.cs
- SwitchLevelAttribute.cs
- CollectionBase.cs
- StylusPointPropertyInfoDefaults.cs
- ConfigXmlWhitespace.cs
- InteropExecutor.cs
- TemplateBindingExpression.cs
- X509IssuerSerialKeyIdentifierClause.cs
- TraceXPathNavigator.cs
- SoapReflectionImporter.cs
- HtmlLink.cs
- ListenerElementsCollection.cs
- AttachedPropertyInfo.cs
- SqlDelegatedTransaction.cs
- RepeatBehavior.cs
- ConnectionManagementElementCollection.cs
- Scalars.cs
- PageStatePersister.cs
- LayoutInformation.cs
- TreeBuilderBamlTranslator.cs
- OperationSelectorBehavior.cs
- SystemFonts.cs
- IEnumerable.cs
- CustomCategoryAttribute.cs
- GridViewRow.cs
- SelectorItemAutomationPeer.cs
- TableItemStyle.cs
- NavigatorOutput.cs
- ObjectPersistData.cs
- BezierSegment.cs
- Debugger.cs
- SoapIgnoreAttribute.cs
- RegistryKey.cs
- HitTestParameters3D.cs
- SystemWebExtensionsSectionGroup.cs
- RegexGroup.cs
- UnsafeNativeMethods.cs
- CharUnicodeInfo.cs
- VisualCollection.cs
- FunctionMappingTranslator.cs
- QilPatternFactory.cs
- Style.cs
- GridItemProviderWrapper.cs
- StaticResourceExtension.cs
- CapabilitiesRule.cs
- PropertyGrid.cs
- InternalRelationshipCollection.cs
- Compiler.cs
- CompilerInfo.cs
- ToolBar.cs
- DataListItem.cs
- AssemblyResourceLoader.cs
- JulianCalendar.cs
- RequestCachePolicy.cs
- TreeNode.cs
- XmlSchemaSimpleContentRestriction.cs
- streamingZipPartStream.cs
- FusionWrap.cs
- TextEffectCollection.cs
- BlobPersonalizationState.cs
- IsolatedStorageFilePermission.cs
- SchemaTypeEmitter.cs