|
//------------------------------------------------------------------------------
// <copyright file="ComponentDispatcherThread.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using MS.Win32;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using MS.Internal.WindowsBase;
namespace System.Windows.Interop
{
/// <summary>
/// This is a class used to implement per-thread instance of the ComponentDispatcher.
///</summary>
internal class ComponentDispatcherThread
{
/// <summary>
/// Returns true if one or more components has gone modal.
/// Although once one component is modal a 2nd shouldn't.
///</summary>
public bool IsThreadModal
{
get
{
return (_modalCount > 0);
}
}
/// <summary>
/// Returns "current" message. More exactly the last MSG Raised.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth to avoid leaking message information
/// </SecurityNote>
public MSG CurrentKeyboardMessage
{
[SecurityCritical]
get
{
return _currentKeyboardMSG;
}
[SecurityCritical]
set
{
_currentKeyboardMSG = value;
}
}
/// <summary>
/// A component calls this to go modal. Current thread wide only.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth
/// </SecurityNote>
[SecurityCritical]
public void PushModal()
{
_modalCount += 1;
if(1 == _modalCount)
{
if(null != _enterThreadModal)
_enterThreadModal(null, EventArgs.Empty);
}
}
/// <summary>
/// A component calls this to end being modal.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth to avoid tampering with input
/// </SecurityNote>
[SecurityCritical]
public void PopModal()
{
_modalCount -= 1;
if(0 == _modalCount)
{
if(null != _leaveThreadModal)
_leaveThreadModal(null, EventArgs.Empty);
}
if(_modalCount < 0)
_modalCount = 0; // Throwing is also good
}
/// <summary>
/// The message loop pumper calls this when it is time to do idle processing.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth
/// </SecurityNote>
[SecurityCritical]
public void RaiseIdle()
{
if(null != _threadIdle)
_threadIdle(null, EventArgs.Empty);
}
/// <summary>
/// The message loop pumper calls this for every keyboard message.
/// </summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth to prevent message leakage
/// </SecurityNote>
[SecurityCritical]
public bool RaiseThreadMessage(ref MSG msg)
{
bool handled = false;
if (null != _threadFilterMessage)
_threadFilterMessage(ref msg, ref handled);
if (handled)
return handled;
if (null != _threadPreprocessMessage)
_threadPreprocessMessage(ref msg, ref handled);
return handled;
}
/// <summary>
/// Components register delegates with this event to handle
/// thread idle processing.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
public event EventHandler ThreadIdle
{
[SecurityCritical]
add
{
_threadIdle += value;
}
[SecurityCritical]
remove
{
_threadIdle -= value;
}
}
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
[method:SecurityCritical]
private event EventHandler _threadIdle;
/// <summary>
/// Components register delegates with this event to handle
/// Keyboard Messages (first chance processing).
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
public event ThreadMessageEventHandler ThreadFilterMessage
{
[SecurityCritical]
add
{
_threadFilterMessage += value;
}
[SecurityCritical]
remove
{
_threadFilterMessage -= value;
}
}
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
[method:SecurityCritical]
private event ThreadMessageEventHandler _threadFilterMessage;
/// <summary>
/// Components register delegates with this event to handle
/// Keyboard Messages (second chance processing).
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
public event ThreadMessageEventHandler ThreadPreprocessMessage
{
[SecurityCritical]
add
{
_threadPreprocessMessage += value;
}
[SecurityCritical]
remove
{
_threadPreprocessMessage -= value;
}
}
/// <summary>
/// Adds the specified handler to the front of the invocation list
/// of the PreprocessMessage event.
/// <summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used
/// to transmit input related information
/// </SecurityNote>
[SecurityCritical]
public void AddThreadPreprocessMessageHandlerFirst(ThreadMessageEventHandler handler)
{
_threadPreprocessMessage = (ThreadMessageEventHandler)Delegate.Combine(handler, _threadPreprocessMessage);
}
/// <summary>
/// Removes the first occurance of the specified handler from the
/// invocation list of the PreprocessMessage event.
/// <summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used
/// to transmit input related information
/// </SecurityNote>
[SecurityCritical]
public void RemoveThreadPreprocessMessageHandlerFirst(ThreadMessageEventHandler handler)
{
if (_threadPreprocessMessage != null)
{
ThreadMessageEventHandler newHandler = null;
foreach (ThreadMessageEventHandler testHandler in _threadPreprocessMessage.GetInvocationList())
{
if (testHandler == handler)
{
// This is the handler to remove. We should not check
// for any more occurances.
handler = null;
}
else
{
newHandler += testHandler;
}
}
_threadPreprocessMessage = newHandler;
}
}
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
[method:SecurityCritical]
private event ThreadMessageEventHandler _threadPreprocessMessage;
/// <summary>
/// Components register delegates with this event to handle
/// a component on this thread has "gone modal", when previously none were.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
public event EventHandler EnterThreadModal
{
[SecurityCritical]
add
{
_enterThreadModal += value;
}
[SecurityCritical]
remove
{
_enterThreadModal -= value;
}
}
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
[method:SecurityCritical]
private event EventHandler _enterThreadModal;
/// <summary>
/// Components register delegates with this event to handle
/// all components on this thread are done being modal.
///</summary>
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
public event EventHandler LeaveThreadModal
{
[SecurityCritical]
add
{
_leaveThreadModal += value;
}
[SecurityCritical]
remove
{
_leaveThreadModal -= value;
}
}
/// <SecurityNote>
/// Critical: This is blocked off as defense in depth and is used to transmit input related information
/// </SecurityNote>
[method:SecurityCritical]
private event EventHandler _leaveThreadModal;
private int _modalCount;
/// <SecurityNote>
/// Critical: This holds the last message that was recieved
/// </SecurityNote>
[SecurityCritical]
private MSG _currentKeyboardMSG;
}
}
|