HwndSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / InterOp / HwndSource.cs / 1305600 / HwndSource.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2004
//
//  File: HwndSource.cs 
//-----------------------------------------------------------------------------
 
using System.Collections; 
using System.Collections.Generic;
using System.Threading; 
using System.Windows.Threading;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Interop; 
using System.Runtime.InteropServices;
using MS.Win32; 
using MS.Utility; 
using MS.Internal;
using MS.Internal.Interop; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using Microsoft.Win32;
using System.Diagnostics;
using System.ComponentModel; 
using System;
using System.Security; 
using System.Security.Permissions; 
using System.IO;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings 

namespace System.Windows.Interop 
{ 
    /// 
    ///     The HwndSource class presents content within a Win32 HWND. 
    /// 
    public class HwndSource : PresentationSource, IDisposable, IWin32Window, IKeyboardInputSink
    {
        ///  
        ///     Critical: This code calls into RegisterWindowMesssage which is critical
        ///     TreatAsSafe: This is safe to call as no external parameters are taken in 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        static HwndSource() 
        {
            _threadSlot = Thread.AllocateDataSlot();
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class that will always resize to its content size. 
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        /// 
        /// 
        ///     The Win32 styles for this window.
        ///  
        /// 
        ///     The extended Win32 styles for this window. 
        ///  
        /// 
        ///     The position of the left edge of this window. 
        /// 
        /// 
        ///     The position of the upper edge of this window.
        ///  
        /// 
        ///     The name of this window. 
        ///  
        /// 
        ///     The Win32 window that should be the parent of this window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions 
        /// 
        [SecurityCritical]
        public HwndSource(
            int classStyle, 
            int style,
            int exStyle, 
            int x, 
            int y,
            string name, 
            IntPtr parent)
        {
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters param = new HwndSourceParameters(name);
            param.WindowClassStyle = classStyle; 
            param.WindowStyle = style; 
            param.ExtendedWindowStyle = exStyle;
            param.SetPosition(x, y); 
            param.ParentWindow = parent;
            Initialize(param);
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an 
        ///    explicit width and height be sepecified. 
        /// 
        ///  
        ///     The Win32 class styles for this window.
        /// 
        /// 
        ///     The Win32 styles for this window. 
        /// 
        ///  
        ///     The extended Win32 styles for this window. 
        /// 
        ///  
        ///     The position of the left edge of this window.
        /// 
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        ///  
        ///     The width of this window. 
        /// 
        ///  
        ///     The height of this window.
        /// 
        /// 
        ///     The name of this window. 
        /// 
        ///  
        ///     The Win32 window that should be the parent of this window. 
        /// 
        ///  
        ///     Indicates that HwndSource should include the non-client area
        ///     of the hwnd when it calls the Layout Manager
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        ///  
        ///     Added a demand - so that this API does not work in InternetZone.
        ///     Critical: This acceses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        /// 
        [SecurityCritical] 
        public HwndSource(int classStyle,
                          int style, 
                          int exStyle, 
                          int x,
                          int y, 
                          int width,
                          int height,
                          string name,
                          IntPtr parent, 
                          bool adjustSizingForNonClientArea)
        { 
            SecurityHelper.DemandUIWindowPermission(); 

            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height); 
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle;
            parameters.SetPosition(x, y); 
            parameters.ParentWindow = parent;
            parameters.AdjustSizingForNonClientArea = adjustSizingForNonClientArea; 
            Initialize(parameters); 
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an
        ///    explicit width and height be sepecified.
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        ///  
        /// 
        ///     The Win32 styles for this window. 
        /// 
        /// 
        ///     The extended Win32 styles for this window.
        ///  
        /// 
        ///     The position of the left edge of this window. 
        ///  
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        /// 
        ///     The width of this window.
        ///  
        /// 
        ///     The height of this window. 
        ///  
        /// 
        ///     The name of this window. 
        /// 
        /// 
        ///     The Win32 window that should be the parent of this window.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        ///  
        [SecurityCritical]
        public HwndSource( 
            int classStyle, 
            int style,
            int exStyle, 
            int x,
            int y,
            int width,
            int height, 
            string name,
            IntPtr parent) 
        { 
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height);
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle; 
            parameters.SetPosition(x, y);
            parameters.ParentWindow = parent; 
            Initialize(parameters); 
        }
 
        /// 
        ///    HwndSource Ctor
        /// 
        ///  parameter block  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Critical: This acceses critical code Initialize 
        /// 
        [SecurityCritical]
        [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        public HwndSource(HwndSourceParameters parameters) 
        {
            Initialize(parameters); 
        } 
        /// 
        ///    HwndSource Ctor 
        /// 
        ///  parameter block 
        /// 
        ///     Critical: This code access critical (HwndMouseInputProvider, HwndKeyboardInputProvider 
        ///     ,HwndStylusInputProvider and the various hooks)objects and creates the
        ///     providers under elevation. 
        ///  
        [SecurityCritical]
        private void Initialize(HwndSourceParameters parameters) 
        {
            _mouse = new SecurityCriticalDataClass(new HwndMouseInputProvider(this));
            _keyboard = new SecurityCriticalDataClass(new HwndKeyboardInputProvider(this));
            _layoutHook = new HwndWrapperHook(LayoutFilterMessage); 
            _inputHook = new HwndWrapperHook(InputFilterMessage);
            _hwndTargetHook = new HwndWrapperHook(HwndTargetFilterMessage); 
 
            _publicHook = new HwndWrapperHook(PublicHooksFilterMessage);
 
            // When processing WM_SIZE, LayoutFilterMessage must be invoked before
            // HwndTargetFilterMessage. This way layout will be updated before resizing
            // HwndTarget, resulting in single render per resize. This means that
            // layout hook should appear before HwndTarget hook in the wrapper hooks 
            // list. If this is done the other way around, first HwndTarget resize will
            // force re-render, then layout will be updated according to the new size, 
            // scheduling another render. 
            HwndWrapperHook[] wrapperHooks = { _hwndTargetHook, _layoutHook, _inputHook, null };
 
            if (null != parameters.HwndSourceHook)
            {
                // In case there's more than one delegate, add these to the event storage backwards
                // so they'll get invoked in the expected order. 
                Delegate[] handlers = parameters.HwndSourceHook.GetInvocationList();
                for (int i = handlers.Length -1; i >= 0; --i) 
                { 
                    _hooks += (HwndSourceHook)handlers[i];
                } 
                wrapperHooks[3] = _publicHook;
            }

            _restoreFocusMode = parameters.RestoreFocusMode; 
            _acquireHwndFocusInMenuMode = parameters.AcquireHwndFocusInMenuMode;
 
            // A window must be marked WS_EX_LAYERED if (and only if): 
            // 1) it is not a child window
            //    -- AND -- 
            // 2) a color-key is specified
            // 3) or an opacity other than 1.0 is specified
            // 4) or per-pixel alpha is requested.
            if((parameters.WindowStyle & NativeMethods.WS_CHILD) == 0 && 
               ( //parameters.ColorKey != null ||
                 //!MS.Internal.DoubleUtil.AreClose(parameters.Opacity, 1.0) || 
                parameters.UsesPerPixelOpacity)) 
            {
                parameters.ExtendedWindowStyle |= NativeMethods.WS_EX_LAYERED; 
            }
            else
            {
                parameters.ExtendedWindowStyle &= (~NativeMethods.WS_EX_LAYERED); 
            }
 
 
            _constructionParameters = parameters;
            _hwndWrapper = new HwndWrapper(parameters.WindowClassStyle, 
                                       parameters.WindowStyle,
                                       parameters.ExtendedWindowStyle,
                                       parameters.PositionX,
                                       parameters.PositionY, 
                                       parameters.Width,
                                       parameters.Height, 
                                       parameters.WindowName, 
                                       parameters.ParentWindow,
                                       wrapperHooks); 

            _hwndTarget = new HwndTarget(_hwndWrapper.Handle);
            //_hwndTarget.ColorKey = parameters.ColorKey;
            //_hwndTarget.Opacity = parameters.Opacity; 
            _hwndTarget.UsesPerPixelOpacity = parameters.UsesPerPixelOpacity;
            if(_hwndTarget.UsesPerPixelOpacity) 
            { 
                _hwndTarget.BackgroundColor = Colors.Transparent;
 
                // Prevent this window from being themed.
                UnsafeNativeMethods.CriticalSetWindowTheme(new HandleRef(this, _hwndWrapper.Handle), "", "");
            }
            _constructionParameters = null; 

            if (!parameters.HasAssignedSize) 
                _sizeToContent = SizeToContent.WidthAndHeight; 
            _adjustSizingForNonClientArea = parameters.AdjustSizingForNonClientArea;
 
            // Listen to the UIContext.Disposed event so we can clean up.
            // The HwndTarget cannot work without a MediaContext which
            // is disposed when the UIContext is disposed.  So we need to
            // dispose the HwndTarget and also never use it again (to 
            // paint or process input).  The easiest way to do this is to just
            // dispose the HwndSource at the same time. 
            _weakShutdownHandler = new WeakEventDispatcherShutdown(this, this.Dispatcher); 

            // Listen to the HwndWrapper.Disposed event so we can clean up. 
            // The HwndTarget cannot work without a live HWND, and since
            // the HwndSource represents an HWND, we make sure we dispose
            // ourselves if the HWND is destroyed out from underneath us.
            _hwndWrapper.Disposed += new EventHandler(OnHwndDisposed); 

            _stylus = new SecurityCriticalDataClass(new HwndStylusInputProvider(this)); 
 
            // WM_APPCOMMAND events are handled thru this.
            _appCommand = new SecurityCriticalDataClass(new HwndAppCommandInputProvider(this)); 

            // Register the top level source with the ComponentDispatcher.
            if (parameters.TreatAsInputRoot)
            { 
                _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this, false);
            } 
            AddSource(); 

            // Register dropable window. 
            // The checking CallerHasPermissionWithAppDomainOptimization will call RegisterDropTarget
            // safely without the security exception in case of no unmanaged code permission.
            // So RegisterDropTarget will be called safely in case of having the unmanged code permission.
            // Otherwise, the security exception cause System.Printing to be instatiated which will 
            // load system.drawing module.
            if (_hwndWrapper.Handle != IntPtr.Zero && 
                SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode))) 
            {
                // This call is safe since DragDrop.RegisterDropTarget is checking the unmanged 
                // code permission.
                DragDrop.RegisterDropTarget(_hwndWrapper.Handle);
                _registeredDropTargetCount++;
            } 
        }
 
        ///  
        ///     Disposes the object
        ///  
        ///
        /// This API is not available in Internet Zone.
        ///
        public void Dispose() 
        {
            Dispose(true); 
            GC.SuppressFinalize(this); 
        }
 
        /// 
        ///     Adds a hook that gets called for every window message.
        /// 
        ///  
        ///     The hook to add.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        ///
        /// Critical - uses a critical field.
        /// PublicOK - as there's a demand.
        /// 
        [SecurityCritical ]
        public void AddHook(HwndSourceHook hook) 
        { 
            SecurityHelper.DemandUIWindowPermission();
            Verify.IsNotNull(hook, "hook"); 

            CheckDisposed(true);

            if(_hooks == null) 
            {
                _hwndWrapper.AddHook(_publicHook); 
            } 
            _hooks += hook;
        } 

        /// 
        ///     Removes a hook that was previously added.
        ///  
        /// 
        ///     The hook to remove. 
        ///  
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///
        ///
        /// Critical - accesses a crtical field - _publicHook
        /// PublicOK - performs a demand. 
        ///
        [SecurityCritical ] 
        public void RemoveHook(HwndSourceHook hook) 
        {
            SecurityHelper.DemandUIWindowPermission(); 

            //this.VerifyAccess();

            _hooks -= hook; 
            if(_hooks == null)
            { 
                _hwndWrapper.RemoveHook(_publicHook); 
            }
        } 

        /// 
        /// GetInputProvider - Given a InputDevice, returns corresponding Provider
        ///  
        /// InputDevice for which we need InputProvider
        /// InputProvider, if known 
        /// 
        /// This API is not available in Internet Zone.
        /// 
        /// 
        ///     Critical: This code accesses and returns critical data *providers*
        /// 
        [SecurityCritical] 
        internal override IInputProvider GetInputProvider(Type inputDevice)
        { 
            if (inputDevice == typeof(MouseDevice)) 
                return (_mouse    != null ?    _mouse.Value : null);
 
            if (inputDevice == typeof(KeyboardDevice))
                return (_keyboard != null ? _keyboard.Value : null);

            if (inputDevice == typeof(StylusDevice)) 
                return (_stylus   != null ?   _stylus.Value : null);
 
            return null; 
        }
 
        /// 
        ///     Announces when this source is disposed.
        /// 
        public event EventHandler Disposed; 

        ///  
        ///     Announces when the SizeToContent property changes on this source. 
        /// 
        public event EventHandler SizeToContentChanged; 

        /// 
        ///     Whether or not the object is disposed.
        ///  
        public override bool IsDisposed {get {return _isDisposed;}}
 
        ///  
        /// The Root Visual for this window. If it is a UIElement
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        ///  
        ///     Critical: This code sets a rootvisual which is risky to do because
        ///     it can destabilize assumptions made in popup code 
        ///     PublicOK: The getter is safe and the setter has a link demand to block unwarrented 
        ///     public use
        ///  
        public override Visual RootVisual
        {
            [SecurityCritical]
            get 
            {
                if (_isDisposed) 
                    return null; 
                return (_rootVisual.Value);
            } 
            [SecurityCritical]
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
            set
            { 
                CheckDisposed(true);
 
                RootVisualInternal = value; 
            }
        } 

        /// 
        /// Critical: Acceses KeyboardInputProvider which is considered as critical data
        /// also it can be used to set root visual which is deemed as an unsafe operation 
        /// 
        private Visual RootVisualInternal 
        { 
            [SecurityCritical]
            set 
            {
                if (_rootVisual.Value != value)
                {
                    Visual oldRoot = _rootVisual.Value; 

                    if(value != null) 
                    { 
                        _rootVisual.Value = value;
 
                        if(_rootVisual.Value is UIElement)
                        {
                            ((UIElement)(_rootVisual.Value)).LayoutUpdated += new EventHandler(OnLayoutUpdated);
                        } 

                        if (_hwndTarget != null && _hwndTarget.IsDisposed == false) 
                        { 
                            _hwndTarget.RootVisual = _rootVisual.Value;
                        } 

                        UIElement.PropagateResumeLayout(null, value);
                    }
                    else 
                    {
                        _rootVisual.Value = null; 
                        if (_hwndTarget != null && !_hwndTarget.IsDisposed) 
                        {
                            _hwndTarget.RootVisual = null; 
                        }
                    }

                    if(oldRoot != null) 
                    {
                        if(oldRoot is UIElement) 
                        { 
                            ((UIElement)oldRoot).LayoutUpdated -= new EventHandler(OnLayoutUpdated);
                        } 

                        UIElement.PropagateSuspendLayout(oldRoot);
                    }
 
                    RootChanged(oldRoot, _rootVisual.Value);
 
                    if (IsLayoutActive() == true) 
                    {
                        // Call the helper method SetLayoutSize to set Layout's size 
                        SetLayoutSize();

                        // Post the firing of ContentRendered as Input priority work item so that ContentRendered will be
                        // fired after render query empties. 
                        this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(FireContentRendered), this);
                    } 
                    else 
                    {
                        // Even though layout won't run (the root visual is either null or not 
                        // a UIElement), the hit-test results will certainly have changed.
                        InputManager.SafeCurrentNotifyHitTestInvalidated();
                    }
 
                    // It is possible that someone would have closed the window in one of the
                    // previous callouts - such as during RootChanged or during the layout 
                    // we syncronously invoke.  In such cases, the state of this object would 
                    // have been torn down.  We just need to protect against that.
                    if(_keyboard != null) 
                    {
                        _keyboard.Value.OnRootChanged(oldRoot, _rootVisual.Value);
                    }
                } 
            }
        } 
 
        /// 
        ///     Returns a sequence of registered input sinks. 
        /// 
        public IEnumerable ChildKeyboardInputSinks
        {
            get 
            {
                if (_keyboardInputSinkChildren != null) 
                { 
                    foreach (IKeyboardInputSite site in _keyboardInputSinkChildren)
                        yield return site.Sink; 
                }
            }
        }
 
        /// 
        ///     Returns the HwndSource that corresponds to the specified window. 
        ///  
        /// The window.
        /// The source that corresponds to the specified window. 
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///
        ///  
        ///     Critical: This information is not ok to expose since this HwndSource
        ///     is deemed critical to expose 
        ///     PublicOK: There is a demand on this method that prevents this 
        ///     from working in partial trust unless you have the right permissions.
        ///  
        [SecurityCritical]
        public static HwndSource FromHwnd(IntPtr hwnd)
        {
            SecurityHelper.DemandUIWindowPermission(); 
            return CriticalFromHwnd(hwnd);
        } 
 
        /// 
        ///    Critical: This code extracts the HwndSource for an HWND 
        ///    This function is only for internal consumption
        /// 
        [SecurityCritical]
        internal static HwndSource CriticalFromHwnd(IntPtr hwnd) 
        {
            if (hwnd == IntPtr.Zero) 
            { 
                throw new ArgumentException(SR.Get(SRID.NullHwnd));
            } 
            HwndSource hwndSource = null;
            foreach (PresentationSource source in PresentationSource.CriticalCurrentSources)
            {
                HwndSource test = source as HwndSource; 
                if (test != null && test.CriticalHandle == hwnd)
                { 
                    // Don't hand out a disposed source. 
                    if (!test.IsDisposed)
                        hwndSource = test; 
                    break;
                }
            }
            return hwndSource; 
        }
 
 
        /// 
        ///     The visual manager for the visuals being presented in the source. 
        ///     Type-specific version of the CompositionTarget property for this source.
        /// 
        /// 
        ///     Critical: Accesses hwndTarget and returns it 
        ///     PublicOk: Protected by a LinkDemand
        ///  
        public new HwndTarget CompositionTarget 
        {
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
            get
            {
                if (_isDisposed) 
                    return null;
 
                // Even though we created the HwndTarget, it can get disposed out from 
                // underneath us.
                if (_hwndTarget!= null && _hwndTarget.IsDisposed == true) 
                {
                    return null;
                }
 
                return _hwndTarget;
            } 
        } 

        ///  
        ///     Returns visual target for this source.
        /// 
        /// 
        ///     Critical: calls get_CompositionTarget() and returns its value. 
        /// 
        [SecurityCritical] 
        protected override CompositionTarget GetCompositionTargetCore() 
        {
            return CompositionTarget; 
        }

        /// 
        ///     When an HwndSource enters menu mode, it subscribes to the 
        ///     ComponentDispatcher.ThreadPreprocessMessage event to get
        ///     privileged access to the window messages. 
        ///  
        /// 
        ///     The ThreadPreprocessMessage handler for menu mode is 
        ///     independent of the handler for the same event used for
        ///     keyboard processing by top-level windows.
        /// 
        ///  
        ///     Critical: Accesses the ComponentDispatcher, which is generally
        ///               considered critical. 
        ///     TreatAsSafe: MenuMode is approved for public access. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void OnEnterMenuMode()
        {
            // We opt-in this HwndSource to the new behavior for "exclusive"
            // menu mode only if AcquireHwndFocusInMenuMode is false. 
            IsInExclusiveMenuMode = !_acquireHwndFocusInMenuMode;
            if(IsInExclusiveMenuMode) 
            { 
                Debug.Assert(_weakMenuModeMessageHandler == null);
 
                // Re-subscribe to the ComponentDispatcher.ThreadPreprocessMessage so we go first.
                _weakMenuModeMessageHandler = new WeakEventPreprocessMessage(this, true);

                // Hide the Win32 caret 
                UnsafeNativeMethods.HideCaret(new HandleRef(this, IntPtr.Zero));
            } 
        } 

        ///  
        ///     When an HwndSource leaves menu mode, it unsubscribes from the
        ///     ComponentDispatcher.ThreadPreprocessMessage event because it no
        ///     longer needs privileged access to the window messages.
        ///  
        /// 
        ///     The ThreadPreprocessMessage handler for menu mode is 
        ///     independent of the handler for the same event used for 
        ///     keyboard processing by top-level windows.
        ///  
        /// 
        ///     Critical: Accesses the ComponentDispatcher, which is generally
        ///               considered critical.
        ///     TreatAsSafe: MenuMode is approved for public access. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void OnLeaveMenuMode() 
        {
            if(IsInExclusiveMenuMode) 
            {
                Debug.Assert(_weakMenuModeMessageHandler != null);

                // Unsubscribe the special menu-mode handler since we don't need to go first anymore. 
                _weakMenuModeMessageHandler.Dispose();
                _weakMenuModeMessageHandler = null; 
 
                // Restore the Win32 caret.  This does not necessarily show the caret, it
                // just undoes the HideCaret call in OnEnterMenuMode. 
                UnsafeNativeMethods.ShowCaret(new HandleRef(this, IntPtr.Zero));
            }
            IsInExclusiveMenuMode = false;
        } 

        internal bool IsInExclusiveMenuMode{get; private set;} 
 
        /// 
        ///     Event invoked when the layout causes the HwndSource to resize automatically. 
        /// 
        public event AutoResizedEventHandler AutoResized;

        ///  
        /// Handler for LayoutUpdated event of a rootVisual.
        ///  
        ///  
        ///     Critical: This code causes resize of window and accesses HwndTarget
        ///  
        [SecurityCritical]
        private void OnLayoutUpdated(object obj, EventArgs args)
        {
            UIElement root = _rootVisual.Value as UIElement; 

            if(root != null) 
            { 
                Size newSize = root.RenderSize;
                if (   _previousSize == null 
                    || !DoubleUtil.AreClose(_previousSize.Value.Width, newSize.Width)
                    || !DoubleUtil.AreClose(_previousSize.Value.Height, newSize.Height))
                {
                    // We should update _previousSize, even if the hwnd is not 
                    // sizing to content.  This fixes the scenario where:
                    // 
                    // 1) hwnd is sized to content to say a, b 
                    // 2) hwnd is resize to a bigger size
                    // 3) hwnd is sized to content to a, b again 
                    _previousSize = newSize;

                    //
                    // Don't resize while the Window is in Minimized mode. 
                    //
                    if (_sizeToContent != SizeToContent.Manual && !_isWindowInMinimizeState ) 
                    { 
                        Resize(newSize);
                    } 
                }
            }
        }
 
        /// 
        /// This is called when LayoutManager was updated and its size (the layout size of top element) changed. 
        /// Ask LayoutManager.Size to see what the new value is. 
        /// 
        ///  
        ///     Critical: This code causes resize of window and accesses HwndTarget
        ///     TreatAsSafe: In RBW the resize values are clamped also one cannot construct or get to a HwndSource in partial trust
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void Resize(Size newSize)
        { 
            try 
            {
                _myOwnUpdate = true; 

                if (IsUsable)
                {
                    NativeMethods.RECT rect = AdjustWindowSize(newSize); 

                    int newWidth = rect.right - rect.left; 
                    int newHeight = rect.bottom - rect.top; 

                    // Set the new window size 
                    UnsafeNativeMethods.SetWindowPos(new HandleRef(this,_hwndWrapper.Handle), new HandleRef(null,IntPtr.Zero),
                                                   0, 0, newWidth, newHeight,
                                                   NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
 
                    if (AutoResized != null)
                    { 
                        AutoResized(this, new AutoResizedEventArgs(newSize)); 
                    }
                } 
            }
            finally
            {
                _myOwnUpdate = false; 
            }
        } 
 
        /// 
        /// This shows the system menu for the top level window that this HwndSource is in. 
        /// 
        /// 
        ///     Critical: Accesses GetAncestor & PostMessage.  This method is deemed inherently unsafe
        ///               because opening the system menu will eat user input. 
        /// 
        [SecurityCritical] 
        internal void ShowSystemMenu() 
        {
            // Find the topmost window.  This will handle the case where the HwndSource 
            // is a child window.
            IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT);

            // Open the system menu. 
            UnsafeNativeMethods.PostMessage(new HandleRef(this, hwndRoot), MS.Internal.Interop.WindowMessage.WM_SYSCOMMAND, new IntPtr(NativeMethods.SC_KEYMENU), new IntPtr(NativeMethods.VK_SPACE));
        } 
 
        /// 
        ///     Critical: This code accesses critical member _hwndTarget. 
        ///     TreatAsSafe: It calculates the new point without changing the HWND.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal Point TransformToDevice(Point pt) 
        {
            // 
            return _hwndTarget.TransformToDevice.Transform(pt); 
        }
 
        /// 
        ///     Critical: This code accesses critical member _hwndTarget.
        ///     TreatAsSafe: It calculates the new point without changing the HWND.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal Point TransformFromDevice(Point pt) 
        { 
            return _hwndTarget.TransformFromDevice.Transform(pt);
        } 

        /// 
        ///     Critical: This code accesses _hwndWrapper.
        ///     TreatAsSafe: It calculates the hwnd size without changing it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private NativeMethods.RECT AdjustWindowSize(Size newSize) 
        {
            // Gather the new client dimensions 
            // The dimension WPF uses is logical unit. We need to convert to device unit first.
            Point pt = TransformToDevice(new Point(newSize.Width, newSize.Height));
            RoundDeviceSize(ref pt);
            NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); 

            // If we're here, and it is the Window case (_adjustSizingForNonClientArea == true) 
            // we get the size which includes the outside size of the window.  For browser case, 
            // we don't support SizeToContent, so we don't take care of this condition.
            // For non-Window cases, we need to calculate the outside size of the window 
            //
            // For windows with UsesPerPixelOpacity, we force the client to
            // fill the window, so we don't need to add in any frame space.
            // 
            if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity)
            { 
                int style = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this, _hwndWrapper.Handle), false)); 
                int styleEx = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this, _hwndWrapper.Handle), true));
 
                SafeNativeMethods.AdjustWindowRectEx(ref rect, style, false, styleEx);
            }
            return rect;
        } 

        // If the root element has Pixel snapping enabled, round the window size to the 
        // nearest int.  Otherwise round the size up to the next int. 
        private void RoundDeviceSize(ref Point size)
        { 
            UIElement root = _rootVisual.Value as UIElement;
            if (root != null && root.SnapsToDevicePixels)
            {
                size = new Point(DoubleUtil.DoubleToInt(size.X), DoubleUtil.DoubleToInt(size.Y)); 
            }
            else 
            { 
                size = new Point(Math.Ceiling(size.X), Math.Ceiling(size.Y));
            } 
        }

        /// 
        /// Returns the hwnd handle to the window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///
        ///  
        ///     Critical:This is not safe to expose in internet zone, it returns a window handle
        ///     PublicOK: There exists a demand on this code
        /// 
        public IntPtr Handle 
        {
            [SecurityCritical] 
            get 
            {
                SecurityHelper.DemandUIWindowPermission(); 
                return CriticalHandle;
            }
        }
 
        /// 
        ///     Critical:Internal helper to retrieve handle for security purposes only Please 
        ///     DO NOT USE THIS TO  EXPOSE HANDLE TO OUTSIDE WORLD 
        /// 
        internal IntPtr CriticalHandle 
        {
            [FriendAccessAllowed]
            [SecurityCritical]
            get 
            {
                if (null != _hwndWrapper) 
                    return _hwndWrapper.Handle; 
                return IntPtr.Zero;
            } 
        }

        /// 
        ///     Critical: returns the critical _hwndWrapper. 
        /// 
        internal HwndWrapper HwndWrapper 
        { 
            [SecurityCritical]
            get { return _hwndWrapper; } 
        }

        // Return whether this presentation source has capture.
        ///  
        ///     Critical: calls CriticalHandle
        ///     TreatAsSafe: Returning whether a presentation source has capture is considered safe. 
        ///  
        internal bool HasCapture
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                IntPtr capture = SafeNativeMethods.GetCapture(); 

                return ( capture == CriticalHandle ); 
            } 
        }
 
        ///
        ///     Critical - accesses _hwndWrapper.
        ///     TreatAsSafe - checking for null is considered safe.
        /// 
        internal bool IsHandleNull
        { 
            [SecurityCritical, SecurityTreatAsSafe ] 
            get
            { 
                return _hwndWrapper.Handle == IntPtr.Zero ;
            }
        }
 
        /// 
        /// Returns the hwnd handle to the window. 
        ///  
        public HandleRef CreateHandleRef()
        { 
            return new HandleRef(this,Handle);
        }

 
        /// 
        /// SizeToContent on HwndSource 
        ///  
        /// 
        /// The default value is SizeToContent.Manual 
        /// 
        public SizeToContent SizeToContent
        {
            get 
            {
                CheckDisposed(true); 
                return _sizeToContent; 
            }
 
            set
            {
                CheckDisposed(true);
 
                if (IsValidSizeToContent(value) != true)
                { 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(SizeToContent)); 
                }
 
                if (_sizeToContent == value)
                {
                    return;
                } 

                _sizeToContent = value; 
 
                // we only raise SizeToContentChanged when user interaction caused the change;
                // if a developer goes directly to HwndSource and sets SizeToContent, we will 
                // not notify the wrapping Window

                if (IsLayoutActive() == true)
                { 
                    // Call the helper method SetLayoutSize to set Layout's size
                    SetLayoutSize(); 
                } 
            }
        } 

        /// 
        ///     Critical: This code elevates to access hwndtarget
        ///     TreatAsSafe: ok to expose 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private bool IsLayoutActive() 
        {
 
            if ((_rootVisual.Value is UIElement) && _hwndTarget!= null && _hwndTarget.IsDisposed == false)
            {
                return true;
            } 

            return false; 
        } 

        ///  
        /// This is the helper method that sets Layout's size basing it on
        /// the current value of SizeToContent.
        /// 
        /// 
        ///  TreatAsSafe: This API could be public in terms of security.
        ///  It does three calls to UnsafeNativeMethods all in a safe way 
        ///  Critical: Makes 3 calls to UnsafeNativeMethods 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void SetLayoutSize()
        {
            Debug.Assert(_hwndTarget!= null, "HwndTarget is null");
            Debug.Assert(_hwndTarget.IsDisposed == false, "HwndTarget is disposed"); 

            UIElement rootUIElement = null; 
            rootUIElement = _rootVisual.Value as UIElement; 
            if (rootUIElement == null) return;
 
            // hamidm - 11/01/2005
            // InvalidateMeasure() call is necessary in the following scenario
            //
            // Window w = new Window(); 
            // w.Measure(new Size(x,y));
            // w.Width = x; 
            // w.Height = y; 
            // w.Show()
            // 
            // In the above scenario, the Measure call from SetLayoutSize will be opt out
            // and window will not receive the MeasureOverride call.  As such, the hwnd min/max
            // restrictions will not be applied since MeasureOverride did not happen after hwnd
            // creation.  Thus, we call InvalidatMeasure() to ensure MeasureOverride call on 
            // Window after hwnd creation.
 
            rootUIElement.InvalidateMeasure(); 

            const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf; 
            bool etwEnabled = EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info);
            long  ctxHashCode = 0;

            if (_sizeToContent == SizeToContent.WidthAndHeight) 
            {
                //setup constraints for measure-to-content 
                Size sz = new Size(double.PositiveInfinity, double.PositiveInfinity); 

                if (etwEnabled) 
                {
                    ctxHashCode = _hwndWrapper.Handle.ToInt64();
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_SetLayoutSize);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }
 
                rootUIElement.Measure(sz); 

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);
                } 

                rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info);
                }
            } 
            else
            { 
                // GetSizeFromHwnd sets either the outside size or the client size of the hwnd based on 
                // _adjustSizeingForNonClientArea flag in logical units.
                Size sizeFromHwndLogicalUnits = GetSizeFromHwnd(); 
                Size sz = new Size(
                        (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Width),
                        (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Height));
 
                if (etwEnabled)
                { 
                    ctxHashCode = _hwndWrapper.Handle.ToInt64(); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_SetLayoutSize);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }

                rootUIElement.Measure(sz);
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);
                } 

                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, sizeFromHwndLogicalUnits.Height);
                else if(_sizeToContent == SizeToContent.Height) sz = new Size(sizeFromHwndLogicalUnits.Width, rootUIElement.DesiredSize.Height);
                else sz = sizeFromHwndLogicalUnits; 

                rootUIElement.Arrange(new Rect(new Point(), sz)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info);
                }
            } 
            rootUIElement.UpdateLayout();
        } 
 
        // /// 
        // ///     Specifies the color to display as transparent. 
        // /// 
        // /// 
        // ///     Use null to indicate that no color should be transparent.
        // ///  
        // public Nullable ColorKey
        // { 
        //     get 
        //     {
        //         CheckDisposed(true); 
        //
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null)
        //         { 
        //             return _hwndTarget.ColorKey;
        //         } 
        //         else 
        //         {
        //             return null; 
        //         }
        //     }
        //
        //     set 
        //     {
        //         CheckDisposed(true); 
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null) 
        //         {
        //             _hwndTarget.ColorKey = value;
        //         }
        //     } 
        // }
 
        // ///  
        // ///     Specifies the constant opacity to apply to the window.
        // ///  
        // /// 
        // ///     The valid values range from [0..1].  Values outside of this range are clamped.
        // /// 
        // public double Opacity 
        // {
        //     get 
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null)
        //         {
        //             return _hwndTarget.Opacity; 
        //         }
        //         else 
        //         { 
        //             return 1.0;
        //         } 
        //     }
        //
        //     set
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
        //         if(_hwndTarget != null)
        //         { 
        //             _hwndTarget.Opacity = value;
        //         }
        //     }
        // } 

        ///  
        ///     Specifies whether or not the per-pixel opacity of the window content 
        ///     is respected.
        ///  
        /// 
        ///     By enabling per-pixel opacity, the system will no longer draw the non-client area.
        /// 
        ///  
        ///     Critical: Because it accesses _hwndTarget
        ///     PublicOK: We don't pass it out; it is just used to query UsesPerPixelOpacity 
        ///  
        public bool UsesPerPixelOpacity
        { 
            [SecurityCritical]
            get
            {
                CheckDisposed(true); 

                HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
                if(_hwndTarget != null) 
                {
                    return _hwndTarget.UsesPerPixelOpacity; 
                }
                else
                {
                    return false; 
                }
            } 
 
/* Not allowing this to change at run-time yet.
            [SecurityCritical] 
            set
            {
                CheckDisposed(true);
 
                HwndTarget hwndTarget = CompositionTarget; // checks for disposed
                if(_hwndTarget != null) 
                { 
                    _hwndTarget.UsesPerPixelOpacity = value;
                } 
            }
*/
        }
 
        /// 
        ///     Critical: Accesses _hwndWrapper.Handle to call unmanaged code to get the client rectangle. 
        ///     TreatAsSafe: The handle is not passed out, and the client rectangle does not need to be protected. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private Size GetSizeFromHwnd()
        {
            // Compute View's size and set
            NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0); 

            if (_adjustSizingForNonClientArea == true) 
            { 
                // get correct size for avalon Window (standalone and browser case)
                GetSizeForWindowObject(ref rc); 
            }
            else
            {
                SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref rc); 
            }
 
            Point convertedPt = TransformFromDevice(new Point(rc.right - rc.left, rc.bottom - rc.top)); 
            return new Size(convertedPt.X, convertedPt.Y);
        } 

        /// 
        ///     Critical: This code can be used to spoof input
        ///  
        [SecurityCritical]
        private IntPtr HwndTargetFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
        { 
            IntPtr result = IntPtr.Zero ;
 
            if (IsUsable)
            {
                HwndTarget hwndTarget = _hwndTarget;
                if (hwndTarget != null) 
                {
                    result = hwndTarget.HandleMessage((WindowMessage)msg, wParam, lParam); 
                    if (result != IntPtr.Zero) 
                    {
                        handled = true; 
                    }
                }

            } 

            return result; 
        } 

        ///  
        /// Critical:These hooks can all be used for input spoofing
        /// 
        [SecurityCritical]
        private IntPtr LayoutFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
        {
            IntPtr result = IntPtr.Zero ; 
            WindowMessage message = (WindowMessage)msg; 

            // We have to revalidate everything because the Access() call 
            // could have caused the CLR to enter a nested message pump,
            // during which almost anything could have happened that might
            // invalidate our checks.
            UIElement rootUIElement=null; 
            rootUIElement = _rootVisual.Value as UIElement;
            if (IsUsable && rootUIElement != null) 
            { 
                switch (message)
                { 
                    // A window receives this message when the user chooses a command from
                    // the Window menu or when the user chooses the maximize button, minimize
                    // button, restore button, or close button.
                    case WindowMessage.WM_SYSCOMMAND: 
                        {
                            // The four low-order bits of the wParam parameter are used 
                            // internally by the system. 
                            Int32 sysCommand = NativeMethods.IntPtrToInt32(wParam) & 0xFFF0;
 
                            // Turn off SizeToContent if user chooses to maximize or resize.
                            if ((sysCommand == NativeMethods.SC_MAXIMIZE) ||
                                (sysCommand == NativeMethods.SC_SIZE))
                            { 
                                DisableSizeToContent(rootUIElement, hwnd);
                            } 
                        } 
                        break;
 
                    // We get WM_SIZING. It means that user starts resizing the window.
                    // It is the first notification sent when user resizes (before WM_WINDOWPOSCHANGING)
                    // and it's not sent if window is resized programmatically.
                    // SizeToContent is turned off after user resizes. 
                    case WindowMessage.WM_SIZING:
                        DisableSizeToContent(rootUIElement, hwnd); 
                        break; 

                    // The WM_WINDOWPOSCHANGING message is sent 
                    // 1. when the size, position, or place in the Z order is about to change as a result of a call to
                    //    the SetWindowPos function or other window-management functions. SizeToContent orverrides all in this case.
                    // 2. when user resizes window. If it's user resize, we have turned SizeToContent off when we get WM_SIZING.
                    // It is sent before WM_SIZE. 
                    // We can't use WM_GETMINMAXINFO, because if there is no window size change (we still need to make sure
                    // the client size not change), that notification wouldnt be sent. 
                    case WindowMessage.WM_WINDOWPOSCHANGING: 
                        Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, message, wParam, lParam);
                        break; 

                    // WM_SIZE message is sent after the size has changed.
                    // lParam has the new width and height of client area.
                    // root element's size should be adjust based on the new width and height and SizeToContent's value. 
                    case WindowMessage.WM_SIZE:
                        Process_WM_SIZE(rootUIElement, hwnd, message, wParam, lParam); 
                        break; 
                }
            } 

            // Certain messages need to be processed while we are in the middle
            // of construction - and thus an HwndTarget is not available.
            if(!handled && (_constructionParameters != null || IsUsable)) 
            {
                // Get the usesPerPixelOpacity from either the constructor parameters or the HwndTarget. 
                bool usesPerPixelOpacity = _constructionParameters != null ? ((HwndSourceParameters)_constructionParameters).UsesPerPixelOpacity : _hwndTarget.UsesPerPixelOpacity; 

                switch(message) 
                {
                    case WindowMessage.WM_NCCALCSIZE:
                        {
                            // Windows that use per-pixel opacity don't get 
                            // their frames drawn by the system.  Generally
                            // this is OK, as users of per-pixel alpha tend 
                            // to be doing customized UI anyways.  But we 
                            // don't render correctly if we leave a non-client
                            // area, so here we expand the client area to 
                            // cover any non-client area.
                            //
                            if(usesPerPixelOpacity)
                            { 
                                if(wParam == IntPtr.Zero)
                                { 
                                    // If wParam is FALSE, lParam points to a RECT 
                                    // structure. On entry, the structure contains
                                    // the proposed window rectangle for the 
                                    // window. On exit, the structure should
                                    // contain the screen coordinates of the
                                    // corresponding window client area.
                                    // 
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything. 
                                    //
                                    result = IntPtr.Zero; 
                                    handled = true;
                                }
                                else
                                { 
                                    // If wParam is TRUE, lParam points to an
                                    // NCCALCSIZE_PARAMS structure that contains 
                                    // information an application can use to 
                                    // calculate the new size and position of
                                    // the client rectangle. 
                                    //
                                    // When Windows sends the WM_NCCALCSIZE
                                    // message, the NCCALCSIZE_PARAMS structure
                                    // is filled out like this: 
                                    //
                                    // rgrc[0] = new window rectangle (in parent coordinates) 
                                    // rgrc[1] = old window rectangle (in parent coordinates) 
                                    // rgrc[2] = old client rectangle (in parent coordinates)
                                    // 
                                    // Notice that the client rectangle is given
                                    // in parent coordinates, not in client
                                    // coordinates.
                                    // 
                                    // When your window procedure returns, Windows
                                    // expects the NCCALCSIZE_PARAMS structure to 
                                    // be filled out like this: 
                                    //
                                    // rgrc[0] = new client rectangle (in parent coordinates) 
                                    //
                                    // Furthermore, if you return anything other
                                    // than 0, Windows expects the remaining two
                                    // rectangles to be filled out like this: 
                                    //
                                    // rgrc[1] = destination rectangle (in parent coordinates) 
                                    // rgrc[2] = source rectangle (in parent coordinates) 
                                    //
                                    // (If you return 0, then Windows assumes that 
                                    // the destination rectangle equals the new
                                    // client rectangle and the source rectangle
                                    // equals the old client rectangle.)
                                    // 
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything. 
                                    //
                                    result = IntPtr.Zero; 
                                    handled = true;
                                }
                            }
                        } 
                        break;
                } 
            } 

            return result; 
        }

        /// 
        /// Critical: Because it uses _hwndTarget 
        /// 
        [SecurityCritical] 
        private void Process_WM_WINDOWPOSCHANGING(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam) 
        {
            // Only if SizeToContent overrides Win32 sizing change calls. 
            // If it's coming from OnResize (_myOwnUpdate != true), it means we are adjusting
            // to the right size; don't need to do anything here.
            if ((_myOwnUpdate != true) && (SizeToContent != SizeToContent.Manual))
            { 
                // Get the current style and calculate the size to be with the new style.
                // If WM_WINDOWPOSCHANGING is sent because of style changes, WM_STYLECHANGED is sent 
                // before this. The style bits we get here are updated ones, but haven't been applied 
                // to Window yet. For example, when the window is changing to borderless, without updating the window size,
                // the window size will remain the same but the client area will be bigger. So when SizeToContent is on, we calculate 
                // the window size to be with the new style using AdustWindowRectEx and adjust it to make sure client area is not affected.
                NativeMethods.RECT rect = AdjustWindowSize(rootUIElement.RenderSize);

                int newCX = rect.right - rect.left; 
                int newCY = rect.bottom - rect.top;
 
                // Get WINDOWPOS structure data from lParam; it contains information about the window's 
                // new size and position.
                NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS)); 

                bool sizeChanged = false;

                // If SWP_NOSIZE is set to ignore cx, cy. It could be a style or position change. 
                if ((windowPos.flags & NativeMethods.SWP_NOSIZE) == NativeMethods.SWP_NOSIZE)
                { 
                    NativeMethods.RECT windowRect = new NativeMethods.RECT(0, 0, 0, 0); 

                    // Get the current Window rect 
                    SafeNativeMethods.GetWindowRect(new HandleRef(this, _hwndWrapper.Handle), ref windowRect);

                    // If there is no size change with the new style we don't need to do anything.
                    if ((newCX != (windowRect.right - windowRect.left)) || 
                        (newCY != (windowRect.bottom - windowRect.top)))
                    { 
                        // Otherwise unmark the flag to make our changes effective. 
                        windowPos.flags &= ~NativeMethods.SWP_NOSIZE;
 
                        // When SWP_NOSIZE is on, the size info in cx and cy is bogus. They are ignored.
                        // When we turn it off, we need to provide valid value for both of them.
                        windowPos.cx = newCX;
                        windowPos.cy = newCY; 
                        sizeChanged = true;
                    } 
                } 
                else
                { 
                    // We have excluded SizeToContent == SizeToContent.Manual before entering this.
                    bool sizeToWidth = (SizeToContent == SizeToContent.Height) ? false : true;
                    bool sizeToHeight = (SizeToContent == SizeToContent.Width) ? false : true;
 
                    // Update WindowPos with the size we want.
                    if ((sizeToWidth) && (windowPos.cx != newCX)) 
                    { 
                        windowPos.cx = newCX;
                        sizeChanged = true; 
                    }

                    if ((sizeToHeight) && (windowPos.cy != newCY))
                    { 
                        windowPos.cy = newCY;
                        sizeChanged = true; 
                    } 
                }
 
                // Marshal the structure back only when changed
                if (sizeChanged)
                {
                    Marshal.StructureToPtr(windowPos, lParam, true); 
                }
            } 
        } 

        ///  
        ///     Critical: Has access to the window handle and uses the parameters provided to modify the layout
        ///         of elements within the window.
        /// 
        [SecurityCritical] 
        private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam)
        { 
            int x = NativeMethods.SignedLOWORD(lParam); 
            int y = NativeMethods.SignedHIWORD(lParam);
            Point pt = new Point(x, y); 
            const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf;
            bool etwEnabled = EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info);
            long ctxHashCode = 0;
 
            // 1. If it's coming from Layout (_myOwnUpdate), it means we are adjusting
            // to the right size; don't need to do anything here. 
            // 2. If SizeToContent is set to WidthAndHeight, then we maintain the current hwnd size 
            // in WM_WINDOWPOSCHANGING, so we don't need to re-layout here.  If SizeToContent
            // is set to Width or Height and developer calls SetWindowPos to set a new 
            // Width/Height, we need to do a layout.
            // 3. We also don't need to do anything if it's minimized.

            // Keeps the status of whether the Window is in Minimized state or not. 
            _isWindowInMinimizeState = (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.SIZE_MINIMIZED) ? true : false;
 
            if ((!_myOwnUpdate) && (_sizeToContent != SizeToContent.WidthAndHeight) && !_isWindowInMinimizeState) 
            {
                Point relevantPt = new Point(pt.X, pt.Y); 

                // WM_SIZE has the client size of the window.
                // for appmodel window case, get the outside size of the hwnd.
                if (_adjustSizingForNonClientArea == true) 
                {
                    NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); 
                    GetSizeForWindowObject(ref rect); 
                    relevantPt.X = rect.right - rect.left;
                    relevantPt.Y = rect.bottom - rect.top; 
                }

                // The lParam/wParam size and the GetSizeForWindowObject size are
                // both in device co-ods, thus we convert to Measure co-ods here. 
                relevantPt = TransformFromDevice(relevantPt);
 
                Size sz = new Size( 
                    (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : relevantPt.X),
                    (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : relevantPt.Y)); 

                // NOTE: hamidm -- 6/03/04
                // 962884 Avalon content does not resize when the favorites
                // (or other side pane) is closed 
                //
                // The issue is that when the browser shows favorites window, avalon 
                // window is resized and we get WM_SIZE.  Here, we pass the IE window's 
                // size to Measure so that Computed[Width/Height] gets the correct
                // IE window dimensions.  Since, IE window's size may not change, the 
                // call to Measure is optimized out and no layout happens.  Invalidating
                // layout here ensures that we do layout.
                // This can happen only in the Window case
                if (_adjustSizingForNonClientArea == true) 
                {
                    rootUIElement.InvalidateMeasure(); 
                } 

                if (etwEnabled) 
                {
                    ctxHashCode = _hwndWrapper.Handle.ToInt64();
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_WMSIZE);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);; 
                }
 
                rootUIElement.Measure(sz); 

                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, relevantPt.Y); 
                else if (_sizeToContent == SizeToContent.Height) sz = new Size(relevantPt.X, rootUIElement.DesiredSize.Height);
                else sz = new Size(relevantPt.X, relevantPt.Y);

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }
 
                rootUIElement.Arrange(new Rect(new Point(), sz));

                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info); 
                } 
                rootUIElement.UpdateLayout(); //finalizes layout
 
            }
        }

        ///  
        /// Critical: Because it uses _hwndTarget
        ///  
        [SecurityCritical] 
        private void DisableSizeToContent(UIElement rootUIElement, IntPtr hwnd)
        { 
            if (_sizeToContent != SizeToContent.Manual)
            {
                _sizeToContent = SizeToContent.Manual;
 
                // hamidm - 10/27/2005
                // 1348020 Window expereience layout issue when SizeToContent is being turned 
                // off by user interaction 
                // This bug was caused b/c we were giving rootUIElement.DesiredSize as input
                // to Measure/Arrange below.  That is incorrect since rootUIElement.DesiredSize may not 
                // cover the entire hwnd client area.

                // GetSizeFromHwnd returns either the outside size or the client size of the hwnd based on
                // _adjustSizeingForNonClientArea flag in logical units. 
                Size sizeLogicalUnits = GetSizeFromHwnd();
                rootUIElement.Measure(sizeLogicalUnits); 
                rootUIElement.Arrange(new Rect(new Point(), sizeLogicalUnits)); 

                rootUIElement.UpdateLayout(); //finalizes layout 


                if (SizeToContentChanged != null)
                { 
                    SizeToContentChanged(this, EventArgs.Empty);
                } 
            } 
        }
 
        // This method makes sure that we get the size from the correct
        // hwnd for the browser case.
        /// 
        /// Critical - calls critical methods (HwndSourceHelper.GetHandle and GetAncestor) 
        /// TreatAsSafe - it's ok to return size of window. it doesn't return info gotten through critical calls.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void GetSizeForWindowObject(ref NativeMethods.RECT rc)
        { 
            IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT);
            SafeNativeMethods.GetWindowRect(new HandleRef(this, hwndRoot), ref rc);
        }
 
        /// 
        ///     Critical: This is a hook that gets called back with information about messages related to input 
        ///     Calling this from outside or causing this to be invoked could yield risky situations 
        /// 
        [SecurityCritical] 
        private IntPtr InputFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr result = IntPtr.Zero ;
            WindowMessage message = (WindowMessage)msg; 

            // NOTE (alexz): invoke _stylus.FilterMessage before _mouse.FilterMessage 
            // to give _stylus a chance to eat mouse message generated by stylus 
            if (!_isDisposed && _stylus != null && !handled)
            { 
                result = _stylus.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled);
            }

            if (!_isDisposed && _mouse != null && !handled) 
            {
                result = _mouse.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled); 
            } 

            if (!_isDisposed && _keyboard != null && !handled) 
            {
                result = _keyboard.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled);
            }
 
            if (!_isDisposed && _appCommand != null && !handled)
            { 
                result = _appCommand.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled); 
            }
 
            return result;
        }

        ///  
        ///    Called from HwndWrapper on all window messages.
        ///  
        // assumes Context.Access() is held. 
        private IntPtr PublicHooksFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        { 
            // The default result for messages we handle is 0.
            IntPtr result = IntPtr.Zero ;
            WindowMessage message = (WindowMessage)msg;
 
            // Call all of the public hooks
            // We do this even if we are disposed because otherwise the hooks 
            // would never see the WM_DESTROY etc. message. 
            if (_hooks != null)
            { 
                Delegate[] handlers = _hooks.GetInvocationList();
                for (int i = handlers.Length -1; i >= 0; --i)
                {
                    var hook = (HwndSourceHook)handlers[i]; 
                    result = hook(hwnd, msg, wParam, lParam, ref handled);
                    if(handled) 
                    { 
                        break;
                    } 
                }
            }
            if (WindowMessage.WM_NCDESTROY == message)
            { 
                // We delivered the message to the hooks and the message
                // is WM_NCDESTROY, so our commitments should be finished 
                // we can do final teardown. (like disposing the _hooks) 
                OnNoMoreWindowMessages();
            } 

            return result;
        }
 
#region IKeyboardInputSink
 
        /// General security note on the implementation pattern of this interface. In Dev10 it was chosen 
        /// to expose the interface implementation for overriding to customers. We did so by keeping the
        /// explicit interface implementations (that do have the property of being hidden from the public 
        /// contract, which limits IntelliSense on derived types like WebBrowser) while sticking protected
        /// virtuals next to them. Those virtuals contain our base implementation, while the explicit
        /// interface implementation methods do call trivially into the virtuals.
        /// 
        /// This comment outlines the security rationale applied to those methods.
        /// 
        ///  
        ///     The security attributes on the virtual methods within this region mirror the corresponding
        ///     IKeyboardInputSink methods; customers can override those methods, so we insert a LinkDemand 
        ///     to encourage them to have a LinkDemand too (via FxCop).
        ///
        ///     While the methods have LinkDemands on them, the bodies of the methods typically contain
        ///     full demands through a SecurityHelper.DemandUnmanagedCode call. This might seem redundant. 
        ///     The point here is we do a full demand for stronger protection of our built-in implementation
        ///     compared to the LinkDemand on the public interface. We really want full demands here but 
        ///     declarative Demand doesn't work on interface methods. In addition, we try to take advantage 
        ///     of the fact LinkDemands are consistently enforced between base and overridden virtual methods,
        ///     something full Demands do not give us, even when applied declaratively. 
        /// 

        private class MSGDATA
        { 
            public MSG msg;
            public bool handled; 
        } 

        ///  
        /// HwndSource keyboard input is sent through this delegate to check for
        /// Child Hwnd interop requirments.  If there are no child hwnds or focus
        /// is on this non-child hwnd then normal Avalon processing is done.
        ///  
        ///
        /// Critical - This can be used to spoof input 
        ///  
        [SecurityCritical]
        private void OnPreprocessMessageThunk(ref MSG msg, ref bool handled) 
        {
//             VerifyAccess();

            if (handled) 
            {
                return; 
            } 

            // We only do these message. 
            switch ((WindowMessage)msg.message)
            {
            case WindowMessage.WM_KEYUP:
            case WindowMessage.WM_KEYDOWN: 
            case WindowMessage.WM_SYSKEYUP:
            case WindowMessage.WM_SYSKEYDOWN: 
            case WindowMessage.WM_CHAR: 
            case WindowMessage.WM_SYSCHAR:
            case WindowMessage.WM_DEADCHAR: 
            case WindowMessage.WM_SYSDEADCHAR:
                MSGDATA msgdata = new MSGDATA();
                msgdata.msg = msg;
                msgdata.handled = handled; 

                // Do this under the exception filter/handlers of the 
                // dispatcher for this thread. 
                //
                // NOTE: we lose the "perf optimization" of passing everything 
                // around by-ref since we have to call through a delegate.
                object result = Dispatcher.CurrentDispatcher.Invoke(
                    DispatcherPriority.Send,
                    new DispatcherOperationCallback(OnPreprocessMessage), 
                    msgdata);
 
                if (result != null) 
                {
                    handled = (bool)result; 
                }

                // the semantics dictate that the callers could change this data.
                msg = msgdata.msg; 
                break;
            } 
        } 

 
        /// 
        ///     Critical:
        ///     Can be used to spoof input.
        ///     Asserts UnmanagedCode permission to call IKeyboardInputSink 
        ///     methods.
        ///     For HANDLED_KEYDOWN_STILL_GENERATES_CHARS we also cause the 
        ///     Dispatcher to defer processing the queue until after any 
        ///     currently pending messages.
        ///  
        [SecurityCritical]
        private object OnPreprocessMessage(object param)
        {
            MSGDATA msgdata = (MSGDATA) param; 

            // Always process messages if this window is in menu mode. 
            // 
            // Otherwise, only process messages if someone below us has Focus.
            // 
            // Mnemonics are broadcast to all branches of the window tree; even
            // those that don't have focus.  BUT! at least someone under this
            // top-level window must have focus.
            if (!((IKeyboardInputSink)this).HasFocusWithin() && !IsInExclusiveMenuMode) 
            {
                return msgdata.handled; 
            } 

            ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys(); 

            // Interop with the Interop layer
            //
            switch ((WindowMessage)msgdata.msg.message) 
            {
            case WindowMessage.WM_SYSKEYDOWN: 
            case WindowMessage.WM_KEYDOWN: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                // In case a nested message pump is used before we return 
                // from processing this message, we disable processing the
                // next WM_CHAR message because if the code pumps messages
                // it should really mark the message as handled.
                _eatCharMessages = true; 
                DispatcherOperation restoreCharMessages = Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(RestoreCharMessages), null);
 
                // Force the Dispatcher to post a new message to service any 
                // pending operations, so that the operation we just posted
                // is guaranteed to get dispatched after any pending WM_CHAR 
                // messages are dispatched.
                Dispatcher.CriticalRequestProcessing(true);

                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); 
                if(!msgdata.handled)
                { 
                    // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
                    // We did not handle the WM_KEYDOWN, so it is OK to process WM_CHAR messages.
                    // We can also abort the pending restore operation since we don't need it. 
                    _eatCharMessages = false;
                    restoreCharMessages.Abort();
                }
 
                // Menu mode handles all keyboard messages so that they don't
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode) 
                {
                    // However, if the WM_KEYDOWN message was not explicitly 
                    // handled, then we need to generate WM_CHAR messages.  WPF
                    // expects this, but when we return handled, the outer
                    // message pump will skip the TranslateMessage and
                    // DispatchMessage calls.  We mitigate this by calling 
                    // TranslateMessage directly.  This is the same trick that
                    // Win32 does in its menu loop. 
                    if(!msgdata.handled) 
                    {
                        UnsafeNativeMethods.TranslateMessage(ref msgdata.msg); 
                    }

                    msgdata.handled = true;
                } 

                break; 
 
            case WindowMessage.WM_SYSKEYUP:
            case WindowMessage.WM_KEYUP: 
                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys);

                // Menu mode handles all keyboard messages so that they don't
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode)
                { 
                    msgdata.handled = true; 
                }
 
                break;

            case WindowMessage.WM_CHAR:
            case WindowMessage.WM_SYSCHAR: 
            case WindowMessage.WM_DEADCHAR:
            case WindowMessage.WM_SYSDEADCHAR: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
                if(!_eatCharMessages)
                { 
                    // IKIS implementation does a demand.
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                    try
                    { 
                        msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys);
 
                        if (!msgdata.handled) 
                        {
                            msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys); 
                        }
                    }
                    finally
                    { 
                        SecurityPermission.RevertAssert();
                    } 
 
                    if (!msgdata.handled)
                    { 
                        _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, (WindowMessage)msgdata.msg.message,
                                                               msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled);
                    }
                } 

                // Menu mode handles all keyboard messages so that they don't 
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode)
                { 
                    // If the WM_CHAR message is not explicitly handled, the
                    // standard behavior is to beep.
                    if(!msgdata.handled)
                    { 
                        SafeNativeMethods.MessageBeep(0);
                    } 
 
                    msgdata.handled = true;
                } 

                break;
            }
            return msgdata.handled; 
        }
 
        ///  
        ///     Registers a child KeyboardInputSink with this sink.  A site
        ///     is returned. 
        /// 
        /// 
        ///     This API requires unrestricted UI Window permission.
        ///     We explicitly don't make this method overridable as we want to keep the 
        ///     precise implementation fixed and make sure the _keyboardInputSinkChildren
        ///     state is kep consistent. By making the method protected, implementors can 
        ///     still call into it when required. Notice as calls are made through the 
        ///     IKIS interface, there's still a way for ---- developers to override
        ///     the behavior by re-implementing the interface. 
        /// 
        /// 
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it. 
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        ///  
        [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)]
        protected IKeyboardInputSite RegisterKeyboardInputSinkCore(IKeyboardInputSink sink) 
        {
            CheckDisposed(true);

            if (sink == null) 
            {
                throw new ArgumentNullException("sink"); 
            } 

            if (sink.KeyboardInputSite != null) 
            {
                throw new ArgumentException(SR.Get(SRID.KeyboardSinkAlreadyOwned));
            }
 
            HwndSourceKeyboardInputSite site = new HwndSourceKeyboardInputSite(this, sink);
 
            if (_keyboardInputSinkChildren == null) 
                _keyboardInputSinkChildren = new List();
            _keyboardInputSinkChildren.Add(site); 

            return site;
        }
 
        /// 
        ///     Critical: This method can be used to intercept and potentially tamper with raw input. 
        ///     PublicOK: The interface declaration for this method has a demand on it. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
        {
            return RegisterKeyboardInputSinkCore(sink);
        } 

        ///  
        ///     Gives the component a chance to process keyboard input. 
        ///     Return value is true if handled, false if not.  Components
        ///     will generally call a child component's TranslateAccelerator 
        ///     if they can't handle the input themselves.  The message must
        ///     either be WM_KEYDOWN or WM_SYSKEYDOWN.  It is illegal to
        ///     modify the MSG structure, it's passed by reference only as
        ///     a performance optimization. 
        /// 
        /// 
        /// This API is not available in Internet Zone. 
        ///
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it.
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        protected virtual bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers) 
        {
            SecurityHelper.DemandUnmanagedCode(); 
//             VerifyAccess();

            return CriticalTranslateAccelerator(ref msg, modifiers);
        } 

        ///  
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it.
        ///  
        [SecurityCritical]
        bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)
        {
            return TranslateAcceleratorCore(ref msg, modifiers); 
        }
 
        ///  
        ///     Set focus to the first or last tab stop (according to the
        ///     TraversalRequest).  If it can't, because it has no tab stops, 
        ///     the return value is false.
        /// 
        protected virtual bool TabIntoCore(TraversalRequest request)
        { 
            bool traversed = false;
 
            if(request == null) 
            {
                throw new ArgumentNullException("request"); 
            }

            UIElement root =_rootVisual.Value as UIElement;
            if(root != null) 
            {
                // atanask: 
                // request.Mode == FocusNavigationDirection.First will navigate to the fist tabstop including root 
                // request.Mode == FocusNavigationDirection.Last will navigate to the last tabstop including root
                traversed = root.MoveFocus(request); 
            }

            return traversed;
        } 

        bool IKeyboardInputSink.TabInto(TraversalRequest request) 
        { 
            if(request == null)
            { 
                throw new ArgumentNullException("request");
            }

            return TabIntoCore(request); 
        }
 
        ///  
        ///     The property should start with a null value.  The component's
        ///     container will set this property to a non-null value before 
        ///     any other methods are called.  It may be set multiple times,
        ///     and should be set to null before disposal.
        /// 
        ///  
        ///     Setting KeyboardInputSite is not available in Internet Zone.
        ///     We explicitly don't make this property overridable as we want to keep the 
        ///     precise implementation as a smart field for _keyboardInputSite fixed. 
        ///     By making the property protected, implementors can still call into it
        ///     when required. Notice as calls are made through the IKIS interface, 
        ///     there's still a way for ---- developers to override the behavior by
        ///     re-implementing the interface.
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This property has demands on its accessors. 
        /// 
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up.
        ///  
        protected IKeyboardInputSite KeyboardInputSiteCore
        {
            [SecurityCritical]
            get 
            {
                SecurityHelper.DemandUnmanagedCode(); 
                return _keyboardInputSite; 
            }
 
            [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
            set
            {
                SecurityHelper.DemandUnmanagedCode(); 

                _keyboardInputSite = value; 
            } 
        }
 
        /// 
        ///     Critical: Calls a property with a LinkDemand on it.
        ///     PublicOK: The interface declaration for this property has a demand on it.
        ///  
        IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite
        { 
            get 
            {
                return KeyboardInputSiteCore; 
            }

            [SecurityCritical]
            set 
            {
                KeyboardInputSiteCore = value; 
            } 
        }
 
        /// 
        ///     This method is called whenever one of the component's
        ///     mnemonics is invoked.  The message must either be WM_KEYDOWN
        ///     or WM_SYSKEYDOWN.  It's illegal to modify the MSG structrure, 
        ///     it's passed by reference only as a performance optimization.
        ///     If this component contains child components, the container 
        ///     OnMnemonic will need to call the child's OnMnemonic method. 
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it.
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        protected virtual bool OnMnemonicCore(ref MSG msg, ModifierKeys modifiers) 
        {
//             VerifyAccess(); 
            SecurityHelper.DemandUnmanagedCode();
            switch((WindowMessage)msg.message)
            {
                case WindowMessage.WM_SYSCHAR: 
                case WindowMessage.WM_SYSDEADCHAR:
                    string text = new string((char)msg.wParam, 1); 
                    if ((text != null) && (text.Length > 0)) 
                    {
                        // We have to work around an ordering issue with mnemonic processing. 
                        //
                        // Imagine you have a top level menu with _File & _Project and under _File you have _Print.
                        // If the user pressses Alt+F,P you would expect _Print to be triggered
                        // however if the top level window processes the mnemonic first 
                        // it will trigger _Project instead.
                        // 
                        // One way to work around this would be for the top level window to notice that 
                        // keyboard focus is in another root window & not handle the mnemonics.  The popup
                        // window would then get a chance to process the mnemonic and _Print would be triggered. 
                        //
                        // This doesn't work out becasue the popup window is no-activate, so it doesn't have Win32 focus
                        // and it will bail out of OnPreprocessMessage before it handles the mnemonic.
                        // 
                        // Instead the top level window should delegate OnMnemonic directly to the mnemonic scope window
                        // instead of processing it here.  This will let the Popup handle mnemonics instead of the top- 
                        // level window. 
                        //
                        // The mnemonic scope window is defined as the window with WPF keyboard focus. 
                        //
                        // This is a behavioral breaking change, so we've decided to only do it when IsInExclusiveMenuMode
                        // is true to force the user to opt-in.
                        DependencyObject focusObject = Keyboard.FocusedElement as DependencyObject; 
                        HwndSource mnemonicScope = (focusObject == null ? null : PresentationSource.CriticalFromVisual(focusObject) as HwndSource);
                        if (mnemonicScope != null && 
                            mnemonicScope != this && 
                            IsInExclusiveMenuMode)
                        { 
                            return ((IKeyboardInputSink)mnemonicScope).OnMnemonic(ref msg, modifiers);
                        }

                        if (AccessKeyManager.IsKeyRegistered(this, text)) 
                        {
                            AccessKeyManager.ProcessKey(this, text, false); 
 
                            //
                            return true; 
                        }
                    }
                    // these are OK
                    break; 

                case WindowMessage.WM_CHAR: 
                case WindowMessage.WM_DEADCHAR: 
                    // these are OK
                    break; 

                default:
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            } 

            // We record the last message that was processed by us. 
            // This is also checked in WndProc processing to prevent double processing. 
            _lastKeyboardMessage = msg;
 
            // The bubble will take care of access key processing for this HWND.  Call
            // the IKIS children unless we are in menu mode.
            if (_keyboardInputSinkChildren != null && !IsInExclusiveMenuMode)
            { 
                foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren )
                { 
                    if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) 
                        return true;
                } 
            }
            return false;
        }
 
        /// 
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it. 
        /// 
        [SecurityCritical] 
        bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
        {
            return OnMnemonicCore(ref msg, modifiers);
        } 

        ///  
        ///     Gives the component a chance to process keyboard input messages 
        ///     WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic.
        ///     Will return true if "handled" meaning don't pass it to OnMnemonic. 
        ///     The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR.
        ///     It is illegal to modify the MSG structure, it's passed by reference
        ///     only as a performance optimization.
        ///  
        /// 
        ///     Critical: This API can be used for input spoofing. 
        ///     PublicOK: This method has a demand on it. 
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
        protected virtual bool TranslateCharCore(ref MSG msg, ModifierKeys modifiers)
        { 
            SecurityHelper.DemandUnmanagedCode();
            if(HasFocus || IsInExclusiveMenuMode) 
                return false; 

            IKeyboardInputSink focusSink = this.ChildSinkWithFocus; 
            if(null != focusSink)
            {
                return focusSink.TranslateChar(ref msg, modifiers);
            } 
            return false;
        } 
 
        /// 
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it.
        /// 
        [SecurityCritical]
        bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers) 
        {
            return TranslateCharCore(ref msg, modifiers); 
        } 

        ///  
        ///
        /// 
        protected virtual bool HasFocusWithinCore()
        { 
            if(HasFocus)
            { 
                return true; 
            }
            else 
            {
                if (null == _keyboardInputSinkChildren)
                    return false;
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    if (((IKeyboardInputSite)site).Sink.HasFocusWithin()) 
                    {
                        return true; 
                    }
                }
                return false;
            } 
        }
 
        bool IKeyboardInputSink.HasFocusWithin() 
        {
            return HasFocusWithinCore(); 
        }

        /// 
        ///     The RestoreFocusMode for the window. 
        /// 
        ///  
        ///     This property can only be set at construction time via the 
        ///     HwndSourceParameters.RestoreFocusMode property.
        ///  
        public RestoreFocusMode RestoreFocusMode
        {
            get
            { 
                return _restoreFocusMode;
            } 
        } 

        ///  
        ///     The default value for the AcquireHwndFocusInMenuMode setting.
        /// 
        public static bool DefaultAcquireHwndFocusInMenuMode
        { 
            get
            { 
                if(!_defaultAcquireHwndFocusInMenuMode.HasValue) 
                {
                    // The default value is true, for compat. 
                    _defaultAcquireHwndFocusInMenuMode = true;
                }

                return _defaultAcquireHwndFocusInMenuMode.Value; 
            }
 
            set 
            {
                _defaultAcquireHwndFocusInMenuMode = value; 
            }
        }

        ///  
        ///     The AcquireHwndFocusInMenuMode setting for the window.
        ///  
        ///  
        ///     This property can only be set at construction time via the
        ///     HwndSourceParameters.AcquireHwndFocusInMenuMode property. 
        /// 
        public bool AcquireHwndFocusInMenuMode
        {
            get 
            {
                return _acquireHwndFocusInMenuMode; 
            } 
        }
 
        /// 
        ///   The method is not part of the interface (IKeyboardInputSink).
        /// 
        /// The Site that containes the sink to unregister 
        /// 
        ///     Critical - calls critical methods. 
        ///  
        [ SecurityCritical ]
        internal void CriticalUnregisterKeyboardInputSink(HwndSourceKeyboardInputSite site) 
        {
            if(_isDisposed)
                return;
 
            if (null != _keyboardInputSinkChildren)
            { 
                if (!_keyboardInputSinkChildren.Remove(site)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.KeyboardSinkNotAChild)); 
                }
            }
        }
 
        IKeyboardInputSink ChildSinkWithFocus
        { 
            get 
            {
                IKeyboardInputSink ikis=null; 

                if(null == _keyboardInputSinkChildren)
                    return null;
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    IKeyboardInputSite isite = (IKeyboardInputSite)site; 

                    if (isite.Sink.HasFocusWithin()) 
                    {
                        ikis = isite.Sink;
                        break;
                    } 
                }
                // This private property should only be called correctly. 
                Debug.Assert(null!=ikis, "ChildSinkWithFocus called when none had focus"); 
                return ikis;
            } 
        }

        /// 
        ///     Critical: This API could be vulnerable to input spoofing. 
        /// 
        [SecurityCritical, FriendAccessAllowed] 
        internal bool CriticalTranslateAccelerator(ref MSG msg, ModifierKeys modifiers) 
        {
            switch ((WindowMessage)msg.message) 
            {
                case WindowMessage.WM_KEYUP:
                case WindowMessage.WM_KEYDOWN:
                case WindowMessage.WM_SYSKEYUP: 
                case WindowMessage.WM_SYSKEYDOWN:
                    // these are OK 
                    break; 

                default: 
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            }

            if (_keyboard == null) 
                return false;
 
            bool handled = false; 

            // TranslateAccelerator is called recursively on child Hwnds (Source & Host) 
            // If this is the first Avalon TranslateAccelerator processing then we send the
            // key to be processed to the standard Avalon Input Filters and stuff.
            if (PerThreadData.TranslateAcceleratorCallDepth == 0)
            { 
                // We record the last message that was processed by us.
                // This is also checked in WndProc processing to prevent double processing. 
                // TranslateAcclerator is called from the pump before DispatchMessage 
                // and the WndProc is called from DispatchMessage.   We have processing
                // in both places.  If we run the pump we process keyboard message here. 
                // If we don't own the pump we process them in HwndKeyboardInputProvider.WndProc.
                _lastKeyboardMessage = msg;

                //  NORMAL AVALON KEYBOARD INPUT CASE 
                // If this is the top most Avalon window (it might be a child Hwnd
                // but no Avalon windows above it).  And focus is on this window then 
                // do the Normal Avalon Keyboard input Processing. 
                if (HasFocus || IsInExclusiveMenuMode)
                { 
                    _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                }
                // ELSE the focus is probably in but not on this HwndSource.
                // Beware: It is possible that someone calls IKIS.TranslateAccelerator() while the focus is 
                //   somewhere entirely outside.
                // Do the once only message input filters etc and Tunnel/Bubble down 
                // to the element that contains the child window with focus. 
                // The Child HwndHost object will hook OnPreviewKeyDown() etc
                // to make the transition to its TranslateAccelerator() between the 
                // tunnel and the bubble.
                else
                {
                    IKeyboardInputSink focusSink = ChildSinkWithFocus; // can be null! 
                    IInputElement focusElement = (IInputElement)focusSink;
 
                    try { 
                        PerThreadData.TranslateAcceleratorCallDepth += 1;
                        Keyboard.PrimaryDevice.ForceTarget = focusElement; 
                       _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                    }
                    finally
                    { 
                        Keyboard.PrimaryDevice.ForceTarget = null;
                        PerThreadData.TranslateAcceleratorCallDepth -= 1; 
                    } 
                }
 
            }
            // ELSE we have seen this MSG before, we are HwndSource decendant of an
            // HwndSource (that ancestor presumably did the processing above).
            // Here we raise the tunnel/bubble events without the once only keyboard 
            // input filtering.
            else 
            { 
                int virtualKey = HwndKeyboardInputProvider.GetVirtualKey(msg.wParam, msg.lParam);
                int scanCode = HwndKeyboardInputProvider.GetScanCode(msg.wParam, msg.lParam); 
                bool isExtendedKey = HwndKeyboardInputProvider.IsExtendedKey(msg.lParam);
                Key key = KeyInterop.KeyFromVirtualKey(virtualKey);

                RoutedEvent keyPreviewEvent=null; 
                RoutedEvent keyEvent=null;
                switch ((WindowMessage)msg.message) 
                { 
                case WindowMessage.WM_KEYUP:
                case WindowMessage.WM_SYSKEYUP: 
                    keyPreviewEvent = Keyboard.PreviewKeyUpEvent;
                    keyEvent = Keyboard.KeyUpEvent;
                    break;
                case WindowMessage.WM_KEYDOWN: 
                case WindowMessage.WM_SYSKEYDOWN:
                    keyPreviewEvent = Keyboard.PreviewKeyDownEvent; 
                    keyEvent = Keyboard.KeyDownEvent; 
                    break;
                } 

                bool hasFocus = HasFocus;
                IKeyboardInputSink focusSink = (hasFocus || IsInExclusiveMenuMode) ? null : ChildSinkWithFocus;
                IInputElement focusElement = focusSink as IInputElement; 
                // focusElement may be null, in which case Target is just "focus", but we use it only if it's an
                // element within this HwndSource. It is possible that someone calls IKIS.TranslateAccelerator() 
                // on a nested HwndSource while the focus is somewhere entirely outside. 
                // HasFocus implies the focused element should be within this HwndSource, but unfortunately
                // we allow 'split focus', at least for popup windows; that's why check explicitly. 
                // Note that KeyboardDevice.Target will likely be the ForceTarget corresponding to the
                // container of this HwndSource. That's why we look at the real FocusedElement.
                if (focusElement == null && hasFocus)
                { 
                    focusElement = Keyboard.PrimaryDevice.FocusedElement;
                    if (focusElement != null && 
                        PresentationSource.CriticalFromVisual((DependencyObject)focusElement) != this) 
                    {
                        focusElement = null; 
                    }
                }

                try { 
                    Keyboard.PrimaryDevice.ForceTarget = focusSink as IInputElement;
 
                    if (focusElement != null) 
                    {
                        KeyEventArgs tunnelArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key); 
                        tunnelArgs.ScanCode = scanCode;
                        tunnelArgs.IsExtendedKey = isExtendedKey;
                        tunnelArgs.RoutedEvent = keyPreviewEvent;
                        focusElement.RaiseEvent(tunnelArgs); 

                        handled = tunnelArgs.Handled; 
                    } 
                    if (!handled)
                    { 
                        KeyEventArgs bubbleArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key);
                        bubbleArgs.ScanCode = scanCode;
                        bubbleArgs.IsExtendedKey = isExtendedKey;
                        bubbleArgs.RoutedEvent=keyEvent; 
                        if(focusElement != null)
                        { 
                            focusElement.RaiseEvent(bubbleArgs); 
                            handled = bubbleArgs.Handled;
                        } 

                        if (!handled)
                        {
                            // Raise the TranslateAccelerator event on the 
                            // InputManager to allow keyboard navigation to
                            // happen on a descendent HwndSource 
                            InputManager.UnsecureCurrent.RaiseTranslateAccelerator(bubbleArgs); 
                            handled = bubbleArgs.Handled;
                        } 
                    }
                }
                finally
                { 
                    Keyboard.PrimaryDevice.ForceTarget = null;
                } 
            } 

            return handled; 
        }

        // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
        // Go back to accepting character messages.  This method is posted 
        // to the dispatcher when char messages are disable.
        internal static object RestoreCharMessages(object unused) 
        { 
            _eatCharMessages = false;
            return null; 
        }

#endregion IKeyboardInputSink
 

        internal bool IsRepeatedKeyboardMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        { 
            if (msg != _lastKeyboardMessage.message)
                return false; 
            if (hwnd != _lastKeyboardMessage.hwnd)
                return false;
            if (wParam != _lastKeyboardMessage.wParam)
                return false; 
            if (lParam != _lastKeyboardMessage.lParam)
                return false; 
            return true; 
        }
 
        /// 
        ///    This event handler is called from HwndWrapper when it is Disposing.
        /// 
        // This could happen if someone calls his Dispose before (or instead 
        // of) our dispose.  Or, more likely, the real window was killed by
        // something like the user clicking the close box. 
        private void OnHwndDisposed(object sender, EventArgs args) 
        {
            // This method is called from the HwndWrapper.Dispose(). 
            // So make sure we don't call HwndWrapper.Dispose().
            _inRealHwndDispose = true;
            Dispose();
        } 

        ///  
        ///    Called after the last window message is processed. 
        /// 
 
        // HwndSource is required to continue certain operations while,
        // and even after, Dispose runs.  HwndSource is resposible for
        // calling WndProcHooks with every message the window sees.
        // Including: WM_CLOSE, WM_DESTROY, WM_NCDESTROY.  The doc says 
        // WM_NCDESTROY is the very last message, so we can release the
        // Hooks after that. 
        // This assumes the Context.Access() is held. 
        private void OnNoMoreWindowMessages()
        { 
            _hooks = null;
        }

        private void OnShutdownFinished(object sender, EventArgs args) 
        {
            // Note: We are already in the context being disposed. 
            Dispose(); 
        }
 
        //
        // NOTE: shutdown order is very important.  Review any changes
        // carefully.
        // 
        /// 
        ///     Critical: This accesses the various sites and providers. 
        ///               Asserting UnmanagedCode to access site, this is consistent with the requirements of the interface declaration 
        ///               as it can potentially be used for spoofing.
        ///     Safe: Disposing the object is a safe operation. 
        ///           Not exposing IKIS, just using it to unregister.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void Dispose(bool disposing) 
        {
            if(disposing) 
            { 
                // Make sure all access is synchronized.
//                 this.VerifyAccess(); 

                if (!_isDisposing)
                {
                    // _isDisposing is a guard against re-entery into this 
                    // routine.  We fire Dispose and SourceChanged (RootVisual
                    // change) events which could cause re-entery. 
                    _isDisposing = true; 

                    // Notify listeners that we are being disposed.  We do this 
                    // before we dispose our internal stuff, in case the event
                    // listener needs to access something.
                    if(Disposed != null)
                    { 
                        try
                        { 
                            Disposed(this, EventArgs.Empty); 
                        }
#pragma warning disable 56500 
                        // We can't tolerate an exception thrown by third-party code to
                        // abort our Dispose half-way through.  So we just eat it.
                        catch
                        { 
                        }
#pragma warning restore 56500 
                        Disposed = null; 
                    }
 
                    // Remove any listeners of the ContentRendered event
                    ClearContentRenderedListeners();

                    // Clear the root visual.  This will raise a SourceChanged 
                    // event to registered listeners.
                    RootVisualInternal = null; 
                    RemoveSource(); 

                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); 
                    try
                    {
                        // Unregister ourselves if we are a registered KeyboardInputSink.
                        // Use the property instead of the backing field in case a subclass has overridden it. 
                        IKeyboardInputSite keyboardInputSite = ((IKeyboardInputSink)this).KeyboardInputSite;
                        if (keyboardInputSite != null) 
                        { 
                            keyboardInputSite.Unregister();
                            ((IKeyboardInputSink)this).KeyboardInputSite = null; 
                        }
                        _keyboardInputSinkChildren = null;
                    }
                    finally 
                    {
                        SecurityPermission.RevertAssert(); 
                    } 

                    // Dispose the HwndStylusInputProvider BEFORE we destroy the HWND. 
                    // This us because the stylus provider has an async channel and
                    // they don't want to process data after the HWND is destroyed.
                    if (_stylus != null)
                    { 
                        _stylus.Value.Dispose();
                        _stylus = null; 
                    } 

                    // Our general shut-down principle is to destroy the window 
                    // and let the individual HwndXXX components respons to WM_DESTROY.
                    //
                    // (see comment above about disposing the HwndStylusInputProvider)
                    // 
                    {
                        if (_hwndTarget != null) 
                        { 
                            _hwndTarget.Dispose();
                            _hwndTarget = null; 
                        }

                        if (_hwndWrapper != null)
                        { 
                            // Revoke the drop target.
                            if (_hwndWrapper.Handle != IntPtr.Zero && _registeredDropTargetCount > 0) 
                            { 
                                // This call is safe since DragDrop.RevokeDropTarget is checking the unmanged
                                // code permission. 
                                DragDrop.RevokeDropTarget(_hwndWrapper.Handle);
                                _registeredDropTargetCount--;
                            }
 
                            // Remove our HwndWrapper.Dispose() hander.
                            _hwndWrapper.Disposed -= new EventHandler(OnHwndDisposed); 
 
                            if (!_inRealHwndDispose)
                                _hwndWrapper.Dispose(); 

                            // Don't null out _hwndWrapper after the Dispose().
                            // Dispose() will start destroying the Window but we
                            // still need to talk to it during that process while 
                            // the WM_ msgs arrive.
                        } 
                    } 

                    if(_mouse != null) 
                    {
                        _mouse.Value.Dispose();
                        _mouse = null;
                    } 

                    if(_keyboard != null) 
                    { 
                        _keyboard.Value.Dispose();
                        _keyboard = null; 
                    }

                    if (_appCommand != null)
                    { 
                        _appCommand.Value.Dispose();
                        _appCommand = null; 
                    } 

                    if(null != _weakShutdownHandler) 
                    {
                        _weakShutdownHandler.Dispose();
                        _weakShutdownHandler = null;
                    } 

                    if(null != _weakPreprocessMessageHandler) 
                    { 
                        _weakPreprocessMessageHandler.Dispose();
                        _weakPreprocessMessageHandler = null; 
                    }

                    // We wait to set the "_isDisposed" flag until after the
                    // Disposed, SourceChange (RootVisual=null), etc. events 
                    // have fired.  We want to remain functional should their
                    // handlers call methods on us. 
                    // 
                    // Note: as the HwndWrapper shuts down, the final few messages
                    // will continue to pass through our WndProc hook. 
                    _isDisposed = true;
                }
            }
        } 

        private void CheckDisposed(bool verifyAccess) 
        { 
            if(verifyAccess)
            { 
//                 this.VerifyAccess();
            }

            if(_isDisposed) 
            {
                throw new ObjectDisposedException(null, SR.Get(SRID.HwndSourceDisposed)); 
            } 
        }
 
        /// 
        ///     Critical: This code accesses hwndtarget
        ///     TreatAsSafe: Information is ok to expose
        ///  
        private bool IsUsable
        { 
            [SecurityCritical,SecurityTreatAsSafe] 
            get
            { 
                return _isDisposed == false &&
                       _hwndTarget != null &&
                       _hwndTarget.IsDisposed == false;
            } 
        }
 
        ///  
        ///     Critical - calls a method with an elevation ( GetFocus )
        ///     TreatAsSafe - determining whether you have focus within the window is considered safe. 
        ///                   Worst case you can know whether keyboard/keypress events will go to the current window.
        /// 
        private bool HasFocus
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 
                return UnsafeNativeMethods.GetFocus() == CriticalHandle;
            } 
        }

        private static bool IsValidSizeToContent(SizeToContent value)
        { 
            return value == SizeToContent.Manual ||
                   value == SizeToContent.Width  || 
                   value == SizeToContent.Height || 
                   value == SizeToContent.WidthAndHeight;
        } 

        class ThreadDataBlob
        {
            public int TranslateAcceleratorCallDepth; 
        }
 
        private static ThreadDataBlob PerThreadData 
        {
            get 
            {
                ThreadDataBlob data;
                object obj = Thread.GetData(_threadSlot);
                if(null == obj) 
                {
                    data = new ThreadDataBlob(); 
                    Thread.SetData(_threadSlot, data); 
                }
                else 
                {
                    data = (ThreadDataBlob) obj;
                }
                return data; 
            }
        } 
 
#region WeakEventHandlers
 
        private class WeakEventDispatcherShutdown: WeakReference
        {
            public WeakEventDispatcherShutdown(HwndSource source, Dispatcher that): base(source)
            { 
                _that = that;
                _that.ShutdownFinished += new EventHandler(this.OnShutdownFinished); 
            } 

            public void OnShutdownFinished(object sender, EventArgs e) 
            {
                HwndSource source = this.Target as HwndSource;
                if(null != source)
                { 
                    source.OnShutdownFinished(sender, e);
                } 
                else 
                {
                    Dispose(); 
                }
            }

            public void Dispose() 
            {
                if(null != _that) 
                { 
                    _that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished);
                } 
            }

            private Dispatcher _that;
        } 

        private class WeakEventPreprocessMessage: WeakReference 
        { 
            /// 
            ///     Critical: This code calls attaches an arbitrary window 
            ///     to the call path for the component dispatcher call back
            /// 
            [SecurityCritical]
            public WeakEventPreprocessMessage(HwndSource source, bool addToFront): base(source) 
            {
                _addToFront = addToFront; 
                _handler = new ThreadMessageEventHandler(this.OnPreprocessMessage); 

                if(addToFront) 
                {
                    ComponentDispatcher.CriticalAddThreadPreprocessMessageHandlerFirst(_handler);
                }
                else 
                {
                    ComponentDispatcher.ThreadPreprocessMessage += _handler; 
                } 
            }
 
            /// 
            ///     Critical: This can be used to spoof and change input
            /// 
            [SecurityCritical] 
            public void OnPreprocessMessage(ref MSG msg, ref bool handled)
            { 
                HwndSource source = this.Target as HwndSource; 
                if(null != source)
                { 
                    source.OnPreprocessMessageThunk(ref msg, ref handled);
                }
                else
                { 
                    Dispose();
                } 
            } 

 
            /// 
            ///     Critical:This code calls into ComponentDispatcher
            ///     to disconnect a listener
            ///     TreatAsSafe: This code is ok to call 
            /// 
            [SecurityCritical,SecurityTreatAsSafe] 
            public void Dispose() 
            {
                if(_addToFront) 
                {
                    ComponentDispatcher.CriticalRemoveThreadPreprocessMessageHandlerFirst(_handler);
                }
                else 
                {
                    ComponentDispatcher.ThreadPreprocessMessage -= _handler; 
                } 

                _handler = null; 
            }

            private bool _addToFront;
            private ThreadMessageEventHandler _handler; 
        }
 
#endregion WeakEventHandlers 

        private object                      _constructionParameters; // boxed HwndSourceParameters 

        private bool                        _isDisposed = false;
        private bool                        _isDisposing = false;
        private bool                        _inRealHwndDispose = false; 
        private bool                        _adjustSizingForNonClientArea;
        private bool                        _myOwnUpdate; 
        private bool                        _isWindowInMinimizeState = false; 

        private int                         _registeredDropTargetCount; 

        private SizeToContent               _sizeToContent = SizeToContent.Manual;
        private Size?                       _previousSize;
 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical. 
        /// 
        [SecurityCritical] 
        private HwndWrapper                 _hwndWrapper;

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical.
        ///  
        [SecurityCritical] 
        private HwndTarget                  _hwndTarget;
 
        private SecurityCriticalDataForSet                      _rootVisual;

        private event HwndSourceHook _hooks;
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        ///  
        private SecurityCriticalDataClass      _mouse;
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical.
        /// 
        private SecurityCriticalDataClass   _keyboard; 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical. 
        /// 
        private SecurityCriticalDataClass     _stylus; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        /// 
        private SecurityCriticalDataClass _appCommand; 
 
        WeakEventDispatcherShutdown _weakShutdownHandler;
        WeakEventPreprocessMessage _weakPreprocessMessageHandler; 
        WeakEventPreprocessMessage _weakMenuModeMessageHandler;

        private static System.LocalDataStoreSlot _threadSlot;
 
        private RestoreFocusMode _restoreFocusMode;
 
        [ThreadStatic] 
        private static bool? _defaultAcquireHwndFocusInMenuMode;
        private bool _acquireHwndFocusInMenuMode; 

        private MSG                         _lastKeyboardMessage;
        private List _keyboardInputSinkChildren;
 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data can be used to spoof input 
        /// 
        // Be careful about accessing this field directly. 
        // It's bound to IKeyboardInputSink.KeyboardInputSite, so if a derived class overrides
        // that property then this field will be incorrect.
        [SecurityCritical]
        private IKeyboardInputSite          _keyboardInputSite = null; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data can be used to spoof input
        ///  
        [SecurityCritical]
        private HwndWrapperHook             _layoutHook;

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        ///  
        [SecurityCritical]
        private HwndWrapperHook             _inputHook; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _hwndTargetHook; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _publicHook;
 
        // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
        //
        // Avalon relies on the policy that if you handle the KeyDown 
        // event, you will not get the TextInput events caused by
        // pressing the key.  This is generally implemented because the
        // message pump calls ComponentDispatcher.RaiseThreadMessage and
        // we return whether or not the WM_KEYDOWN message was handled, 
        // and the message pump will only call TranslateMessage() if the
        // WM_KEYDOWN was not handled.  However, naive message pumps don't 
        // call ComponentDispatcher.RaiseThreadMessage, and always call 
        // TranslateMessage, so the WM_CHAR is generated no matter what.
        // The best work around we could think of was to eat the WM_CHAR 
        // messages and not report them to Avalon.
        //
        [ThreadStatic]
        internal static bool _eatCharMessages; // used from HwndKeyboardInputProvider 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2004
//
//  File: HwndSource.cs 
//-----------------------------------------------------------------------------
 
using System.Collections; 
using System.Collections.Generic;
using System.Threading; 
using System.Windows.Threading;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Interop; 
using System.Runtime.InteropServices;
using MS.Win32; 
using MS.Utility; 
using MS.Internal;
using MS.Internal.Interop; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using Microsoft.Win32;
using System.Diagnostics;
using System.ComponentModel; 
using System;
using System.Security; 
using System.Security.Permissions; 
using System.IO;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings 

namespace System.Windows.Interop 
{ 
    /// 
    ///     The HwndSource class presents content within a Win32 HWND. 
    /// 
    public class HwndSource : PresentationSource, IDisposable, IWin32Window, IKeyboardInputSink
    {
        ///  
        ///     Critical: This code calls into RegisterWindowMesssage which is critical
        ///     TreatAsSafe: This is safe to call as no external parameters are taken in 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        static HwndSource() 
        {
            _threadSlot = Thread.AllocateDataSlot();
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class that will always resize to its content size. 
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        /// 
        /// 
        ///     The Win32 styles for this window.
        ///  
        /// 
        ///     The extended Win32 styles for this window. 
        ///  
        /// 
        ///     The position of the left edge of this window. 
        /// 
        /// 
        ///     The position of the upper edge of this window.
        ///  
        /// 
        ///     The name of this window. 
        ///  
        /// 
        ///     The Win32 window that should be the parent of this window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions 
        /// 
        [SecurityCritical]
        public HwndSource(
            int classStyle, 
            int style,
            int exStyle, 
            int x, 
            int y,
            string name, 
            IntPtr parent)
        {
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters param = new HwndSourceParameters(name);
            param.WindowClassStyle = classStyle; 
            param.WindowStyle = style; 
            param.ExtendedWindowStyle = exStyle;
            param.SetPosition(x, y); 
            param.ParentWindow = parent;
            Initialize(param);
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an 
        ///    explicit width and height be sepecified. 
        /// 
        ///  
        ///     The Win32 class styles for this window.
        /// 
        /// 
        ///     The Win32 styles for this window. 
        /// 
        ///  
        ///     The extended Win32 styles for this window. 
        /// 
        ///  
        ///     The position of the left edge of this window.
        /// 
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        ///  
        ///     The width of this window. 
        /// 
        ///  
        ///     The height of this window.
        /// 
        /// 
        ///     The name of this window. 
        /// 
        ///  
        ///     The Win32 window that should be the parent of this window. 
        /// 
        ///  
        ///     Indicates that HwndSource should include the non-client area
        ///     of the hwnd when it calls the Layout Manager
        /// 
        ///  
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        ///  
        ///     Added a demand - so that this API does not work in InternetZone.
        ///     Critical: This acceses critical code Initialize 
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        /// 
        [SecurityCritical] 
        public HwndSource(int classStyle,
                          int style, 
                          int exStyle, 
                          int x,
                          int y, 
                          int width,
                          int height,
                          string name,
                          IntPtr parent, 
                          bool adjustSizingForNonClientArea)
        { 
            SecurityHelper.DemandUIWindowPermission(); 

            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height); 
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle;
            parameters.SetPosition(x, y); 
            parameters.ParentWindow = parent;
            parameters.AdjustSizingForNonClientArea = adjustSizingForNonClientArea; 
            Initialize(parameters); 
        }
 
        /// 
        ///    Constructs an instance of the HwndSource class. This version requires an
        ///    explicit width and height be sepecified.
        ///  
        /// 
        ///     The Win32 class styles for this window. 
        ///  
        /// 
        ///     The Win32 styles for this window. 
        /// 
        /// 
        ///     The extended Win32 styles for this window.
        ///  
        /// 
        ///     The position of the left edge of this window. 
        ///  
        /// 
        ///     The position of the upper edge of this window. 
        /// 
        /// 
        ///     The width of this window.
        ///  
        /// 
        ///     The height of this window. 
        ///  
        /// 
        ///     The name of this window. 
        /// 
        /// 
        ///     The Win32 window that should be the parent of this window.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Added a demand - so that this API does not work in InternetZone. 
        ///     Critical: This accesses critical code Initialize
        ///     PublicOK: This code has a demand which will ensure that it does
        ///     not work in partial trust without the correct permissions
        ///  
        [SecurityCritical]
        public HwndSource( 
            int classStyle, 
            int style,
            int exStyle, 
            int x,
            int y,
            int width,
            int height, 
            string name,
            IntPtr parent) 
        { 
            SecurityHelper.DemandUIWindowPermission();
 
            HwndSourceParameters parameters = new HwndSourceParameters(name, width, height);
            parameters.WindowClassStyle = classStyle;
            parameters.WindowStyle = style;
            parameters.ExtendedWindowStyle = exStyle; 
            parameters.SetPosition(x, y);
            parameters.ParentWindow = parent; 
            Initialize(parameters); 
        }
 
        /// 
        ///    HwndSource Ctor
        /// 
        ///  parameter block  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Critical: This acceses critical code Initialize 
        /// 
        [SecurityCritical]
        [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        public HwndSource(HwndSourceParameters parameters) 
        {
            Initialize(parameters); 
        } 
        /// 
        ///    HwndSource Ctor 
        /// 
        ///  parameter block 
        /// 
        ///     Critical: This code access critical (HwndMouseInputProvider, HwndKeyboardInputProvider 
        ///     ,HwndStylusInputProvider and the various hooks)objects and creates the
        ///     providers under elevation. 
        ///  
        [SecurityCritical]
        private void Initialize(HwndSourceParameters parameters) 
        {
            _mouse = new SecurityCriticalDataClass(new HwndMouseInputProvider(this));
            _keyboard = new SecurityCriticalDataClass(new HwndKeyboardInputProvider(this));
            _layoutHook = new HwndWrapperHook(LayoutFilterMessage); 
            _inputHook = new HwndWrapperHook(InputFilterMessage);
            _hwndTargetHook = new HwndWrapperHook(HwndTargetFilterMessage); 
 
            _publicHook = new HwndWrapperHook(PublicHooksFilterMessage);
 
            // When processing WM_SIZE, LayoutFilterMessage must be invoked before
            // HwndTargetFilterMessage. This way layout will be updated before resizing
            // HwndTarget, resulting in single render per resize. This means that
            // layout hook should appear before HwndTarget hook in the wrapper hooks 
            // list. If this is done the other way around, first HwndTarget resize will
            // force re-render, then layout will be updated according to the new size, 
            // scheduling another render. 
            HwndWrapperHook[] wrapperHooks = { _hwndTargetHook, _layoutHook, _inputHook, null };
 
            if (null != parameters.HwndSourceHook)
            {
                // In case there's more than one delegate, add these to the event storage backwards
                // so they'll get invoked in the expected order. 
                Delegate[] handlers = parameters.HwndSourceHook.GetInvocationList();
                for (int i = handlers.Length -1; i >= 0; --i) 
                { 
                    _hooks += (HwndSourceHook)handlers[i];
                } 
                wrapperHooks[3] = _publicHook;
            }

            _restoreFocusMode = parameters.RestoreFocusMode; 
            _acquireHwndFocusInMenuMode = parameters.AcquireHwndFocusInMenuMode;
 
            // A window must be marked WS_EX_LAYERED if (and only if): 
            // 1) it is not a child window
            //    -- AND -- 
            // 2) a color-key is specified
            // 3) or an opacity other than 1.0 is specified
            // 4) or per-pixel alpha is requested.
            if((parameters.WindowStyle & NativeMethods.WS_CHILD) == 0 && 
               ( //parameters.ColorKey != null ||
                 //!MS.Internal.DoubleUtil.AreClose(parameters.Opacity, 1.0) || 
                parameters.UsesPerPixelOpacity)) 
            {
                parameters.ExtendedWindowStyle |= NativeMethods.WS_EX_LAYERED; 
            }
            else
            {
                parameters.ExtendedWindowStyle &= (~NativeMethods.WS_EX_LAYERED); 
            }
 
 
            _constructionParameters = parameters;
            _hwndWrapper = new HwndWrapper(parameters.WindowClassStyle, 
                                       parameters.WindowStyle,
                                       parameters.ExtendedWindowStyle,
                                       parameters.PositionX,
                                       parameters.PositionY, 
                                       parameters.Width,
                                       parameters.Height, 
                                       parameters.WindowName, 
                                       parameters.ParentWindow,
                                       wrapperHooks); 

            _hwndTarget = new HwndTarget(_hwndWrapper.Handle);
            //_hwndTarget.ColorKey = parameters.ColorKey;
            //_hwndTarget.Opacity = parameters.Opacity; 
            _hwndTarget.UsesPerPixelOpacity = parameters.UsesPerPixelOpacity;
            if(_hwndTarget.UsesPerPixelOpacity) 
            { 
                _hwndTarget.BackgroundColor = Colors.Transparent;
 
                // Prevent this window from being themed.
                UnsafeNativeMethods.CriticalSetWindowTheme(new HandleRef(this, _hwndWrapper.Handle), "", "");
            }
            _constructionParameters = null; 

            if (!parameters.HasAssignedSize) 
                _sizeToContent = SizeToContent.WidthAndHeight; 
            _adjustSizingForNonClientArea = parameters.AdjustSizingForNonClientArea;
 
            // Listen to the UIContext.Disposed event so we can clean up.
            // The HwndTarget cannot work without a MediaContext which
            // is disposed when the UIContext is disposed.  So we need to
            // dispose the HwndTarget and also never use it again (to 
            // paint or process input).  The easiest way to do this is to just
            // dispose the HwndSource at the same time. 
            _weakShutdownHandler = new WeakEventDispatcherShutdown(this, this.Dispatcher); 

            // Listen to the HwndWrapper.Disposed event so we can clean up. 
            // The HwndTarget cannot work without a live HWND, and since
            // the HwndSource represents an HWND, we make sure we dispose
            // ourselves if the HWND is destroyed out from underneath us.
            _hwndWrapper.Disposed += new EventHandler(OnHwndDisposed); 

            _stylus = new SecurityCriticalDataClass(new HwndStylusInputProvider(this)); 
 
            // WM_APPCOMMAND events are handled thru this.
            _appCommand = new SecurityCriticalDataClass(new HwndAppCommandInputProvider(this)); 

            // Register the top level source with the ComponentDispatcher.
            if (parameters.TreatAsInputRoot)
            { 
                _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this, false);
            } 
            AddSource(); 

            // Register dropable window. 
            // The checking CallerHasPermissionWithAppDomainOptimization will call RegisterDropTarget
            // safely without the security exception in case of no unmanaged code permission.
            // So RegisterDropTarget will be called safely in case of having the unmanged code permission.
            // Otherwise, the security exception cause System.Printing to be instatiated which will 
            // load system.drawing module.
            if (_hwndWrapper.Handle != IntPtr.Zero && 
                SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode))) 
            {
                // This call is safe since DragDrop.RegisterDropTarget is checking the unmanged 
                // code permission.
                DragDrop.RegisterDropTarget(_hwndWrapper.Handle);
                _registeredDropTargetCount++;
            } 
        }
 
        ///  
        ///     Disposes the object
        ///  
        ///
        /// This API is not available in Internet Zone.
        ///
        public void Dispose() 
        {
            Dispose(true); 
            GC.SuppressFinalize(this); 
        }
 
        /// 
        ///     Adds a hook that gets called for every window message.
        /// 
        ///  
        ///     The hook to add.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        ///
        /// Critical - uses a critical field.
        /// PublicOK - as there's a demand.
        /// 
        [SecurityCritical ]
        public void AddHook(HwndSourceHook hook) 
        { 
            SecurityHelper.DemandUIWindowPermission();
            Verify.IsNotNull(hook, "hook"); 

            CheckDisposed(true);

            if(_hooks == null) 
            {
                _hwndWrapper.AddHook(_publicHook); 
            } 
            _hooks += hook;
        } 

        /// 
        ///     Removes a hook that was previously added.
        ///  
        /// 
        ///     The hook to remove. 
        ///  
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///
        ///
        /// Critical - accesses a crtical field - _publicHook
        /// PublicOK - performs a demand. 
        ///
        [SecurityCritical ] 
        public void RemoveHook(HwndSourceHook hook) 
        {
            SecurityHelper.DemandUIWindowPermission(); 

            //this.VerifyAccess();

            _hooks -= hook; 
            if(_hooks == null)
            { 
                _hwndWrapper.RemoveHook(_publicHook); 
            }
        } 

        /// 
        /// GetInputProvider - Given a InputDevice, returns corresponding Provider
        ///  
        /// InputDevice for which we need InputProvider
        /// InputProvider, if known 
        /// 
        /// This API is not available in Internet Zone.
        /// 
        /// 
        ///     Critical: This code accesses and returns critical data *providers*
        /// 
        [SecurityCritical] 
        internal override IInputProvider GetInputProvider(Type inputDevice)
        { 
            if (inputDevice == typeof(MouseDevice)) 
                return (_mouse    != null ?    _mouse.Value : null);
 
            if (inputDevice == typeof(KeyboardDevice))
                return (_keyboard != null ? _keyboard.Value : null);

            if (inputDevice == typeof(StylusDevice)) 
                return (_stylus   != null ?   _stylus.Value : null);
 
            return null; 
        }
 
        /// 
        ///     Announces when this source is disposed.
        /// 
        public event EventHandler Disposed; 

        ///  
        ///     Announces when the SizeToContent property changes on this source. 
        /// 
        public event EventHandler SizeToContentChanged; 

        /// 
        ///     Whether or not the object is disposed.
        ///  
        public override bool IsDisposed {get {return _isDisposed;}}
 
        ///  
        /// The Root Visual for this window. If it is a UIElement
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// 
        ///  
        ///     Critical: This code sets a rootvisual which is risky to do because
        ///     it can destabilize assumptions made in popup code 
        ///     PublicOK: The getter is safe and the setter has a link demand to block unwarrented 
        ///     public use
        ///  
        public override Visual RootVisual
        {
            [SecurityCritical]
            get 
            {
                if (_isDisposed) 
                    return null; 
                return (_rootVisual.Value);
            } 
            [SecurityCritical]
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
            set
            { 
                CheckDisposed(true);
 
                RootVisualInternal = value; 
            }
        } 

        /// 
        /// Critical: Acceses KeyboardInputProvider which is considered as critical data
        /// also it can be used to set root visual which is deemed as an unsafe operation 
        /// 
        private Visual RootVisualInternal 
        { 
            [SecurityCritical]
            set 
            {
                if (_rootVisual.Value != value)
                {
                    Visual oldRoot = _rootVisual.Value; 

                    if(value != null) 
                    { 
                        _rootVisual.Value = value;
 
                        if(_rootVisual.Value is UIElement)
                        {
                            ((UIElement)(_rootVisual.Value)).LayoutUpdated += new EventHandler(OnLayoutUpdated);
                        } 

                        if (_hwndTarget != null && _hwndTarget.IsDisposed == false) 
                        { 
                            _hwndTarget.RootVisual = _rootVisual.Value;
                        } 

                        UIElement.PropagateResumeLayout(null, value);
                    }
                    else 
                    {
                        _rootVisual.Value = null; 
                        if (_hwndTarget != null && !_hwndTarget.IsDisposed) 
                        {
                            _hwndTarget.RootVisual = null; 
                        }
                    }

                    if(oldRoot != null) 
                    {
                        if(oldRoot is UIElement) 
                        { 
                            ((UIElement)oldRoot).LayoutUpdated -= new EventHandler(OnLayoutUpdated);
                        } 

                        UIElement.PropagateSuspendLayout(oldRoot);
                    }
 
                    RootChanged(oldRoot, _rootVisual.Value);
 
                    if (IsLayoutActive() == true) 
                    {
                        // Call the helper method SetLayoutSize to set Layout's size 
                        SetLayoutSize();

                        // Post the firing of ContentRendered as Input priority work item so that ContentRendered will be
                        // fired after render query empties. 
                        this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(FireContentRendered), this);
                    } 
                    else 
                    {
                        // Even though layout won't run (the root visual is either null or not 
                        // a UIElement), the hit-test results will certainly have changed.
                        InputManager.SafeCurrentNotifyHitTestInvalidated();
                    }
 
                    // It is possible that someone would have closed the window in one of the
                    // previous callouts - such as during RootChanged or during the layout 
                    // we syncronously invoke.  In such cases, the state of this object would 
                    // have been torn down.  We just need to protect against that.
                    if(_keyboard != null) 
                    {
                        _keyboard.Value.OnRootChanged(oldRoot, _rootVisual.Value);
                    }
                } 
            }
        } 
 
        /// 
        ///     Returns a sequence of registered input sinks. 
        /// 
        public IEnumerable ChildKeyboardInputSinks
        {
            get 
            {
                if (_keyboardInputSinkChildren != null) 
                { 
                    foreach (IKeyboardInputSite site in _keyboardInputSinkChildren)
                        yield return site.Sink; 
                }
            }
        }
 
        /// 
        ///     Returns the HwndSource that corresponds to the specified window. 
        ///  
        /// The window.
        /// The source that corresponds to the specified window. 
        ///
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///
        ///  
        ///     Critical: This information is not ok to expose since this HwndSource
        ///     is deemed critical to expose 
        ///     PublicOK: There is a demand on this method that prevents this 
        ///     from working in partial trust unless you have the right permissions.
        ///  
        [SecurityCritical]
        public static HwndSource FromHwnd(IntPtr hwnd)
        {
            SecurityHelper.DemandUIWindowPermission(); 
            return CriticalFromHwnd(hwnd);
        } 
 
        /// 
        ///    Critical: This code extracts the HwndSource for an HWND 
        ///    This function is only for internal consumption
        /// 
        [SecurityCritical]
        internal static HwndSource CriticalFromHwnd(IntPtr hwnd) 
        {
            if (hwnd == IntPtr.Zero) 
            { 
                throw new ArgumentException(SR.Get(SRID.NullHwnd));
            } 
            HwndSource hwndSource = null;
            foreach (PresentationSource source in PresentationSource.CriticalCurrentSources)
            {
                HwndSource test = source as HwndSource; 
                if (test != null && test.CriticalHandle == hwnd)
                { 
                    // Don't hand out a disposed source. 
                    if (!test.IsDisposed)
                        hwndSource = test; 
                    break;
                }
            }
            return hwndSource; 
        }
 
 
        /// 
        ///     The visual manager for the visuals being presented in the source. 
        ///     Type-specific version of the CompositionTarget property for this source.
        /// 
        /// 
        ///     Critical: Accesses hwndTarget and returns it 
        ///     PublicOk: Protected by a LinkDemand
        ///  
        public new HwndTarget CompositionTarget 
        {
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
            get
            {
                if (_isDisposed) 
                    return null;
 
                // Even though we created the HwndTarget, it can get disposed out from 
                // underneath us.
                if (_hwndTarget!= null && _hwndTarget.IsDisposed == true) 
                {
                    return null;
                }
 
                return _hwndTarget;
            } 
        } 

        ///  
        ///     Returns visual target for this source.
        /// 
        /// 
        ///     Critical: calls get_CompositionTarget() and returns its value. 
        /// 
        [SecurityCritical] 
        protected override CompositionTarget GetCompositionTargetCore() 
        {
            return CompositionTarget; 
        }

        /// 
        ///     When an HwndSource enters menu mode, it subscribes to the 
        ///     ComponentDispatcher.ThreadPreprocessMessage event to get
        ///     privileged access to the window messages. 
        ///  
        /// 
        ///     The ThreadPreprocessMessage handler for menu mode is 
        ///     independent of the handler for the same event used for
        ///     keyboard processing by top-level windows.
        /// 
        ///  
        ///     Critical: Accesses the ComponentDispatcher, which is generally
        ///               considered critical. 
        ///     TreatAsSafe: MenuMode is approved for public access. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void OnEnterMenuMode()
        {
            // We opt-in this HwndSource to the new behavior for "exclusive"
            // menu mode only if AcquireHwndFocusInMenuMode is false. 
            IsInExclusiveMenuMode = !_acquireHwndFocusInMenuMode;
            if(IsInExclusiveMenuMode) 
            { 
                Debug.Assert(_weakMenuModeMessageHandler == null);
 
                // Re-subscribe to the ComponentDispatcher.ThreadPreprocessMessage so we go first.
                _weakMenuModeMessageHandler = new WeakEventPreprocessMessage(this, true);

                // Hide the Win32 caret 
                UnsafeNativeMethods.HideCaret(new HandleRef(this, IntPtr.Zero));
            } 
        } 

        ///  
        ///     When an HwndSource leaves menu mode, it unsubscribes from the
        ///     ComponentDispatcher.ThreadPreprocessMessage event because it no
        ///     longer needs privileged access to the window messages.
        ///  
        /// 
        ///     The ThreadPreprocessMessage handler for menu mode is 
        ///     independent of the handler for the same event used for 
        ///     keyboard processing by top-level windows.
        ///  
        /// 
        ///     Critical: Accesses the ComponentDispatcher, which is generally
        ///               considered critical.
        ///     TreatAsSafe: MenuMode is approved for public access. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void OnLeaveMenuMode() 
        {
            if(IsInExclusiveMenuMode) 
            {
                Debug.Assert(_weakMenuModeMessageHandler != null);

                // Unsubscribe the special menu-mode handler since we don't need to go first anymore. 
                _weakMenuModeMessageHandler.Dispose();
                _weakMenuModeMessageHandler = null; 
 
                // Restore the Win32 caret.  This does not necessarily show the caret, it
                // just undoes the HideCaret call in OnEnterMenuMode. 
                UnsafeNativeMethods.ShowCaret(new HandleRef(this, IntPtr.Zero));
            }
            IsInExclusiveMenuMode = false;
        } 

        internal bool IsInExclusiveMenuMode{get; private set;} 
 
        /// 
        ///     Event invoked when the layout causes the HwndSource to resize automatically. 
        /// 
        public event AutoResizedEventHandler AutoResized;

        ///  
        /// Handler for LayoutUpdated event of a rootVisual.
        ///  
        ///  
        ///     Critical: This code causes resize of window and accesses HwndTarget
        ///  
        [SecurityCritical]
        private void OnLayoutUpdated(object obj, EventArgs args)
        {
            UIElement root = _rootVisual.Value as UIElement; 

            if(root != null) 
            { 
                Size newSize = root.RenderSize;
                if (   _previousSize == null 
                    || !DoubleUtil.AreClose(_previousSize.Value.Width, newSize.Width)
                    || !DoubleUtil.AreClose(_previousSize.Value.Height, newSize.Height))
                {
                    // We should update _previousSize, even if the hwnd is not 
                    // sizing to content.  This fixes the scenario where:
                    // 
                    // 1) hwnd is sized to content to say a, b 
                    // 2) hwnd is resize to a bigger size
                    // 3) hwnd is sized to content to a, b again 
                    _previousSize = newSize;

                    //
                    // Don't resize while the Window is in Minimized mode. 
                    //
                    if (_sizeToContent != SizeToContent.Manual && !_isWindowInMinimizeState ) 
                    { 
                        Resize(newSize);
                    } 
                }
            }
        }
 
        /// 
        /// This is called when LayoutManager was updated and its size (the layout size of top element) changed. 
        /// Ask LayoutManager.Size to see what the new value is. 
        /// 
        ///  
        ///     Critical: This code causes resize of window and accesses HwndTarget
        ///     TreatAsSafe: In RBW the resize values are clamped also one cannot construct or get to a HwndSource in partial trust
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private void Resize(Size newSize)
        { 
            try 
            {
                _myOwnUpdate = true; 

                if (IsUsable)
                {
                    NativeMethods.RECT rect = AdjustWindowSize(newSize); 

                    int newWidth = rect.right - rect.left; 
                    int newHeight = rect.bottom - rect.top; 

                    // Set the new window size 
                    UnsafeNativeMethods.SetWindowPos(new HandleRef(this,_hwndWrapper.Handle), new HandleRef(null,IntPtr.Zero),
                                                   0, 0, newWidth, newHeight,
                                                   NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);
 
                    if (AutoResized != null)
                    { 
                        AutoResized(this, new AutoResizedEventArgs(newSize)); 
                    }
                } 
            }
            finally
            {
                _myOwnUpdate = false; 
            }
        } 
 
        /// 
        /// This shows the system menu for the top level window that this HwndSource is in. 
        /// 
        /// 
        ///     Critical: Accesses GetAncestor & PostMessage.  This method is deemed inherently unsafe
        ///               because opening the system menu will eat user input. 
        /// 
        [SecurityCritical] 
        internal void ShowSystemMenu() 
        {
            // Find the topmost window.  This will handle the case where the HwndSource 
            // is a child window.
            IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT);

            // Open the system menu. 
            UnsafeNativeMethods.PostMessage(new HandleRef(this, hwndRoot), MS.Internal.Interop.WindowMessage.WM_SYSCOMMAND, new IntPtr(NativeMethods.SC_KEYMENU), new IntPtr(NativeMethods.VK_SPACE));
        } 
 
        /// 
        ///     Critical: This code accesses critical member _hwndTarget. 
        ///     TreatAsSafe: It calculates the new point without changing the HWND.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal Point TransformToDevice(Point pt) 
        {
            // 
            return _hwndTarget.TransformToDevice.Transform(pt); 
        }
 
        /// 
        ///     Critical: This code accesses critical member _hwndTarget.
        ///     TreatAsSafe: It calculates the new point without changing the HWND.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal Point TransformFromDevice(Point pt) 
        { 
            return _hwndTarget.TransformFromDevice.Transform(pt);
        } 

        /// 
        ///     Critical: This code accesses _hwndWrapper.
        ///     TreatAsSafe: It calculates the hwnd size without changing it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private NativeMethods.RECT AdjustWindowSize(Size newSize) 
        {
            // Gather the new client dimensions 
            // The dimension WPF uses is logical unit. We need to convert to device unit first.
            Point pt = TransformToDevice(new Point(newSize.Width, newSize.Height));
            RoundDeviceSize(ref pt);
            NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); 

            // If we're here, and it is the Window case (_adjustSizingForNonClientArea == true) 
            // we get the size which includes the outside size of the window.  For browser case, 
            // we don't support SizeToContent, so we don't take care of this condition.
            // For non-Window cases, we need to calculate the outside size of the window 
            //
            // For windows with UsesPerPixelOpacity, we force the client to
            // fill the window, so we don't need to add in any frame space.
            // 
            if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity)
            { 
                int style = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this, _hwndWrapper.Handle), false)); 
                int styleEx = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this, _hwndWrapper.Handle), true));
 
                SafeNativeMethods.AdjustWindowRectEx(ref rect, style, false, styleEx);
            }
            return rect;
        } 

        // If the root element has Pixel snapping enabled, round the window size to the 
        // nearest int.  Otherwise round the size up to the next int. 
        private void RoundDeviceSize(ref Point size)
        { 
            UIElement root = _rootVisual.Value as UIElement;
            if (root != null && root.SnapsToDevicePixels)
            {
                size = new Point(DoubleUtil.DoubleToInt(size.X), DoubleUtil.DoubleToInt(size.Y)); 
            }
            else 
            { 
                size = new Point(Math.Ceiling(size.X), Math.Ceiling(size.Y));
            } 
        }

        /// 
        /// Returns the hwnd handle to the window. 
        /// 
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///
        ///  
        ///     Critical:This is not safe to expose in internet zone, it returns a window handle
        ///     PublicOK: There exists a demand on this code
        /// 
        public IntPtr Handle 
        {
            [SecurityCritical] 
            get 
            {
                SecurityHelper.DemandUIWindowPermission(); 
                return CriticalHandle;
            }
        }
 
        /// 
        ///     Critical:Internal helper to retrieve handle for security purposes only Please 
        ///     DO NOT USE THIS TO  EXPOSE HANDLE TO OUTSIDE WORLD 
        /// 
        internal IntPtr CriticalHandle 
        {
            [FriendAccessAllowed]
            [SecurityCritical]
            get 
            {
                if (null != _hwndWrapper) 
                    return _hwndWrapper.Handle; 
                return IntPtr.Zero;
            } 
        }

        /// 
        ///     Critical: returns the critical _hwndWrapper. 
        /// 
        internal HwndWrapper HwndWrapper 
        { 
            [SecurityCritical]
            get { return _hwndWrapper; } 
        }

        // Return whether this presentation source has capture.
        ///  
        ///     Critical: calls CriticalHandle
        ///     TreatAsSafe: Returning whether a presentation source has capture is considered safe. 
        ///  
        internal bool HasCapture
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get
            {
                IntPtr capture = SafeNativeMethods.GetCapture(); 

                return ( capture == CriticalHandle ); 
            } 
        }
 
        ///
        ///     Critical - accesses _hwndWrapper.
        ///     TreatAsSafe - checking for null is considered safe.
        /// 
        internal bool IsHandleNull
        { 
            [SecurityCritical, SecurityTreatAsSafe ] 
            get
            { 
                return _hwndWrapper.Handle == IntPtr.Zero ;
            }
        }
 
        /// 
        /// Returns the hwnd handle to the window. 
        ///  
        public HandleRef CreateHandleRef()
        { 
            return new HandleRef(this,Handle);
        }

 
        /// 
        /// SizeToContent on HwndSource 
        ///  
        /// 
        /// The default value is SizeToContent.Manual 
        /// 
        public SizeToContent SizeToContent
        {
            get 
            {
                CheckDisposed(true); 
                return _sizeToContent; 
            }
 
            set
            {
                CheckDisposed(true);
 
                if (IsValidSizeToContent(value) != true)
                { 
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(SizeToContent)); 
                }
 
                if (_sizeToContent == value)
                {
                    return;
                } 

                _sizeToContent = value; 
 
                // we only raise SizeToContentChanged when user interaction caused the change;
                // if a developer goes directly to HwndSource and sets SizeToContent, we will 
                // not notify the wrapping Window

                if (IsLayoutActive() == true)
                { 
                    // Call the helper method SetLayoutSize to set Layout's size
                    SetLayoutSize(); 
                } 
            }
        } 

        /// 
        ///     Critical: This code elevates to access hwndtarget
        ///     TreatAsSafe: ok to expose 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        private bool IsLayoutActive() 
        {
 
            if ((_rootVisual.Value is UIElement) && _hwndTarget!= null && _hwndTarget.IsDisposed == false)
            {
                return true;
            } 

            return false; 
        } 

        ///  
        /// This is the helper method that sets Layout's size basing it on
        /// the current value of SizeToContent.
        /// 
        /// 
        ///  TreatAsSafe: This API could be public in terms of security.
        ///  It does three calls to UnsafeNativeMethods all in a safe way 
        ///  Critical: Makes 3 calls to UnsafeNativeMethods 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void SetLayoutSize()
        {
            Debug.Assert(_hwndTarget!= null, "HwndTarget is null");
            Debug.Assert(_hwndTarget.IsDisposed == false, "HwndTarget is disposed"); 

            UIElement rootUIElement = null; 
            rootUIElement = _rootVisual.Value as UIElement; 
            if (rootUIElement == null) return;
 
            // hamidm - 11/01/2005
            // InvalidateMeasure() call is necessary in the following scenario
            //
            // Window w = new Window(); 
            // w.Measure(new Size(x,y));
            // w.Width = x; 
            // w.Height = y; 
            // w.Show()
            // 
            // In the above scenario, the Measure call from SetLayoutSize will be opt out
            // and window will not receive the MeasureOverride call.  As such, the hwnd min/max
            // restrictions will not be applied since MeasureOverride did not happen after hwnd
            // creation.  Thus, we call InvalidatMeasure() to ensure MeasureOverride call on 
            // Window after hwnd creation.
 
            rootUIElement.InvalidateMeasure(); 

            const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf; 
            bool etwEnabled = EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info);
            long  ctxHashCode = 0;

            if (_sizeToContent == SizeToContent.WidthAndHeight) 
            {
                //setup constraints for measure-to-content 
                Size sz = new Size(double.PositiveInfinity, double.PositiveInfinity); 

                if (etwEnabled) 
                {
                    ctxHashCode = _hwndWrapper.Handle.ToInt64();
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_SetLayoutSize);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }
 
                rootUIElement.Measure(sz); 

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);
                } 

                rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info);
                }
            } 
            else
            { 
                // GetSizeFromHwnd sets either the outside size or the client size of the hwnd based on 
                // _adjustSizeingForNonClientArea flag in logical units.
                Size sizeFromHwndLogicalUnits = GetSizeFromHwnd(); 
                Size sz = new Size(
                        (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Width),
                        (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Height));
 
                if (etwEnabled)
                { 
                    ctxHashCode = _hwndWrapper.Handle.ToInt64(); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_SetLayoutSize);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }

                rootUIElement.Measure(sz);
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);
                } 

                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, sizeFromHwndLogicalUnits.Height);
                else if(_sizeToContent == SizeToContent.Height) sz = new Size(sizeFromHwndLogicalUnits.Width, rootUIElement.DesiredSize.Height);
                else sz = sizeFromHwndLogicalUnits; 

                rootUIElement.Arrange(new Rect(new Point(), sz)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info);
                }
            } 
            rootUIElement.UpdateLayout();
        } 
 
        // /// 
        // ///     Specifies the color to display as transparent. 
        // /// 
        // /// 
        // ///     Use null to indicate that no color should be transparent.
        // ///  
        // public Nullable ColorKey
        // { 
        //     get 
        //     {
        //         CheckDisposed(true); 
        //
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null)
        //         { 
        //             return _hwndTarget.ColorKey;
        //         } 
        //         else 
        //         {
        //             return null; 
        //         }
        //     }
        //
        //     set 
        //     {
        //         CheckDisposed(true); 
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null) 
        //         {
        //             _hwndTarget.ColorKey = value;
        //         }
        //     } 
        // }
 
        // ///  
        // ///     Specifies the constant opacity to apply to the window.
        // ///  
        // /// 
        // ///     The valid values range from [0..1].  Values outside of this range are clamped.
        // /// 
        // public double Opacity 
        // {
        //     get 
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed
        //         if(_hwndTarget != null)
        //         {
        //             return _hwndTarget.Opacity; 
        //         }
        //         else 
        //         { 
        //             return 1.0;
        //         } 
        //     }
        //
        //     set
        //     { 
        //         CheckDisposed(true);
        // 
        //         HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
        //         if(_hwndTarget != null)
        //         { 
        //             _hwndTarget.Opacity = value;
        //         }
        //     }
        // } 

        ///  
        ///     Specifies whether or not the per-pixel opacity of the window content 
        ///     is respected.
        ///  
        /// 
        ///     By enabling per-pixel opacity, the system will no longer draw the non-client area.
        /// 
        ///  
        ///     Critical: Because it accesses _hwndTarget
        ///     PublicOK: We don't pass it out; it is just used to query UsesPerPixelOpacity 
        ///  
        public bool UsesPerPixelOpacity
        { 
            [SecurityCritical]
            get
            {
                CheckDisposed(true); 

                HwndTarget hwndTarget = CompositionTarget; // checks for disposed 
                if(_hwndTarget != null) 
                {
                    return _hwndTarget.UsesPerPixelOpacity; 
                }
                else
                {
                    return false; 
                }
            } 
 
/* Not allowing this to change at run-time yet.
            [SecurityCritical] 
            set
            {
                CheckDisposed(true);
 
                HwndTarget hwndTarget = CompositionTarget; // checks for disposed
                if(_hwndTarget != null) 
                { 
                    _hwndTarget.UsesPerPixelOpacity = value;
                } 
            }
*/
        }
 
        /// 
        ///     Critical: Accesses _hwndWrapper.Handle to call unmanaged code to get the client rectangle. 
        ///     TreatAsSafe: The handle is not passed out, and the client rectangle does not need to be protected. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private Size GetSizeFromHwnd()
        {
            // Compute View's size and set
            NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0); 

            if (_adjustSizingForNonClientArea == true) 
            { 
                // get correct size for avalon Window (standalone and browser case)
                GetSizeForWindowObject(ref rc); 
            }
            else
            {
                SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref rc); 
            }
 
            Point convertedPt = TransformFromDevice(new Point(rc.right - rc.left, rc.bottom - rc.top)); 
            return new Size(convertedPt.X, convertedPt.Y);
        } 

        /// 
        ///     Critical: This code can be used to spoof input
        ///  
        [SecurityCritical]
        private IntPtr HwndTargetFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
        { 
            IntPtr result = IntPtr.Zero ;
 
            if (IsUsable)
            {
                HwndTarget hwndTarget = _hwndTarget;
                if (hwndTarget != null) 
                {
                    result = hwndTarget.HandleMessage((WindowMessage)msg, wParam, lParam); 
                    if (result != IntPtr.Zero) 
                    {
                        handled = true; 
                    }
                }

            } 

            return result; 
        } 

        ///  
        /// Critical:These hooks can all be used for input spoofing
        /// 
        [SecurityCritical]
        private IntPtr LayoutFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
        {
            IntPtr result = IntPtr.Zero ; 
            WindowMessage message = (WindowMessage)msg; 

            // We have to revalidate everything because the Access() call 
            // could have caused the CLR to enter a nested message pump,
            // during which almost anything could have happened that might
            // invalidate our checks.
            UIElement rootUIElement=null; 
            rootUIElement = _rootVisual.Value as UIElement;
            if (IsUsable && rootUIElement != null) 
            { 
                switch (message)
                { 
                    // A window receives this message when the user chooses a command from
                    // the Window menu or when the user chooses the maximize button, minimize
                    // button, restore button, or close button.
                    case WindowMessage.WM_SYSCOMMAND: 
                        {
                            // The four low-order bits of the wParam parameter are used 
                            // internally by the system. 
                            Int32 sysCommand = NativeMethods.IntPtrToInt32(wParam) & 0xFFF0;
 
                            // Turn off SizeToContent if user chooses to maximize or resize.
                            if ((sysCommand == NativeMethods.SC_MAXIMIZE) ||
                                (sysCommand == NativeMethods.SC_SIZE))
                            { 
                                DisableSizeToContent(rootUIElement, hwnd);
                            } 
                        } 
                        break;
 
                    // We get WM_SIZING. It means that user starts resizing the window.
                    // It is the first notification sent when user resizes (before WM_WINDOWPOSCHANGING)
                    // and it's not sent if window is resized programmatically.
                    // SizeToContent is turned off after user resizes. 
                    case WindowMessage.WM_SIZING:
                        DisableSizeToContent(rootUIElement, hwnd); 
                        break; 

                    // The WM_WINDOWPOSCHANGING message is sent 
                    // 1. when the size, position, or place in the Z order is about to change as a result of a call to
                    //    the SetWindowPos function or other window-management functions. SizeToContent orverrides all in this case.
                    // 2. when user resizes window. If it's user resize, we have turned SizeToContent off when we get WM_SIZING.
                    // It is sent before WM_SIZE. 
                    // We can't use WM_GETMINMAXINFO, because if there is no window size change (we still need to make sure
                    // the client size not change), that notification wouldnt be sent. 
                    case WindowMessage.WM_WINDOWPOSCHANGING: 
                        Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, message, wParam, lParam);
                        break; 

                    // WM_SIZE message is sent after the size has changed.
                    // lParam has the new width and height of client area.
                    // root element's size should be adjust based on the new width and height and SizeToContent's value. 
                    case WindowMessage.WM_SIZE:
                        Process_WM_SIZE(rootUIElement, hwnd, message, wParam, lParam); 
                        break; 
                }
            } 

            // Certain messages need to be processed while we are in the middle
            // of construction - and thus an HwndTarget is not available.
            if(!handled && (_constructionParameters != null || IsUsable)) 
            {
                // Get the usesPerPixelOpacity from either the constructor parameters or the HwndTarget. 
                bool usesPerPixelOpacity = _constructionParameters != null ? ((HwndSourceParameters)_constructionParameters).UsesPerPixelOpacity : _hwndTarget.UsesPerPixelOpacity; 

                switch(message) 
                {
                    case WindowMessage.WM_NCCALCSIZE:
                        {
                            // Windows that use per-pixel opacity don't get 
                            // their frames drawn by the system.  Generally
                            // this is OK, as users of per-pixel alpha tend 
                            // to be doing customized UI anyways.  But we 
                            // don't render correctly if we leave a non-client
                            // area, so here we expand the client area to 
                            // cover any non-client area.
                            //
                            if(usesPerPixelOpacity)
                            { 
                                if(wParam == IntPtr.Zero)
                                { 
                                    // If wParam is FALSE, lParam points to a RECT 
                                    // structure. On entry, the structure contains
                                    // the proposed window rectangle for the 
                                    // window. On exit, the structure should
                                    // contain the screen coordinates of the
                                    // corresponding window client area.
                                    // 
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything. 
                                    //
                                    result = IntPtr.Zero; 
                                    handled = true;
                                }
                                else
                                { 
                                    // If wParam is TRUE, lParam points to an
                                    // NCCALCSIZE_PARAMS structure that contains 
                                    // information an application can use to 
                                    // calculate the new size and position of
                                    // the client rectangle. 
                                    //
                                    // When Windows sends the WM_NCCALCSIZE
                                    // message, the NCCALCSIZE_PARAMS structure
                                    // is filled out like this: 
                                    //
                                    // rgrc[0] = new window rectangle (in parent coordinates) 
                                    // rgrc[1] = old window rectangle (in parent coordinates) 
                                    // rgrc[2] = old client rectangle (in parent coordinates)
                                    // 
                                    // Notice that the client rectangle is given
                                    // in parent coordinates, not in client
                                    // coordinates.
                                    // 
                                    // When your window procedure returns, Windows
                                    // expects the NCCALCSIZE_PARAMS structure to 
                                    // be filled out like this: 
                                    //
                                    // rgrc[0] = new client rectangle (in parent coordinates) 
                                    //
                                    // Furthermore, if you return anything other
                                    // than 0, Windows expects the remaining two
                                    // rectangles to be filled out like this: 
                                    //
                                    // rgrc[1] = destination rectangle (in parent coordinates) 
                                    // rgrc[2] = source rectangle (in parent coordinates) 
                                    //
                                    // (If you return 0, then Windows assumes that 
                                    // the destination rectangle equals the new
                                    // client rectangle and the source rectangle
                                    // equals the old client rectangle.)
                                    // 
                                    // Since all we want to do is make the client
                                    // rect the same as the window rect, we don't 
                                    // have to do anything. 
                                    //
                                    result = IntPtr.Zero; 
                                    handled = true;
                                }
                            }
                        } 
                        break;
                } 
            } 

            return result; 
        }

        /// 
        /// Critical: Because it uses _hwndTarget 
        /// 
        [SecurityCritical] 
        private void Process_WM_WINDOWPOSCHANGING(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam) 
        {
            // Only if SizeToContent overrides Win32 sizing change calls. 
            // If it's coming from OnResize (_myOwnUpdate != true), it means we are adjusting
            // to the right size; don't need to do anything here.
            if ((_myOwnUpdate != true) && (SizeToContent != SizeToContent.Manual))
            { 
                // Get the current style and calculate the size to be with the new style.
                // If WM_WINDOWPOSCHANGING is sent because of style changes, WM_STYLECHANGED is sent 
                // before this. The style bits we get here are updated ones, but haven't been applied 
                // to Window yet. For example, when the window is changing to borderless, without updating the window size,
                // the window size will remain the same but the client area will be bigger. So when SizeToContent is on, we calculate 
                // the window size to be with the new style using AdustWindowRectEx and adjust it to make sure client area is not affected.
                NativeMethods.RECT rect = AdjustWindowSize(rootUIElement.RenderSize);

                int newCX = rect.right - rect.left; 
                int newCY = rect.bottom - rect.top;
 
                // Get WINDOWPOS structure data from lParam; it contains information about the window's 
                // new size and position.
                NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS)); 

                bool sizeChanged = false;

                // If SWP_NOSIZE is set to ignore cx, cy. It could be a style or position change. 
                if ((windowPos.flags & NativeMethods.SWP_NOSIZE) == NativeMethods.SWP_NOSIZE)
                { 
                    NativeMethods.RECT windowRect = new NativeMethods.RECT(0, 0, 0, 0); 

                    // Get the current Window rect 
                    SafeNativeMethods.GetWindowRect(new HandleRef(this, _hwndWrapper.Handle), ref windowRect);

                    // If there is no size change with the new style we don't need to do anything.
                    if ((newCX != (windowRect.right - windowRect.left)) || 
                        (newCY != (windowRect.bottom - windowRect.top)))
                    { 
                        // Otherwise unmark the flag to make our changes effective. 
                        windowPos.flags &= ~NativeMethods.SWP_NOSIZE;
 
                        // When SWP_NOSIZE is on, the size info in cx and cy is bogus. They are ignored.
                        // When we turn it off, we need to provide valid value for both of them.
                        windowPos.cx = newCX;
                        windowPos.cy = newCY; 
                        sizeChanged = true;
                    } 
                } 
                else
                { 
                    // We have excluded SizeToContent == SizeToContent.Manual before entering this.
                    bool sizeToWidth = (SizeToContent == SizeToContent.Height) ? false : true;
                    bool sizeToHeight = (SizeToContent == SizeToContent.Width) ? false : true;
 
                    // Update WindowPos with the size we want.
                    if ((sizeToWidth) && (windowPos.cx != newCX)) 
                    { 
                        windowPos.cx = newCX;
                        sizeChanged = true; 
                    }

                    if ((sizeToHeight) && (windowPos.cy != newCY))
                    { 
                        windowPos.cy = newCY;
                        sizeChanged = true; 
                    } 
                }
 
                // Marshal the structure back only when changed
                if (sizeChanged)
                {
                    Marshal.StructureToPtr(windowPos, lParam, true); 
                }
            } 
        } 

        ///  
        ///     Critical: Has access to the window handle and uses the parameters provided to modify the layout
        ///         of elements within the window.
        /// 
        [SecurityCritical] 
        private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam)
        { 
            int x = NativeMethods.SignedLOWORD(lParam); 
            int y = NativeMethods.SignedHIWORD(lParam);
            Point pt = new Point(x, y); 
            const EventTrace.Keyword etwKeywords = EventTrace.Keyword.KeywordLayout | EventTrace.Keyword.KeywordPerf;
            bool etwEnabled = EventTrace.IsEnabled(etwKeywords, EventTrace.Level.Info);
            long ctxHashCode = 0;
 
            // 1. If it's coming from Layout (_myOwnUpdate), it means we are adjusting
            // to the right size; don't need to do anything here. 
            // 2. If SizeToContent is set to WidthAndHeight, then we maintain the current hwnd size 
            // in WM_WINDOWPOSCHANGING, so we don't need to re-layout here.  If SizeToContent
            // is set to Width or Height and developer calls SetWindowPos to set a new 
            // Width/Height, we need to do a layout.
            // 3. We also don't need to do anything if it's minimized.

            // Keeps the status of whether the Window is in Minimized state or not. 
            _isWindowInMinimizeState = (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.SIZE_MINIMIZED) ? true : false;
 
            if ((!_myOwnUpdate) && (_sizeToContent != SizeToContent.WidthAndHeight) && !_isWindowInMinimizeState) 
            {
                Point relevantPt = new Point(pt.X, pt.Y); 

                // WM_SIZE has the client size of the window.
                // for appmodel window case, get the outside size of the hwnd.
                if (_adjustSizingForNonClientArea == true) 
                {
                    NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); 
                    GetSizeForWindowObject(ref rect); 
                    relevantPt.X = rect.right - rect.left;
                    relevantPt.Y = rect.bottom - rect.top; 
                }

                // The lParam/wParam size and the GetSizeForWindowObject size are
                // both in device co-ods, thus we convert to Measure co-ods here. 
                relevantPt = TransformFromDevice(relevantPt);
 
                Size sz = new Size( 
                    (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : relevantPt.X),
                    (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : relevantPt.Y)); 

                // NOTE: hamidm -- 6/03/04
                // 962884 Avalon content does not resize when the favorites
                // (or other side pane) is closed 
                //
                // The issue is that when the browser shows favorites window, avalon 
                // window is resized and we get WM_SIZE.  Here, we pass the IE window's 
                // size to Measure so that Computed[Width/Height] gets the correct
                // IE window dimensions.  Since, IE window's size may not change, the 
                // call to Measure is optimized out and no layout happens.  Invalidating
                // layout here ensures that we do layout.
                // This can happen only in the Window case
                if (_adjustSizingForNonClientArea == true) 
                {
                    rootUIElement.InvalidateMeasure(); 
                } 

                if (etwEnabled) 
                {
                    ctxHashCode = _hwndWrapper.Handle.ToInt64();
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode, EventTrace.LayoutSource.HwndSource_WMSIZE);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode);; 
                }
 
                rootUIElement.Measure(sz); 

                if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, relevantPt.Y); 
                else if (_sizeToContent == SizeToContent.Height) sz = new Size(relevantPt.X, rootUIElement.DesiredSize.Height);
                else sz = new Size(relevantPt.X, relevantPt.Y);

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientMeasureEnd, etwKeywords, EventTrace.Level.Info, 1); 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeBegin, etwKeywords, EventTrace.Level.Info, ctxHashCode); 
                }
 
                rootUIElement.Arrange(new Rect(new Point(), sz));

                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientArrangeEnd, etwKeywords, EventTrace.Level.Info, 1);
                    EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientLayoutEnd, etwKeywords, EventTrace.Level.Info); 
                } 
                rootUIElement.UpdateLayout(); //finalizes layout
 
            }
        }

        ///  
        /// Critical: Because it uses _hwndTarget
        ///  
        [SecurityCritical] 
        private void DisableSizeToContent(UIElement rootUIElement, IntPtr hwnd)
        { 
            if (_sizeToContent != SizeToContent.Manual)
            {
                _sizeToContent = SizeToContent.Manual;
 
                // hamidm - 10/27/2005
                // 1348020 Window expereience layout issue when SizeToContent is being turned 
                // off by user interaction 
                // This bug was caused b/c we were giving rootUIElement.DesiredSize as input
                // to Measure/Arrange below.  That is incorrect since rootUIElement.DesiredSize may not 
                // cover the entire hwnd client area.

                // GetSizeFromHwnd returns either the outside size or the client size of the hwnd based on
                // _adjustSizeingForNonClientArea flag in logical units. 
                Size sizeLogicalUnits = GetSizeFromHwnd();
                rootUIElement.Measure(sizeLogicalUnits); 
                rootUIElement.Arrange(new Rect(new Point(), sizeLogicalUnits)); 

                rootUIElement.UpdateLayout(); //finalizes layout 


                if (SizeToContentChanged != null)
                { 
                    SizeToContentChanged(this, EventArgs.Empty);
                } 
            } 
        }
 
        // This method makes sure that we get the size from the correct
        // hwnd for the browser case.
        /// 
        /// Critical - calls critical methods (HwndSourceHelper.GetHandle and GetAncestor) 
        /// TreatAsSafe - it's ok to return size of window. it doesn't return info gotten through critical calls.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void GetSizeForWindowObject(ref NativeMethods.RECT rc)
        { 
            IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT);
            SafeNativeMethods.GetWindowRect(new HandleRef(this, hwndRoot), ref rc);
        }
 
        /// 
        ///     Critical: This is a hook that gets called back with information about messages related to input 
        ///     Calling this from outside or causing this to be invoked could yield risky situations 
        /// 
        [SecurityCritical] 
        private IntPtr InputFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr result = IntPtr.Zero ;
            WindowMessage message = (WindowMessage)msg; 

            // NOTE (alexz): invoke _stylus.FilterMessage before _mouse.FilterMessage 
            // to give _stylus a chance to eat mouse message generated by stylus 
            if (!_isDisposed && _stylus != null && !handled)
            { 
                result = _stylus.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled);
            }

            if (!_isDisposed && _mouse != null && !handled) 
            {
                result = _mouse.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled); 
            } 

            if (!_isDisposed && _keyboard != null && !handled) 
            {
                result = _keyboard.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled);
            }
 
            if (!_isDisposed && _appCommand != null && !handled)
            { 
                result = _appCommand.Value.FilterMessage(hwnd, message, wParam, lParam, ref handled); 
            }
 
            return result;
        }

        ///  
        ///    Called from HwndWrapper on all window messages.
        ///  
        // assumes Context.Access() is held. 
        private IntPtr PublicHooksFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        { 
            // The default result for messages we handle is 0.
            IntPtr result = IntPtr.Zero ;
            WindowMessage message = (WindowMessage)msg;
 
            // Call all of the public hooks
            // We do this even if we are disposed because otherwise the hooks 
            // would never see the WM_DESTROY etc. message. 
            if (_hooks != null)
            { 
                Delegate[] handlers = _hooks.GetInvocationList();
                for (int i = handlers.Length -1; i >= 0; --i)
                {
                    var hook = (HwndSourceHook)handlers[i]; 
                    result = hook(hwnd, msg, wParam, lParam, ref handled);
                    if(handled) 
                    { 
                        break;
                    } 
                }
            }
            if (WindowMessage.WM_NCDESTROY == message)
            { 
                // We delivered the message to the hooks and the message
                // is WM_NCDESTROY, so our commitments should be finished 
                // we can do final teardown. (like disposing the _hooks) 
                OnNoMoreWindowMessages();
            } 

            return result;
        }
 
#region IKeyboardInputSink
 
        /// General security note on the implementation pattern of this interface. In Dev10 it was chosen 
        /// to expose the interface implementation for overriding to customers. We did so by keeping the
        /// explicit interface implementations (that do have the property of being hidden from the public 
        /// contract, which limits IntelliSense on derived types like WebBrowser) while sticking protected
        /// virtuals next to them. Those virtuals contain our base implementation, while the explicit
        /// interface implementation methods do call trivially into the virtuals.
        /// 
        /// This comment outlines the security rationale applied to those methods.
        /// 
        ///  
        ///     The security attributes on the virtual methods within this region mirror the corresponding
        ///     IKeyboardInputSink methods; customers can override those methods, so we insert a LinkDemand 
        ///     to encourage them to have a LinkDemand too (via FxCop).
        ///
        ///     While the methods have LinkDemands on them, the bodies of the methods typically contain
        ///     full demands through a SecurityHelper.DemandUnmanagedCode call. This might seem redundant. 
        ///     The point here is we do a full demand for stronger protection of our built-in implementation
        ///     compared to the LinkDemand on the public interface. We really want full demands here but 
        ///     declarative Demand doesn't work on interface methods. In addition, we try to take advantage 
        ///     of the fact LinkDemands are consistently enforced between base and overridden virtual methods,
        ///     something full Demands do not give us, even when applied declaratively. 
        /// 

        private class MSGDATA
        { 
            public MSG msg;
            public bool handled; 
        } 

        ///  
        /// HwndSource keyboard input is sent through this delegate to check for
        /// Child Hwnd interop requirments.  If there are no child hwnds or focus
        /// is on this non-child hwnd then normal Avalon processing is done.
        ///  
        ///
        /// Critical - This can be used to spoof input 
        ///  
        [SecurityCritical]
        private void OnPreprocessMessageThunk(ref MSG msg, ref bool handled) 
        {
//             VerifyAccess();

            if (handled) 
            {
                return; 
            } 

            // We only do these message. 
            switch ((WindowMessage)msg.message)
            {
            case WindowMessage.WM_KEYUP:
            case WindowMessage.WM_KEYDOWN: 
            case WindowMessage.WM_SYSKEYUP:
            case WindowMessage.WM_SYSKEYDOWN: 
            case WindowMessage.WM_CHAR: 
            case WindowMessage.WM_SYSCHAR:
            case WindowMessage.WM_DEADCHAR: 
            case WindowMessage.WM_SYSDEADCHAR:
                MSGDATA msgdata = new MSGDATA();
                msgdata.msg = msg;
                msgdata.handled = handled; 

                // Do this under the exception filter/handlers of the 
                // dispatcher for this thread. 
                //
                // NOTE: we lose the "perf optimization" of passing everything 
                // around by-ref since we have to call through a delegate.
                object result = Dispatcher.CurrentDispatcher.Invoke(
                    DispatcherPriority.Send,
                    new DispatcherOperationCallback(OnPreprocessMessage), 
                    msgdata);
 
                if (result != null) 
                {
                    handled = (bool)result; 
                }

                // the semantics dictate that the callers could change this data.
                msg = msgdata.msg; 
                break;
            } 
        } 

 
        /// 
        ///     Critical:
        ///     Can be used to spoof input.
        ///     Asserts UnmanagedCode permission to call IKeyboardInputSink 
        ///     methods.
        ///     For HANDLED_KEYDOWN_STILL_GENERATES_CHARS we also cause the 
        ///     Dispatcher to defer processing the queue until after any 
        ///     currently pending messages.
        ///  
        [SecurityCritical]
        private object OnPreprocessMessage(object param)
        {
            MSGDATA msgdata = (MSGDATA) param; 

            // Always process messages if this window is in menu mode. 
            // 
            // Otherwise, only process messages if someone below us has Focus.
            // 
            // Mnemonics are broadcast to all branches of the window tree; even
            // those that don't have focus.  BUT! at least someone under this
            // top-level window must have focus.
            if (!((IKeyboardInputSink)this).HasFocusWithin() && !IsInExclusiveMenuMode) 
            {
                return msgdata.handled; 
            } 

            ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys(); 

            // Interop with the Interop layer
            //
            switch ((WindowMessage)msgdata.msg.message) 
            {
            case WindowMessage.WM_SYSKEYDOWN: 
            case WindowMessage.WM_KEYDOWN: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                // In case a nested message pump is used before we return 
                // from processing this message, we disable processing the
                // next WM_CHAR message because if the code pumps messages
                // it should really mark the message as handled.
                _eatCharMessages = true; 
                DispatcherOperation restoreCharMessages = Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(RestoreCharMessages), null);
 
                // Force the Dispatcher to post a new message to service any 
                // pending operations, so that the operation we just posted
                // is guaranteed to get dispatched after any pending WM_CHAR 
                // messages are dispatched.
                Dispatcher.CriticalRequestProcessing(true);

                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); 
                if(!msgdata.handled)
                { 
                    // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
                    // We did not handle the WM_KEYDOWN, so it is OK to process WM_CHAR messages.
                    // We can also abort the pending restore operation since we don't need it. 
                    _eatCharMessages = false;
                    restoreCharMessages.Abort();
                }
 
                // Menu mode handles all keyboard messages so that they don't
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode) 
                {
                    // However, if the WM_KEYDOWN message was not explicitly 
                    // handled, then we need to generate WM_CHAR messages.  WPF
                    // expects this, but when we return handled, the outer
                    // message pump will skip the TranslateMessage and
                    // DispatchMessage calls.  We mitigate this by calling 
                    // TranslateMessage directly.  This is the same trick that
                    // Win32 does in its menu loop. 
                    if(!msgdata.handled) 
                    {
                        UnsafeNativeMethods.TranslateMessage(ref msgdata.msg); 
                    }

                    msgdata.handled = true;
                } 

                break; 
 
            case WindowMessage.WM_SYSKEYUP:
            case WindowMessage.WM_KEYUP: 
                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys);

                // Menu mode handles all keyboard messages so that they don't
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode)
                { 
                    msgdata.handled = true; 
                }
 
                break;

            case WindowMessage.WM_CHAR:
            case WindowMessage.WM_SYSCHAR: 
            case WindowMessage.WM_DEADCHAR:
            case WindowMessage.WM_SYSDEADCHAR: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
                if(!_eatCharMessages)
                { 
                    // IKIS implementation does a demand.
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                    try
                    { 
                        msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys);
 
                        if (!msgdata.handled) 
                        {
                            msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys); 
                        }
                    }
                    finally
                    { 
                        SecurityPermission.RevertAssert();
                    } 
 
                    if (!msgdata.handled)
                    { 
                        _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, (WindowMessage)msgdata.msg.message,
                                                               msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled);
                    }
                } 

                // Menu mode handles all keyboard messages so that they don't 
                // get dispatched to some random window with focus. 
                if(IsInExclusiveMenuMode)
                { 
                    // If the WM_CHAR message is not explicitly handled, the
                    // standard behavior is to beep.
                    if(!msgdata.handled)
                    { 
                        SafeNativeMethods.MessageBeep(0);
                    } 
 
                    msgdata.handled = true;
                } 

                break;
            }
            return msgdata.handled; 
        }
 
        ///  
        ///     Registers a child KeyboardInputSink with this sink.  A site
        ///     is returned. 
        /// 
        /// 
        ///     This API requires unrestricted UI Window permission.
        ///     We explicitly don't make this method overridable as we want to keep the 
        ///     precise implementation fixed and make sure the _keyboardInputSinkChildren
        ///     state is kep consistent. By making the method protected, implementors can 
        ///     still call into it when required. Notice as calls are made through the 
        ///     IKIS interface, there's still a way for ---- developers to override
        ///     the behavior by re-implementing the interface. 
        /// 
        /// 
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it. 
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        ///  
        [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)]
        protected IKeyboardInputSite RegisterKeyboardInputSinkCore(IKeyboardInputSink sink) 
        {
            CheckDisposed(true);

            if (sink == null) 
            {
                throw new ArgumentNullException("sink"); 
            } 

            if (sink.KeyboardInputSite != null) 
            {
                throw new ArgumentException(SR.Get(SRID.KeyboardSinkAlreadyOwned));
            }
 
            HwndSourceKeyboardInputSite site = new HwndSourceKeyboardInputSite(this, sink);
 
            if (_keyboardInputSinkChildren == null) 
                _keyboardInputSinkChildren = new List();
            _keyboardInputSinkChildren.Add(site); 

            return site;
        }
 
        /// 
        ///     Critical: This method can be used to intercept and potentially tamper with raw input. 
        ///     PublicOK: The interface declaration for this method has a demand on it. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
        {
            return RegisterKeyboardInputSinkCore(sink);
        } 

        ///  
        ///     Gives the component a chance to process keyboard input. 
        ///     Return value is true if handled, false if not.  Components
        ///     will generally call a child component's TranslateAccelerator 
        ///     if they can't handle the input themselves.  The message must
        ///     either be WM_KEYDOWN or WM_SYSKEYDOWN.  It is illegal to
        ///     modify the MSG structure, it's passed by reference only as
        ///     a performance optimization. 
        /// 
        /// 
        /// This API is not available in Internet Zone. 
        ///
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it.
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        protected virtual bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers) 
        {
            SecurityHelper.DemandUnmanagedCode(); 
//             VerifyAccess();

            return CriticalTranslateAccelerator(ref msg, modifiers);
        } 

        ///  
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it.
        ///  
        [SecurityCritical]
        bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)
        {
            return TranslateAcceleratorCore(ref msg, modifiers); 
        }
 
        ///  
        ///     Set focus to the first or last tab stop (according to the
        ///     TraversalRequest).  If it can't, because it has no tab stops, 
        ///     the return value is false.
        /// 
        protected virtual bool TabIntoCore(TraversalRequest request)
        { 
            bool traversed = false;
 
            if(request == null) 
            {
                throw new ArgumentNullException("request"); 
            }

            UIElement root =_rootVisual.Value as UIElement;
            if(root != null) 
            {
                // atanask: 
                // request.Mode == FocusNavigationDirection.First will navigate to the fist tabstop including root 
                // request.Mode == FocusNavigationDirection.Last will navigate to the last tabstop including root
                traversed = root.MoveFocus(request); 
            }

            return traversed;
        } 

        bool IKeyboardInputSink.TabInto(TraversalRequest request) 
        { 
            if(request == null)
            { 
                throw new ArgumentNullException("request");
            }

            return TabIntoCore(request); 
        }
 
        ///  
        ///     The property should start with a null value.  The component's
        ///     container will set this property to a non-null value before 
        ///     any other methods are called.  It may be set multiple times,
        ///     and should be set to null before disposal.
        /// 
        ///  
        ///     Setting KeyboardInputSite is not available in Internet Zone.
        ///     We explicitly don't make this property overridable as we want to keep the 
        ///     precise implementation as a smart field for _keyboardInputSite fixed. 
        ///     By making the property protected, implementors can still call into it
        ///     when required. Notice as calls are made through the IKIS interface, 
        ///     there's still a way for ---- developers to override the behavior by
        ///     re-implementing the interface.
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This property has demands on its accessors. 
        /// 
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up.
        ///  
        protected IKeyboardInputSite KeyboardInputSiteCore
        {
            [SecurityCritical]
            get 
            {
                SecurityHelper.DemandUnmanagedCode(); 
                return _keyboardInputSite; 
            }
 
            [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
            set
            {
                SecurityHelper.DemandUnmanagedCode(); 

                _keyboardInputSite = value; 
            } 
        }
 
        /// 
        ///     Critical: Calls a property with a LinkDemand on it.
        ///     PublicOK: The interface declaration for this property has a demand on it.
        ///  
        IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite
        { 
            get 
            {
                return KeyboardInputSiteCore; 
            }

            [SecurityCritical]
            set 
            {
                KeyboardInputSiteCore = value; 
            } 
        }
 
        /// 
        ///     This method is called whenever one of the component's
        ///     mnemonics is invoked.  The message must either be WM_KEYDOWN
        ///     or WM_SYSKEYDOWN.  It's illegal to modify the MSG structrure, 
        ///     it's passed by reference only as a performance optimization.
        ///     If this component contains child components, the container 
        ///     OnMnemonic will need to call the child's OnMnemonic method. 
        /// 
        ///  
        ///     Critical: This API can be used for input spoofing.
        ///     PublicOK: This method has a demand on it.
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)] 
        protected virtual bool OnMnemonicCore(ref MSG msg, ModifierKeys modifiers) 
        {
//             VerifyAccess(); 
            SecurityHelper.DemandUnmanagedCode();
            switch((WindowMessage)msg.message)
            {
                case WindowMessage.WM_SYSCHAR: 
                case WindowMessage.WM_SYSDEADCHAR:
                    string text = new string((char)msg.wParam, 1); 
                    if ((text != null) && (text.Length > 0)) 
                    {
                        // We have to work around an ordering issue with mnemonic processing. 
                        //
                        // Imagine you have a top level menu with _File & _Project and under _File you have _Print.
                        // If the user pressses Alt+F,P you would expect _Print to be triggered
                        // however if the top level window processes the mnemonic first 
                        // it will trigger _Project instead.
                        // 
                        // One way to work around this would be for the top level window to notice that 
                        // keyboard focus is in another root window & not handle the mnemonics.  The popup
                        // window would then get a chance to process the mnemonic and _Print would be triggered. 
                        //
                        // This doesn't work out becasue the popup window is no-activate, so it doesn't have Win32 focus
                        // and it will bail out of OnPreprocessMessage before it handles the mnemonic.
                        // 
                        // Instead the top level window should delegate OnMnemonic directly to the mnemonic scope window
                        // instead of processing it here.  This will let the Popup handle mnemonics instead of the top- 
                        // level window. 
                        //
                        // The mnemonic scope window is defined as the window with WPF keyboard focus. 
                        //
                        // This is a behavioral breaking change, so we've decided to only do it when IsInExclusiveMenuMode
                        // is true to force the user to opt-in.
                        DependencyObject focusObject = Keyboard.FocusedElement as DependencyObject; 
                        HwndSource mnemonicScope = (focusObject == null ? null : PresentationSource.CriticalFromVisual(focusObject) as HwndSource);
                        if (mnemonicScope != null && 
                            mnemonicScope != this && 
                            IsInExclusiveMenuMode)
                        { 
                            return ((IKeyboardInputSink)mnemonicScope).OnMnemonic(ref msg, modifiers);
                        }

                        if (AccessKeyManager.IsKeyRegistered(this, text)) 
                        {
                            AccessKeyManager.ProcessKey(this, text, false); 
 
                            //
                            return true; 
                        }
                    }
                    // these are OK
                    break; 

                case WindowMessage.WM_CHAR: 
                case WindowMessage.WM_DEADCHAR: 
                    // these are OK
                    break; 

                default:
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            } 

            // We record the last message that was processed by us. 
            // This is also checked in WndProc processing to prevent double processing. 
            _lastKeyboardMessage = msg;
 
            // The bubble will take care of access key processing for this HWND.  Call
            // the IKIS children unless we are in menu mode.
            if (_keyboardInputSinkChildren != null && !IsInExclusiveMenuMode)
            { 
                foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren )
                { 
                    if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) 
                        return true;
                } 
            }
            return false;
        }
 
        /// 
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it. 
        /// 
        [SecurityCritical] 
        bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
        {
            return OnMnemonicCore(ref msg, modifiers);
        } 

        ///  
        ///     Gives the component a chance to process keyboard input messages 
        ///     WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic.
        ///     Will return true if "handled" meaning don't pass it to OnMnemonic. 
        ///     The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR.
        ///     It is illegal to modify the MSG structure, it's passed by reference
        ///     only as a performance optimization.
        ///  
        /// 
        ///     Critical: This API can be used for input spoofing. 
        ///     PublicOK: This method has a demand on it. 
        ///
        ///     Also see SecurityNote named IKeyboardInputSink_Implementation higher up. 
        /// 
        [SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
        protected virtual bool TranslateCharCore(ref MSG msg, ModifierKeys modifiers)
        { 
            SecurityHelper.DemandUnmanagedCode();
            if(HasFocus || IsInExclusiveMenuMode) 
                return false; 

            IKeyboardInputSink focusSink = this.ChildSinkWithFocus; 
            if(null != focusSink)
            {
                return focusSink.TranslateChar(ref msg, modifiers);
            } 
            return false;
        } 
 
        /// 
        ///     Critical: Calls a method with a LinkDemand on it. 
        ///     PublicOK: The interface declaration for this method has a demand on it.
        /// 
        [SecurityCritical]
        bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers) 
        {
            return TranslateCharCore(ref msg, modifiers); 
        } 

        ///  
        ///
        /// 
        protected virtual bool HasFocusWithinCore()
        { 
            if(HasFocus)
            { 
                return true; 
            }
            else 
            {
                if (null == _keyboardInputSinkChildren)
                    return false;
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    if (((IKeyboardInputSite)site).Sink.HasFocusWithin()) 
                    {
                        return true; 
                    }
                }
                return false;
            } 
        }
 
        bool IKeyboardInputSink.HasFocusWithin() 
        {
            return HasFocusWithinCore(); 
        }

        /// 
        ///     The RestoreFocusMode for the window. 
        /// 
        ///  
        ///     This property can only be set at construction time via the 
        ///     HwndSourceParameters.RestoreFocusMode property.
        ///  
        public RestoreFocusMode RestoreFocusMode
        {
            get
            { 
                return _restoreFocusMode;
            } 
        } 

        ///  
        ///     The default value for the AcquireHwndFocusInMenuMode setting.
        /// 
        public static bool DefaultAcquireHwndFocusInMenuMode
        { 
            get
            { 
                if(!_defaultAcquireHwndFocusInMenuMode.HasValue) 
                {
                    // The default value is true, for compat. 
                    _defaultAcquireHwndFocusInMenuMode = true;
                }

                return _defaultAcquireHwndFocusInMenuMode.Value; 
            }
 
            set 
            {
                _defaultAcquireHwndFocusInMenuMode = value; 
            }
        }

        ///  
        ///     The AcquireHwndFocusInMenuMode setting for the window.
        ///  
        ///  
        ///     This property can only be set at construction time via the
        ///     HwndSourceParameters.AcquireHwndFocusInMenuMode property. 
        /// 
        public bool AcquireHwndFocusInMenuMode
        {
            get 
            {
                return _acquireHwndFocusInMenuMode; 
            } 
        }
 
        /// 
        ///   The method is not part of the interface (IKeyboardInputSink).
        /// 
        /// The Site that containes the sink to unregister 
        /// 
        ///     Critical - calls critical methods. 
        ///  
        [ SecurityCritical ]
        internal void CriticalUnregisterKeyboardInputSink(HwndSourceKeyboardInputSite site) 
        {
            if(_isDisposed)
                return;
 
            if (null != _keyboardInputSinkChildren)
            { 
                if (!_keyboardInputSinkChildren.Remove(site)) 
                {
                    throw new InvalidOperationException(SR.Get(SRID.KeyboardSinkNotAChild)); 
                }
            }
        }
 
        IKeyboardInputSink ChildSinkWithFocus
        { 
            get 
            {
                IKeyboardInputSink ikis=null; 

                if(null == _keyboardInputSinkChildren)
                    return null;
 
                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                { 
                    IKeyboardInputSite isite = (IKeyboardInputSite)site; 

                    if (isite.Sink.HasFocusWithin()) 
                    {
                        ikis = isite.Sink;
                        break;
                    } 
                }
                // This private property should only be called correctly. 
                Debug.Assert(null!=ikis, "ChildSinkWithFocus called when none had focus"); 
                return ikis;
            } 
        }

        /// 
        ///     Critical: This API could be vulnerable to input spoofing. 
        /// 
        [SecurityCritical, FriendAccessAllowed] 
        internal bool CriticalTranslateAccelerator(ref MSG msg, ModifierKeys modifiers) 
        {
            switch ((WindowMessage)msg.message) 
            {
                case WindowMessage.WM_KEYUP:
                case WindowMessage.WM_KEYDOWN:
                case WindowMessage.WM_SYSKEYUP: 
                case WindowMessage.WM_SYSKEYDOWN:
                    // these are OK 
                    break; 

                default: 
                    throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages));
            }

            if (_keyboard == null) 
                return false;
 
            bool handled = false; 

            // TranslateAccelerator is called recursively on child Hwnds (Source & Host) 
            // If this is the first Avalon TranslateAccelerator processing then we send the
            // key to be processed to the standard Avalon Input Filters and stuff.
            if (PerThreadData.TranslateAcceleratorCallDepth == 0)
            { 
                // We record the last message that was processed by us.
                // This is also checked in WndProc processing to prevent double processing. 
                // TranslateAcclerator is called from the pump before DispatchMessage 
                // and the WndProc is called from DispatchMessage.   We have processing
                // in both places.  If we run the pump we process keyboard message here. 
                // If we don't own the pump we process them in HwndKeyboardInputProvider.WndProc.
                _lastKeyboardMessage = msg;

                //  NORMAL AVALON KEYBOARD INPUT CASE 
                // If this is the top most Avalon window (it might be a child Hwnd
                // but no Avalon windows above it).  And focus is on this window then 
                // do the Normal Avalon Keyboard input Processing. 
                if (HasFocus || IsInExclusiveMenuMode)
                { 
                    _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                }
                // ELSE the focus is probably in but not on this HwndSource.
                // Beware: It is possible that someone calls IKIS.TranslateAccelerator() while the focus is 
                //   somewhere entirely outside.
                // Do the once only message input filters etc and Tunnel/Bubble down 
                // to the element that contains the child window with focus. 
                // The Child HwndHost object will hook OnPreviewKeyDown() etc
                // to make the transition to its TranslateAccelerator() between the 
                // tunnel and the bubble.
                else
                {
                    IKeyboardInputSink focusSink = ChildSinkWithFocus; // can be null! 
                    IInputElement focusElement = (IInputElement)focusSink;
 
                    try { 
                        PerThreadData.TranslateAcceleratorCallDepth += 1;
                        Keyboard.PrimaryDevice.ForceTarget = focusElement; 
                       _keyboard.Value.ProcessKeyAction(ref msg, ref handled);
                    }
                    finally
                    { 
                        Keyboard.PrimaryDevice.ForceTarget = null;
                        PerThreadData.TranslateAcceleratorCallDepth -= 1; 
                    } 
                }
 
            }
            // ELSE we have seen this MSG before, we are HwndSource decendant of an
            // HwndSource (that ancestor presumably did the processing above).
            // Here we raise the tunnel/bubble events without the once only keyboard 
            // input filtering.
            else 
            { 
                int virtualKey = HwndKeyboardInputProvider.GetVirtualKey(msg.wParam, msg.lParam);
                int scanCode = HwndKeyboardInputProvider.GetScanCode(msg.wParam, msg.lParam); 
                bool isExtendedKey = HwndKeyboardInputProvider.IsExtendedKey(msg.lParam);
                Key key = KeyInterop.KeyFromVirtualKey(virtualKey);

                RoutedEvent keyPreviewEvent=null; 
                RoutedEvent keyEvent=null;
                switch ((WindowMessage)msg.message) 
                { 
                case WindowMessage.WM_KEYUP:
                case WindowMessage.WM_SYSKEYUP: 
                    keyPreviewEvent = Keyboard.PreviewKeyUpEvent;
                    keyEvent = Keyboard.KeyUpEvent;
                    break;
                case WindowMessage.WM_KEYDOWN: 
                case WindowMessage.WM_SYSKEYDOWN:
                    keyPreviewEvent = Keyboard.PreviewKeyDownEvent; 
                    keyEvent = Keyboard.KeyDownEvent; 
                    break;
                } 

                bool hasFocus = HasFocus;
                IKeyboardInputSink focusSink = (hasFocus || IsInExclusiveMenuMode) ? null : ChildSinkWithFocus;
                IInputElement focusElement = focusSink as IInputElement; 
                // focusElement may be null, in which case Target is just "focus", but we use it only if it's an
                // element within this HwndSource. It is possible that someone calls IKIS.TranslateAccelerator() 
                // on a nested HwndSource while the focus is somewhere entirely outside. 
                // HasFocus implies the focused element should be within this HwndSource, but unfortunately
                // we allow 'split focus', at least for popup windows; that's why check explicitly. 
                // Note that KeyboardDevice.Target will likely be the ForceTarget corresponding to the
                // container of this HwndSource. That's why we look at the real FocusedElement.
                if (focusElement == null && hasFocus)
                { 
                    focusElement = Keyboard.PrimaryDevice.FocusedElement;
                    if (focusElement != null && 
                        PresentationSource.CriticalFromVisual((DependencyObject)focusElement) != this) 
                    {
                        focusElement = null; 
                    }
                }

                try { 
                    Keyboard.PrimaryDevice.ForceTarget = focusSink as IInputElement;
 
                    if (focusElement != null) 
                    {
                        KeyEventArgs tunnelArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key); 
                        tunnelArgs.ScanCode = scanCode;
                        tunnelArgs.IsExtendedKey = isExtendedKey;
                        tunnelArgs.RoutedEvent = keyPreviewEvent;
                        focusElement.RaiseEvent(tunnelArgs); 

                        handled = tunnelArgs.Handled; 
                    } 
                    if (!handled)
                    { 
                        KeyEventArgs bubbleArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key);
                        bubbleArgs.ScanCode = scanCode;
                        bubbleArgs.IsExtendedKey = isExtendedKey;
                        bubbleArgs.RoutedEvent=keyEvent; 
                        if(focusElement != null)
                        { 
                            focusElement.RaiseEvent(bubbleArgs); 
                            handled = bubbleArgs.Handled;
                        } 

                        if (!handled)
                        {
                            // Raise the TranslateAccelerator event on the 
                            // InputManager to allow keyboard navigation to
                            // happen on a descendent HwndSource 
                            InputManager.UnsecureCurrent.RaiseTranslateAccelerator(bubbleArgs); 
                            handled = bubbleArgs.Handled;
                        } 
                    }
                }
                finally
                { 
                    Keyboard.PrimaryDevice.ForceTarget = null;
                } 
            } 

            return handled; 
        }

        // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
        // Go back to accepting character messages.  This method is posted 
        // to the dispatcher when char messages are disable.
        internal static object RestoreCharMessages(object unused) 
        { 
            _eatCharMessages = false;
            return null; 
        }

#endregion IKeyboardInputSink
 

        internal bool IsRepeatedKeyboardMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        { 
            if (msg != _lastKeyboardMessage.message)
                return false; 
            if (hwnd != _lastKeyboardMessage.hwnd)
                return false;
            if (wParam != _lastKeyboardMessage.wParam)
                return false; 
            if (lParam != _lastKeyboardMessage.lParam)
                return false; 
            return true; 
        }
 
        /// 
        ///    This event handler is called from HwndWrapper when it is Disposing.
        /// 
        // This could happen if someone calls his Dispose before (or instead 
        // of) our dispose.  Or, more likely, the real window was killed by
        // something like the user clicking the close box. 
        private void OnHwndDisposed(object sender, EventArgs args) 
        {
            // This method is called from the HwndWrapper.Dispose(). 
            // So make sure we don't call HwndWrapper.Dispose().
            _inRealHwndDispose = true;
            Dispose();
        } 

        ///  
        ///    Called after the last window message is processed. 
        /// 
 
        // HwndSource is required to continue certain operations while,
        // and even after, Dispose runs.  HwndSource is resposible for
        // calling WndProcHooks with every message the window sees.
        // Including: WM_CLOSE, WM_DESTROY, WM_NCDESTROY.  The doc says 
        // WM_NCDESTROY is the very last message, so we can release the
        // Hooks after that. 
        // This assumes the Context.Access() is held. 
        private void OnNoMoreWindowMessages()
        { 
            _hooks = null;
        }

        private void OnShutdownFinished(object sender, EventArgs args) 
        {
            // Note: We are already in the context being disposed. 
            Dispose(); 
        }
 
        //
        // NOTE: shutdown order is very important.  Review any changes
        // carefully.
        // 
        /// 
        ///     Critical: This accesses the various sites and providers. 
        ///               Asserting UnmanagedCode to access site, this is consistent with the requirements of the interface declaration 
        ///               as it can potentially be used for spoofing.
        ///     Safe: Disposing the object is a safe operation. 
        ///           Not exposing IKIS, just using it to unregister.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void Dispose(bool disposing) 
        {
            if(disposing) 
            { 
                // Make sure all access is synchronized.
//                 this.VerifyAccess(); 

                if (!_isDisposing)
                {
                    // _isDisposing is a guard against re-entery into this 
                    // routine.  We fire Dispose and SourceChanged (RootVisual
                    // change) events which could cause re-entery. 
                    _isDisposing = true; 

                    // Notify listeners that we are being disposed.  We do this 
                    // before we dispose our internal stuff, in case the event
                    // listener needs to access something.
                    if(Disposed != null)
                    { 
                        try
                        { 
                            Disposed(this, EventArgs.Empty); 
                        }
#pragma warning disable 56500 
                        // We can't tolerate an exception thrown by third-party code to
                        // abort our Dispose half-way through.  So we just eat it.
                        catch
                        { 
                        }
#pragma warning restore 56500 
                        Disposed = null; 
                    }
 
                    // Remove any listeners of the ContentRendered event
                    ClearContentRenderedListeners();

                    // Clear the root visual.  This will raise a SourceChanged 
                    // event to registered listeners.
                    RootVisualInternal = null; 
                    RemoveSource(); 

                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); 
                    try
                    {
                        // Unregister ourselves if we are a registered KeyboardInputSink.
                        // Use the property instead of the backing field in case a subclass has overridden it. 
                        IKeyboardInputSite keyboardInputSite = ((IKeyboardInputSink)this).KeyboardInputSite;
                        if (keyboardInputSite != null) 
                        { 
                            keyboardInputSite.Unregister();
                            ((IKeyboardInputSink)this).KeyboardInputSite = null; 
                        }
                        _keyboardInputSinkChildren = null;
                    }
                    finally 
                    {
                        SecurityPermission.RevertAssert(); 
                    } 

                    // Dispose the HwndStylusInputProvider BEFORE we destroy the HWND. 
                    // This us because the stylus provider has an async channel and
                    // they don't want to process data after the HWND is destroyed.
                    if (_stylus != null)
                    { 
                        _stylus.Value.Dispose();
                        _stylus = null; 
                    } 

                    // Our general shut-down principle is to destroy the window 
                    // and let the individual HwndXXX components respons to WM_DESTROY.
                    //
                    // (see comment above about disposing the HwndStylusInputProvider)
                    // 
                    {
                        if (_hwndTarget != null) 
                        { 
                            _hwndTarget.Dispose();
                            _hwndTarget = null; 
                        }

                        if (_hwndWrapper != null)
                        { 
                            // Revoke the drop target.
                            if (_hwndWrapper.Handle != IntPtr.Zero && _registeredDropTargetCount > 0) 
                            { 
                                // This call is safe since DragDrop.RevokeDropTarget is checking the unmanged
                                // code permission. 
                                DragDrop.RevokeDropTarget(_hwndWrapper.Handle);
                                _registeredDropTargetCount--;
                            }
 
                            // Remove our HwndWrapper.Dispose() hander.
                            _hwndWrapper.Disposed -= new EventHandler(OnHwndDisposed); 
 
                            if (!_inRealHwndDispose)
                                _hwndWrapper.Dispose(); 

                            // Don't null out _hwndWrapper after the Dispose().
                            // Dispose() will start destroying the Window but we
                            // still need to talk to it during that process while 
                            // the WM_ msgs arrive.
                        } 
                    } 

                    if(_mouse != null) 
                    {
                        _mouse.Value.Dispose();
                        _mouse = null;
                    } 

                    if(_keyboard != null) 
                    { 
                        _keyboard.Value.Dispose();
                        _keyboard = null; 
                    }

                    if (_appCommand != null)
                    { 
                        _appCommand.Value.Dispose();
                        _appCommand = null; 
                    } 

                    if(null != _weakShutdownHandler) 
                    {
                        _weakShutdownHandler.Dispose();
                        _weakShutdownHandler = null;
                    } 

                    if(null != _weakPreprocessMessageHandler) 
                    { 
                        _weakPreprocessMessageHandler.Dispose();
                        _weakPreprocessMessageHandler = null; 
                    }

                    // We wait to set the "_isDisposed" flag until after the
                    // Disposed, SourceChange (RootVisual=null), etc. events 
                    // have fired.  We want to remain functional should their
                    // handlers call methods on us. 
                    // 
                    // Note: as the HwndWrapper shuts down, the final few messages
                    // will continue to pass through our WndProc hook. 
                    _isDisposed = true;
                }
            }
        } 

        private void CheckDisposed(bool verifyAccess) 
        { 
            if(verifyAccess)
            { 
//                 this.VerifyAccess();
            }

            if(_isDisposed) 
            {
                throw new ObjectDisposedException(null, SR.Get(SRID.HwndSourceDisposed)); 
            } 
        }
 
        /// 
        ///     Critical: This code accesses hwndtarget
        ///     TreatAsSafe: Information is ok to expose
        ///  
        private bool IsUsable
        { 
            [SecurityCritical,SecurityTreatAsSafe] 
            get
            { 
                return _isDisposed == false &&
                       _hwndTarget != null &&
                       _hwndTarget.IsDisposed == false;
            } 
        }
 
        ///  
        ///     Critical - calls a method with an elevation ( GetFocus )
        ///     TreatAsSafe - determining whether you have focus within the window is considered safe. 
        ///                   Worst case you can know whether keyboard/keypress events will go to the current window.
        /// 
        private bool HasFocus
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 
                return UnsafeNativeMethods.GetFocus() == CriticalHandle;
            } 
        }

        private static bool IsValidSizeToContent(SizeToContent value)
        { 
            return value == SizeToContent.Manual ||
                   value == SizeToContent.Width  || 
                   value == SizeToContent.Height || 
                   value == SizeToContent.WidthAndHeight;
        } 

        class ThreadDataBlob
        {
            public int TranslateAcceleratorCallDepth; 
        }
 
        private static ThreadDataBlob PerThreadData 
        {
            get 
            {
                ThreadDataBlob data;
                object obj = Thread.GetData(_threadSlot);
                if(null == obj) 
                {
                    data = new ThreadDataBlob(); 
                    Thread.SetData(_threadSlot, data); 
                }
                else 
                {
                    data = (ThreadDataBlob) obj;
                }
                return data; 
            }
        } 
 
#region WeakEventHandlers
 
        private class WeakEventDispatcherShutdown: WeakReference
        {
            public WeakEventDispatcherShutdown(HwndSource source, Dispatcher that): base(source)
            { 
                _that = that;
                _that.ShutdownFinished += new EventHandler(this.OnShutdownFinished); 
            } 

            public void OnShutdownFinished(object sender, EventArgs e) 
            {
                HwndSource source = this.Target as HwndSource;
                if(null != source)
                { 
                    source.OnShutdownFinished(sender, e);
                } 
                else 
                {
                    Dispose(); 
                }
            }

            public void Dispose() 
            {
                if(null != _that) 
                { 
                    _that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished);
                } 
            }

            private Dispatcher _that;
        } 

        private class WeakEventPreprocessMessage: WeakReference 
        { 
            /// 
            ///     Critical: This code calls attaches an arbitrary window 
            ///     to the call path for the component dispatcher call back
            /// 
            [SecurityCritical]
            public WeakEventPreprocessMessage(HwndSource source, bool addToFront): base(source) 
            {
                _addToFront = addToFront; 
                _handler = new ThreadMessageEventHandler(this.OnPreprocessMessage); 

                if(addToFront) 
                {
                    ComponentDispatcher.CriticalAddThreadPreprocessMessageHandlerFirst(_handler);
                }
                else 
                {
                    ComponentDispatcher.ThreadPreprocessMessage += _handler; 
                } 
            }
 
            /// 
            ///     Critical: This can be used to spoof and change input
            /// 
            [SecurityCritical] 
            public void OnPreprocessMessage(ref MSG msg, ref bool handled)
            { 
                HwndSource source = this.Target as HwndSource; 
                if(null != source)
                { 
                    source.OnPreprocessMessageThunk(ref msg, ref handled);
                }
                else
                { 
                    Dispose();
                } 
            } 

 
            /// 
            ///     Critical:This code calls into ComponentDispatcher
            ///     to disconnect a listener
            ///     TreatAsSafe: This code is ok to call 
            /// 
            [SecurityCritical,SecurityTreatAsSafe] 
            public void Dispose() 
            {
                if(_addToFront) 
                {
                    ComponentDispatcher.CriticalRemoveThreadPreprocessMessageHandlerFirst(_handler);
                }
                else 
                {
                    ComponentDispatcher.ThreadPreprocessMessage -= _handler; 
                } 

                _handler = null; 
            }

            private bool _addToFront;
            private ThreadMessageEventHandler _handler; 
        }
 
#endregion WeakEventHandlers 

        private object                      _constructionParameters; // boxed HwndSourceParameters 

        private bool                        _isDisposed = false;
        private bool                        _isDisposing = false;
        private bool                        _inRealHwndDispose = false; 
        private bool                        _adjustSizingForNonClientArea;
        private bool                        _myOwnUpdate; 
        private bool                        _isWindowInMinimizeState = false; 

        private int                         _registeredDropTargetCount; 

        private SizeToContent               _sizeToContent = SizeToContent.Manual;
        private Size?                       _previousSize;
 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical. 
        /// 
        [SecurityCritical] 
        private HwndWrapper                 _hwndWrapper;

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical.
        ///  
        [SecurityCritical] 
        private HwndTarget                  _hwndTarget;
 
        private SecurityCriticalDataForSet                      _rootVisual;

        private event HwndSourceHook _hooks;
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        ///  
        private SecurityCriticalDataClass      _mouse;
        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical.
        /// 
        private SecurityCriticalDataClass   _keyboard; 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data is considered critical. 
        /// 
        private SecurityCriticalDataClass     _stylus; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data is considered critical. 
        /// 
        private SecurityCriticalDataClass _appCommand; 
 
        WeakEventDispatcherShutdown _weakShutdownHandler;
        WeakEventPreprocessMessage _weakPreprocessMessageHandler; 
        WeakEventPreprocessMessage _weakMenuModeMessageHandler;

        private static System.LocalDataStoreSlot _threadSlot;
 
        private RestoreFocusMode _restoreFocusMode;
 
        [ThreadStatic] 
        private static bool? _defaultAcquireHwndFocusInMenuMode;
        private bool _acquireHwndFocusInMenuMode; 

        private MSG                         _lastKeyboardMessage;
        private List _keyboardInputSinkChildren;
 
        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data can be used to spoof input 
        /// 
        // Be careful about accessing this field directly. 
        // It's bound to IKeyboardInputSink.KeyboardInputSite, so if a derived class overrides
        // that property then this field will be incorrect.
        [SecurityCritical]
        private IKeyboardInputSite          _keyboardInputSite = null; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified 
        ///     elevation. This data can be used to spoof input
        ///  
        [SecurityCritical]
        private HwndWrapperHook             _layoutHook;

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        ///  
        [SecurityCritical]
        private HwndWrapperHook             _inputHook; 

        /// 
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input 
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _hwndTargetHook; 

        ///  
        ///     Critical:This reference cannot be given out or assigned to outside of a verified
        ///     elevation. This data can be used to spoof input
        /// 
        [SecurityCritical] 
        private HwndWrapperHook             _publicHook;
 
        // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS 
        //
        // Avalon relies on the policy that if you handle the KeyDown 
        // event, you will not get the TextInput events caused by
        // pressing the key.  This is generally implemented because the
        // message pump calls ComponentDispatcher.RaiseThreadMessage and
        // we return whether or not the WM_KEYDOWN message was handled, 
        // and the message pump will only call TranslateMessage() if the
        // WM_KEYDOWN was not handled.  However, naive message pumps don't 
        // call ComponentDispatcher.RaiseThreadMessage, and always call 
        // TranslateMessage, so the WM_CHAR is generated no matter what.
        // The best work around we could think of was to eat the WM_CHAR 
        // messages and not report them to Avalon.
        //
        [ThreadStatic]
        internal static bool _eatCharMessages; // used from HwndKeyboardInputProvider 
    }
} 

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