HwndSource.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / InterOp / HwndSource.cs / 2 / 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.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) 
            {
                _hooks = new ArrayList(8);
                _hooks.Insert(0, parameters.HwndSourceHook);
                wrapperHooks[3] = _publicHook; 
            }
 
            // 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 (0 == ((uint)parameters.WindowStyle & NativeMethods.WS_CHILD))
            { 
                // This code path only gets executed in the non browser hosted case
                // because in the browser hosted case the app window is child window 
                _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this); 
            }
            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();

            CheckDisposed(true);
 
            if(_hooks == null)
            { 
                _hooks = new ArrayList(8); 
                _hwndWrapper.AddHook(_publicHook);
            } 
            _hooks.Insert(0, 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(); 

            if(_hooks != null) 
            { 
                _hooks.Remove(hook);
                if(_hooks.Count == 0) 
                {
                    _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 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; 
        }

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

        /// 
        ///     Critical: This code accesses critical member _hwndTarget. 
        ///     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 = _hwndTarget.TransformToDevice.Transform(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();
 
            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  ctxHashCode = 0;

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

                if (etwEnabled) 
                {
                    ctxHashCode = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 
 
                rootUIElement.Measure(sz);
 
                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 
 
                rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize));
 
                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
            } 
            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 = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                }
 
                rootUIElement.Measure(sz); 

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, 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.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); 
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
            }
            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: Because it accesses _hwndTarget
        ///     TreatAsSafe: We don't pass it out; it is just used to convert to logical units 
        /// 
        [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 = _hwndTarget.TransformFromDevice.Transform(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(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 ;
 
            // 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 (msg) 
                {
                    // 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 NativeMethods.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 NativeMethods.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 NativeMethods.WM_WINDOWPOSCHANGING:
                        Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, msg, 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 NativeMethods.WM_SIZE:
                        Process_WM_SIZE(rootUIElement, hwnd, msg, 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(msg)
                { 
                    case NativeMethods.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, int 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: Because it uses _hwndTarget 
        ///  
        [SecurityCritical]
        private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            int x = NativeMethods.SignedLOWORD(lParam);
            int y = NativeMethods.SignedHIWORD(lParam);
            Point pt = new Point(x, y); 
            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  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 = _hwndTarget.TransformFromDevice.Transform(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 = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, 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.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 

                rootUIElement.Arrange(new Rect(new Point(), sz)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
                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 ; 

            // 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, msg, wParam, lParam, ref handled); 
            } 

            if (!_isDisposed && _mouse != null && !handled) 
            {
                result = _mouse.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled);
            }
 
            if (!_isDisposed && _keyboard != null && !handled)
            { 
                result = _keyboard.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); 
            }
 
            if (!_isDisposed && _appCommand != null && !handled)
            {
                result = _appCommand.Value.FilterMessage(hwnd, msg, 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 ; 

            // 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)
            { 
                for (int i = 0, nCount = _hooks.Count; i < nCount; i++)
                { 
                    result = ((HwndSourceHook)_hooks[i])(hwnd, msg, wParam, lParam, ref handled); 
                    if(handled)
                    { 
                        break;
                    }
                }
            } 
            if (NativeMethods.WM_NCDESTROY == msg)
            { 
                // 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 
        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 (msg.message) 
            { 
            case NativeMethods.WM_KEYUP:
            case NativeMethods.WM_KEYDOWN: 
            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.WM_CHAR:
            case NativeMethods.WM_SYSCHAR: 
            case NativeMethods.WM_DEADCHAR:
            case NativeMethods.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 
        /// 
        [SecurityCritical] 
        private object OnPreprocessMessage(object param)
        {
            MSGDATA msgdata = (MSGDATA) param;
 
            // At the top level check 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 
            // TopLevel window must have focus.
            if (!((IKeyboardInputSink)this).HasFocusWithin()) 
            {
                return msgdata.handled;
            }
 
            ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys();
 
            // Interop with the Interop layer 
            //
            switch (msgdata.msg.message) 
            {
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.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);

                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();
                }
                break;
 
            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_KEYUP: 
                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); 
                break;
 
            case NativeMethods.WM_CHAR:
            case NativeMethods.WM_SYSCHAR:
            case NativeMethods.WM_DEADCHAR:
            case NativeMethods.WM_SYSDEADCHAR: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                if(!_eatCharMessages) 
                { 
                    msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys);
 
                    if (!msgdata.handled)
                    {
                        msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys);
                    } 

                    if (!msgdata.handled) 
                    { 
                        _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, msgdata.msg.message,
                                                               msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled); 
                    }
                }
                break;
            } 
            return msgdata.handled;
        } 
 
        /// 
        ///     Registers a child KeyboardInputSink with this sink.  A site 
        ///     is returned.
        /// 
        ///
        /// This API requires unrestricted UI Window permission. 
        ///
        ///  
        ///     Critical: This API can be used for input spoofing 
        ///     PublicOK: This method has a demand on it.
        ///  
        [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)]
        IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(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; 
        }
 
        ///  
        ///     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
        ///     TreatAsSafe: This method has a demand on it.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers) 
        { 
            SecurityHelper.DemandUnmanagedCode();
//             VerifyAccess(); 

            return CriticalTranslateAccelerator(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.
        ///  
        bool IKeyboardInputSink.TabInto(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;
        }

        ///  
        ///     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.
        ///
        ///  
        ///     Critical: This API can be used for input spoofing
        ///     PublicOK: This method has a demand on it. 
        ///  
        IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite
        { 
            [SecurityCritical]
            get
            {
                SecurityHelper.DemandUnmanagedCode(); 
                return _keyboardInputSite;
            } 
 
            [SecurityCritical]
            set 
            {
                SecurityHelper.DemandUnmanagedCode();

                _keyboardInputSite = 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
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
        { 
//             VerifyAccess();
            SecurityHelper.DemandUnmanagedCode(); 
            switch(msg.message) 
            {
                case NativeMethods.WM_SYSCHAR: 
                case NativeMethods.WM_SYSDEADCHAR:
                    string text = new string((char)msg.wParam, 1);
                    if ((text != null) && (text.Length > 0))
                    { 
                        if (AccessKeyManager.IsKeyRegistered(this, text))
                        { 
                            AccessKeyManager.ProcessKey(this, text, false); 

                            // 
                            return true;
                        }
                    }
                    // these are OK 
                    break;
 
                case NativeMethods.WM_CHAR: 
                case NativeMethods.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 Avalon bubble will take care of access key processing for this HWND
            // So now we just call the children.
            if (null == _keyboardInputSinkChildren) 
                return false;
 
            foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren ) 
            {
                if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) 
                    return true;
            }
            return false;
        } 

        ///  
        ///     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 
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers)
        {
            SecurityHelper.DemandUnmanagedCode();
            if(HasFocus) 
                return false;
 
            IKeyboardInputSink focusSink = this.ChildSinkWithFocus; 
            if(null != focusSink)
            { 
                return focusSink.TranslateChar(ref msg, modifiers);
            }
            return false;
        } 

        ///  
        /// 
        /// 
        bool IKeyboardInputSink.HasFocusWithin() 
        {
            if(HasFocus)
            {
                return true; 
            }
            else 
            { 
                if (null == _keyboardInputSinkChildren)
                    return false; 

                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                {
                    if (((IKeyboardInputSite)site).Sink.HasFocusWithin()) 
                    {
                        return true; 
                    } 
                }
                return false; 
            }
        }

        ///  
        ///   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 (msg.message)
            { 
                case NativeMethods.WM_KEYUP:
                case NativeMethods.WM_KEYDOWN: 
                case NativeMethods.WM_SYSKEYUP: 
                case NativeMethods.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)
                {
                    _keyboard.Value.ProcessKeyAction(ref msg, ref handled); 
                }
                // ELSE the focus is in but not on this HwndSource. 
                // 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;
                    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 (msg.message) 
                {
                case NativeMethods.WM_KEYUP: 
                case NativeMethods.WM_SYSKEYUP:
                    keyPreviewEvent = Keyboard.PreviewKeyUpEvent;
                    keyEvent = Keyboard.KeyUpEvent;
                    break; 
                case NativeMethods.WM_KEYDOWN:
                case NativeMethods.WM_SYSKEYDOWN: 
                    keyPreviewEvent = Keyboard.PreviewKeyDownEvent; 
                    keyEvent = Keyboard.KeyDownEvent;
                    break; 
                }

                IKeyboardInputSink focusSink = HasFocus ? null : ChildSinkWithFocus;
                IInputElement focusElement = focusSink as IInputElement; 

                // focusElement may be null, in which case Target is just "focus" 
                try { 
                    Keyboard.PrimaryDevice.ForceTarget = focusElement;
                    focusElement = Keyboard.PrimaryDevice.Target; 

                    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;
                        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.Clear();
            _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
        ///     Safe: Disposing the object is a safe operation. 
        ///  
        [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();
 
                    // Unregister ourselves if we are a registered KeyboardInputSink.
                    if(_keyboardInputSite != null) 
                    { 
                        _keyboardInputSite.Unregister();
                        _keyboardInputSite = null; 
                    }
                    _keyboardInputSinkChildren = null;

                    // 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): base(source)
            { 
                ComponentDispatcher.ThreadPreprocessMessage +=
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            }
 
            /// 
            ///     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()
            {
                ComponentDispatcher.ThreadPreprocessMessage -= 
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            } 
        } 

#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 ArrayList                   _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;

        private static System.LocalDataStoreSlot _threadSlot; 

        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
        /// 
        [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.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) 
            {
                _hooks = new ArrayList(8);
                _hooks.Insert(0, parameters.HwndSourceHook);
                wrapperHooks[3] = _publicHook; 
            }
 
            // 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 (0 == ((uint)parameters.WindowStyle & NativeMethods.WS_CHILD))
            { 
                // This code path only gets executed in the non browser hosted case
                // because in the browser hosted case the app window is child window 
                _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this); 
            }
            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();

            CheckDisposed(true);
 
            if(_hooks == null)
            { 
                _hooks = new ArrayList(8); 
                _hwndWrapper.AddHook(_publicHook);
            } 
            _hooks.Insert(0, 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(); 

            if(_hooks != null) 
            { 
                _hooks.Remove(hook);
                if(_hooks.Count == 0) 
                {
                    _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 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; 
        }

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

        /// 
        ///     Critical: This code accesses critical member _hwndTarget. 
        ///     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 = _hwndTarget.TransformToDevice.Transform(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();
 
            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  ctxHashCode = 0;

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

                if (etwEnabled) 
                {
                    ctxHashCode = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 
 
                rootUIElement.Measure(sz);
 
                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 
 
                rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize));
 
                if (etwEnabled)
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
            } 
            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 = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
                }
 
                rootUIElement.Measure(sz); 

                if (etwEnabled) 
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, 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.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); 
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
            }
            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: Because it accesses _hwndTarget
        ///     TreatAsSafe: We don't pass it out; it is just used to convert to logical units 
        /// 
        [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 = _hwndTarget.TransformFromDevice.Transform(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(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 ;
 
            // 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 (msg) 
                {
                    // 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 NativeMethods.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 NativeMethods.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 NativeMethods.WM_WINDOWPOSCHANGING:
                        Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, msg, 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 NativeMethods.WM_SIZE:
                        Process_WM_SIZE(rootUIElement, hwnd, msg, 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(msg)
                { 
                    case NativeMethods.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, int 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: Because it uses _hwndTarget 
        ///  
        [SecurityCritical]
        private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            int x = NativeMethods.SignedLOWORD(lParam);
            int y = NativeMethods.SignedHIWORD(lParam);
            Point pt = new Point(x, y); 
            bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal);
            int  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 = _hwndTarget.TransformFromDevice.Transform(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 = this.Dispatcher.GetHashCode();
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); 
 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, 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.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode);
                } 

                rootUIElement.Arrange(new Rect(new Point(), sz)); 
 
                if (etwEnabled)
                { 
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent);

                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent);
                } 
                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 ; 

            // 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, msg, wParam, lParam, ref handled); 
            } 

            if (!_isDisposed && _mouse != null && !handled) 
            {
                result = _mouse.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled);
            }
 
            if (!_isDisposed && _keyboard != null && !handled)
            { 
                result = _keyboard.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); 
            }
 
            if (!_isDisposed && _appCommand != null && !handled)
            {
                result = _appCommand.Value.FilterMessage(hwnd, msg, 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 ; 

            // 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)
            { 
                for (int i = 0, nCount = _hooks.Count; i < nCount; i++)
                { 
                    result = ((HwndSourceHook)_hooks[i])(hwnd, msg, wParam, lParam, ref handled); 
                    if(handled)
                    { 
                        break;
                    }
                }
            } 
            if (NativeMethods.WM_NCDESTROY == msg)
            { 
                // 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 
        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 (msg.message) 
            { 
            case NativeMethods.WM_KEYUP:
            case NativeMethods.WM_KEYDOWN: 
            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.WM_CHAR:
            case NativeMethods.WM_SYSCHAR: 
            case NativeMethods.WM_DEADCHAR:
            case NativeMethods.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 
        /// 
        [SecurityCritical] 
        private object OnPreprocessMessage(object param)
        {
            MSGDATA msgdata = (MSGDATA) param;
 
            // At the top level check 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 
            // TopLevel window must have focus.
            if (!((IKeyboardInputSink)this).HasFocusWithin()) 
            {
                return msgdata.handled;
            }
 
            ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys();
 
            // Interop with the Interop layer 
            //
            switch (msgdata.msg.message) 
            {
            case NativeMethods.WM_SYSKEYDOWN:
            case NativeMethods.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);

                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();
                }
                break;
 
            case NativeMethods.WM_SYSKEYUP:
            case NativeMethods.WM_KEYUP: 
                msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); 
                break;
 
            case NativeMethods.WM_CHAR:
            case NativeMethods.WM_SYSCHAR:
            case NativeMethods.WM_DEADCHAR:
            case NativeMethods.WM_SYSDEADCHAR: 
                // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS
                if(!_eatCharMessages) 
                { 
                    msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys);
 
                    if (!msgdata.handled)
                    {
                        msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys);
                    } 

                    if (!msgdata.handled) 
                    { 
                        _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, msgdata.msg.message,
                                                               msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled); 
                    }
                }
                break;
            } 
            return msgdata.handled;
        } 
 
        /// 
        ///     Registers a child KeyboardInputSink with this sink.  A site 
        ///     is returned.
        /// 
        ///
        /// This API requires unrestricted UI Window permission. 
        ///
        ///  
        ///     Critical: This API can be used for input spoofing 
        ///     PublicOK: This method has a demand on it.
        ///  
        [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)]
        IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(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; 
        }
 
        ///  
        ///     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
        ///     TreatAsSafe: This method has a demand on it.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers) 
        { 
            SecurityHelper.DemandUnmanagedCode();
//             VerifyAccess(); 

            return CriticalTranslateAccelerator(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.
        ///  
        bool IKeyboardInputSink.TabInto(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;
        }

        ///  
        ///     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.
        ///
        ///  
        ///     Critical: This API can be used for input spoofing
        ///     PublicOK: This method has a demand on it. 
        ///  
        IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite
        { 
            [SecurityCritical]
            get
            {
                SecurityHelper.DemandUnmanagedCode(); 
                return _keyboardInputSite;
            } 
 
            [SecurityCritical]
            set 
            {
                SecurityHelper.DemandUnmanagedCode();

                _keyboardInputSite = 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
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
        { 
//             VerifyAccess();
            SecurityHelper.DemandUnmanagedCode(); 
            switch(msg.message) 
            {
                case NativeMethods.WM_SYSCHAR: 
                case NativeMethods.WM_SYSDEADCHAR:
                    string text = new string((char)msg.wParam, 1);
                    if ((text != null) && (text.Length > 0))
                    { 
                        if (AccessKeyManager.IsKeyRegistered(this, text))
                        { 
                            AccessKeyManager.ProcessKey(this, text, false); 

                            // 
                            return true;
                        }
                    }
                    // these are OK 
                    break;
 
                case NativeMethods.WM_CHAR: 
                case NativeMethods.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 Avalon bubble will take care of access key processing for this HWND
            // So now we just call the children.
            if (null == _keyboardInputSinkChildren) 
                return false;
 
            foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren ) 
            {
                if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) 
                    return true;
            }
            return false;
        } 

        ///  
        ///     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 
        ///     TreatAsSafe: This method has a demand on it. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers)
        {
            SecurityHelper.DemandUnmanagedCode();
            if(HasFocus) 
                return false;
 
            IKeyboardInputSink focusSink = this.ChildSinkWithFocus; 
            if(null != focusSink)
            { 
                return focusSink.TranslateChar(ref msg, modifiers);
            }
            return false;
        } 

        ///  
        /// 
        /// 
        bool IKeyboardInputSink.HasFocusWithin() 
        {
            if(HasFocus)
            {
                return true; 
            }
            else 
            { 
                if (null == _keyboardInputSinkChildren)
                    return false; 

                foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren)
                {
                    if (((IKeyboardInputSite)site).Sink.HasFocusWithin()) 
                    {
                        return true; 
                    } 
                }
                return false; 
            }
        }

        ///  
        ///   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 (msg.message)
            { 
                case NativeMethods.WM_KEYUP:
                case NativeMethods.WM_KEYDOWN: 
                case NativeMethods.WM_SYSKEYUP: 
                case NativeMethods.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)
                {
                    _keyboard.Value.ProcessKeyAction(ref msg, ref handled); 
                }
                // ELSE the focus is in but not on this HwndSource. 
                // 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;
                    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 (msg.message) 
                {
                case NativeMethods.WM_KEYUP: 
                case NativeMethods.WM_SYSKEYUP:
                    keyPreviewEvent = Keyboard.PreviewKeyUpEvent;
                    keyEvent = Keyboard.KeyUpEvent;
                    break; 
                case NativeMethods.WM_KEYDOWN:
                case NativeMethods.WM_SYSKEYDOWN: 
                    keyPreviewEvent = Keyboard.PreviewKeyDownEvent; 
                    keyEvent = Keyboard.KeyDownEvent;
                    break; 
                }

                IKeyboardInputSink focusSink = HasFocus ? null : ChildSinkWithFocus;
                IInputElement focusElement = focusSink as IInputElement; 

                // focusElement may be null, in which case Target is just "focus" 
                try { 
                    Keyboard.PrimaryDevice.ForceTarget = focusElement;
                    focusElement = Keyboard.PrimaryDevice.Target; 

                    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;
                        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.Clear();
            _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
        ///     Safe: Disposing the object is a safe operation. 
        ///  
        [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();
 
                    // Unregister ourselves if we are a registered KeyboardInputSink.
                    if(_keyboardInputSite != null) 
                    { 
                        _keyboardInputSite.Unregister();
                        _keyboardInputSite = null; 
                    }
                    _keyboardInputSinkChildren = null;

                    // 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): base(source)
            { 
                ComponentDispatcher.ThreadPreprocessMessage +=
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            }
 
            /// 
            ///     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()
            {
                ComponentDispatcher.ThreadPreprocessMessage -= 
                                new ThreadMessageEventHandler(this.OnPreprocessMessage);
            } 
        } 

#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 ArrayList                   _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;

        private static System.LocalDataStoreSlot _threadSlot; 

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