HwndTarget.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / InterOp / HwndTarget.cs / 1 / HwndTarget.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//  File:       HwndTarget.cs 
//
//----------------------------------------------------------------------------- 
using System; 
using System.Diagnostics;
using System.Windows.Threading; 
using System.Threading;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Automation.Provider; 
using System.Windows.Automation.Peers; 
using System.Windows.Media.Composition;
using System.Runtime.InteropServices; 
using System.Security.Permissions;
using System.Security;
using MS.Internal;
using MS.Internal.Automation; 
using MS.Win32;
using MS.Utility; 
using Microsoft.Internal; 
using MS.Internal.PresentationCore;                        // SecurityHelper
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

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

namespace System.Windows.Interop 
{ 
    // This is the internal, more expressive, enum used by the SetRenderingMode method.
    // See the RenderMode enum and the RenderMode property for the public version. 
    internal enum RenderingMode
    {
        Default = MILRTInitializationFlags.MIL_RT_INITIALIZE_DEFAULT,
        Software = MILRTInitializationFlags.MIL_RT_SOFTWARE_ONLY, 
        Hardware = MILRTInitializationFlags.MIL_RT_HARDWARE_ONLY,
        HardwareReference = MILRTInitializationFlags.MIL_RT_HARDWARE_ONLY | MILRTInitializationFlags.MIL_RT_USE_REF_RAST, 
    } 

    // This is the public, more limited, enum exposed for use with the RenderMode property. 
    // See the RenderingMode enum and SetRenderingMode method for the internal version.
    /// 
    ///     Render mode preference.
    ///  
    public enum RenderMode
    { 
        ///  
        /// The rendering layer should use the GPU and CPU as appropriate.
        ///  
        Default,

        /// 
        /// The rendering layer should only use the CPU. 
        /// 
        SoftwareOnly 
    } 

    ///  
    /// The HwndTarget class represents a binding to an HWND.
    /// 
    /// The HwndTarget is not thread-safe. Accessing the HwndTarget from a different
    /// thread than it was created will throw a . 
    public class HwndTarget : CompositionTarget
    { 
        ///  
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, HandleMessage).
        ///  
        [SecurityCritical]
        private static int s_dwmRedirectionEnvironmentChanged;

        ///  
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, SetChannelNotificationWindow).
        ///  
        [SecurityCritical] 
        private static int s_channelNotifyMessage;
 
        /// 
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, HandleMessage).
        /// 
        [SecurityCritical] 
        private static int s_transformHintUpdateMessage;
 
        ///  
        /// Critical - Gets to the unmanaged layer (ctor, HandleMessage, UpdateWindowSettings).
        ///  
        [SecurityCritical]
        private static int s_updateWindowSettings;

        private MatrixTransform _worldTransform; 
        private double _devicePixelsPerInchX;
        private double _devicePixelsPerInchY; 
 
        /// 
        /// Critical -  We don't want partial trust code changing the rendering preference. 
        /// 
        private SecurityCriticalDataForSet _renderModePreference = new SecurityCriticalDataForSet(RenderMode.Default);
 	
        /// 
        /// Critical - obtained under an elevation.
        /// 
        [SecurityCritical] 
        private NativeMethods.HWND _hWnd;
 
        private NativeMethods.RECT _hwndClientRectInScreenCoords;
        private NativeMethods.RECT _hwndWindowRectInScreenCoords;

        private Color _backgroundColor = Color.FromRgb(0, 0, 0); 

        private DUCE.MultiChannelResource _compositionTarget = 
            new DUCE.MultiChannelResource(); 

        private bool _isRenderTargetEnabled = true; 
        // private Nullable _colorKey = null;
        // private double _opacity = 1.0;
        private bool _usesPerPixelOpacity = false;
 
        // It is important that this start at zero to allow an initial
        // UpdateWindowSettings(enable) command to enable the render target 
        // without a preceeding UpdateWindowSettings(disable) command. 
        private int _disableCookie = 0;
 
        // Used to deal with layered window problems. See comments where they are used.
        private bool _isMinimized = false;
        private bool _isSessionDisconnected = false;
        private bool _isSuspended = false; 

        ///  
        /// Initializes static variables for this class. 
        /// 
        ///  
        /// Critical        - Sets the SecurityCritical static variables holding the message ids; calls RegisterWindowMessage.
        /// TreatAsSafe     - The message ids are not exposed; no external parameters are taken in.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        static HwndTarget()
        { 
            s_dwmRedirectionEnvironmentChanged = UnsafeNativeMethods.RegisterWindowMessage("DwmRedirectionEnvironmentChangedHint"); 
            s_channelNotifyMessage = UnsafeNativeMethods.RegisterWindowMessage("MilChannelNotify");
            s_transformHintUpdateMessage = UnsafeNativeMethods.RegisterWindowMessage("TransformHintUpdate"); 
            s_updateWindowSettings = UnsafeNativeMethods.RegisterWindowMessage("UpdateWindowSettings");
        }

        ///  
        /// Attaches a hwndTarget to the hWnd
        ///  
        ///     This API link demands for UIWindowPermission.AllWindows 
        /// 
        ///  
        /// The HWND to which the HwndTarget will draw.
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        /// Critical - accepts unmanaged pointer handle.Not safe to create since it 
        ///            can be used to draw to a window 
        /// PublicOk - demands UIPermission
        ///  
        [SecurityCritical]
        [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
        public HwndTarget(IntPtr hwnd)
        { 
            bool exceptionThrown = true;
 
            AttachToHwnd(hwnd); 

            try 
            {
                if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal))
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEDIACREATEVISUALGUID), MS.Utility.EventType.Info, 
                                                         Dispatcher.GetHashCode(), hwnd.ToInt64());
                } 
 
                _hWnd = NativeMethods.HWND.Cast(hwnd);
 
                // Get the client rectangle...
                GetWindowRectsInScreenCoordinates();

                // Set device independent resolution to 96 DPI. 
                // NativeMethods.HDC hdc = NativeMethods.GetDC(_hWnd);
 
                _devicePixelsPerInchX = 96.0f; 
                _devicePixelsPerInchY = 96.0f;
 
                //
                // Determine whether hWnd corresponds to MIL or GDI window.
                //
                IntPtr hdcW = UnsafeNativeMethods.GetDC( 
                    new HandleRef(this, _hWnd));
 
                if (hdcW == IntPtr.Zero) 
                {
                    // 
                    // If we were unable to obtain HDC for the given
                    // window, assume the default of 96 DPI.
                    //
 
                    _devicePixelsPerInchX = 96.0f;
                    _devicePixelsPerInchY = 96.0f; 
                } 
                else
                { 
                    //
                    // Obtain and cache DPI values for window's HDC.
                    //
 
                    _devicePixelsPerInchX = (double)UnsafeNativeMethods.GetDeviceCaps(
                        new HandleRef(this, hdcW), 
                        NativeMethods.LOGPIXELSX); 

                    _devicePixelsPerInchY = (double)UnsafeNativeMethods.GetDeviceCaps( 
                        new HandleRef(this, hdcW),
                        NativeMethods.LOGPIXELSY);

                    // 
                    // Release DC object.
                    // 
 
                    UnsafeNativeMethods.ReleaseDC(
                        new HandleRef(this, _hWnd), 
                        new HandleRef(this, hdcW));
                }

                _worldTransform = new MatrixTransform(new Matrix( 
                  _devicePixelsPerInchX * (1.0f / 96.0f), 0,
                  0, _devicePixelsPerInchY * (1.0f / 96.0f), 
                  0, 0)); 

                // 
                // Register CompositionTarget with MediaContext.
                //
                MediaContext.RegisterICompositionTarget(Dispatcher, this);
 

                // 
                // Change the window message filter to allow session and transform 
                // hint control messages to be sent from the DWM. On down-level
                // platforms, these calls will result in no-op. 
                //

                ChangeWindowMessageFilter((uint)s_dwmRedirectionEnvironmentChanged, 1 /* MSGFLT_ADD */);
                ChangeWindowMessageFilter((uint)s_transformHintUpdateMessage, 1 /* MSGFLT_ADD */); 

                // 
                // Hint window redirection layer that Avalon content has been attached 
                // to this window. As a result, redirection layer will create necessary
                // resources and manage clip and position for this window in TS and 
                // Accessibility scenarios. If DWM is not running, this call will result
                // in NoOp.
                //
                HRESULT.Check(MilContent_AttachToHwnd(_hWnd)); 

                exceptionThrown = false; 
            } 
            finally
            { 
                //
                // If exception has occurred after we attached this target to
                // the window, we need to detach from this window. Otherwise, window
                // will be left in a state when no other HwndTarget can be created 
                // for it.
                // 
                if(exceptionThrown) 
                {
                    #pragma warning suppress 6031 // Return value ignored on purpose. 
                    VisualTarget_DetachFromHwnd(hwnd);
                }
            }
        } 

        ///  
        /// AttachToHwnd 
        /// 
        /// 
        /// Critical as it calls a function that performs an elevation (IsWindow).
        ///
        [SecurityCritical]
        internal void AttachToHwnd(IntPtr hwnd) 
        {
            int processId = 0; 
            int threadId = UnsafeNativeMethods.GetWindowThreadProcessId( 
                new HandleRef(this, hwnd),
                out processId 
                );

            if (!UnsafeNativeMethods.IsWindow(new HandleRef(this, hwnd)))
            { 
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowHandle), 
                    "hwnd" 
                    );
            } 
            else if (processId != SafeNativeMethods.GetCurrentProcessId())
            {
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowProcess), 
                    "hwnd"
                    ); 
            } 
            else if (threadId != SafeNativeMethods.GetCurrentThreadId())
            { 
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowThread),
                    "hwnd"
                    ); 
            }
 
            int hr = VisualTarget_AttachToHwnd(hwnd); 

            if (HRESULT.Failed(hr)) 
            {
                if (hr == unchecked((int)0x80070005)) // E_ACCESSDENIED
                {
                    throw new InvalidOperationException( 
                        SR.Get(SRID.HwndTarget_WindowAlreadyHasContent)
                        ); 
                } 
                else
                { 
                    HRESULT.Check(hr);
                }
            }
        } 

        ///  
        ///     Critical: This code causes unmanaged code elevation 
        /// 
        [SecurityCritical,SuppressUnmanagedCodeSecurity] 
        [DllImport(DllImport.MilCore, EntryPoint = "MilVisualTarget_AttachToHwnd")]
        internal static extern int VisualTarget_AttachToHwnd(
            IntPtr hwnd
            ); 

 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore, EntryPoint = "MilVisualTarget_DetachFromHwnd")]
        internal static extern int VisualTarget_DetachFromHwnd(
            IntPtr hwnd 
            );
 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore)]
        internal static extern int MilContent_AttachToHwnd(
            IntPtr hwnd 
            );
 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore)]
        internal static extern int MilContent_DetachFromHwnd(
            IntPtr hwnd 
            );
 
        ///  
        /// Allow lower integrity applications to send specified window messages
        /// in case we are elevated. Failure is non-fatal and on down-level 
        /// platforms this call will result in a no-op.
        /// 
        /// 
        /// Critical -- Calls unsafe native methods GetModuleHandle and GetProcAddress. 
        ///             Manually elevates unmanaged code permissions to pinvoke through
        ///             a function pointer. 
        ///  
        [SecurityCritical]
        private void ChangeWindowMessageFilter(uint message, uint flag) 
        {
            // Find the address of ChangeWindowMessageFilter in user32.dll.
            IntPtr user32Module = UnsafeNativeMethods.GetModuleHandle("user32.dll");
 
            // Get the address of the function. If this fails it means the OS
            // doesn't support this function, in which case we don't 
            // need to do anything further. 
            IntPtr functionAddress = UnsafeNativeMethods.GetProcAddressNoThrow(
                    new HandleRef(null, user32Module), 
                    "ChangeWindowMessageFilter");

            if  (functionAddress != IntPtr.Zero)
            { 
                // Convert the function pointer into a callable delegate and then call it
                ChangeWindowMessageFilterNative function = Marshal.GetDelegateForFunctionPointer( 
                    functionAddress, 
                    typeof(ChangeWindowMessageFilterNative)) as ChangeWindowMessageFilterNative;
 
                // In order to call the function we need unmanaged code access,
                // because the function is native code.
                (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
                try 
                {
                    function(message, flag); 
                } 
                finally
                { 
                    SecurityPermission.RevertAssert();
                }
            }
        } 

        ///  
        /// Prototype for user32's ChangeWindowMessageFilter function, which we load dynamically on Longhorn. 
        /// 
        private delegate void ChangeWindowMessageFilterNative(uint message, uint flag); 

        internal void SetRenderingMode(RenderingMode mode)
        {
            // 
            // If ForceLocalTransport is set then the transport is connected to a client (magnifier) that cannot
            // handle our transport protocol version. Therefore we force software rendering so that the rendered 
            // content is available through NTUser redirection. If software is not allowed an exception is thrown. 
            //
            if (MediaSystem.ForcedLocalTransport) // present using bitblt if a local transport was forced 
            {
                if (mode == RenderingMode.Hardware ||
                    mode == RenderingMode.HardwareReference)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.HwndTarget_HardwareNotSupportDueToProtocolMismatch));
                } 
                else 
                {
                    Debug.Assert(mode == RenderingMode.Software || mode == RenderingMode.Default); 
                    // If the mode is default we can chose what works. When we have a mismatched transport protocol version
                    // we need to fallback to software rendering.
                    mode = RenderingMode.Software;
                } 
            }
 
            // Select the render target initialization flags based on the requested 
            // rendering mode.
 
            DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels();
            DUCE.Channel channel = channelSet.Channel;

            DUCE.CompositionTarget.SetRenderingMode( 
                _compositionTarget.GetHandle(channel),
                (MILRTInitializationFlags)mode, 
                channel); 
        }
 
        /// 
        /// Specifies the render mode preference for the window.
        /// 
        ///  
        ///     This property specifies a preference, it does not necessarily change the actual
        ///     rendering mode.  Among other things, this can be trumped by the registry settings. 
        ///      
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to set this property.
        ///  
        /// 
        ///     Critical: This code influences the low-level rendering code by specifying whether the
        ///     rendering system should use the GPU or CPU.
        ///     PublicOK: We don't want to enable this in partial trust, so we have a link demand 
        ///     on the setter.  It is not privileged data, so the getter is not protected.
        ///  
        public RenderMode RenderMode 
        {
            get 
            {
                return _renderModePreference.Value;
            }
 
            // Note: We think it is safe to expose this in partial trust, but doing so would suggest
            // we should also expose HwndSource (the only way to get to the HwndTarget instance). 
            // We don't want to bite off that much exposure at this point in the product, so we enforce 
            // that this is not accessible from partial trust for now.
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
            set
            {
                if (value != RenderMode.Default && value != RenderMode.SoftwareOnly) 
                {
                    throw new System.ComponentModel.InvalidEnumArgumentException("value", (int)value, typeof(RenderMode)); 
                } 

                _renderModePreference.Value = value; 

                SetRenderingMode(value == RenderMode.SoftwareOnly ? RenderingMode.Software : RenderingMode.Default);
            }
        } 

        ///  
        /// Dispose cleans up the state associated with HwndTarget. 
        /// 
        ///  
        /// Critical - accesses the _hwnd that is critical, calls unmanaged code
        /// PublicOK - dispose is in effect stoping the contents of the target from
        /// rendering. Equivalent to removing all elements in window, considered safe.
        ///  
        [SecurityCritical]
        public override void Dispose() 
        { 
           // Its outside the try finally block because we want the exception to be
           // thrown if we are on a different thread and we don't want to call Dispose 
           // on base class in that case.
           VerifyAccess();

           try 
           {
                // According to spec: Dispose should not raise exception if called multiple times. 
                // This test is needed because the HwndTarget is Disposed from both the media contex and 
                // the hwndsrc.
                if (!IsDisposed) 
                {
                    RootVisual = null;

                    HRESULT.Check(VisualTarget_DetachFromHwnd(_hWnd)); 

                    // 
                    // Unregister this CompositionTarget from the MediaSystem. 
                    //
                    MediaContext.UnregisterICompositionTarget(Dispatcher, this); 

                    //
                    // Hint window redirection layer that Avalon content has been detached
                    // from this window. Redirection layer will then have a chance to clean 
                    // up the resources that it created for Avalon hosting. If DWM is not
                    // running, this call will result in NoOp. 
                    // 
                    HRESULT.Check(MilContent_DetachFromHwnd(_hWnd));
 
                    // Unregister for Fast User Switching messages if necessary
                    if (_usesPerPixelOpacity)
                    {
                        UnsafeNativeMethods.WTSUnRegisterSessionNotification(_hWnd); 
                    }
                } 
 
            }
            finally 
            {
                base.Dispose();
            }
        } 

        ///  
        /// This method is used to create all uce resources either on Startup or session connect 
        /// 
        ///  
        /// Critical - uses unmanaged pointer handle _hWnd
        /// TreatAsSafe - doesn't return or expose _hWnd
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void CreateUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel)
        { 
            // create visual target resources 
            // this forces the creation of the media context if we don't already have one.
 
            base.CreateUCEResources(channel, outOfBandChannel);

            Debug.Assert(!_compositionTarget.IsOnChannel(channel));
            Debug.Assert(!_compositionTarget.IsOnChannel(outOfBandChannel)); 

            // 
            // For each HwndTarget we are building some structures in the UCE. 
            // This includes spinning up a UCE render target. We need to commit the
            // batch for those changes right away, since we need to be able to process 
            // the invalidate packages that we send down on WM_PAINTs. If we don't commit
            // right away a WM_PAINT can get fired before we get a chance to commit
            // the batch.
            // 

            // 
            // First we create the composition target, composition context, and the composition root node. 
            // Note, that composition target will be created out of band because invalidate
            // command is also sent out of band and that can occur before current channel is committed. 
            // We would like to avoid commiting channel here to prevent visual artifacts.
            //

            bool resourceCreated = _compositionTarget.CreateOrAddRefOnChannel(outOfBandChannel, DUCE.ResourceType.TYPE_HWNDRENDERTARGET); 
            Debug.Assert(resourceCreated);
            _compositionTarget.DuplicateHandle(outOfBandChannel, channel); 
            outOfBandChannel.Commit(); 

            DUCE.CompositionTarget.HwndInitialize( 
                _compositionTarget.GetHandle(channel),
                _hWnd,
                _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left,
                _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top, 
                MediaSystem.ForcedLocalTransport, // present using bitblt if a local transport was forced
                channel 
                ); 

            DUCE.ResourceHandle hWorldTransform = ((DUCE.IResource)_worldTransform).AddRefOnChannel(channel); 

            DUCE.CompositionNode.SetTransform(
                _contentRoot.GetHandle(channel),
                hWorldTransform, 
                channel);
 
            DUCE.CompositionTarget.SetClearColor( 
                _compositionTarget.GetHandle(channel),
                _backgroundColor, 
                channel);

            //
            // Set initial state on the visual target. 
            //
 
            Rect clientRect = new Rect( 
                0,
                0, 
                (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left))),
                (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top))));

            StateChangedCallback( 
                new object[]
                { 
                    HostStateFlags.WorldTransform | 
                    HostStateFlags.ClipBounds,
                    _worldTransform.Matrix, 
                    clientRect
                });

            DUCE.CompositionTarget.SetRoot( 
                _compositionTarget.GetHandle(channel),
                _contentRoot.GetHandle(channel), 
                channel); 

            // reset the disable cookie when creating the slave resource. This happens when creating the 
            // managed resource and on handling a connect.
            _disableCookie = 0;

            // 
            // Finally, update window settings to reflect the state of this object.
            // Because CreateUCEResources is called for each channel, only call 
            // UpdateWindowSettings on that channel this time. 
            //
            DUCE.ChannelSet channelSet; 
            channelSet.Channel = channel;
            channelSet.OutOfBandChannel = outOfBandChannel;
            UpdateWindowSettings(_isRenderTargetEnabled, channelSet);
        } 

        ///  
        /// This method is used to release all uce resources either on Shutdown or session disconnect 
        /// 
        ///  
        /// Critical - uses unmanaged pointer handle _hWnd
        /// TreatAsSafe - doesn't return or expose _hWnd
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void ReleaseUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel)
        { 
            if (_compositionTarget.IsOnChannel(channel)) 
            {
                // 
                // GSchneid: If we need to flush the batch we need to render first all visual targets that
                // are still registered with the MediaContext to avoid strutural tearing.

 
                // Set the composition target root node to null.
                DUCE.CompositionTarget.SetRoot( 
                    _compositionTarget.GetHandle(channel), 
                    DUCE.ResourceHandle.Null,
                    channel); 

                _compositionTarget.ReleaseOnChannel(channel);
            }
 
            if (_compositionTarget.IsOnChannel(outOfBandChannel))
            { 
                _compositionTarget.ReleaseOnChannel(outOfBandChannel); 
            }
 
            DUCE.ResourceHandle hWorldTransform = ((DUCE.IResource)_worldTransform).GetHandle(channel);
            if (!hWorldTransform.IsNull)
            {
                // Release the world transform from this channel if it's currently on the channel. 
                ((DUCE.IResource)_worldTransform).ReleaseOnChannel(channel);
            } 
 
            // release all the visual target resources.
            base.ReleaseUCEResources(channel, outOfBandChannel); 
        }

        /// 
        /// The HwndTarget needs to see all windows messages so that 
        /// it can appropriately react to them.
        ///  
        ///  
        /// Critical - accepts unmanaged pointer handle, also
        /// Elevates permissions via unsafe native methods, handles messages to 
        /// retrieve automation provider the last one is most risky
        /// 
        [SecurityCritical]
        internal IntPtr HandleMessage(int msg, IntPtr wparam, IntPtr lparam) 
        {
            IntPtr handled = new IntPtr(0x1); // return 1 if the message is handled by this method exclusively. 
            IntPtr unhandled = IntPtr.Zero; // return 0 if other win procs should be called. 
            IntPtr result = unhandled;
 
            if (msg == s_dwmRedirectionEnvironmentChanged)
            {
                System.Windows.Media.MediaSystem.NotifyRedirectionEnvironmentChanged();
                return handled; 
            }
            else if (msg == s_channelNotifyMessage) 
            { 
                MediaContext.From(Dispatcher).NotifyChannelMessage();
            } 
            else if(msg == s_updateWindowSettings)
            {
                // Make sure we enable the render target if the window is visible.
                if(SafeNativeMethods.IsWindowVisible(_hWnd.MakeHandleRef(this))) 
                {
                    UpdateWindowSettings(true); 
                } 
            }
 
            if (IsDisposed)
            {
                return result;
            } 

            switch (msg) 
                { 
                case NativeMethods.WM_ERASEBKGND:
                    result = handled; // Indicates that this message is handled. 
                    break;

                case NativeMethods.WM_PAINT:
                    DoPaint(); 
                    result = handled;
                    break; 
 
                case NativeMethods.WM_SIZE:
                    // 
                    // NTRAID#Longhorn-1946030-2007/03/23-jordanpa:
                    //      When locked on downlevel, MIL stops rendering and invalidates the
                    //      window causing WM_PAINT. When the window is layered and minimized
                    //      before the lock, it'll never get the WM_PAINT on unlock and the MIL will 
                    //      never get out of the "don't render" state.
                    // 
                    //      To work around this, we will invalidate ourselves on restore and not 
                    //      render while minimized.
                    // 

                    // If the Window is in minimized state, don't do layout. otherwise, in some cases, it would
                    // pollute the measure data based on the Minized window size.
                    if (NativeMethods.IntPtrToInt32(wparam) != NativeMethods.SIZE_MINIMIZED) 
                    {
                        _isMinimized = false; 
                        DoPaint(); 

                        OnResize(); 
                    }
                    else
                    {
                        _isMinimized = true; 
                    }
 
                    break; 

                case NativeMethods.WM_SETTINGCHANGE: 
                    if (OnSettingChange(NativeMethods.IntPtrToInt32(wparam)))
                    {
                        UnsafeNativeMethods.InvalidateRect(_hWnd.MakeHandleRef(this), IntPtr.Zero , true);
                    } 
                    break;
 
                case NativeMethods.WM_GETOBJECT: 
                    result = CriticalHandleWMGetobject( wparam, lparam, RootVisual, _hWnd );
                    break; 

                case NativeMethods.WM_WINDOWPOSCHANGING:
                    OnWindowPosChanging(lparam);
                    break; 

                case NativeMethods.WM_WINDOWPOSCHANGED: 
                    OnWindowPosChanged(lparam); 
                    break;
 
                case NativeMethods.WM_SHOWWINDOW:
                    OnShowWindow(wparam != IntPtr.Zero);
                    break;
 
                case NativeMethods.WM_EXITSIZEMOVE:
                    OnExitSizeMove(); 
                    break; 

                case NativeMethods.WM_STYLECHANGING: 
                    unsafe
                    {
                        NativeMethods.STYLESTRUCT * styleStruct = (NativeMethods.STYLESTRUCT *) lparam;
 
                        if ((int)wparam == NativeMethods.GWL_EXSTYLE)
                        { 
                            if(UsesPerPixelOpacity) 
                            {
                                // We need layered composition to accomplish per-pixel opacity. 
                                //
                                styleStruct->styleNew |= NativeMethods.WS_EX_LAYERED;
                            }
                            else 
                            {
                                // No properties that require layered composition exist. 
                                // Make sure the layered bit is off. 
                                //
                                // Note: this prevents an external program from making 
                                // us system-layered (if we are a top-level window).
                                //
                                // If we are a child window, we still can't stop our
                                // parent from being made system-layered, and we will 
                                // end up leaving visual artifacts on the screen under
                                // WindowsXP. 
                                // 
                                styleStruct->styleNew &= (~NativeMethods.WS_EX_LAYERED);
                            } 
                        }
                    }

                    break; 

                case NativeMethods.WM_STYLECHANGED: 
                    unsafe 
                    {
                        bool updateWindowSettings = false; 

                        NativeMethods.STYLESTRUCT * styleStruct = (NativeMethods.STYLESTRUCT *) lparam;

                        if ((int)wparam == NativeMethods.GWL_STYLE) 
                        {
                            bool oldIsChild = (styleStruct->styleOld & NativeMethods.WS_CHILD) == NativeMethods.WS_CHILD; 
                            bool newIsChild = (styleStruct->styleNew & NativeMethods.WS_CHILD) == NativeMethods.WS_CHILD; 
                            updateWindowSettings = (oldIsChild != newIsChild);
                        } 
                        else
                        {
                            bool oldIsRTL = (styleStruct->styleOld & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL;
                            bool newIsRTL  = (styleStruct->styleNew & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL; 
                            updateWindowSettings = (oldIsRTL != newIsRTL);
                        } 
 
                        if(updateWindowSettings)
                        { 
                            UpdateWindowSettings();
                        }
                    }
 
                    break;
 
                // 
                // NTRAID#Longhorn-1967619-2007/03/23-jordanpa:
                //      When a Fast User Switch happens, MIL gets an invalid display error when trying to 
                //      render and they invalidate the window resulting in us getting a WM_PAINT. For
                //      layered windows, we get the WM_PAINT immediately which causes us to
                //      tell MIL to render and the cycle repeats. On Vista, this creates an infinite loop.
                //      Downlevel there isn't a loop, but the layered window will never update again. 
                //
                //      To work around this problem, we'll make sure not to tell MIL to render when 
                //      we're switched out and will render on coming back. 
                //
                case NativeMethods.WM_WTSSESSION_CHANGE: 
                    switch (NativeMethods.IntPtrToInt32(wparam))
                    {
                        // Session is disconnected. Due to:
                        // 1. Switched to a different user 
                        // 2. TS logoff
                        // 3. Screen locked 
                        case NativeMethods.WTS_CONSOLE_DISCONNECT: 
                        case NativeMethods.WTS_REMOTE_DISCONNECT:
                        case NativeMethods.WTS_SESSION_LOCK: 
                            _isSessionDisconnected = true;
                            break;

                        // Session is reconnected. See above 
                        case NativeMethods.WTS_CONSOLE_CONNECT:
                        case NativeMethods.WTS_REMOTE_CONNECT: 
                        case NativeMethods.WTS_SESSION_UNLOCK: 
                            _isSessionDisconnected = false;
                            DoPaint(); 

                            break;

                        default: 
                            break;
                    } 
 
                    break;
 
                //
                // NTRAID#Longhorn-1975236-2007/05/22-jordanpa:
                //      Downlevel, if we try to present a layered window while suspended the app will crash.
                //      This has been fixed in Vista but we still need to work around it for older versions 
                //      by not invalidating while suspended.
                // 
                case NativeMethods.WM_POWERBROADCAST: 
                    switch (NativeMethods.IntPtrToInt32(wparam))
                    { 
                        case NativeMethods.PBT_APMSUSPEND:
                            _isSuspended = true;
                            break;
 
                        case NativeMethods.PBT_APMRESUMESUSPEND:
                        case NativeMethods.PBT_APMRESUMECRITICAL: 
                        case NativeMethods.PBT_APMRESUMEAUTOMATIC: 
                            _isSuspended = false;
                            DoPaint(); 
                            break;

                        default:
                            break; 
                    }
                    break; 
 
                default:
                    break; 
            }

            return result;
        } 

        ///  
        /// Paints a rect 
        ///
        /// Note: This gets called a lot to help with layered window problems even when 
        ///         the window isn't layered, but that's okay because rcPaint will be empty.
        ///
        /// 
        ///  
        /// Critical - Elevates permissions via unsafe native methods, calls into begin paint
        ///  
        [SecurityCritical] 
        private void DoPaint()
        { 
            NativeMethods.PAINTSTRUCT ps = new NativeMethods.PAINTSTRUCT();
            NativeMethods.HDC hdc;

            HandleRef handleRef = new HandleRef(this, _hWnd); 
            hdc.h = UnsafeNativeMethods.BeginPaint(handleRef, ref ps);
            int retval = UnsafeNativeMethods.GetWindowLong(handleRef, NativeMethods.GWL_EXSTYLE); 
 
            NativeMethods.RECT rcPaint = new NativeMethods.RECT(ps.rcPaint_left, ps.rcPaint_top, ps.rcPaint_right, ps.rcPaint_bottom);
 
            //
            // If we get a BeginPaint with an empty rect then check
            // if this is a special layered, non-redirected window
            // which would mean we need to do a full paint when it 
            // won't cause a problem.
            // 
            if (rcPaint.IsEmpty 
                && ((retval & NativeMethods.WS_EX_LAYERED) != 0)
                && !UnsafeNativeMethods.GetLayeredWindowAttributes(_hWnd.MakeHandleRef(this), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) 
                && !_isSessionDisconnected
                && !_isMinimized
                && !_isSuspended)
            { 
                rcPaint = new NativeMethods.RECT(
                          0, 
                          0, 
                          _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left,
                          _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top); 
            }

            AdjustForRightToLeft(ref rcPaint, handleRef);
 
            if (!rcPaint.IsEmpty)
            { 
                InvalidateRect(rcPaint); 
            }
 
            UnsafeNativeMethods.EndPaint(_hWnd.MakeHandleRef(this), ref ps);
        }

        ///  
        /// Critical - 1) This method exposes the automation object which can be used to
        /// query the system for critical information or spoof input. 
        /// 2) it Asserts to call ReturnRawElementProvider 
        /// 
        [SecurityCritical] 
        private static IntPtr CriticalHandleWMGetobject(IntPtr wparam, IntPtr lparam, Visual root, IntPtr handle)
        {
            try
            { 
                if (root == null)
                { 
                    // Valid case, but need to handle separately. For now, return 0 to avoid exceptions 
                    // in referencing this later on. Real solution is more complex, see WindowsClient#873800.
                    return IntPtr.Zero; 
                }

                AutomationPeer peer = null;
 
                if (root.CheckFlagsAnd(VisualFlags.IsUIElement))
                { 
                    UIElement uiroot = (UIElement)root; 

                    peer = UIElementAutomationPeer.CreatePeerForElement(uiroot); 

                    //there si no specific peer for this UIElement, create a generic root
                    if(peer == null)
                        peer = uiroot.CreateGenericRootAutomationPeer(); 

                    if(peer != null) 
                        peer.Hwnd = handle; 
                }
 
                // This can happen if the root visual is not UIElement. In this case,
                // attempt to find one in the visual tree.
                if (peer == null)
                { 
                    peer = UIElementAutomationPeer.GetRootAutomationPeer(root, handle);
                } 
 
                if (peer == null)
                { 
                    return IntPtr.Zero;
                }

                // get the element proxy 
                // it's ok to pass the same peer as reference connected peer here because
                // it's guaranteed to be a connected one (it's initialized as root already) 
                IRawElementProviderSimple el = ElementProxy.StaticWrap(peer, peer); 

                peer.AddToAutomationEventList(); 

                // The assert here is considered OK
                // as we're assuming the WM_GETOBJECT is coming only from a PostMessage of an Hwnd.
                // to do the post message - you needed to have Unmanaged code permission 
                //
 
                PermissionSet unpackPermissionSet = new PermissionSet(PermissionState.None); 
                // below permissions needed to unpack an object.
                unpackPermissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter | SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.RemotingConfiguration)); 
                unpackPermissionSet.AddPermission(new System.Net.DnsPermission(PermissionState.Unrestricted));
                unpackPermissionSet.AddPermission(new System.Net.SocketPermission(PermissionState.Unrestricted));

                unpackPermissionSet.Assert(); 
                try
                { 
                    return AutomationInteropProvider.ReturnRawElementProvider(handle, wparam, lparam, el); 
                }
                finally 
                {
                    CodeAccessPermission.RevertAll();
                }
            } 
#pragma warning disable 56500
            catch (Exception e) 
            { 
                if(CriticalExceptions.IsCriticalException(e))
                { 
                    throw;
                }

                return new IntPtr(Marshal.GetHRForException(e)); 
            }
#pragma warning restore 56500 
        } 

        ///  
        ///     Adjusts a RECT to compensate for Win32 RTL conversion logic
        /// 
        /// 
        ///     When a window is marked with the WS_EX_LAYOUTRTL style, Win32 
        ///     mirrors the coordinates during the various translation APIs.
        /// 
        ///     Avalon also sets up mirroring transforms so that we properly 
        ///     mirror the output since we render to DirectX, not a GDI DC.
        /// 
        ///     Unfortunately, this means that our coordinates are already mirrored
        ///     by Win32, and Avalon mirrors them again.  To solve this
        ///     problem, we un-mirror the coordinates from Win32 before painting
        ///     in Avalon. 
        /// 
        ///  
        ///     The RECT to be adjusted 
        /// 
        ///  
        /// 
        internal void AdjustForRightToLeft(ref NativeMethods.RECT rc, HandleRef handleRef)
        {
            int windowStyle = SafeNativeMethods.GetWindowStyle(handleRef, true); 

            if(( windowStyle & NativeMethods.WS_EX_LAYOUTRTL ) == NativeMethods.WS_EX_LAYOUTRTL) 
            { 
                NativeMethods.RECT rcClient = new NativeMethods.RECT();
                SafeNativeMethods.GetClientRect(handleRef, ref rcClient); 

                int width   = rc.right - rc.left;       // preserve width
                rc.right    = rcClient.right - rc.left; // set right of rect to be as far from right of window as left of rect was from left of window
                rc.left     = rc.right - width;         // restore width by adjusting left and preserving right 
            }
        } 
 
        /// 
        /// Force total re-rendering to handle system parameters change 
        /// (font smoothing settings, gamma correction, etc.)
        ///
        ///true if rerendering was forced
        ///  
        ///   Critical: This can be used to cause annoyance by causing re rendering
        ///  
        [SecurityCritical] 
        private bool OnSettingChange(Int32 firstParam)
        { 
            if ( (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHING ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGTYPE ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGCONTRAST ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGORIENTATION || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYPIXELSTRUCTURE ||
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYGAMMA || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYCLEARTYPELEVEL || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYTEXTCONTRASTLEVEL
                ) 
            {
                HRESULT.Check(MILUpdateSystemParametersInfo.Update());
                return true;
            } 

            return false; 
        } 

        ///  
        /// Let the DWM know of this HWND as belonging to a MIL/WPF application.
        /// Force total re-rendering to handle system Desktop Window Manager change
        /// 
        ///  
        ///   Critical: This can be used to cause annoyance by trying to cause re rendering.
        ///  
        [SecurityCritical] 
        internal void OnDWMCompositionChanged(bool isDesktopCompositionEnabled)
        { 
            //
            // Hint window redirection layer that Avalon content has been attached
            // to this window. As a result, redirection layer will create necessary
            // resources and manage clip and position for this window in TS and 
            // Accessibility scenarios.
            // 
            // We're going to attempt to attach to DWM every time the desktop composition 
            // state changes to ensure that we properly handle DWM crashing/restarting/etc.
            // 
            HRESULT.Check(MilContent_AttachToHwnd(_hWnd));

            //
 

            HRESULT.Check(MILUpdateSystemParametersInfo.Update()); 
            UnsafeNativeMethods.InvalidateRect(_hWnd.MakeHandleRef(this), IntPtr.Zero , true); 
        }
 
        /// 
        /// This function should be called to paint the specified
        /// region of the window along with any other pending
        /// changes.  While this function is generally called 
        /// in response to a WM_PAINT it is up to the user to
        /// call BeginPaint and EndPaint or to otherwise validate 
        /// the bitmap region. 
        /// 
        /// The rectangle that is dirty. 
        private void InvalidateRect(NativeMethods.RECT rcDirty)
        {
            DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels();
            DUCE.Channel channel = channelSet.Channel; 
            DUCE.Channel outOfBandChannel = channelSet.OutOfBandChannel;
 
            // handle InvalidateRect requests only if we have uce resources. 
            if (_compositionTarget.IsOnChannel(channel))
            { 
                //
                // Send a message with the invalid region to the compositor. We create a little batch to send this
                // out of order.
                // 
                DUCE.CompositionTarget.Invalidate(
                    _compositionTarget.GetHandle(outOfBandChannel), 
                    ref rcDirty, 
                    outOfBandChannel);
            } 
        }

        /// 
        /// Calling this function causes us to update state to reflect a 
        /// size change of the underlying HWND
        ///  
        /// 
        /// Critical - accesses a critical member (_hwnd)
        /// TreatAsSafe - uses the _hwnd to call a safeNativeMethods. Data is cached - but not considered critical. 
        ///
        [SecurityCritical, SecurityTreatAsSafe ]
        private void OnResize()
        { 
#if DEBUG
            MediaTrace.HwndTarget.Trace("OnResize"); 
#endif 

            // handle OnResize requests only if we have uce resources. 
            if (_compositionTarget.IsOnAnyChannel)
            {
                MediaContext mctx = MediaContext.From(Dispatcher);
 
                //
                // Let the render target know that window size has changed. 
                // 

                UpdateWindowSettings(); 

                //
                // Push client size chnage to the visual target.
                // 
                Rect clientRect = new Rect(
                    0, 
                    0, 
                    (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left))),
                    (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top)))); 

                StateChangedCallback(
                    new object[] { HostStateFlags.ClipBounds, null, clientRect });
 
                mctx.Resize(this);
 
                // To ensure that the client area and the non-client area resize 
                // together, we need to wait, on resize, for the composition
                // engine to present the resized frame. The call to CompleteRender 
                // blocks until that happens.

                mctx.CompleteRender();
            } 
        }
 
 
        /// 
        /// Calculates the client and window rectangle in screen coordinates. 
        /// 
        ///
        /// Critical - calls critical methods (ClientToScreen)
        /// TreatAsSafe - no information returned, coordinates stored in member field. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void GetWindowRectsInScreenCoordinates() 
        {
            NativeMethods.RECT rcClient = new NativeMethods.RECT(); 

            //
            // Get the window and client rectangles
            // 

            SafeNativeMethods.GetWindowRect(_hWnd.MakeHandleRef(this), ref _hwndWindowRectInScreenCoords); 
            SafeNativeMethods.GetClientRect(_hWnd.MakeHandleRef(this), ref rcClient); 

 
            NativeMethods.POINT ptClientTopLeft = new NativeMethods.POINT(rcClient.left, rcClient.top);
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientTopLeft);

            NativeMethods.POINT ptClientBottomRight = new NativeMethods.POINT(rcClient.right, rcClient.bottom); 
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientBottomRight);
 
            if(ptClientBottomRight.x >= ptClientTopLeft.x) 
            {
                _hwndClientRectInScreenCoords.left = ptClientTopLeft.x; 
                _hwndClientRectInScreenCoords.right = ptClientBottomRight.x;
            }
            else
            { 
                // RTL windows will cause the right edge to be on the left...
                _hwndClientRectInScreenCoords.left = ptClientBottomRight.x; 
                _hwndClientRectInScreenCoords.right = ptClientTopLeft.x; 
            }
 
            if(ptClientBottomRight.y >= ptClientTopLeft.y)
            {
                _hwndClientRectInScreenCoords.top = ptClientTopLeft.y;
                _hwndClientRectInScreenCoords.bottom = ptClientBottomRight.y; 
            }
            else 
            { 
                // RTL windows will cause the right edge to be on the left...
                // This doesn't affect top/bottom, but the code should be symmetrical. 
                _hwndClientRectInScreenCoords.top = ptClientBottomRight.y;
                _hwndClientRectInScreenCoords.bottom = ptClientTopLeft.y;
            }
 
            //
        } 
 
        ///
        /// Critical - accepts an unmanaged pointer to a structure 
        ///
        [SecurityCritical]
        private void OnWindowPosChanging(IntPtr lParam)
        { 
            _windowPosChanging = true;
 
            UpdateWindowPos(lParam); 
        }
 
        ///
        /// Critical - accepts an unmanaged pointer to a structure
        ///
        [SecurityCritical] 
        private void OnWindowPosChanged(IntPtr lParam)
        { 
            _windowPosChanging = false; 

            UpdateWindowPos(lParam); 
        }

        ///
        /// Critical - accepts an unmanaged pointer to a structure 
        ///
        [SecurityCritical] 
        private void UpdateWindowPos(IntPtr lParam) 
        {
            // 
            // We need to update the window settings used by the render thread when
            // 1) The size or position of the render target needs to change
            // 2) The render target needs to be enabled or disabled.
            // 
            // Further, we need to synchronize the render thread during sizing operations.
            // This is because some APIs that the render thread uses (such as 
            // UpdateLayeredWindow) have the unintended side-effect of also changing the 
            // window size.  We can't let the render thread and the UI thread fight
            // over setting the window size. 
            //
            // Generally, Windows sends our window to messages that bracket the size
            // operation:
            // 1) WM_WINDOWPOSCHANGING 
            //    Here we synchronize with the render thread, and ask the render thread
            //    to not render to this window for a while. 
            // 2) WM_WINDOWPOSCHANGED 
            //    This is after the window size has actually been changed, so we tell
            //    the render thread that it can render to the window again. 
            //
            // However, there are complications.  Sometimes Windows will send a
            // WM_WINDOWPOSCHANGING without sending a WM_WINDOWPOSCHANGED.  This happens
            // when the window size is not really going to change.  Also note that 
            // more than just size/position information is provided by these messages.
            // We'll get these messages when nothing but the z-order changes for instance. 
            // 

 
            //
            // The first order of business is to determine if the render target
            // size or position changed.  If so, we need to pass this information to
            // the render thread. 
            //
            NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS)); 
            bool isMove = (windowPos.flags & NativeMethods.SWP_NOMOVE) == 0; 
            bool isSize = (windowPos.flags & NativeMethods.SWP_NOSIZE) == 0;
            bool positionChanged = (isMove || isSize); 
            if (positionChanged)
            {
                //
                // We have found that sometimes we get told that the size or position 
                // of the window has changed, when it really hasn't.  So we double
                // check here.  This is critical because we won't be given a 
                // WM_WINDOWPOSCHANGED unless the size or position really had changed. 
                //
                if (!isMove) 
                {
                    // This is just to avoid any possible integer overflow problems.
                    windowPos.x = windowPos.y = 0;
                } 
                if (!isSize)
                { 
                    // This is just to avoid any possible integer overflow problems. 
                    windowPos.cx = windowPos.cy = 0;
                } 

                //
                // WINDOWPOS stores the window coordinates relative to its parent.
                // If the parent is NULL, then these are already screen coordinates. 
                // Otherwise, we need to convert to screen coordinates.
                // 
                NativeMethods.RECT windowRectInScreenCoords = new NativeMethods.RECT(windowPos.x, windowPos.y, windowPos.x + windowPos.cx, windowPos.y + windowPos.cy); 
                IntPtr hwndParent = UnsafeNativeMethods.GetParent(new HandleRef(null, windowPos.hwnd));
                if(hwndParent != IntPtr.Zero) 
                {
                    SafeSecurityHelper.TransformLocalRectToScreen(new HandleRef(null, hwndParent), ref windowRectInScreenCoords);
                }
 
                if (!isMove)
                { 
                    // We weren't actually moving, so the WINDOWPOS structure 
                    // did not contain valid (x,y) information.  Just use our
                    // old values. 
                    int width = (windowRectInScreenCoords.right - windowRectInScreenCoords.left);
                    int height = (windowRectInScreenCoords.bottom - windowRectInScreenCoords.top);
                    windowRectInScreenCoords.left = _hwndWindowRectInScreenCoords.left;
                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width; 
                    windowRectInScreenCoords.top = _hwndWindowRectInScreenCoords.top;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height; 
                } 

                if (!isSize) 
                {
                    // We weren't actually sizing, so the WINDOWPOS structure
                    // did not contain valid (cx,cy) information.  Just use our
                    // old values. 
                    int width = (_hwndWindowRectInScreenCoords.right - _hwndWindowRectInScreenCoords.left);
                    int height = (_hwndWindowRectInScreenCoords.bottom - _hwndWindowRectInScreenCoords.top); 
 
                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height; 
                }

                positionChanged = (   _hwndWindowRectInScreenCoords.left != windowRectInScreenCoords.left
                                   || _hwndWindowRectInScreenCoords.top != windowRectInScreenCoords.top 
                                   || _hwndWindowRectInScreenCoords.right != windowRectInScreenCoords.right
                                   || _hwndWindowRectInScreenCoords.bottom != windowRectInScreenCoords.bottom); 
            } 

 
            //
            // The second order of business is to determine whether or not the render
            // target should be enabled.  If we are disabling the render target, then
            // we need to synchronize with the render thread.  Basically, 
            // a WM_WINDOWPOSCHANGED always enables the render target it the window is
            // visible.  And a WM_WINDOWPOSCHANGING will disable the render target 
            // unless it is not really a size/move, in which case we will not be sent 
            // a WM_WINDOWPOSCHANGED, so we can't disable the render target.
            // 
            bool enableRenderTarget = SafeNativeMethods.IsWindowVisible(_hWnd.MakeHandleRef(this));
            if(enableRenderTarget)
            {
                if(_windowPosChanging && (positionChanged)) 
                {
                    enableRenderTarget = false; 
                } 
            }
 

            if (positionChanged || (enableRenderTarget != _isRenderTargetEnabled))
            {
                UpdateWindowSettings(enableRenderTarget); 
            }
        } 
 
        bool _windowPosChanging;
 
        private void OnShowWindow(bool enableRenderTarget)
        {
            if (enableRenderTarget != _isRenderTargetEnabled)
            { 
                UpdateWindowSettings(enableRenderTarget);
            } 
        } 

        private void OnExitSizeMove() 
        {
            if (_windowPosChanging)
            {
                _windowPosChanging = false; 
                UpdateWindowSettings(true);
            } 
        } 

        private void UpdateWindowSettings() 
        {
            UpdateWindowSettings(_isRenderTargetEnabled, null);
        }
 
        private void UpdateWindowSettings(bool enableRenderTarget)
        { 
            UpdateWindowSettings(enableRenderTarget, null); 
        }
 
        ///
        /// Critical - calls critical methods (UpdateWindowSettings)
        /// TreatAsSafe - just updates composition information for this window,
        ///               does not accept arbitrary input. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void UpdateWindowSettings(bool enableRenderTarget, DUCE.ChannelSet? channelSet) 
        {
            MediaContext mctx = MediaContext.From(Dispatcher); 
            if (_isRenderTargetEnabled != enableRenderTarget)
            {
                _isRenderTargetEnabled = enableRenderTarget;
 
                // Basic idea: the render thread and the UI thread have a
                // race condition when the UI thread wants to modify 
                // HWND data and the render thread is using it.  The render 
                // thread can paint garbage on the screen, and it can also
                // cause the old data to be set again (ULW issue, hence ULWEx). 
                //
                // So we tell the render thread to stop rendering and then we
                // wait for them to stop when disabling the render target by
                // issuing the UpdateWindowSettings command synchronously on 
                // an out-of-band channel.
            } 
 

            // if we are disconnected we are done. 
            if (!_compositionTarget.IsOnAnyChannel)
            {
                return;
            } 

            // 
            // Calculate the client rectangle in screen coordinates. 
            //
 
            GetWindowRectsInScreenCoordinates();

            Int32 style = UnsafeNativeMethods.GetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_STYLE);
            Int32 exStyle = UnsafeNativeMethods.GetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE); 

            bool isLayered = (exStyle & NativeMethods.WS_EX_LAYERED) != 0; 
 
            bool isChild = (style & NativeMethods.WS_CHILD) != 0;
            bool isRTL = (exStyle & NativeMethods.WS_EX_LAYOUTRTL) != 0; 

            int width = _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left;
            int height = _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top;
 
            MILTransparencyFlags flags = MILTransparencyFlags.Opaque;
            // if (!DoubleUtil.AreClose(_opacity, 1.0)) 
            // { 
            //     flags |= MILTransparencyFlags.ConstantAlpha;
            // } 

            // if (_colorKey.HasValue)
            // {
            //     flags |= MILTransparencyFlags.ColorKey; 
            // }
 
            if (_usesPerPixelOpacity) 
            {
                flags |= MILTransparencyFlags.PerPixelAlpha; 
            }

            if (!isLayered && flags != MILTransparencyFlags.Opaque)
            { 
                // The window is not layered, but it should be -- set the layered flag.
                UnsafeNativeMethods.SetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE, new IntPtr(exStyle | NativeMethods.WS_EX_LAYERED)); 
            } 
            else if (isLayered && flags == MILTransparencyFlags.Opaque)
            { 
                // The window is layered but should not be -- unset the layered flag.
                UnsafeNativeMethods.SetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE, new IntPtr(exStyle & ~NativeMethods.WS_EX_LAYERED));
            }
            else if(isLayered && flags != MILTransparencyFlags.Opaque && _isRenderTargetEnabled && (width == 0 || height == 0)) 
            {
                // The window is already layered, and it should be.  But we are enabling a window 
                // that is has a 0-size dimension.  This may cause us to leave the last sprite 
                // on the screen.  The best way to get rid of this is to just make the entire
                // sprite transparent. 

                NativeMethods.BLENDFUNCTION blend = new NativeMethods.BLENDFUNCTION();
                blend.BlendOp = NativeMethods.AC_SRC_OVER;
                blend.SourceConstantAlpha = 0; // transparent 
                UnsafeNativeMethods.UpdateLayeredWindow(_hWnd.h, IntPtr.Zero, null, null, IntPtr.Zero, null, 0, ref blend, NativeMethods.ULW_ALPHA);
            } 
            isLayered = (flags != MILTransparencyFlags.Opaque); 

            // Every UpdateWindowSettings command that disables the render target is 
            // assigned a new cookie.  Every UpdateWindowSettings command that enables
            // the render target uses the most recent cookie.  This allows the
            // compositor to ignore UpdateWindowSettings(enable) commands that come
            // out of order due to us disabling out-of-band and enabling in-band. 
            if (!_isRenderTargetEnabled)
            { 
                _disableCookie++; 
            }
 
            if (channelSet == null)
            {
                channelSet = mctx.GetChannels();
            } 

 
            // 
            // When enabling the render target, stay in-band.  This allows any
            // client-side rendering instructions to be included in the same packet. 
            // Otherwise pass in the OutOfBand handle.
            //
            DUCE.Channel channel = channelSet.Value.Channel;
            DUCE.Channel outOfBandChannel = channelSet.Value.OutOfBandChannel; 
            DUCE.CompositionTarget.UpdateWindowSettings(
                _isRenderTargetEnabled ? _compositionTarget.GetHandle(channel) : _compositionTarget.GetHandle(outOfBandChannel), 
                _hwndClientRectInScreenCoords, 
                Colors.Transparent, // _colorKey.GetValueOrDefault(Colors.Black),
                1.0f, // (float)_opacity, 
                isLayered ? (_usesPerPixelOpacity ? MILWindowLayerType.ApplicationManagedLayer : MILWindowLayerType.SystemManagedLayer) : MILWindowLayerType.NotLayered,
                flags,
                isChild,
                isRTL, 
                _isRenderTargetEnabled,
                _disableCookie, 
                _isRenderTargetEnabled ? channel : outOfBandChannel); 

            if (_isRenderTargetEnabled) 
            {
                //
                // Re-render the visual tree.
                // 

                mctx.PostRender(); 
            } 
            else
            { 
                // If we disabled the render target, we run the risk of leaving it disabled.
                // One such example is when a window is programatically sized, but then
                // GetMinMaxInfo denies the change.  We do not receive any message that would
                // allow us to re-enable the render targer.  To cover these odd cases, we 
                // post ourselves a message to possible re-enable the render target when
                // we are done with the current message processing. 
                UnsafeNativeMethods.PostMessage(new HandleRef(this, _hWnd), s_updateWindowSettings, IntPtr.Zero, IntPtr.Zero); 
            }
        } 

        /// 
        /// Gets and sets the root Visual of this HwndTarget.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Critical: This code accesses HWND which is critical and setting RootVisual 
        ///     is critical
        ///     PublicOK: This code blocks inheritance and public callers via Inheritance (in base class) and link demands
        /// 
        public override Visual RootVisual 
        {
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)] 
            set
            { 

                base.RootVisual = value;

                if (value != null) 
                {
                    // UIAutomation listens for the EventObjectUIFragmentCreate WinEvent to 
                    // understand when UI that natively implements UIAutomation comes up 
                    //
 


                    UnsafeNativeMethods.NotifyWinEvent(UnsafeNativeMethods.EventObjectUIFragmentCreate, _hWnd.MakeHandleRef(this), 0, 0);
                } 
            }
        } 
 
        /// 
        /// Returns matrix that can be used to transform coordinates from this 
        /// target to the rendering destination device.
        /// 
        public override Matrix TransformToDevice
        { 
            get
            { 
                VerifyAPIReadOnly(); 
                Matrix m = Matrix.Identity;
                m.Scale(_devicePixelsPerInchX / 96.0, _devicePixelsPerInchY / 96.0); 
                return m;
            }
        }
 
        /// 
        /// Returns matrix that can be used to transform coordinates from 
        /// the rendering destination device to this target. 
        /// 
        public override Matrix TransformFromDevice 
        {
            get
            {
                VerifyAPIReadOnly(); 
                Matrix m = Matrix.Identity;
                m.Scale(96.0 / _devicePixelsPerInchX, 96.0 / _devicePixelsPerInchY); 
                return m; 
            }
        } 

        /// 
        /// This is the color that is drawn before everything else.  If
        /// this color has an alpha component other than 1 it will be ignored. 
        /// 
        public Color BackgroundColor 
        { 
            get
            { 
                VerifyAPIReadOnly();

                return _backgroundColor;
            } 
            set
            { 
                VerifyAPIReadWrite(); 

                if (_backgroundColor != value) 
                {
                    _backgroundColor = value;
                    MediaContext mctx = MediaContext.From(Dispatcher);
 
                    DUCE.ChannelSet channelSet = mctx.GetChannels();
                    DUCE.Channel channel = channelSet.Channel; 
                    if (channel == null) 
                    {
                        // MediaContext is in disconnected state, so we will send 
                        // the clear color when CreateUCEResources gets called
                        Debug.Assert(!_compositionTarget.IsOnChannel(channel));
                    }
                    else 
                    {
                        DUCE.CompositionTarget.SetClearColor( 
                            _compositionTarget.GetHandle(channel), 
                            _backgroundColor,
                            channel); 
                        mctx.PostRender();
                    }
                }
            } 
        }
 
        // ///  
        // ///     Specifies the color to display as transparent.
        // ///  
        // /// 
        // ///     Use null to indicate that no color should be transparent.
        // /// 
        // public Nullable ColorKey 
        // {
        //     get 
        //     { 
        //         VerifyAPIReadOnly();
        // 
        //         return _colorKey;
        //     }
        //
        //     set 
        //     {
        //         VerifyAPIReadWrite(); 
        // 
        //         if(_colorKey != value)
        //         { 
        //             _colorKey = value;
        //
        //             UpdateWindowSettings();
        //         } 
        //     }
        // } 
 
        // /// 
        // ///     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 
        //     {
        //         VerifyAPIReadOnly(); 
        //
        //         return _opacity;
        //     }
        // 
        //     set
        //     { 
        //         VerifyAPIReadWrite(); 
        //
        //         if(value < 0.0) value = 0.0; 
        //         if(value > 1.0) value = 1.0;
        //
        //         if(!MS.Internal.DoubleUtil.AreClose(value, _opacity))
        //         { 
        //             _opacity = value;
        // 
        //             UpdateWindowSettings(); 
        //         }
        //     } 
        // }

        /// 
        ///     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 - accesses critical _hWnd, calls unmanaged code
        /// PublicOK - internal property, hwnd not exposed or modified, WTSRegisterSessionNotification
        ///            only results in the hwnd getting more messages that we use to enable/disable 
        ///            rendering
        ///  
        public bool UsesPerPixelOpacity 
        {
            get 
            {
                VerifyAPIReadOnly();

                return _usesPerPixelOpacity; 
            }
 
            [SecurityCritical, SecurityTreatAsSafe] 
            internal set
            { 
                VerifyAPIReadWrite();

                if(_usesPerPixelOpacity != value)
                { 
                    _usesPerPixelOpacity = value;
 
                    // Register/unregister for Fast User Switching messages only if necessary because 
                    // this pinvoke loads wtsapi32.dll
                    if (_usesPerPixelOpacity) 
                    {
                        UnsafeNativeMethods.WTSRegisterSessionNotification(_hWnd, NativeMethods.NOTIFY_FOR_THIS_SESSION);
                    }
                    else 
                    {
                        UnsafeNativeMethods.WTSUnRegisterSessionNotification(_hWnd); 
                    } 

                    UpdateWindowSettings(); 
                }
            }
        }
 
        /// 
        /// Tells a channel to send notifications to a particular target's window. 
        ///  
        /// 
        /// The channel from which we want notifications. 
        /// 
        /// 
        /// The target whose window will receive the notifications.
        ///  
        /// 
        /// Critical        - Calls a critical channel method. 
        /// TreatAsSafe     - We are associated with the window handle that we 
        ///                   are passing to the channel, so somebody already
        ///                   decided that it's OK for us to interact with that 
        ///                   window. We also registered a window message so
        ///                   that we can avoid collisions with other messages.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static void SetChannelNotificationWindow(DUCE.Channel channel, HwndTarget target)
        { 
            channel.SetNotificationWindow(target._hWnd, s_channelNotifyMessage); 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//  File:       HwndTarget.cs 
//
//----------------------------------------------------------------------------- 
using System; 
using System.Diagnostics;
using System.Windows.Threading; 
using System.Threading;
using System.Windows;
using System.Collections.Generic;
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Automation.Provider; 
using System.Windows.Automation.Peers; 
using System.Windows.Media.Composition;
using System.Runtime.InteropServices; 
using System.Security.Permissions;
using System.Security;
using MS.Internal;
using MS.Internal.Automation; 
using MS.Win32;
using MS.Utility; 
using Microsoft.Internal; 
using MS.Internal.PresentationCore;                        // SecurityHelper
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

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

namespace System.Windows.Interop 
{ 
    // This is the internal, more expressive, enum used by the SetRenderingMode method.
    // See the RenderMode enum and the RenderMode property for the public version. 
    internal enum RenderingMode
    {
        Default = MILRTInitializationFlags.MIL_RT_INITIALIZE_DEFAULT,
        Software = MILRTInitializationFlags.MIL_RT_SOFTWARE_ONLY, 
        Hardware = MILRTInitializationFlags.MIL_RT_HARDWARE_ONLY,
        HardwareReference = MILRTInitializationFlags.MIL_RT_HARDWARE_ONLY | MILRTInitializationFlags.MIL_RT_USE_REF_RAST, 
    } 

    // This is the public, more limited, enum exposed for use with the RenderMode property. 
    // See the RenderingMode enum and SetRenderingMode method for the internal version.
    /// 
    ///     Render mode preference.
    ///  
    public enum RenderMode
    { 
        ///  
        /// The rendering layer should use the GPU and CPU as appropriate.
        ///  
        Default,

        /// 
        /// The rendering layer should only use the CPU. 
        /// 
        SoftwareOnly 
    } 

    ///  
    /// The HwndTarget class represents a binding to an HWND.
    /// 
    /// The HwndTarget is not thread-safe. Accessing the HwndTarget from a different
    /// thread than it was created will throw a . 
    public class HwndTarget : CompositionTarget
    { 
        ///  
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, HandleMessage).
        ///  
        [SecurityCritical]
        private static int s_dwmRedirectionEnvironmentChanged;

        ///  
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, SetChannelNotificationWindow).
        ///  
        [SecurityCritical] 
        private static int s_channelNotifyMessage;
 
        /// 
        /// Critical - Gets to the unmanaged layer under elevation (cctor, ctor, HandleMessage).
        /// 
        [SecurityCritical] 
        private static int s_transformHintUpdateMessage;
 
        ///  
        /// Critical - Gets to the unmanaged layer (ctor, HandleMessage, UpdateWindowSettings).
        ///  
        [SecurityCritical]
        private static int s_updateWindowSettings;

        private MatrixTransform _worldTransform; 
        private double _devicePixelsPerInchX;
        private double _devicePixelsPerInchY; 
 
        /// 
        /// Critical -  We don't want partial trust code changing the rendering preference. 
        /// 
        private SecurityCriticalDataForSet _renderModePreference = new SecurityCriticalDataForSet(RenderMode.Default);
 	
        /// 
        /// Critical - obtained under an elevation.
        /// 
        [SecurityCritical] 
        private NativeMethods.HWND _hWnd;
 
        private NativeMethods.RECT _hwndClientRectInScreenCoords;
        private NativeMethods.RECT _hwndWindowRectInScreenCoords;

        private Color _backgroundColor = Color.FromRgb(0, 0, 0); 

        private DUCE.MultiChannelResource _compositionTarget = 
            new DUCE.MultiChannelResource(); 

        private bool _isRenderTargetEnabled = true; 
        // private Nullable _colorKey = null;
        // private double _opacity = 1.0;
        private bool _usesPerPixelOpacity = false;
 
        // It is important that this start at zero to allow an initial
        // UpdateWindowSettings(enable) command to enable the render target 
        // without a preceeding UpdateWindowSettings(disable) command. 
        private int _disableCookie = 0;
 
        // Used to deal with layered window problems. See comments where they are used.
        private bool _isMinimized = false;
        private bool _isSessionDisconnected = false;
        private bool _isSuspended = false; 

        ///  
        /// Initializes static variables for this class. 
        /// 
        ///  
        /// Critical        - Sets the SecurityCritical static variables holding the message ids; calls RegisterWindowMessage.
        /// TreatAsSafe     - The message ids are not exposed; no external parameters are taken in.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        static HwndTarget()
        { 
            s_dwmRedirectionEnvironmentChanged = UnsafeNativeMethods.RegisterWindowMessage("DwmRedirectionEnvironmentChangedHint"); 
            s_channelNotifyMessage = UnsafeNativeMethods.RegisterWindowMessage("MilChannelNotify");
            s_transformHintUpdateMessage = UnsafeNativeMethods.RegisterWindowMessage("TransformHintUpdate"); 
            s_updateWindowSettings = UnsafeNativeMethods.RegisterWindowMessage("UpdateWindowSettings");
        }

        ///  
        /// Attaches a hwndTarget to the hWnd
        ///  
        ///     This API link demands for UIWindowPermission.AllWindows 
        /// 
        ///  
        /// The HWND to which the HwndTarget will draw.
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        ///  
        /// 
        /// Critical - accepts unmanaged pointer handle.Not safe to create since it 
        ///            can be used to draw to a window 
        /// PublicOk - demands UIPermission
        ///  
        [SecurityCritical]
        [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
        public HwndTarget(IntPtr hwnd)
        { 
            bool exceptionThrown = true;
 
            AttachToHwnd(hwnd); 

            try 
            {
                if (EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal))
                {
                    EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEDIACREATEVISUALGUID), MS.Utility.EventType.Info, 
                                                         Dispatcher.GetHashCode(), hwnd.ToInt64());
                } 
 
                _hWnd = NativeMethods.HWND.Cast(hwnd);
 
                // Get the client rectangle...
                GetWindowRectsInScreenCoordinates();

                // Set device independent resolution to 96 DPI. 
                // NativeMethods.HDC hdc = NativeMethods.GetDC(_hWnd);
 
                _devicePixelsPerInchX = 96.0f; 
                _devicePixelsPerInchY = 96.0f;
 
                //
                // Determine whether hWnd corresponds to MIL or GDI window.
                //
                IntPtr hdcW = UnsafeNativeMethods.GetDC( 
                    new HandleRef(this, _hWnd));
 
                if (hdcW == IntPtr.Zero) 
                {
                    // 
                    // If we were unable to obtain HDC for the given
                    // window, assume the default of 96 DPI.
                    //
 
                    _devicePixelsPerInchX = 96.0f;
                    _devicePixelsPerInchY = 96.0f; 
                } 
                else
                { 
                    //
                    // Obtain and cache DPI values for window's HDC.
                    //
 
                    _devicePixelsPerInchX = (double)UnsafeNativeMethods.GetDeviceCaps(
                        new HandleRef(this, hdcW), 
                        NativeMethods.LOGPIXELSX); 

                    _devicePixelsPerInchY = (double)UnsafeNativeMethods.GetDeviceCaps( 
                        new HandleRef(this, hdcW),
                        NativeMethods.LOGPIXELSY);

                    // 
                    // Release DC object.
                    // 
 
                    UnsafeNativeMethods.ReleaseDC(
                        new HandleRef(this, _hWnd), 
                        new HandleRef(this, hdcW));
                }

                _worldTransform = new MatrixTransform(new Matrix( 
                  _devicePixelsPerInchX * (1.0f / 96.0f), 0,
                  0, _devicePixelsPerInchY * (1.0f / 96.0f), 
                  0, 0)); 

                // 
                // Register CompositionTarget with MediaContext.
                //
                MediaContext.RegisterICompositionTarget(Dispatcher, this);
 

                // 
                // Change the window message filter to allow session and transform 
                // hint control messages to be sent from the DWM. On down-level
                // platforms, these calls will result in no-op. 
                //

                ChangeWindowMessageFilter((uint)s_dwmRedirectionEnvironmentChanged, 1 /* MSGFLT_ADD */);
                ChangeWindowMessageFilter((uint)s_transformHintUpdateMessage, 1 /* MSGFLT_ADD */); 

                // 
                // Hint window redirection layer that Avalon content has been attached 
                // to this window. As a result, redirection layer will create necessary
                // resources and manage clip and position for this window in TS and 
                // Accessibility scenarios. If DWM is not running, this call will result
                // in NoOp.
                //
                HRESULT.Check(MilContent_AttachToHwnd(_hWnd)); 

                exceptionThrown = false; 
            } 
            finally
            { 
                //
                // If exception has occurred after we attached this target to
                // the window, we need to detach from this window. Otherwise, window
                // will be left in a state when no other HwndTarget can be created 
                // for it.
                // 
                if(exceptionThrown) 
                {
                    #pragma warning suppress 6031 // Return value ignored on purpose. 
                    VisualTarget_DetachFromHwnd(hwnd);
                }
            }
        } 

        ///  
        /// AttachToHwnd 
        /// 
        /// 
        /// Critical as it calls a function that performs an elevation (IsWindow).
        ///
        [SecurityCritical]
        internal void AttachToHwnd(IntPtr hwnd) 
        {
            int processId = 0; 
            int threadId = UnsafeNativeMethods.GetWindowThreadProcessId( 
                new HandleRef(this, hwnd),
                out processId 
                );

            if (!UnsafeNativeMethods.IsWindow(new HandleRef(this, hwnd)))
            { 
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowHandle), 
                    "hwnd" 
                    );
            } 
            else if (processId != SafeNativeMethods.GetCurrentProcessId())
            {
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowProcess), 
                    "hwnd"
                    ); 
            } 
            else if (threadId != SafeNativeMethods.GetCurrentThreadId())
            { 
                throw new ArgumentException(
                    SR.Get(SRID.HwndTarget_InvalidWindowThread),
                    "hwnd"
                    ); 
            }
 
            int hr = VisualTarget_AttachToHwnd(hwnd); 

            if (HRESULT.Failed(hr)) 
            {
                if (hr == unchecked((int)0x80070005)) // E_ACCESSDENIED
                {
                    throw new InvalidOperationException( 
                        SR.Get(SRID.HwndTarget_WindowAlreadyHasContent)
                        ); 
                } 
                else
                { 
                    HRESULT.Check(hr);
                }
            }
        } 

        ///  
        ///     Critical: This code causes unmanaged code elevation 
        /// 
        [SecurityCritical,SuppressUnmanagedCodeSecurity] 
        [DllImport(DllImport.MilCore, EntryPoint = "MilVisualTarget_AttachToHwnd")]
        internal static extern int VisualTarget_AttachToHwnd(
            IntPtr hwnd
            ); 

 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore, EntryPoint = "MilVisualTarget_DetachFromHwnd")]
        internal static extern int VisualTarget_DetachFromHwnd(
            IntPtr hwnd 
            );
 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore)]
        internal static extern int MilContent_AttachToHwnd(
            IntPtr hwnd 
            );
 
        ///  
        ///     Critical: This code causes unmanaged code elevation
        ///  
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(DllImport.MilCore)]
        internal static extern int MilContent_DetachFromHwnd(
            IntPtr hwnd 
            );
 
        ///  
        /// Allow lower integrity applications to send specified window messages
        /// in case we are elevated. Failure is non-fatal and on down-level 
        /// platforms this call will result in a no-op.
        /// 
        /// 
        /// Critical -- Calls unsafe native methods GetModuleHandle and GetProcAddress. 
        ///             Manually elevates unmanaged code permissions to pinvoke through
        ///             a function pointer. 
        ///  
        [SecurityCritical]
        private void ChangeWindowMessageFilter(uint message, uint flag) 
        {
            // Find the address of ChangeWindowMessageFilter in user32.dll.
            IntPtr user32Module = UnsafeNativeMethods.GetModuleHandle("user32.dll");
 
            // Get the address of the function. If this fails it means the OS
            // doesn't support this function, in which case we don't 
            // need to do anything further. 
            IntPtr functionAddress = UnsafeNativeMethods.GetProcAddressNoThrow(
                    new HandleRef(null, user32Module), 
                    "ChangeWindowMessageFilter");

            if  (functionAddress != IntPtr.Zero)
            { 
                // Convert the function pointer into a callable delegate and then call it
                ChangeWindowMessageFilterNative function = Marshal.GetDelegateForFunctionPointer( 
                    functionAddress, 
                    typeof(ChangeWindowMessageFilterNative)) as ChangeWindowMessageFilterNative;
 
                // In order to call the function we need unmanaged code access,
                // because the function is native code.
                (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
                try 
                {
                    function(message, flag); 
                } 
                finally
                { 
                    SecurityPermission.RevertAssert();
                }
            }
        } 

        ///  
        /// Prototype for user32's ChangeWindowMessageFilter function, which we load dynamically on Longhorn. 
        /// 
        private delegate void ChangeWindowMessageFilterNative(uint message, uint flag); 

        internal void SetRenderingMode(RenderingMode mode)
        {
            // 
            // If ForceLocalTransport is set then the transport is connected to a client (magnifier) that cannot
            // handle our transport protocol version. Therefore we force software rendering so that the rendered 
            // content is available through NTUser redirection. If software is not allowed an exception is thrown. 
            //
            if (MediaSystem.ForcedLocalTransport) // present using bitblt if a local transport was forced 
            {
                if (mode == RenderingMode.Hardware ||
                    mode == RenderingMode.HardwareReference)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.HwndTarget_HardwareNotSupportDueToProtocolMismatch));
                } 
                else 
                {
                    Debug.Assert(mode == RenderingMode.Software || mode == RenderingMode.Default); 
                    // If the mode is default we can chose what works. When we have a mismatched transport protocol version
                    // we need to fallback to software rendering.
                    mode = RenderingMode.Software;
                } 
            }
 
            // Select the render target initialization flags based on the requested 
            // rendering mode.
 
            DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels();
            DUCE.Channel channel = channelSet.Channel;

            DUCE.CompositionTarget.SetRenderingMode( 
                _compositionTarget.GetHandle(channel),
                (MILRTInitializationFlags)mode, 
                channel); 
        }
 
        /// 
        /// Specifies the render mode preference for the window.
        /// 
        ///  
        ///     This property specifies a preference, it does not necessarily change the actual
        ///     rendering mode.  Among other things, this can be trumped by the registry settings. 
        ///      
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to set this property.
        ///  
        /// 
        ///     Critical: This code influences the low-level rendering code by specifying whether the
        ///     rendering system should use the GPU or CPU.
        ///     PublicOK: We don't want to enable this in partial trust, so we have a link demand 
        ///     on the setter.  It is not privileged data, so the getter is not protected.
        ///  
        public RenderMode RenderMode 
        {
            get 
            {
                return _renderModePreference.Value;
            }
 
            // Note: We think it is safe to expose this in partial trust, but doing so would suggest
            // we should also expose HwndSource (the only way to get to the HwndTarget instance). 
            // We don't want to bite off that much exposure at this point in the product, so we enforce 
            // that this is not accessible from partial trust for now.
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
            set
            {
                if (value != RenderMode.Default && value != RenderMode.SoftwareOnly) 
                {
                    throw new System.ComponentModel.InvalidEnumArgumentException("value", (int)value, typeof(RenderMode)); 
                } 

                _renderModePreference.Value = value; 

                SetRenderingMode(value == RenderMode.SoftwareOnly ? RenderingMode.Software : RenderingMode.Default);
            }
        } 

        ///  
        /// Dispose cleans up the state associated with HwndTarget. 
        /// 
        ///  
        /// Critical - accesses the _hwnd that is critical, calls unmanaged code
        /// PublicOK - dispose is in effect stoping the contents of the target from
        /// rendering. Equivalent to removing all elements in window, considered safe.
        ///  
        [SecurityCritical]
        public override void Dispose() 
        { 
           // Its outside the try finally block because we want the exception to be
           // thrown if we are on a different thread and we don't want to call Dispose 
           // on base class in that case.
           VerifyAccess();

           try 
           {
                // According to spec: Dispose should not raise exception if called multiple times. 
                // This test is needed because the HwndTarget is Disposed from both the media contex and 
                // the hwndsrc.
                if (!IsDisposed) 
                {
                    RootVisual = null;

                    HRESULT.Check(VisualTarget_DetachFromHwnd(_hWnd)); 

                    // 
                    // Unregister this CompositionTarget from the MediaSystem. 
                    //
                    MediaContext.UnregisterICompositionTarget(Dispatcher, this); 

                    //
                    // Hint window redirection layer that Avalon content has been detached
                    // from this window. Redirection layer will then have a chance to clean 
                    // up the resources that it created for Avalon hosting. If DWM is not
                    // running, this call will result in NoOp. 
                    // 
                    HRESULT.Check(MilContent_DetachFromHwnd(_hWnd));
 
                    // Unregister for Fast User Switching messages if necessary
                    if (_usesPerPixelOpacity)
                    {
                        UnsafeNativeMethods.WTSUnRegisterSessionNotification(_hWnd); 
                    }
                } 
 
            }
            finally 
            {
                base.Dispose();
            }
        } 

        ///  
        /// This method is used to create all uce resources either on Startup or session connect 
        /// 
        ///  
        /// Critical - uses unmanaged pointer handle _hWnd
        /// TreatAsSafe - doesn't return or expose _hWnd
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void CreateUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel)
        { 
            // create visual target resources 
            // this forces the creation of the media context if we don't already have one.
 
            base.CreateUCEResources(channel, outOfBandChannel);

            Debug.Assert(!_compositionTarget.IsOnChannel(channel));
            Debug.Assert(!_compositionTarget.IsOnChannel(outOfBandChannel)); 

            // 
            // For each HwndTarget we are building some structures in the UCE. 
            // This includes spinning up a UCE render target. We need to commit the
            // batch for those changes right away, since we need to be able to process 
            // the invalidate packages that we send down on WM_PAINTs. If we don't commit
            // right away a WM_PAINT can get fired before we get a chance to commit
            // the batch.
            // 

            // 
            // First we create the composition target, composition context, and the composition root node. 
            // Note, that composition target will be created out of band because invalidate
            // command is also sent out of band and that can occur before current channel is committed. 
            // We would like to avoid commiting channel here to prevent visual artifacts.
            //

            bool resourceCreated = _compositionTarget.CreateOrAddRefOnChannel(outOfBandChannel, DUCE.ResourceType.TYPE_HWNDRENDERTARGET); 
            Debug.Assert(resourceCreated);
            _compositionTarget.DuplicateHandle(outOfBandChannel, channel); 
            outOfBandChannel.Commit(); 

            DUCE.CompositionTarget.HwndInitialize( 
                _compositionTarget.GetHandle(channel),
                _hWnd,
                _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left,
                _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top, 
                MediaSystem.ForcedLocalTransport, // present using bitblt if a local transport was forced
                channel 
                ); 

            DUCE.ResourceHandle hWorldTransform = ((DUCE.IResource)_worldTransform).AddRefOnChannel(channel); 

            DUCE.CompositionNode.SetTransform(
                _contentRoot.GetHandle(channel),
                hWorldTransform, 
                channel);
 
            DUCE.CompositionTarget.SetClearColor( 
                _compositionTarget.GetHandle(channel),
                _backgroundColor, 
                channel);

            //
            // Set initial state on the visual target. 
            //
 
            Rect clientRect = new Rect( 
                0,
                0, 
                (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left))),
                (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top))));

            StateChangedCallback( 
                new object[]
                { 
                    HostStateFlags.WorldTransform | 
                    HostStateFlags.ClipBounds,
                    _worldTransform.Matrix, 
                    clientRect
                });

            DUCE.CompositionTarget.SetRoot( 
                _compositionTarget.GetHandle(channel),
                _contentRoot.GetHandle(channel), 
                channel); 

            // reset the disable cookie when creating the slave resource. This happens when creating the 
            // managed resource and on handling a connect.
            _disableCookie = 0;

            // 
            // Finally, update window settings to reflect the state of this object.
            // Because CreateUCEResources is called for each channel, only call 
            // UpdateWindowSettings on that channel this time. 
            //
            DUCE.ChannelSet channelSet; 
            channelSet.Channel = channel;
            channelSet.OutOfBandChannel = outOfBandChannel;
            UpdateWindowSettings(_isRenderTargetEnabled, channelSet);
        } 

        ///  
        /// This method is used to release all uce resources either on Shutdown or session disconnect 
        /// 
        ///  
        /// Critical - uses unmanaged pointer handle _hWnd
        /// TreatAsSafe - doesn't return or expose _hWnd
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal override void ReleaseUCEResources(DUCE.Channel channel, DUCE.Channel outOfBandChannel)
        { 
            if (_compositionTarget.IsOnChannel(channel)) 
            {
                // 
                // GSchneid: If we need to flush the batch we need to render first all visual targets that
                // are still registered with the MediaContext to avoid strutural tearing.

 
                // Set the composition target root node to null.
                DUCE.CompositionTarget.SetRoot( 
                    _compositionTarget.GetHandle(channel), 
                    DUCE.ResourceHandle.Null,
                    channel); 

                _compositionTarget.ReleaseOnChannel(channel);
            }
 
            if (_compositionTarget.IsOnChannel(outOfBandChannel))
            { 
                _compositionTarget.ReleaseOnChannel(outOfBandChannel); 
            }
 
            DUCE.ResourceHandle hWorldTransform = ((DUCE.IResource)_worldTransform).GetHandle(channel);
            if (!hWorldTransform.IsNull)
            {
                // Release the world transform from this channel if it's currently on the channel. 
                ((DUCE.IResource)_worldTransform).ReleaseOnChannel(channel);
            } 
 
            // release all the visual target resources.
            base.ReleaseUCEResources(channel, outOfBandChannel); 
        }

        /// 
        /// The HwndTarget needs to see all windows messages so that 
        /// it can appropriately react to them.
        ///  
        ///  
        /// Critical - accepts unmanaged pointer handle, also
        /// Elevates permissions via unsafe native methods, handles messages to 
        /// retrieve automation provider the last one is most risky
        /// 
        [SecurityCritical]
        internal IntPtr HandleMessage(int msg, IntPtr wparam, IntPtr lparam) 
        {
            IntPtr handled = new IntPtr(0x1); // return 1 if the message is handled by this method exclusively. 
            IntPtr unhandled = IntPtr.Zero; // return 0 if other win procs should be called. 
            IntPtr result = unhandled;
 
            if (msg == s_dwmRedirectionEnvironmentChanged)
            {
                System.Windows.Media.MediaSystem.NotifyRedirectionEnvironmentChanged();
                return handled; 
            }
            else if (msg == s_channelNotifyMessage) 
            { 
                MediaContext.From(Dispatcher).NotifyChannelMessage();
            } 
            else if(msg == s_updateWindowSettings)
            {
                // Make sure we enable the render target if the window is visible.
                if(SafeNativeMethods.IsWindowVisible(_hWnd.MakeHandleRef(this))) 
                {
                    UpdateWindowSettings(true); 
                } 
            }
 
            if (IsDisposed)
            {
                return result;
            } 

            switch (msg) 
                { 
                case NativeMethods.WM_ERASEBKGND:
                    result = handled; // Indicates that this message is handled. 
                    break;

                case NativeMethods.WM_PAINT:
                    DoPaint(); 
                    result = handled;
                    break; 
 
                case NativeMethods.WM_SIZE:
                    // 
                    // NTRAID#Longhorn-1946030-2007/03/23-jordanpa:
                    //      When locked on downlevel, MIL stops rendering and invalidates the
                    //      window causing WM_PAINT. When the window is layered and minimized
                    //      before the lock, it'll never get the WM_PAINT on unlock and the MIL will 
                    //      never get out of the "don't render" state.
                    // 
                    //      To work around this, we will invalidate ourselves on restore and not 
                    //      render while minimized.
                    // 

                    // If the Window is in minimized state, don't do layout. otherwise, in some cases, it would
                    // pollute the measure data based on the Minized window size.
                    if (NativeMethods.IntPtrToInt32(wparam) != NativeMethods.SIZE_MINIMIZED) 
                    {
                        _isMinimized = false; 
                        DoPaint(); 

                        OnResize(); 
                    }
                    else
                    {
                        _isMinimized = true; 
                    }
 
                    break; 

                case NativeMethods.WM_SETTINGCHANGE: 
                    if (OnSettingChange(NativeMethods.IntPtrToInt32(wparam)))
                    {
                        UnsafeNativeMethods.InvalidateRect(_hWnd.MakeHandleRef(this), IntPtr.Zero , true);
                    } 
                    break;
 
                case NativeMethods.WM_GETOBJECT: 
                    result = CriticalHandleWMGetobject( wparam, lparam, RootVisual, _hWnd );
                    break; 

                case NativeMethods.WM_WINDOWPOSCHANGING:
                    OnWindowPosChanging(lparam);
                    break; 

                case NativeMethods.WM_WINDOWPOSCHANGED: 
                    OnWindowPosChanged(lparam); 
                    break;
 
                case NativeMethods.WM_SHOWWINDOW:
                    OnShowWindow(wparam != IntPtr.Zero);
                    break;
 
                case NativeMethods.WM_EXITSIZEMOVE:
                    OnExitSizeMove(); 
                    break; 

                case NativeMethods.WM_STYLECHANGING: 
                    unsafe
                    {
                        NativeMethods.STYLESTRUCT * styleStruct = (NativeMethods.STYLESTRUCT *) lparam;
 
                        if ((int)wparam == NativeMethods.GWL_EXSTYLE)
                        { 
                            if(UsesPerPixelOpacity) 
                            {
                                // We need layered composition to accomplish per-pixel opacity. 
                                //
                                styleStruct->styleNew |= NativeMethods.WS_EX_LAYERED;
                            }
                            else 
                            {
                                // No properties that require layered composition exist. 
                                // Make sure the layered bit is off. 
                                //
                                // Note: this prevents an external program from making 
                                // us system-layered (if we are a top-level window).
                                //
                                // If we are a child window, we still can't stop our
                                // parent from being made system-layered, and we will 
                                // end up leaving visual artifacts on the screen under
                                // WindowsXP. 
                                // 
                                styleStruct->styleNew &= (~NativeMethods.WS_EX_LAYERED);
                            } 
                        }
                    }

                    break; 

                case NativeMethods.WM_STYLECHANGED: 
                    unsafe 
                    {
                        bool updateWindowSettings = false; 

                        NativeMethods.STYLESTRUCT * styleStruct = (NativeMethods.STYLESTRUCT *) lparam;

                        if ((int)wparam == NativeMethods.GWL_STYLE) 
                        {
                            bool oldIsChild = (styleStruct->styleOld & NativeMethods.WS_CHILD) == NativeMethods.WS_CHILD; 
                            bool newIsChild = (styleStruct->styleNew & NativeMethods.WS_CHILD) == NativeMethods.WS_CHILD; 
                            updateWindowSettings = (oldIsChild != newIsChild);
                        } 
                        else
                        {
                            bool oldIsRTL = (styleStruct->styleOld & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL;
                            bool newIsRTL  = (styleStruct->styleNew & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL; 
                            updateWindowSettings = (oldIsRTL != newIsRTL);
                        } 
 
                        if(updateWindowSettings)
                        { 
                            UpdateWindowSettings();
                        }
                    }
 
                    break;
 
                // 
                // NTRAID#Longhorn-1967619-2007/03/23-jordanpa:
                //      When a Fast User Switch happens, MIL gets an invalid display error when trying to 
                //      render and they invalidate the window resulting in us getting a WM_PAINT. For
                //      layered windows, we get the WM_PAINT immediately which causes us to
                //      tell MIL to render and the cycle repeats. On Vista, this creates an infinite loop.
                //      Downlevel there isn't a loop, but the layered window will never update again. 
                //
                //      To work around this problem, we'll make sure not to tell MIL to render when 
                //      we're switched out and will render on coming back. 
                //
                case NativeMethods.WM_WTSSESSION_CHANGE: 
                    switch (NativeMethods.IntPtrToInt32(wparam))
                    {
                        // Session is disconnected. Due to:
                        // 1. Switched to a different user 
                        // 2. TS logoff
                        // 3. Screen locked 
                        case NativeMethods.WTS_CONSOLE_DISCONNECT: 
                        case NativeMethods.WTS_REMOTE_DISCONNECT:
                        case NativeMethods.WTS_SESSION_LOCK: 
                            _isSessionDisconnected = true;
                            break;

                        // Session is reconnected. See above 
                        case NativeMethods.WTS_CONSOLE_CONNECT:
                        case NativeMethods.WTS_REMOTE_CONNECT: 
                        case NativeMethods.WTS_SESSION_UNLOCK: 
                            _isSessionDisconnected = false;
                            DoPaint(); 

                            break;

                        default: 
                            break;
                    } 
 
                    break;
 
                //
                // NTRAID#Longhorn-1975236-2007/05/22-jordanpa:
                //      Downlevel, if we try to present a layered window while suspended the app will crash.
                //      This has been fixed in Vista but we still need to work around it for older versions 
                //      by not invalidating while suspended.
                // 
                case NativeMethods.WM_POWERBROADCAST: 
                    switch (NativeMethods.IntPtrToInt32(wparam))
                    { 
                        case NativeMethods.PBT_APMSUSPEND:
                            _isSuspended = true;
                            break;
 
                        case NativeMethods.PBT_APMRESUMESUSPEND:
                        case NativeMethods.PBT_APMRESUMECRITICAL: 
                        case NativeMethods.PBT_APMRESUMEAUTOMATIC: 
                            _isSuspended = false;
                            DoPaint(); 
                            break;

                        default:
                            break; 
                    }
                    break; 
 
                default:
                    break; 
            }

            return result;
        } 

        ///  
        /// Paints a rect 
        ///
        /// Note: This gets called a lot to help with layered window problems even when 
        ///         the window isn't layered, but that's okay because rcPaint will be empty.
        ///
        /// 
        ///  
        /// Critical - Elevates permissions via unsafe native methods, calls into begin paint
        ///  
        [SecurityCritical] 
        private void DoPaint()
        { 
            NativeMethods.PAINTSTRUCT ps = new NativeMethods.PAINTSTRUCT();
            NativeMethods.HDC hdc;

            HandleRef handleRef = new HandleRef(this, _hWnd); 
            hdc.h = UnsafeNativeMethods.BeginPaint(handleRef, ref ps);
            int retval = UnsafeNativeMethods.GetWindowLong(handleRef, NativeMethods.GWL_EXSTYLE); 
 
            NativeMethods.RECT rcPaint = new NativeMethods.RECT(ps.rcPaint_left, ps.rcPaint_top, ps.rcPaint_right, ps.rcPaint_bottom);
 
            //
            // If we get a BeginPaint with an empty rect then check
            // if this is a special layered, non-redirected window
            // which would mean we need to do a full paint when it 
            // won't cause a problem.
            // 
            if (rcPaint.IsEmpty 
                && ((retval & NativeMethods.WS_EX_LAYERED) != 0)
                && !UnsafeNativeMethods.GetLayeredWindowAttributes(_hWnd.MakeHandleRef(this), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) 
                && !_isSessionDisconnected
                && !_isMinimized
                && !_isSuspended)
            { 
                rcPaint = new NativeMethods.RECT(
                          0, 
                          0, 
                          _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left,
                          _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top); 
            }

            AdjustForRightToLeft(ref rcPaint, handleRef);
 
            if (!rcPaint.IsEmpty)
            { 
                InvalidateRect(rcPaint); 
            }
 
            UnsafeNativeMethods.EndPaint(_hWnd.MakeHandleRef(this), ref ps);
        }

        ///  
        /// Critical - 1) This method exposes the automation object which can be used to
        /// query the system for critical information or spoof input. 
        /// 2) it Asserts to call ReturnRawElementProvider 
        /// 
        [SecurityCritical] 
        private static IntPtr CriticalHandleWMGetobject(IntPtr wparam, IntPtr lparam, Visual root, IntPtr handle)
        {
            try
            { 
                if (root == null)
                { 
                    // Valid case, but need to handle separately. For now, return 0 to avoid exceptions 
                    // in referencing this later on. Real solution is more complex, see WindowsClient#873800.
                    return IntPtr.Zero; 
                }

                AutomationPeer peer = null;
 
                if (root.CheckFlagsAnd(VisualFlags.IsUIElement))
                { 
                    UIElement uiroot = (UIElement)root; 

                    peer = UIElementAutomationPeer.CreatePeerForElement(uiroot); 

                    //there si no specific peer for this UIElement, create a generic root
                    if(peer == null)
                        peer = uiroot.CreateGenericRootAutomationPeer(); 

                    if(peer != null) 
                        peer.Hwnd = handle; 
                }
 
                // This can happen if the root visual is not UIElement. In this case,
                // attempt to find one in the visual tree.
                if (peer == null)
                { 
                    peer = UIElementAutomationPeer.GetRootAutomationPeer(root, handle);
                } 
 
                if (peer == null)
                { 
                    return IntPtr.Zero;
                }

                // get the element proxy 
                // it's ok to pass the same peer as reference connected peer here because
                // it's guaranteed to be a connected one (it's initialized as root already) 
                IRawElementProviderSimple el = ElementProxy.StaticWrap(peer, peer); 

                peer.AddToAutomationEventList(); 

                // The assert here is considered OK
                // as we're assuming the WM_GETOBJECT is coming only from a PostMessage of an Hwnd.
                // to do the post message - you needed to have Unmanaged code permission 
                //
 
                PermissionSet unpackPermissionSet = new PermissionSet(PermissionState.None); 
                // below permissions needed to unpack an object.
                unpackPermissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter | SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.RemotingConfiguration)); 
                unpackPermissionSet.AddPermission(new System.Net.DnsPermission(PermissionState.Unrestricted));
                unpackPermissionSet.AddPermission(new System.Net.SocketPermission(PermissionState.Unrestricted));

                unpackPermissionSet.Assert(); 
                try
                { 
                    return AutomationInteropProvider.ReturnRawElementProvider(handle, wparam, lparam, el); 
                }
                finally 
                {
                    CodeAccessPermission.RevertAll();
                }
            } 
#pragma warning disable 56500
            catch (Exception e) 
            { 
                if(CriticalExceptions.IsCriticalException(e))
                { 
                    throw;
                }

                return new IntPtr(Marshal.GetHRForException(e)); 
            }
#pragma warning restore 56500 
        } 

        ///  
        ///     Adjusts a RECT to compensate for Win32 RTL conversion logic
        /// 
        /// 
        ///     When a window is marked with the WS_EX_LAYOUTRTL style, Win32 
        ///     mirrors the coordinates during the various translation APIs.
        /// 
        ///     Avalon also sets up mirroring transforms so that we properly 
        ///     mirror the output since we render to DirectX, not a GDI DC.
        /// 
        ///     Unfortunately, this means that our coordinates are already mirrored
        ///     by Win32, and Avalon mirrors them again.  To solve this
        ///     problem, we un-mirror the coordinates from Win32 before painting
        ///     in Avalon. 
        /// 
        ///  
        ///     The RECT to be adjusted 
        /// 
        ///  
        /// 
        internal void AdjustForRightToLeft(ref NativeMethods.RECT rc, HandleRef handleRef)
        {
            int windowStyle = SafeNativeMethods.GetWindowStyle(handleRef, true); 

            if(( windowStyle & NativeMethods.WS_EX_LAYOUTRTL ) == NativeMethods.WS_EX_LAYOUTRTL) 
            { 
                NativeMethods.RECT rcClient = new NativeMethods.RECT();
                SafeNativeMethods.GetClientRect(handleRef, ref rcClient); 

                int width   = rc.right - rc.left;       // preserve width
                rc.right    = rcClient.right - rc.left; // set right of rect to be as far from right of window as left of rect was from left of window
                rc.left     = rc.right - width;         // restore width by adjusting left and preserving right 
            }
        } 
 
        /// 
        /// Force total re-rendering to handle system parameters change 
        /// (font smoothing settings, gamma correction, etc.)
        ///
        ///true if rerendering was forced
        ///  
        ///   Critical: This can be used to cause annoyance by causing re rendering
        ///  
        [SecurityCritical] 
        private bool OnSettingChange(Int32 firstParam)
        { 
            if ( (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHING ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGTYPE ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGCONTRAST ||
                 (int)firstParam == (int)NativeMethods.SPI_SETFONTSMOOTHINGORIENTATION || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYPIXELSTRUCTURE ||
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYGAMMA || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYCLEARTYPELEVEL || 
                 (int)firstParam == (int)NativeMethods.SPI_SETDISPLAYTEXTCONTRASTLEVEL
                ) 
            {
                HRESULT.Check(MILUpdateSystemParametersInfo.Update());
                return true;
            } 

            return false; 
        } 

        ///  
        /// Let the DWM know of this HWND as belonging to a MIL/WPF application.
        /// Force total re-rendering to handle system Desktop Window Manager change
        /// 
        ///  
        ///   Critical: This can be used to cause annoyance by trying to cause re rendering.
        ///  
        [SecurityCritical] 
        internal void OnDWMCompositionChanged(bool isDesktopCompositionEnabled)
        { 
            //
            // Hint window redirection layer that Avalon content has been attached
            // to this window. As a result, redirection layer will create necessary
            // resources and manage clip and position for this window in TS and 
            // Accessibility scenarios.
            // 
            // We're going to attempt to attach to DWM every time the desktop composition 
            // state changes to ensure that we properly handle DWM crashing/restarting/etc.
            // 
            HRESULT.Check(MilContent_AttachToHwnd(_hWnd));

            //
 

            HRESULT.Check(MILUpdateSystemParametersInfo.Update()); 
            UnsafeNativeMethods.InvalidateRect(_hWnd.MakeHandleRef(this), IntPtr.Zero , true); 
        }
 
        /// 
        /// This function should be called to paint the specified
        /// region of the window along with any other pending
        /// changes.  While this function is generally called 
        /// in response to a WM_PAINT it is up to the user to
        /// call BeginPaint and EndPaint or to otherwise validate 
        /// the bitmap region. 
        /// 
        /// The rectangle that is dirty. 
        private void InvalidateRect(NativeMethods.RECT rcDirty)
        {
            DUCE.ChannelSet channelSet = MediaContext.From(Dispatcher).GetChannels();
            DUCE.Channel channel = channelSet.Channel; 
            DUCE.Channel outOfBandChannel = channelSet.OutOfBandChannel;
 
            // handle InvalidateRect requests only if we have uce resources. 
            if (_compositionTarget.IsOnChannel(channel))
            { 
                //
                // Send a message with the invalid region to the compositor. We create a little batch to send this
                // out of order.
                // 
                DUCE.CompositionTarget.Invalidate(
                    _compositionTarget.GetHandle(outOfBandChannel), 
                    ref rcDirty, 
                    outOfBandChannel);
            } 
        }

        /// 
        /// Calling this function causes us to update state to reflect a 
        /// size change of the underlying HWND
        ///  
        /// 
        /// Critical - accesses a critical member (_hwnd)
        /// TreatAsSafe - uses the _hwnd to call a safeNativeMethods. Data is cached - but not considered critical. 
        ///
        [SecurityCritical, SecurityTreatAsSafe ]
        private void OnResize()
        { 
#if DEBUG
            MediaTrace.HwndTarget.Trace("OnResize"); 
#endif 

            // handle OnResize requests only if we have uce resources. 
            if (_compositionTarget.IsOnAnyChannel)
            {
                MediaContext mctx = MediaContext.From(Dispatcher);
 
                //
                // Let the render target know that window size has changed. 
                // 

                UpdateWindowSettings(); 

                //
                // Push client size chnage to the visual target.
                // 
                Rect clientRect = new Rect(
                    0, 
                    0, 
                    (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left))),
                    (float)(Math.Ceiling((double)(_hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top)))); 

                StateChangedCallback(
                    new object[] { HostStateFlags.ClipBounds, null, clientRect });
 
                mctx.Resize(this);
 
                // To ensure that the client area and the non-client area resize 
                // together, we need to wait, on resize, for the composition
                // engine to present the resized frame. The call to CompleteRender 
                // blocks until that happens.

                mctx.CompleteRender();
            } 
        }
 
 
        /// 
        /// Calculates the client and window rectangle in screen coordinates. 
        /// 
        ///
        /// Critical - calls critical methods (ClientToScreen)
        /// TreatAsSafe - no information returned, coordinates stored in member field. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void GetWindowRectsInScreenCoordinates() 
        {
            NativeMethods.RECT rcClient = new NativeMethods.RECT(); 

            //
            // Get the window and client rectangles
            // 

            SafeNativeMethods.GetWindowRect(_hWnd.MakeHandleRef(this), ref _hwndWindowRectInScreenCoords); 
            SafeNativeMethods.GetClientRect(_hWnd.MakeHandleRef(this), ref rcClient); 

 
            NativeMethods.POINT ptClientTopLeft = new NativeMethods.POINT(rcClient.left, rcClient.top);
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientTopLeft);

            NativeMethods.POINT ptClientBottomRight = new NativeMethods.POINT(rcClient.right, rcClient.bottom); 
            UnsafeNativeMethods.ClientToScreen(_hWnd.MakeHandleRef(this), ptClientBottomRight);
 
            if(ptClientBottomRight.x >= ptClientTopLeft.x) 
            {
                _hwndClientRectInScreenCoords.left = ptClientTopLeft.x; 
                _hwndClientRectInScreenCoords.right = ptClientBottomRight.x;
            }
            else
            { 
                // RTL windows will cause the right edge to be on the left...
                _hwndClientRectInScreenCoords.left = ptClientBottomRight.x; 
                _hwndClientRectInScreenCoords.right = ptClientTopLeft.x; 
            }
 
            if(ptClientBottomRight.y >= ptClientTopLeft.y)
            {
                _hwndClientRectInScreenCoords.top = ptClientTopLeft.y;
                _hwndClientRectInScreenCoords.bottom = ptClientBottomRight.y; 
            }
            else 
            { 
                // RTL windows will cause the right edge to be on the left...
                // This doesn't affect top/bottom, but the code should be symmetrical. 
                _hwndClientRectInScreenCoords.top = ptClientBottomRight.y;
                _hwndClientRectInScreenCoords.bottom = ptClientTopLeft.y;
            }
 
            //
        } 
 
        ///
        /// Critical - accepts an unmanaged pointer to a structure 
        ///
        [SecurityCritical]
        private void OnWindowPosChanging(IntPtr lParam)
        { 
            _windowPosChanging = true;
 
            UpdateWindowPos(lParam); 
        }
 
        ///
        /// Critical - accepts an unmanaged pointer to a structure
        ///
        [SecurityCritical] 
        private void OnWindowPosChanged(IntPtr lParam)
        { 
            _windowPosChanging = false; 

            UpdateWindowPos(lParam); 
        }

        ///
        /// Critical - accepts an unmanaged pointer to a structure 
        ///
        [SecurityCritical] 
        private void UpdateWindowPos(IntPtr lParam) 
        {
            // 
            // We need to update the window settings used by the render thread when
            // 1) The size or position of the render target needs to change
            // 2) The render target needs to be enabled or disabled.
            // 
            // Further, we need to synchronize the render thread during sizing operations.
            // This is because some APIs that the render thread uses (such as 
            // UpdateLayeredWindow) have the unintended side-effect of also changing the 
            // window size.  We can't let the render thread and the UI thread fight
            // over setting the window size. 
            //
            // Generally, Windows sends our window to messages that bracket the size
            // operation:
            // 1) WM_WINDOWPOSCHANGING 
            //    Here we synchronize with the render thread, and ask the render thread
            //    to not render to this window for a while. 
            // 2) WM_WINDOWPOSCHANGED 
            //    This is after the window size has actually been changed, so we tell
            //    the render thread that it can render to the window again. 
            //
            // However, there are complications.  Sometimes Windows will send a
            // WM_WINDOWPOSCHANGING without sending a WM_WINDOWPOSCHANGED.  This happens
            // when the window size is not really going to change.  Also note that 
            // more than just size/position information is provided by these messages.
            // We'll get these messages when nothing but the z-order changes for instance. 
            // 

 
            //
            // The first order of business is to determine if the render target
            // size or position changed.  If so, we need to pass this information to
            // the render thread. 
            //
            NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS)); 
            bool isMove = (windowPos.flags & NativeMethods.SWP_NOMOVE) == 0; 
            bool isSize = (windowPos.flags & NativeMethods.SWP_NOSIZE) == 0;
            bool positionChanged = (isMove || isSize); 
            if (positionChanged)
            {
                //
                // We have found that sometimes we get told that the size or position 
                // of the window has changed, when it really hasn't.  So we double
                // check here.  This is critical because we won't be given a 
                // WM_WINDOWPOSCHANGED unless the size or position really had changed. 
                //
                if (!isMove) 
                {
                    // This is just to avoid any possible integer overflow problems.
                    windowPos.x = windowPos.y = 0;
                } 
                if (!isSize)
                { 
                    // This is just to avoid any possible integer overflow problems. 
                    windowPos.cx = windowPos.cy = 0;
                } 

                //
                // WINDOWPOS stores the window coordinates relative to its parent.
                // If the parent is NULL, then these are already screen coordinates. 
                // Otherwise, we need to convert to screen coordinates.
                // 
                NativeMethods.RECT windowRectInScreenCoords = new NativeMethods.RECT(windowPos.x, windowPos.y, windowPos.x + windowPos.cx, windowPos.y + windowPos.cy); 
                IntPtr hwndParent = UnsafeNativeMethods.GetParent(new HandleRef(null, windowPos.hwnd));
                if(hwndParent != IntPtr.Zero) 
                {
                    SafeSecurityHelper.TransformLocalRectToScreen(new HandleRef(null, hwndParent), ref windowRectInScreenCoords);
                }
 
                if (!isMove)
                { 
                    // We weren't actually moving, so the WINDOWPOS structure 
                    // did not contain valid (x,y) information.  Just use our
                    // old values. 
                    int width = (windowRectInScreenCoords.right - windowRectInScreenCoords.left);
                    int height = (windowRectInScreenCoords.bottom - windowRectInScreenCoords.top);
                    windowRectInScreenCoords.left = _hwndWindowRectInScreenCoords.left;
                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width; 
                    windowRectInScreenCoords.top = _hwndWindowRectInScreenCoords.top;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height; 
                } 

                if (!isSize) 
                {
                    // We weren't actually sizing, so the WINDOWPOS structure
                    // did not contain valid (cx,cy) information.  Just use our
                    // old values. 
                    int width = (_hwndWindowRectInScreenCoords.right - _hwndWindowRectInScreenCoords.left);
                    int height = (_hwndWindowRectInScreenCoords.bottom - _hwndWindowRectInScreenCoords.top); 
 
                    windowRectInScreenCoords.right = windowRectInScreenCoords.left + width;
                    windowRectInScreenCoords.bottom = windowRectInScreenCoords.top + height; 
                }

                positionChanged = (   _hwndWindowRectInScreenCoords.left != windowRectInScreenCoords.left
                                   || _hwndWindowRectInScreenCoords.top != windowRectInScreenCoords.top 
                                   || _hwndWindowRectInScreenCoords.right != windowRectInScreenCoords.right
                                   || _hwndWindowRectInScreenCoords.bottom != windowRectInScreenCoords.bottom); 
            } 

 
            //
            // The second order of business is to determine whether or not the render
            // target should be enabled.  If we are disabling the render target, then
            // we need to synchronize with the render thread.  Basically, 
            // a WM_WINDOWPOSCHANGED always enables the render target it the window is
            // visible.  And a WM_WINDOWPOSCHANGING will disable the render target 
            // unless it is not really a size/move, in which case we will not be sent 
            // a WM_WINDOWPOSCHANGED, so we can't disable the render target.
            // 
            bool enableRenderTarget = SafeNativeMethods.IsWindowVisible(_hWnd.MakeHandleRef(this));
            if(enableRenderTarget)
            {
                if(_windowPosChanging && (positionChanged)) 
                {
                    enableRenderTarget = false; 
                } 
            }
 

            if (positionChanged || (enableRenderTarget != _isRenderTargetEnabled))
            {
                UpdateWindowSettings(enableRenderTarget); 
            }
        } 
 
        bool _windowPosChanging;
 
        private void OnShowWindow(bool enableRenderTarget)
        {
            if (enableRenderTarget != _isRenderTargetEnabled)
            { 
                UpdateWindowSettings(enableRenderTarget);
            } 
        } 

        private void OnExitSizeMove() 
        {
            if (_windowPosChanging)
            {
                _windowPosChanging = false; 
                UpdateWindowSettings(true);
            } 
        } 

        private void UpdateWindowSettings() 
        {
            UpdateWindowSettings(_isRenderTargetEnabled, null);
        }
 
        private void UpdateWindowSettings(bool enableRenderTarget)
        { 
            UpdateWindowSettings(enableRenderTarget, null); 
        }
 
        ///
        /// Critical - calls critical methods (UpdateWindowSettings)
        /// TreatAsSafe - just updates composition information for this window,
        ///               does not accept arbitrary input. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        private void UpdateWindowSettings(bool enableRenderTarget, DUCE.ChannelSet? channelSet) 
        {
            MediaContext mctx = MediaContext.From(Dispatcher); 
            if (_isRenderTargetEnabled != enableRenderTarget)
            {
                _isRenderTargetEnabled = enableRenderTarget;
 
                // Basic idea: the render thread and the UI thread have a
                // race condition when the UI thread wants to modify 
                // HWND data and the render thread is using it.  The render 
                // thread can paint garbage on the screen, and it can also
                // cause the old data to be set again (ULW issue, hence ULWEx). 
                //
                // So we tell the render thread to stop rendering and then we
                // wait for them to stop when disabling the render target by
                // issuing the UpdateWindowSettings command synchronously on 
                // an out-of-band channel.
            } 
 

            // if we are disconnected we are done. 
            if (!_compositionTarget.IsOnAnyChannel)
            {
                return;
            } 

            // 
            // Calculate the client rectangle in screen coordinates. 
            //
 
            GetWindowRectsInScreenCoordinates();

            Int32 style = UnsafeNativeMethods.GetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_STYLE);
            Int32 exStyle = UnsafeNativeMethods.GetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE); 

            bool isLayered = (exStyle & NativeMethods.WS_EX_LAYERED) != 0; 
 
            bool isChild = (style & NativeMethods.WS_CHILD) != 0;
            bool isRTL = (exStyle & NativeMethods.WS_EX_LAYOUTRTL) != 0; 

            int width = _hwndClientRectInScreenCoords.right - _hwndClientRectInScreenCoords.left;
            int height = _hwndClientRectInScreenCoords.bottom - _hwndClientRectInScreenCoords.top;
 
            MILTransparencyFlags flags = MILTransparencyFlags.Opaque;
            // if (!DoubleUtil.AreClose(_opacity, 1.0)) 
            // { 
            //     flags |= MILTransparencyFlags.ConstantAlpha;
            // } 

            // if (_colorKey.HasValue)
            // {
            //     flags |= MILTransparencyFlags.ColorKey; 
            // }
 
            if (_usesPerPixelOpacity) 
            {
                flags |= MILTransparencyFlags.PerPixelAlpha; 
            }

            if (!isLayered && flags != MILTransparencyFlags.Opaque)
            { 
                // The window is not layered, but it should be -- set the layered flag.
                UnsafeNativeMethods.SetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE, new IntPtr(exStyle | NativeMethods.WS_EX_LAYERED)); 
            } 
            else if (isLayered && flags == MILTransparencyFlags.Opaque)
            { 
                // The window is layered but should not be -- unset the layered flag.
                UnsafeNativeMethods.SetWindowLong(_hWnd.MakeHandleRef(this), NativeMethods.GWL_EXSTYLE, new IntPtr(exStyle & ~NativeMethods.WS_EX_LAYERED));
            }
            else if(isLayered && flags != MILTransparencyFlags.Opaque && _isRenderTargetEnabled && (width == 0 || height == 0)) 
            {
                // The window is already layered, and it should be.  But we are enabling a window 
                // that is has a 0-size dimension.  This may cause us to leave the last sprite 
                // on the screen.  The best way to get rid of this is to just make the entire
                // sprite transparent. 

                NativeMethods.BLENDFUNCTION blend = new NativeMethods.BLENDFUNCTION();
                blend.BlendOp = NativeMethods.AC_SRC_OVER;
                blend.SourceConstantAlpha = 0; // transparent 
                UnsafeNativeMethods.UpdateLayeredWindow(_hWnd.h, IntPtr.Zero, null, null, IntPtr.Zero, null, 0, ref blend, NativeMethods.ULW_ALPHA);
            } 
            isLayered = (flags != MILTransparencyFlags.Opaque); 

            // Every UpdateWindowSettings command that disables the render target is 
            // assigned a new cookie.  Every UpdateWindowSettings command that enables
            // the render target uses the most recent cookie.  This allows the
            // compositor to ignore UpdateWindowSettings(enable) commands that come
            // out of order due to us disabling out-of-band and enabling in-band. 
            if (!_isRenderTargetEnabled)
            { 
                _disableCookie++; 
            }
 
            if (channelSet == null)
            {
                channelSet = mctx.GetChannels();
            } 

 
            // 
            // When enabling the render target, stay in-band.  This allows any
            // client-side rendering instructions to be included in the same packet. 
            // Otherwise pass in the OutOfBand handle.
            //
            DUCE.Channel channel = channelSet.Value.Channel;
            DUCE.Channel outOfBandChannel = channelSet.Value.OutOfBandChannel; 
            DUCE.CompositionTarget.UpdateWindowSettings(
                _isRenderTargetEnabled ? _compositionTarget.GetHandle(channel) : _compositionTarget.GetHandle(outOfBandChannel), 
                _hwndClientRectInScreenCoords, 
                Colors.Transparent, // _colorKey.GetValueOrDefault(Colors.Black),
                1.0f, // (float)_opacity, 
                isLayered ? (_usesPerPixelOpacity ? MILWindowLayerType.ApplicationManagedLayer : MILWindowLayerType.SystemManagedLayer) : MILWindowLayerType.NotLayered,
                flags,
                isChild,
                isRTL, 
                _isRenderTargetEnabled,
                _disableCookie, 
                _isRenderTargetEnabled ? channel : outOfBandChannel); 

            if (_isRenderTargetEnabled) 
            {
                //
                // Re-render the visual tree.
                // 

                mctx.PostRender(); 
            } 
            else
            { 
                // If we disabled the render target, we run the risk of leaving it disabled.
                // One such example is when a window is programatically sized, but then
                // GetMinMaxInfo denies the change.  We do not receive any message that would
                // allow us to re-enable the render targer.  To cover these odd cases, we 
                // post ourselves a message to possible re-enable the render target when
                // we are done with the current message processing. 
                UnsafeNativeMethods.PostMessage(new HandleRef(this, _hWnd), s_updateWindowSettings, IntPtr.Zero, IntPtr.Zero); 
            }
        } 

        /// 
        /// Gets and sets the root Visual of this HwndTarget.
        ///  
        /// 
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. 
        ///  
        /// 
        ///     Critical: This code accesses HWND which is critical and setting RootVisual 
        ///     is critical
        ///     PublicOK: This code blocks inheritance and public callers via Inheritance (in base class) and link demands
        /// 
        public override Visual RootVisual 
        {
            [SecurityCritical] 
            [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)] 
            set
            { 

                base.RootVisual = value;

                if (value != null) 
                {
                    // UIAutomation listens for the EventObjectUIFragmentCreate WinEvent to 
                    // understand when UI that natively implements UIAutomation comes up 
                    //
 


                    UnsafeNativeMethods.NotifyWinEvent(UnsafeNativeMethods.EventObjectUIFragmentCreate, _hWnd.MakeHandleRef(this), 0, 0);
                } 
            }
        } 
 
        /// 
        /// Returns matrix that can be used to transform coordinates from this 
        /// target to the rendering destination device.
        /// 
        public override Matrix TransformToDevice
        { 
            get
            { 
                VerifyAPIReadOnly(); 
                Matrix m = Matrix.Identity;
                m.Scale(_devicePixelsPerInchX / 96.0, _devicePixelsPerInchY / 96.0); 
                return m;
            }
        }
 
        /// 
        /// Returns matrix that can be used to transform coordinates from 
        /// the rendering destination device to this target. 
        /// 
        public override Matrix TransformFromDevice 
        {
            get
            {
                VerifyAPIReadOnly(); 
                Matrix m = Matrix.Identity;
                m.Scale(96.0 / _devicePixelsPerInchX, 96.0 / _devicePixelsPerInchY); 
                return m; 
            }
        } 

        /// 
        /// This is the color that is drawn before everything else.  If
        /// this color has an alpha component other than 1 it will be ignored. 
        /// 
        public Color BackgroundColor 
        { 
            get
            { 
                VerifyAPIReadOnly();

                return _backgroundColor;
            } 
            set
            { 
                VerifyAPIReadWrite(); 

                if (_backgroundColor != value) 
                {
                    _backgroundColor = value;
                    MediaContext mctx = MediaContext.From(Dispatcher);
 
                    DUCE.ChannelSet channelSet = mctx.GetChannels();
                    DUCE.Channel channel = channelSet.Channel; 
                    if (channel == null) 
                    {
                        // MediaContext is in disconnected state, so we will send 
                        // the clear color when CreateUCEResources gets called
                        Debug.Assert(!_compositionTarget.IsOnChannel(channel));
                    }
                    else 
                    {
                        DUCE.CompositionTarget.SetClearColor( 
                            _compositionTarget.GetHandle(channel), 
                            _backgroundColor,
                            channel); 
                        mctx.PostRender();
                    }
                }
            } 
        }
 
        // ///  
        // ///     Specifies the color to display as transparent.
        // ///  
        // /// 
        // ///     Use null to indicate that no color should be transparent.
        // /// 
        // public Nullable ColorKey 
        // {
        //     get 
        //     { 
        //         VerifyAPIReadOnly();
        // 
        //         return _colorKey;
        //     }
        //
        //     set 
        //     {
        //         VerifyAPIReadWrite(); 
        // 
        //         if(_colorKey != value)
        //         { 
        //             _colorKey = value;
        //
        //             UpdateWindowSettings();
        //         } 
        //     }
        // } 
 
        // /// 
        // ///     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 
        //     {
        //         VerifyAPIReadOnly(); 
        //
        //         return _opacity;
        //     }
        // 
        //     set
        //     { 
        //         VerifyAPIReadWrite(); 
        //
        //         if(value < 0.0) value = 0.0; 
        //         if(value > 1.0) value = 1.0;
        //
        //         if(!MS.Internal.DoubleUtil.AreClose(value, _opacity))
        //         { 
        //             _opacity = value;
        // 
        //             UpdateWindowSettings(); 
        //         }
        //     } 
        // }

        /// 
        ///     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 - accesses critical _hWnd, calls unmanaged code
        /// PublicOK - internal property, hwnd not exposed or modified, WTSRegisterSessionNotification
        ///            only results in the hwnd getting more messages that we use to enable/disable 
        ///            rendering
        ///  
        public bool UsesPerPixelOpacity 
        {
            get 
            {
                VerifyAPIReadOnly();

                return _usesPerPixelOpacity; 
            }
 
            [SecurityCritical, SecurityTreatAsSafe] 
            internal set
            { 
                VerifyAPIReadWrite();

                if(_usesPerPixelOpacity != value)
                { 
                    _usesPerPixelOpacity = value;
 
                    // Register/unregister for Fast User Switching messages only if necessary because 
                    // this pinvoke loads wtsapi32.dll
                    if (_usesPerPixelOpacity) 
                    {
                        UnsafeNativeMethods.WTSRegisterSessionNotification(_hWnd, NativeMethods.NOTIFY_FOR_THIS_SESSION);
                    }
                    else 
                    {
                        UnsafeNativeMethods.WTSUnRegisterSessionNotification(_hWnd); 
                    } 

                    UpdateWindowSettings(); 
                }
            }
        }
 
        /// 
        /// Tells a channel to send notifications to a particular target's window. 
        ///  
        /// 
        /// The channel from which we want notifications. 
        /// 
        /// 
        /// The target whose window will receive the notifications.
        ///  
        /// 
        /// Critical        - Calls a critical channel method. 
        /// TreatAsSafe     - We are associated with the window handle that we 
        ///                   are passing to the channel, so somebody already
        ///                   decided that it's OK for us to interact with that 
        ///                   window. We also registered a window message so
        ///                   that we can avoid collisions with other messages.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal static void SetChannelNotificationWindow(DUCE.Channel channel, HwndTarget target)
        { 
            channel.SetNotificationWindow(target._hWnd, s_channelNotifyMessage); 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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