Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / InterOp / HwndSource.cs / 4 / HwndSource.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2004 // // File: HwndSource.cs //----------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using System.Threading; using System.Windows.Threading; using System.Windows.Input; using System.Windows.Media; using System.Windows.Interop; using System.Runtime.InteropServices; using MS.Win32; using MS.Utility; using MS.Internal; using MS.Internal.PresentationCore; // SecurityHelper using Microsoft.Win32; using System.Diagnostics; using System.ComponentModel; using System; using System.Security; using System.Security.Permissions; using System.IO; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.Windows.Interop { ////// The HwndSource class presents content within a Win32 HWND. /// public class HwndSource : PresentationSource, IDisposable, IWin32Window, IKeyboardInputSink { ////// Critical: This code calls into RegisterWindowMesssage which is critical /// TreatAsSafe: This is safe to call as no external parameters are taken in /// [SecurityCritical,SecurityTreatAsSafe] static HwndSource() { _threadSlot = Thread.AllocateDataSlot(); _msgEnableCharMessages = UnsafeNativeMethods.RegisterWindowMessage("HwndSourceEnableCharMessages"); } ////// Constructs an instance of the HwndSource class that will always resize to its content size. /// /// /// The Win32 class styles for this window. /// /// /// The Win32 styles for this window. /// /// /// The extended Win32 styles for this window. /// /// /// The position of the left edge of this window. /// /// /// The position of the upper edge of this window. /// /// /// The name of this window. /// /// /// The Win32 window that should be the parent of this window. /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Added a demand - so that this API does not work in InternetZone. /// Critical: This accesses critical code Initialize /// PublicOK: This code has a demand which will ensure that it does /// not work in partial trust without the correct permissions /// [SecurityCritical] public HwndSource( int classStyle, int style, int exStyle, int x, int y, string name, IntPtr parent) { SecurityHelper.DemandUIWindowPermission(); HwndSourceParameters param = new HwndSourceParameters(name); param.WindowClassStyle = classStyle; param.WindowStyle = style; param.ExtendedWindowStyle = exStyle; param.SetPosition(x, y); param.ParentWindow = parent; Initialize(param); } ////// Constructs an instance of the HwndSource class. This version requires an /// explicit width and height be sepecified. /// /// /// The Win32 class styles for this window. /// /// /// The Win32 styles for this window. /// /// /// The extended Win32 styles for this window. /// /// /// The position of the left edge of this window. /// /// /// The position of the upper edge of this window. /// /// /// The width of this window. /// /// /// The height of this window. /// /// /// The name of this window. /// /// /// The Win32 window that should be the parent of this window. /// /// /// Indicates that HwndSource should include the non-client area /// of the hwnd when it calls the Layout Manager /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Added a demand - so that this API does not work in InternetZone. /// Critical: This acceses critical code Initialize /// PublicOK: This code has a demand which will ensure that it does /// not work in partial trust without the correct permissions /// [SecurityCritical] public HwndSource(int classStyle, int style, int exStyle, int x, int y, int width, int height, string name, IntPtr parent, bool adjustSizingForNonClientArea) { SecurityHelper.DemandUIWindowPermission(); HwndSourceParameters parameters = new HwndSourceParameters(name, width, height); parameters.WindowClassStyle = classStyle; parameters.WindowStyle = style; parameters.ExtendedWindowStyle = exStyle; parameters.SetPosition(x, y); parameters.ParentWindow = parent; parameters.AdjustSizingForNonClientArea = adjustSizingForNonClientArea; Initialize(parameters); } ////// Constructs an instance of the HwndSource class. This version requires an /// explicit width and height be sepecified. /// /// /// The Win32 class styles for this window. /// /// /// The Win32 styles for this window. /// /// /// The extended Win32 styles for this window. /// /// /// The position of the left edge of this window. /// /// /// The position of the upper edge of this window. /// /// /// The width of this window. /// /// /// The height of this window. /// /// /// The name of this window. /// /// /// The Win32 window that should be the parent of this window. /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Added a demand - so that this API does not work in InternetZone. /// Critical: This accesses critical code Initialize /// PublicOK: This code has a demand which will ensure that it does /// not work in partial trust without the correct permissions /// [SecurityCritical] public HwndSource( int classStyle, int style, int exStyle, int x, int y, int width, int height, string name, IntPtr parent) { SecurityHelper.DemandUIWindowPermission(); HwndSourceParameters parameters = new HwndSourceParameters(name, width, height); parameters.WindowClassStyle = classStyle; parameters.WindowStyle = style; parameters.ExtendedWindowStyle = exStyle; parameters.SetPosition(x, y); parameters.ParentWindow = parent; Initialize(parameters); } ////// HwndSource Ctor /// /// parameter block ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical: This acceses critical code Initialize /// [SecurityCritical] [UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)] public HwndSource(HwndSourceParameters parameters) { Initialize(parameters); } ////// HwndSource Ctor /// /// parameter block ////// Critical: This code access critical (HwndMouseInputProvider, HwndKeyboardInputProvider /// ,HwndStylusInputProvider and the various hooks)objects and creates the /// providers under elevation. /// [SecurityCritical] private void Initialize(HwndSourceParameters parameters) { _mouse = new SecurityCriticalDataClass(new HwndMouseInputProvider(this)); _keyboard = new SecurityCriticalDataClass (new HwndKeyboardInputProvider(this)); _layoutHook = new HwndWrapperHook(LayoutFilterMessage); _inputHook = new HwndWrapperHook(InputFilterMessage); _hwndTargetHook = new HwndWrapperHook(HwndTargetFilterMessage); _publicHook = new HwndWrapperHook(PublicHooksFilterMessage); // When processing WM_SIZE, LayoutFilterMessage must be invoked before // HwndTargetFilterMessage. This way layout will be updated before resizing // HwndTarget, resulting in single render per resize. This means that // layout hook should appear before HwndTarget hook in the wrapper hooks // list. If this is done the other way around, first HwndTarget resize will // force re-render, then layout will be updated according to the new size, // scheduling another render. HwndWrapperHook[] wrapperHooks = { _hwndTargetHook, _layoutHook, _inputHook, null }; if(null != parameters.HwndSourceHook) { _hooks = new ArrayList(8); _hooks.Insert(0, parameters.HwndSourceHook); wrapperHooks[3] = _publicHook; } // A window must be marked WS_EX_LAYERED if (and only if): // 1) it is not a child window // -- AND -- // 2) a color-key is specified // 3) or an opacity other than 1.0 is specified // 4) or per-pixel alpha is requested. if((parameters.WindowStyle & NativeMethods.WS_CHILD) == 0 && ( //parameters.ColorKey != null || //!MS.Internal.DoubleUtil.AreClose(parameters.Opacity, 1.0) || parameters.UsesPerPixelOpacity)) { parameters.ExtendedWindowStyle |= NativeMethods.WS_EX_LAYERED; } else { parameters.ExtendedWindowStyle &= (~NativeMethods.WS_EX_LAYERED); } _constructionParameters = parameters; _hwndWrapper = new HwndWrapper(parameters.WindowClassStyle, parameters.WindowStyle, parameters.ExtendedWindowStyle, parameters.PositionX, parameters.PositionY, parameters.Width, parameters.Height, parameters.WindowName, parameters.ParentWindow, wrapperHooks); _hwndTarget = new HwndTarget(_hwndWrapper.Handle); //_hwndTarget.ColorKey = parameters.ColorKey; //_hwndTarget.Opacity = parameters.Opacity; _hwndTarget.UsesPerPixelOpacity = parameters.UsesPerPixelOpacity; if(_hwndTarget.UsesPerPixelOpacity) { _hwndTarget.BackgroundColor = Colors.Transparent; // Prevent this window from being themed. UnsafeNativeMethods.CriticalSetWindowTheme(new HandleRef(this, _hwndWrapper.Handle), "", ""); } _constructionParameters = null; if (!parameters.HasAssignedSize) _sizeToContent = SizeToContent.WidthAndHeight; _adjustSizingForNonClientArea = parameters.AdjustSizingForNonClientArea; // Listen to the UIContext.Disposed event so we can clean up. // The HwndTarget cannot work without a MediaContext which // is disposed when the UIContext is disposed. So we need to // dispose the HwndTarget and also never use it again (to // paint or process input). The easiest way to do this is to just // dispose the HwndSource at the same time. _weakShutdownHandler = new WeakEventDispatcherShutdown(this, this.Dispatcher); // Listen to the HwndWrapper.Disposed event so we can clean up. // The HwndTarget cannot work without a live HWND, and since // the HwndSource represents an HWND, we make sure we dispose // ourselves if the HWND is destroyed out from underneath us. _hwndWrapper.Disposed += new EventHandler(OnHwndDisposed); _stylus = new SecurityCriticalDataClass (new HwndStylusInputProvider(this)); // WM_APPCOMMAND events are handled thru this. _appCommand = new SecurityCriticalDataClass (new HwndAppCommandInputProvider(this)); // Register the top level source with the ComponentDispatcher. if (0 == ((uint)parameters.WindowStyle & NativeMethods.WS_CHILD)) { // This code path only gets executed in the non browser hosted case // because in the browser hosted case the app window is child window _weakPreprocessMessageHandler = new WeakEventPreprocessMessage(this); } AddSource(); // Register dropable window. // The checking CallerHasPermissionWithAppDomainOptimization will call RegisterDropTarget // safely without the security exception in case of no unmanaged code permission. // So RegisterDropTarget will be called safely in case of having the unmanged code permission. // Otherwise, the security exception cause System.Printing to be instatiated which will // load system.drawing module. if (_hwndWrapper.Handle != IntPtr.Zero && SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode))) { // This call is safe since DragDrop.RegisterDropTarget is checking the unmanged // code permission. DragDrop.RegisterDropTarget(_hwndWrapper.Handle); _registeredDropTargetCount++; } } /// /// Disposes the object /// ////// This API is not available in Internet Zone. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ////// Adds a hook that gets called for every window message. /// /// /// The hook to add. /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical - uses a critical field. /// PublicOK - as there's a demand. /// [SecurityCritical ] public void AddHook(HwndSourceHook hook) { SecurityHelper.DemandUIWindowPermission(); CheckDisposed(true); if(_hooks == null) { _hooks = new ArrayList(8); _hwndWrapper.AddHook(_publicHook); } _hooks.Insert(0, hook); } ////// Removes a hook that was previously added. /// /// /// The hook to remove. /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical - accesses a crtical field - _publicHook /// PublicOK - performs a demand. /// [SecurityCritical ] public void RemoveHook(HwndSourceHook hook) { SecurityHelper.DemandUIWindowPermission(); //this.VerifyAccess(); if(_hooks != null) { _hooks.Remove(hook); if(_hooks.Count == 0) { _hooks = null; _hwndWrapper.RemoveHook(_publicHook); } } } ////// GetInputProvider - Given a InputDevice, returns corresponding Provider /// /// InputDevice for which we need InputProvider ///InputProvider, if known ////// This API is not available in Internet Zone. /// ////// Critical: This code accesses and returns critical data *providers* /// [SecurityCritical] internal override IInputProvider GetInputProvider(Type inputDevice) { if (inputDevice == typeof(MouseDevice)) return (_mouse != null ? _mouse.Value : null); if (inputDevice == typeof(KeyboardDevice)) return (_keyboard != null ? _keyboard.Value : null); if (inputDevice == typeof(StylusDevice)) return (_stylus != null ? _stylus.Value : null); return null; } ////// Announces when this source is disposed. /// public event EventHandler Disposed; ////// Announces when the SizeToContent property changes on this source. /// public event EventHandler SizeToContentChanged; ////// Whether or not the object is disposed. /// public override bool IsDisposed {get {return _isDisposed;}} ////// The Root Visual for this window. If it is a UIElement /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical: This code sets a rootvisual which is risky to do because /// it can destabilize assumptions made in popup code /// PublicOK: The getter is safe and the setter has a link demand to block unwarrented /// public use /// public override Visual RootVisual { [SecurityCritical] get { if (_isDisposed) return null; return (_rootVisual.Value); } [SecurityCritical] [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)] set { CheckDisposed(true); RootVisualInternal = value; } } ////// Critical: Acceses KeyboardInputProvider which is considered as critical data /// also it can be used to set root visual which is deemed as an unsafe operation /// private Visual RootVisualInternal { [SecurityCritical] set { if (_rootVisual.Value != value) { Visual oldRoot = _rootVisual.Value; if(value != null) { _rootVisual.Value = value; if(_rootVisual.Value is UIElement) { ((UIElement)(_rootVisual.Value)).LayoutUpdated += new EventHandler(OnLayoutUpdated); } if (_hwndTarget != null && _hwndTarget.IsDisposed == false) { _hwndTarget.RootVisual = _rootVisual.Value; } UIElement.PropagateResumeLayout(null, value); } else { _rootVisual.Value = null; if (_hwndTarget != null && !_hwndTarget.IsDisposed) { _hwndTarget.RootVisual = null; } } if(oldRoot != null) { if(oldRoot is UIElement) { ((UIElement)oldRoot).LayoutUpdated -= new EventHandler(OnLayoutUpdated); } UIElement.PropagateSuspendLayout(oldRoot); } RootChanged(oldRoot, _rootVisual.Value); if (IsLayoutActive() == true) { // Call the helper method SetLayoutSize to set Layout's size SetLayoutSize(); // Post the firing of ContentRendered as Input priority work item so that ContentRendered will be // fired after render query empties. this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(FireContentRendered), this); } else { // Even though layout won't run (the root visual is either null or not // a UIElement), the hit-test results will certainly have changed. InputManager.SafeCurrentNotifyHitTestInvalidated(); } // It is possible that someone would have closed the window in one of the // previous callouts - such as during RootChanged or during the layout // we syncronously invoke. In such cases, the state of this object would // have been torn down. We just need to protect against that. if(_keyboard != null) { _keyboard.Value.OnRootChanged(oldRoot, _rootVisual.Value); } } } } ////// Returns the HwndSource that corresponds to the specified window. /// /// The window. ///The source that corresponds to the specified window. ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical: This information is not ok to expose since this HwndSource /// is deemed critical to expose /// PublicOK: There is a demand on this method that prevents this /// from working in partial trust unless you have the right permissions. /// [SecurityCritical] public static HwndSource FromHwnd(IntPtr hwnd) { SecurityHelper.DemandUIWindowPermission(); return CriticalFromHwnd(hwnd); } ////// Critical: This code extracts the HwndSource for an HWND /// This function is only for internal consumption /// [SecurityCritical] internal static HwndSource CriticalFromHwnd(IntPtr hwnd) { if (hwnd == IntPtr.Zero) { throw new ArgumentException(SR.Get(SRID.NullHwnd)); } HwndSource hwndSource = null; foreach (PresentationSource source in PresentationSource.CriticalCurrentSources) { HwndSource test = source as HwndSource; if (test != null && test.CriticalHandle == hwnd) { // Don't hand out a disposed source. if (!test.IsDisposed) hwndSource = test; break; } } return hwndSource; } ////// The visual manager for the visuals being presented in the source. /// Type-specific version of the CompositionTarget property for this source. /// ////// Critical: Accesses hwndTarget and returns it /// PublicOk: Protected by a LinkDemand /// public new HwndTarget CompositionTarget { [SecurityCritical] [UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)] get { if (_isDisposed) return null; // Even though we created the HwndTarget, it can get disposed out from // underneath us. if (_hwndTarget!= null && _hwndTarget.IsDisposed == true) { return null; } return _hwndTarget; } } ////// Returns visual target for this source. /// ////// Critical: calls get_CompositionTarget() and returns its value. /// [SecurityCritical] protected override CompositionTarget GetCompositionTargetCore() { return CompositionTarget; } ////// Event invoked when the layout causes the HwndSource to resize automatically. /// public event AutoResizedEventHandler AutoResized; ////// Handler for LayoutUpdated event of a rootVisual. /// ////// Critical: This code causes resize of window and accesses HwndTarget /// [SecurityCritical] private void OnLayoutUpdated(object obj, EventArgs args) { UIElement root = _rootVisual.Value as UIElement; if(root != null) { Size newSize = root.RenderSize; if ( _previousSize == null || !DoubleUtil.AreClose(_previousSize.Value.Width, newSize.Width) || !DoubleUtil.AreClose(_previousSize.Value.Height, newSize.Height)) { // We should update _previousSize, even if the hwnd is not // sizing to content. This fixes the scenario where: // // 1) hwnd is sized to content to say a, b // 2) hwnd is resize to a bigger size // 3) hwnd is sized to content to a, b again _previousSize = newSize; // // Don't resize while the Window is in Minimized mode. // if (_sizeToContent != SizeToContent.Manual && !_isWindowInMinimizeState ) { Resize(newSize); } } } } ////// This is called when LayoutManager was updated and its size (the layout size of top element) changed. /// Ask LayoutManager.Size to see what the new value is. /// ////// Critical: This code causes resize of window and accesses HwndTarget /// TreatAsSafe: In RBW the resize values are clamped also one cannot construct or get to a HwndSource in partial trust /// [SecurityCritical, SecurityTreatAsSafe] private void Resize(Size newSize) { try { _myOwnUpdate = true; if (IsUsable) { // Gather the new client dimensions Point convertedPt = _hwndTarget.TransformToDevice.Transform(new Point(newSize.Width, newSize.Height)); int frameWidth = 0; int frameHeight = 0; // If we're here, and it is the Window case (_adjustSizingForNonClientArea == true) // we get the size which includes the outside size of the window. For browser case, // we don't support SizeToContent, so we don't take care of this condition. // For non-Window cases, we need to calculate the outside size of the window // // For windows with UsesPerPixelOpacity, we force the client to // fill the window, so we don't need to add in any frame space. // if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity) { // Gather current client and frame dimensions from the window NativeMethods.RECT oldClientRect = new NativeMethods.RECT(0, 0, 0, 0); SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref oldClientRect); NativeMethods.RECT oldFrameRect = new NativeMethods.RECT(0, 0, 0, 0); SafeNativeMethods.GetWindowRect(new HandleRef(this,_hwndWrapper.Handle), ref oldFrameRect); frameWidth = (oldFrameRect.right - oldFrameRect.left) - (oldClientRect.right - oldClientRect.left) ; frameHeight = (oldFrameRect.bottom - oldFrameRect.top) - (oldClientRect.bottom - oldClientRect.top); } // Add the difference between the client and frame dimensions (i.e. the window chrome) to the new client dimensions RoundDeviceSize(ref convertedPt); int newWidth = frameWidth + (int)convertedPt.X; int newHeight = frameHeight + (int)convertedPt.Y; // Set the new frame size bool set = UnsafeNativeMethods.SetWindowPos(new HandleRef(this,_hwndWrapper.Handle), new HandleRef(null,IntPtr.Zero), 0, 0, newWidth, newHeight, NativeMethods.SWP_NOMOVE | NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE); if (AutoResized != null) { AutoResized(this, new AutoResizedEventArgs(newSize)); } } } finally { _myOwnUpdate = false; } } // If the root element has Pixel snapping enabled, round the window size to the // nearest int. Otherwise round the size up to the next int. private void RoundDeviceSize(ref Point size) { UIElement root = _rootVisual.Value as UIElement; if (root != null && root.SnapsToDevicePixels) { size = new Point(DoubleUtil.DoubleToInt(size.X), DoubleUtil.DoubleToInt(size.Y)); } else { size = new Point(Math.Ceiling(size.X), Math.Ceiling(size.Y)); } } ////// Returns the hwnd handle to the window. /// ////// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API. /// ////// Critical:This is not safe to expose in internet zone, it returns a window handle /// PublicOK: There exists a demand on this code /// public IntPtr Handle { [SecurityCritical] get { SecurityHelper.DemandUIWindowPermission(); return CriticalHandle; } } ////// Critical:Internal helper to retrieve handle for security purposes only Please /// DO NOT USE THIS TO EXPOSE HANDLE TO OUTSIDE WORLD /// internal IntPtr CriticalHandle { [FriendAccessAllowed] [SecurityCritical] get { if (null != _hwndWrapper) return _hwndWrapper.Handle; return IntPtr.Zero; } } ////// Critical: returns the critical _hwndWrapper. /// internal HwndWrapper HwndWrapper { [SecurityCritical] get { return _hwndWrapper; } } // Return whether this presentation source has capture. ////// Critical: calls CriticalHandle /// TreatAsSafe: Returning whether a presentation source has capture is considered safe. /// internal bool HasCapture { [SecurityCritical, SecurityTreatAsSafe] get { IntPtr capture = SafeNativeMethods.GetCapture(); return ( capture == CriticalHandle ); } } ////// Critical - accesses _hwndWrapper. /// TreatAsSafe - checking for null is considered safe. /// internal bool IsHandleNull { [SecurityCritical, SecurityTreatAsSafe ] get { return _hwndWrapper.Handle == IntPtr.Zero ; } } ////// Returns the hwnd handle to the window. /// public HandleRef CreateHandleRef() { return new HandleRef(this,Handle); } ////// SizeToContent on HwndSource /// ////// The default value is SizeToContent.Manual /// public SizeToContent SizeToContent { get { CheckDisposed(true); return _sizeToContent; } set { CheckDisposed(true); if (IsValidSizeToContent(value) != true) { throw new InvalidEnumArgumentException("value", (int)value, typeof(SizeToContent)); } if (_sizeToContent == value) { return; } _sizeToContent = value; // we only raise SizeToContentChanged when user interaction caused the change; // if a developer goes directly to HwndSource and sets SizeToContent, we will // not notify the wrapping Window if (IsLayoutActive() == true) { // Call the helper method SetLayoutSize to set Layout's size SetLayoutSize(); } } } ////// Critical: This code elevates to access hwndtarget /// TreatAsSafe: ok to expose /// [SecurityCritical,SecurityTreatAsSafe] private bool IsLayoutActive() { if ((_rootVisual.Value is UIElement) && _hwndTarget!= null && _hwndTarget.IsDisposed == false) { return true; } return false; } ////// This is the helper method that sets Layout's size basing it on /// the current value of SizeToContent. /// ////// TreatAsSafe: This API could be public in terms of security. /// It does three calls to UnsafeNativeMethods all in a safe way /// Critical: Makes 3 calls to UnsafeNativeMethods /// [SecurityCritical, SecurityTreatAsSafe] private void SetLayoutSize() { Debug.Assert(_hwndTarget!= null, "HwndTarget is null"); Debug.Assert(_hwndTarget.IsDisposed == false, "HwndTarget is disposed"); UIElement rootUIElement = null; rootUIElement = _rootVisual.Value as UIElement; if (rootUIElement == null) return; // [....] - 11/01/2005 // InvalidateMeasure() call is necessary in the following scenario // // Window w = new Window(); // w.Measure(new Size(x,y)); // w.Width = x; // w.Height = y; // w.Show() // // In the above scenario, the Measure call from SetLayoutSize will be opt out // and window will not receive the MeasureOverride call. As such, the hwnd min/max // restrictions will not be applied since MeasureOverride did not happen after hwnd // creation. Thus, we call InvalidatMeasure() to ensure MeasureOverride call on // Window after hwnd creation. rootUIElement.InvalidateMeasure(); bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal); int ctxHashCode = 0; if (_sizeToContent == SizeToContent.WidthAndHeight) { //setup constraints for measure-to-content Size sz = new Size(double.PositiveInfinity, double.PositiveInfinity); if (etwEnabled) { ctxHashCode = this.Dispatcher.GetHashCode(); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } rootUIElement.Measure(sz); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } rootUIElement.Arrange(new Rect(new Point(), rootUIElement.DesiredSize)); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent); } } else { // GetSizeFromHwnd sets either the outside size or the client size of the hwnd based on // _adjustSizeingForNonClientArea flag in logical units. Size sizeFromHwndLogicalUnits = GetSizeFromHwnd(); Size sz = new Size( (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Width), (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : sizeFromHwndLogicalUnits.Height)); if (etwEnabled) { ctxHashCode = this.Dispatcher.GetHashCode(); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } rootUIElement.Measure(sz); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, sizeFromHwndLogicalUnits.Height); else if(_sizeToContent == SizeToContent.Height) sz = new Size(sizeFromHwndLogicalUnits.Width, rootUIElement.DesiredSize.Height); else sz = sizeFromHwndLogicalUnits; rootUIElement.Arrange(new Rect(new Point(), sz)); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent); } } rootUIElement.UpdateLayout(); } // ///// /// Specifies the color to display as transparent. // /// // ///// /// Use null to indicate that no color should be transparent. // /// // public NullableColorKey // { // get // { // CheckDisposed(true); // // HwndTarget hwndTarget = CompositionTarget; // checks for disposed // if(_hwndTarget != null) // { // return _hwndTarget.ColorKey; // } // else // { // return null; // } // } // // set // { // CheckDisposed(true); // // HwndTarget hwndTarget = CompositionTarget; // checks for disposed // if(_hwndTarget != null) // { // _hwndTarget.ColorKey = value; // } // } // } // /// // /// Specifies the constant opacity to apply to the window. // /// // ///// /// The valid values range from [0..1]. Values outside of this range are clamped. // /// // public double Opacity // { // get // { // CheckDisposed(true); // // HwndTarget hwndTarget = CompositionTarget; // checks for disposed // if(_hwndTarget != null) // { // return _hwndTarget.Opacity; // } // else // { // return 1.0; // } // } // // set // { // CheckDisposed(true); // // HwndTarget hwndTarget = CompositionTarget; // checks for disposed // if(_hwndTarget != null) // { // _hwndTarget.Opacity = value; // } // } // } ////// Specifies whether or not the per-pixel opacity of the window content /// is respected. /// ////// By enabling per-pixel opacity, the system will no longer draw the non-client area. /// ////// Critical: Because it accesses _hwndTarget /// PublicOK: We don't pass it out; it is just used to query UsesPerPixelOpacity /// public bool UsesPerPixelOpacity { [SecurityCritical] get { CheckDisposed(true); HwndTarget hwndTarget = CompositionTarget; // checks for disposed if(_hwndTarget != null) { return _hwndTarget.UsesPerPixelOpacity; } else { return false; } } /* Not allowing this to change at run-time yet. [SecurityCritical] set { CheckDisposed(true); HwndTarget hwndTarget = CompositionTarget; // checks for disposed if(_hwndTarget != null) { _hwndTarget.UsesPerPixelOpacity = value; } } */ } ////// Critical: Because it accesses _hwndTarget /// TreatAsSafe: We don't pass it out; it is just used to convert to logical units /// [SecurityCritical, SecurityTreatAsSafe] private Size GetSizeFromHwnd() { // Compute View's size and set NativeMethods.RECT rc = new NativeMethods.RECT(0, 0, 0, 0); if (_adjustSizingForNonClientArea == true) { // get correct size for avalon Window (standalone and browser case) GetSizeForWindowObject(ref rc); } else { SafeNativeMethods.GetClientRect(new HandleRef(this,_hwndWrapper.Handle), ref rc); } Point convertedPt = _hwndTarget.TransformFromDevice.Transform(new Point(rc.right - rc.left, rc.bottom - rc.top)); return new Size(convertedPt.X, convertedPt.Y); } ////// Critical: This code can be used to spoof input /// [SecurityCritical] private IntPtr HwndTargetFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { IntPtr result = IntPtr.Zero ; if (IsUsable) { HwndTarget hwndTarget = _hwndTarget; if (hwndTarget != null) { result = hwndTarget.HandleMessage(msg, wParam, lParam); if (result != IntPtr.Zero) { handled = true; } } } return result; } ////// Critical:These hooks can all be used for input spoofing /// [SecurityCritical] private IntPtr LayoutFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { IntPtr result = IntPtr.Zero ; // We have to revalidate everything because the Access() call // could have caused the CLR to enter a nested message pump, // during which almost anything could have happened that might // invalidate our checks. UIElement rootUIElement=null; rootUIElement = _rootVisual.Value as UIElement; if (IsUsable && rootUIElement != null) { switch (msg) { // A window receives this message when the user chooses a command from // the Window menu or when the user chooses the maximize button, minimize // button, restore button, or close button. case NativeMethods.WM_SYSCOMMAND: { // The four low-order bits of the wParam parameter are used // internally by the system. Int32 sysCommand = NativeMethods.IntPtrToInt32(wParam) & 0xFFF0; // Turn off SizeToContent if user chooses to maximize or resize. if ((sysCommand == NativeMethods.SC_MAXIMIZE) || (sysCommand == NativeMethods.SC_SIZE)) { DisableSizeToContent(rootUIElement, hwnd); } } break; // We get WM_SIZING. It means that user starts resizing the window. // It is the first notification sent when user resizes (before WM_WINDOWPOSCHANGING) // and it's not sent if window is resized programmatically. // SizeToContent is turned off after user resizes. case NativeMethods.WM_SIZING: DisableSizeToContent(rootUIElement, hwnd); break; // The WM_WINDOWPOSCHANGING message is sent // 1. when the size, position, or place in the Z order is about to change as a result of a call to // the SetWindowPos function or other window-management functions. SizeToContent orverrides all in this case. // 2. when user resizes window. If it's user resize, we have turned SizeToContent off when we get WM_SIZING. // It is sent before WM_SIZE. // We can't use WM_GETMINMAXINFO, because if there is no window size change (we still need to make sure // the client size not change), that notification wouldnt be sent. case NativeMethods.WM_WINDOWPOSCHANGING: Process_WM_WINDOWPOSCHANGING(rootUIElement, hwnd, msg, wParam, lParam); break; // WM_SIZE message is sent after the size has changed. // lParam has the new width and height of client area. // root element's size should be adjust based on the new width and height and SizeToContent's value. case NativeMethods.WM_SIZE: Process_WM_SIZE(rootUIElement, hwnd, msg, wParam, lParam); break; } } // Certain messages need to be processed while we are in the middle // of construction - and thus an HwndTarget is not available. if(!handled && (_constructionParameters != null || IsUsable)) { // Get the usesPerPixelOpacity from either the constructor parameters or the HwndTarget. bool usesPerPixelOpacity = _constructionParameters != null ? ((HwndSourceParameters)_constructionParameters).UsesPerPixelOpacity : _hwndTarget.UsesPerPixelOpacity; switch(msg) { case NativeMethods.WM_NCCALCSIZE: { // Windows that use per-pixel opacity don't get // their frames drawn by the system. Generally // this is OK, as users of per-pixel alpha tend // to be doing customized UI anyways. But we // don't render correctly if we leave a non-client // area, so here we expand the client area to // cover any non-client area. // if(usesPerPixelOpacity) { if(wParam == IntPtr.Zero) { // If wParam is FALSE, lParam points to a RECT // structure. On entry, the structure contains // the proposed window rectangle for the // window. On exit, the structure should // contain the screen coordinates of the // corresponding window client area. // // Since all we want to do is make the client // rect the same as the window rect, we don't // have to do anything. // result = IntPtr.Zero; handled = true; } else { // If wParam is TRUE, lParam points to an // NCCALCSIZE_PARAMS structure that contains // information an application can use to // calculate the new size and position of // the client rectangle. // // When Windows sends the WM_NCCALCSIZE // message, the NCCALCSIZE_PARAMS structure // is filled out like this: // // rgrc[0] = new window rectangle (in parent coordinates) // rgrc[1] = old window rectangle (in parent coordinates) // rgrc[2] = old client rectangle (in parent coordinates) // // Notice that the client rectangle is given // in parent coordinates, not in client // coordinates. // // When your window procedure returns, Windows // expects the NCCALCSIZE_PARAMS structure to // be filled out like this: // // rgrc[0] = new client rectangle (in parent coordinates) // // Furthermore, if you return anything other // than 0, Windows expects the remaining two // rectangles to be filled out like this: // // rgrc[1] = destination rectangle (in parent coordinates) // rgrc[2] = source rectangle (in parent coordinates) // // (If you return 0, then Windows assumes that // the destination rectangle equals the new // client rectangle and the source rectangle // equals the old client rectangle.) // // Since all we want to do is make the client // rect the same as the window rect, we don't // have to do anything. // result = IntPtr.Zero; handled = true; } } } break; } } return result; } ////// Critical: Because it uses _hwndTarget /// [SecurityCritical] private void Process_WM_WINDOWPOSCHANGING(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) { // Only if SizeToContent overrides Win32 sizing change calls. // If it's coming from OnResize (_myOwnUpdate != true), it means we are adjusting // to the right size; don't need to do anything here. if ((_myOwnUpdate != true) && (SizeToContent != SizeToContent.Manual)) { Size sz = rootUIElement.RenderSize; Point pt = _hwndTarget.TransformToDevice.Transform(new Point(sz.Width, sz.Height)); RoundDeviceSize(ref pt); NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); // get the outside size of the window only if LM has the client area // as its size. LM has the client are when it is not the app model // window case thus we calculate the outside size here. // // For windows with UsesPerPixelOpacity, we force the client to // fill the window, so we don't need to add in any frame space. // if (_adjustSizingForNonClientArea == false && !UsesPerPixelOpacity) { // Get the current style and calculate the size to be with the new style. // If WM_WINDOWPOSCHANGING is sent because of style changes, WM_STYLECHANGED is sent // before this. The style bits we get here are updated ones, but haven't been applied // to Window yet. For example, when the window is changing to borderless, without updating the window size, // the window size will remain the same but the client area will be bigger. So when SizeToContent is on, we calculate // the window size to be with the new style using AdustWindowRectEx and adjust it to make sure client area is not affected. int style = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this,_hwndWrapper.Handle), false)); int styleEx = NativeMethods.IntPtrToInt32((IntPtr)SafeNativeMethods.GetWindowStyle(new HandleRef(this,_hwndWrapper.Handle), true)); SafeNativeMethods.AdjustWindowRectEx(ref rect, style, false, styleEx); } int newCX = rect.right - rect.left; int newCY = rect.bottom - rect.top; // Get WINDOWPOS structure data from lParam; it contains information about the window's // new size and position. NativeMethods.WINDOWPOS windowPos = (NativeMethods.WINDOWPOS)UnsafeNativeMethods.PtrToStructure(lParam, typeof(NativeMethods.WINDOWPOS)); bool sizeChanged = false; // If SWP_NOSIZE is set to ignore cx, cy. It could be a style or position change. if ((windowPos.flags & NativeMethods.SWP_NOSIZE) == NativeMethods.SWP_NOSIZE) { NativeMethods.RECT windowRect = new NativeMethods.RECT(0, 0, 0, 0); // Get the current Window rect SafeNativeMethods.GetWindowRect(new HandleRef(this, _hwndWrapper.Handle), ref windowRect); // If there is no size change with the new style we don't need to do anything. if ((newCX != (windowRect.right - windowRect.left)) || (newCY != (windowRect.bottom - windowRect.top))) { // Otherwise unmark the flag to make our changes effective. windowPos.flags &= ~NativeMethods.SWP_NOSIZE; // When SWP_NOSIZE is on, the size info in cx and cy is bogus. They are ignored. // When we turn it off, we need to provide valid value for both of them. windowPos.cx = newCX; windowPos.cy = newCY; sizeChanged = true; } } else { // We have excluded SizeToContent == SizeToContent.Manual before entering this. bool sizeToWidth = (SizeToContent == SizeToContent.Height) ? false : true; bool sizeToHeight = (SizeToContent == SizeToContent.Width) ? false : true; // Update WindowPos with the size we want. if ((sizeToWidth) && (windowPos.cx != newCX)) { windowPos.cx = newCX; sizeChanged = true; } if ((sizeToHeight) && (windowPos.cy != newCY)) { windowPos.cy = newCY; sizeChanged = true; } } // Marshal the structure back only when changed if (sizeChanged) { Marshal.StructureToPtr(windowPos, lParam, true); } } } ////// Critical: Because it uses _hwndTarget /// [SecurityCritical] private void Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) { int x = NativeMethods.SignedLOWORD(lParam); int y = NativeMethods.SignedHIWORD(lParam); Point pt = new Point(x, y); bool etwEnabled = EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal); int ctxHashCode = 0; // 1. If it's coming from Layout (_myOwnUpdate), it means we are adjusting // to the right size; don't need to do anything here. // 2. If SizeToContent is set to WidthAndHeight, then we maintain the current hwnd size // in WM_WINDOWPOSCHANGING, so we don't need to re-layout here. If SizeToContent // is set to Width or Height and developer calls SetWindowPos to set a new // Width/Height, we need to do a layout. // 3. We also don't need to do anything if it's minimized. // Keeps the status of whether the Window is in Minimized state or not. _isWindowInMinimizeState = (NativeMethods.IntPtrToInt32(wParam) == NativeMethods.SIZE_MINIMIZED) ? true : false; if ((!_myOwnUpdate) && (_sizeToContent != SizeToContent.WidthAndHeight) && !_isWindowInMinimizeState) { Point relevantPt = new Point(pt.X, pt.Y); // WM_SIZE has the client size of the window. // for appmodel window case, get the outside size of the hwnd. if (_adjustSizingForNonClientArea == true) { NativeMethods.RECT rect = new NativeMethods.RECT(0, 0, (int)pt.X, (int)pt.Y); GetSizeForWindowObject(ref rect); relevantPt.X = rect.right - rect.left; relevantPt.Y = rect.bottom - rect.top; } // The lParam/wParam size and the GetSizeForWindowObject size are // both in device co-ods, thus we convert to Measure co-ods here. relevantPt = _hwndTarget.TransformFromDevice.Transform(relevantPt); Size sz = new Size( (_sizeToContent == SizeToContent.Width ? double.PositiveInfinity : relevantPt.X), (_sizeToContent == SizeToContent.Height ? double.PositiveInfinity : relevantPt.Y)); // NOTE: [....] -- 6/03/04 // 962884 Avalon content does not resize when the favorites // (or other side pane) is closed // // The issue is that when the browser shows favorites window, avalon // window is resized and we get WM_SIZE. Here, we pass the IE window's // size to Measure so that Computed[Width/Height] gets the correct // IE window dimensions. Since, IE window's size may not change, the // call to Measure is optimized out and no layout happens. Invalidating // layout here ensures that we do layout. // This can happen only in the Window case if (_adjustSizingForNonClientArea == true) { rootUIElement.InvalidateMeasure(); } if (etwEnabled) { ctxHashCode = this.Dispatcher.GetHashCode(); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.StartEvent, ctxHashCode); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } rootUIElement.Measure(sz); if (_sizeToContent == SizeToContent.Width) sz = new Size(rootUIElement.DesiredSize.Width, relevantPt.Y); else if (_sizeToContent == SizeToContent.Height) sz = new Size(relevantPt.X, rootUIElement.DesiredSize.Height); else sz = new Size(relevantPt.X, relevantPt.Y); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.StartEvent, ctxHashCode); } rootUIElement.Arrange(new Rect(new Point(), sz)); if (etwEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), MS.Utility.EventType.EndEvent); EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.LAYOUTPASSGUID), MS.Utility.EventType.EndEvent); } rootUIElement.UpdateLayout(); //finalizes layout } } ////// Critical: Because it uses _hwndTarget /// [SecurityCritical] private void DisableSizeToContent(UIElement rootUIElement, IntPtr hwnd) { if (_sizeToContent != SizeToContent.Manual) { _sizeToContent = SizeToContent.Manual; // [....] - 10/27/2005 // 1348020 Window expereience layout issue when SizeToContent is being turned // off by user interaction // This bug was caused b/c we were giving rootUIElement.DesiredSize as input // to Measure/Arrange below. That is incorrect since rootUIElement.DesiredSize may not // cover the entire hwnd client area. // GetSizeFromHwnd returns either the outside size or the client size of the hwnd based on // _adjustSizeingForNonClientArea flag in logical units. Size sizeLogicalUnits = GetSizeFromHwnd(); rootUIElement.Measure(sizeLogicalUnits); rootUIElement.Arrange(new Rect(new Point(), sizeLogicalUnits)); rootUIElement.UpdateLayout(); //finalizes layout if (SizeToContentChanged != null) { SizeToContentChanged(this, EventArgs.Empty); } } } // This method makes sure that we get the size from the correct // hwnd for the browser case. ////// Critical - calls critical methods (HwndSourceHelper.GetHandle and GetAncestor) /// TreatAsSafe - it's ok to return size of window. it doesn't return info gotten through critical calls. /// [SecurityCritical, SecurityTreatAsSafe] private void GetSizeForWindowObject(ref NativeMethods.RECT rc) { IntPtr hwndRoot = UnsafeNativeMethods.GetAncestor(new HandleRef(this, CriticalHandle), NativeMethods.GA_ROOT); SafeNativeMethods.GetWindowRect(new HandleRef(this, hwndRoot), ref rc); } ////// Critical: This is a hook that gets called back with information about messages related to input /// Calling this from outside or causing this to be invoked could yield risky situations /// [SecurityCritical] private IntPtr InputFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { IntPtr result = IntPtr.Zero ; // NOTE ([....]): invoke _stylus.FilterMessage before _mouse.FilterMessage // to give _stylus a chance to eat mouse message generated by stylus if (!_isDisposed && _stylus != null && !handled) { result = _stylus.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); } if (!_isDisposed && _mouse != null && !handled) { result = _mouse.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); } if (!_isDisposed && _keyboard != null && !handled) { result = _keyboard.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); } if (!_isDisposed && _appCommand != null && !handled) { result = _appCommand.Value.FilterMessage(hwnd, msg, wParam, lParam, ref handled); } return result; } ////// Called from HwndWrapper on all window messages. /// // assumes Context.Access() is held. private IntPtr PublicHooksFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // The default result for messages we handle is 0. IntPtr result = IntPtr.Zero ; // Call all of the public hooks // We do this even if we are disposed because otherwise the hooks // would never see the WM_DESTROY etc. message. if (_hooks != null) { for (int i = 0, nCount = _hooks.Count; i < nCount; i++) { result = ((HwndSourceHook)_hooks[i])(hwnd, msg, wParam, lParam, ref handled); if(handled) { break; } } } if (NativeMethods.WM_NCDESTROY == msg) { // We delivered the message to the hooks and the message // is WM_NCDESTROY, so our commitments should be finished // we can do final teardown. (like disposing the _hooks) OnNoMoreWindowMessages(); } return result; } #region IKeyboardInputSink private class MSGDATA { public MSG msg; public bool handled; } ////// HwndSource keyboard input is sent through this delegate to check for /// Child Hwnd interop requirments. If there are no child hwnds or focus /// is on this non-child hwnd then normal Avalon processing is done. /// ////// Critical - This can be used to spoof input /// [SecurityCritical] private void OnPreprocessMessageThunk(ref MSG msg, ref bool handled) { // VerifyAccess(); if (handled) { return; } // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS if(msg.message == _msgEnableCharMessages) { // This is our cue to go back to accepting character messages _eatCharMessages = false; } // We only do these message. switch (msg.message) { case NativeMethods.WM_KEYUP: case NativeMethods.WM_KEYDOWN: case NativeMethods.WM_SYSKEYUP: case NativeMethods.WM_SYSKEYDOWN: case NativeMethods.WM_CHAR: case NativeMethods.WM_SYSCHAR: case NativeMethods.WM_DEADCHAR: case NativeMethods.WM_SYSDEADCHAR: MSGDATA msgdata = new MSGDATA(); msgdata.msg = msg; msgdata.handled = handled; // Do this under the exception filter/handlers of the // dispatcher for this thread. // // NOTE: we lose the "perf optimization" of passing everything // around by-ref since we have to call through a delegate. object result = Dispatcher.CurrentDispatcher.Invoke( DispatcherPriority.Send, new DispatcherOperationCallback(OnPreprocessMessage), msgdata); if (result != null) { handled = (bool)result; } // the semantics dictate that the callers could change this data. msg = msgdata.msg; break; } } ////// Critical - Can be used to spoof input /// [SecurityCritical] private object OnPreprocessMessage(object param) { MSGDATA msgdata = (MSGDATA) param; // At the top level check if someone below us has Focus. // Mnemonics are broadcast to all branches of the window tree; even // those that don't have focus. BUT! at least someone under this // TopLevel window must have focus. if (!((IKeyboardInputSink)this).HasFocusWithin()) { return msgdata.handled; } ModifierKeys modifierKeys = HwndKeyboardInputProvider.GetSystemModifierKeys(); // Interop with the Interop layer // switch (msgdata.msg.message) { case NativeMethods.WM_SYSKEYDOWN: case NativeMethods.WM_KEYDOWN: // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS // In case a nested message pump is used before we return // from processing this message, we disable character // messages. _eatCharMessages = true; // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS _eatCharMessages = msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); if(_eatCharMessages) { UnsafeNativeMethods.PostMessage(new HandleRef(this, CriticalHandle), _msgEnableCharMessages, IntPtr.Zero, IntPtr.Zero); } break; case NativeMethods.WM_SYSKEYUP: case NativeMethods.WM_KEYUP: msgdata.handled = CriticalTranslateAccelerator(ref msgdata.msg, modifierKeys); break; case NativeMethods.WM_CHAR: case NativeMethods.WM_SYSCHAR: case NativeMethods.WM_DEADCHAR: case NativeMethods.WM_SYSDEADCHAR: // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS if(!_eatCharMessages) { msgdata.handled = ((IKeyboardInputSink)this).TranslateChar(ref msgdata.msg, modifierKeys); if (!msgdata.handled) { msgdata.handled = ((IKeyboardInputSink)this).OnMnemonic(ref msgdata.msg, modifierKeys); } if (!msgdata.handled) { _keyboard.Value.ProcessTextInputAction(msgdata.msg.hwnd, msgdata.msg.message, msgdata.msg.wParam, msgdata.msg.lParam, ref msgdata.handled); } } break; } return msgdata.handled; } ////// Registers a child KeyboardInputSink with this sink. A site /// is returned. /// ////// This API requires unrestricted UI Window permission. /// ////// Critical: This API can be used for input spoofing /// PublicOK: This method has a demand on it. /// [SecurityCritical, UIPermissionAttribute(SecurityAction.Demand, Unrestricted=true)] IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink) { CheckDisposed(true); if (sink == null) { throw new ArgumentNullException("sink"); } if (sink.KeyboardInputSite != null) { throw new ArgumentException(SR.Get(SRID.KeyboardSinkAlreadyOwned)); } HwndSourceKeyboardInputSite site = new HwndSourceKeyboardInputSite(this, sink); if (_keyboardInputSinkChildren == null) _keyboardInputSinkChildren = new List(); _keyboardInputSinkChildren.Add(site); return site; } /// /// Gives the component a chance to process keyboard input. /// Return value is true if handled, false if not. Components /// will generally call a child component's TranslateAccelerator /// if they can't handle the input themselves. The message must /// either be WM_KEYDOWN or WM_SYSKEYDOWN. It is illegal to /// modify the MSG structure, it's passed by reference only as /// a performance optimization. /// ////// This API is not available in Internet Zone. /// ////// Critical: This API can be used for input spoofing /// TreatAsSafe: This method has a demand on it. /// [SecurityCritical, SecurityTreatAsSafe] bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers) { SecurityHelper.DemandUnmanagedCode(); // VerifyAccess(); return CriticalTranslateAccelerator(ref msg, modifiers); } ////// Set focus to the first or last tab stop (according to the /// TraversalRequest). If it can't, because it has no tab stops, /// the return value is false. /// bool IKeyboardInputSink.TabInto(TraversalRequest request) { bool traversed = false; if(request == null) { throw new ArgumentNullException("request"); } UIElement root =_rootVisual.Value as UIElement; if(root != null) { // [....]: // request.Mode == FocusNavigationDirection.First will navigate to the fist tabstop including root // request.Mode == FocusNavigationDirection.Last will navigate to the last tabstop including root traversed = root.MoveFocus(request); } return traversed; } ////// The property should start with a null value. The component's /// container will set this property to a non-null value before /// any other methods are called. It may be set multiple times, /// and should be set to null before disposal. /// ////// Setting KeyboardInputSite is not available in Internet Zone. /// ////// Critical: This API can be used for input spoofing /// PublicOK: This method has a demand on it. /// IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite { [SecurityCritical] get { SecurityHelper.DemandUnmanagedCode(); return _keyboardInputSite; } [SecurityCritical] set { SecurityHelper.DemandUnmanagedCode(); _keyboardInputSite = value; } } ////// This method is called whenever one of the component's /// mnemonics is invoked. The message must either be WM_KEYDOWN /// or WM_SYSKEYDOWN. It's illegal to modify the MSG structrure, /// it's passed by reference only as a performance optimization. /// If this component contains child components, the container /// OnMnemonic will need to call the child's OnMnemonic method. /// ////// Critical: This API can be used for input spoofing /// TreatAsSafe: This method has a demand on it. /// [SecurityCritical, SecurityTreatAsSafe] bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers) { // VerifyAccess(); SecurityHelper.DemandUnmanagedCode(); switch(msg.message) { case NativeMethods.WM_SYSCHAR: case NativeMethods.WM_SYSDEADCHAR: string text = new string((char)msg.wParam, 1); if ((text != null) && (text.Length > 0)) { if (AccessKeyManager.IsKeyRegistered(this, text)) { AccessKeyManager.ProcessKey(this, text, false); // return true; } } // these are OK break; case NativeMethods.WM_CHAR: case NativeMethods.WM_DEADCHAR: // these are OK break; default: throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages)); } // We record the last message that was processed by us. // This is also checked in WndProc processing to prevent double processing. _lastKeyboardMessage = msg; // The Avalon bubble will take care of access key processing for this HWND // So now we just call the children. if (null == _keyboardInputSinkChildren) return false; foreach ( HwndSourceKeyboardInputSite childSite in _keyboardInputSinkChildren ) { if (((IKeyboardInputSite)childSite).Sink.OnMnemonic(ref msg, modifiers)) return true; } return false; } ////// Gives the component a chance to process keyboard input messages /// WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic. /// Will return true if "handled" meaning don't pass it to OnMnemonic. /// The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR. /// It is illegal to modify the MSG structure, it's passed by reference /// only as a performance optimization. /// ////// Critical: This API can be used for input spoofing /// TreatAsSafe: This method has a demand on it. /// [SecurityCritical, SecurityTreatAsSafe] bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers) { SecurityHelper.DemandUnmanagedCode(); if(HasFocus) return false; IKeyboardInputSink focusSink = this.ChildSinkWithFocus; if(null != focusSink) { return focusSink.TranslateChar(ref msg, modifiers); } return false; } ////// /// bool IKeyboardInputSink.HasFocusWithin() { if(HasFocus) { return true; } else { if (null == _keyboardInputSinkChildren) return false; foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren) { if (((IKeyboardInputSite)site).Sink.HasFocusWithin()) { return true; } } return false; } } ////// The method is not part of the interface (IKeyboardInputSink). /// /// The Site that containes the sink to unregister ////// Critical - calls critical methods. /// [ SecurityCritical ] internal void CriticalUnregisterKeyboardInputSink(HwndSourceKeyboardInputSite site) { if(_isDisposed) return; if (null != _keyboardInputSinkChildren) { if (!_keyboardInputSinkChildren.Remove(site)) { throw new InvalidOperationException(SR.Get(SRID.KeyboardSinkNotAChild)); } } } IKeyboardInputSink ChildSinkWithFocus { get { IKeyboardInputSink ikis=null; if(null == _keyboardInputSinkChildren) return null; foreach (HwndSourceKeyboardInputSite site in _keyboardInputSinkChildren) { IKeyboardInputSite isite = (IKeyboardInputSite)site; if (isite.Sink.HasFocusWithin()) { ikis = isite.Sink; break; } } // This private property should only be called correctly. Debug.Assert(null!=ikis, "ChildSinkWithFocus called when none had focus"); return ikis; } } ////// Critical: This API could be vulnerable to input spoofing. /// [SecurityCritical, FriendAccessAllowed] internal bool CriticalTranslateAccelerator(ref MSG msg, ModifierKeys modifiers) { switch (msg.message) { case NativeMethods.WM_KEYUP: case NativeMethods.WM_KEYDOWN: case NativeMethods.WM_SYSKEYUP: case NativeMethods.WM_SYSKEYDOWN: // these are OK break; default: throw new ArgumentException(SR.Get(SRID.OnlyAcceptsKeyMessages)); } if (_keyboard == null) return false; bool handled = false; // TranslateAccelerator is called recursively on child Hwnds (Source & Host) // If this is the first Avalon TranslateAccelerator processing then we send the // key to be processed to the standard Avalon Input Filters and stuff. if (PerThreadData.TranslateAcceleratorCallDepth == 0) { // We record the last message that was processed by us. // This is also checked in WndProc processing to prevent double processing. // TranslateAcclerator is called from the pump before DispatchMessage // and the WndProc is called from DispatchMessage. We have processing // in both places. If we run the pump we process keyboard message here. // If we don't own the pump we process them in HwndKeyboardInputProvider.WndProc. _lastKeyboardMessage = msg; // NORMAL AVALON KEYBOARD INPUT CASE // If this is the top most Avalon window (it might be a child Hwnd // but no Avalon windows above it). And focus is on this window then // do the Normal Avalon Keyboard input Processing. if (HasFocus) { _keyboard.Value.ProcessKeyAction(ref msg, ref handled); } // ELSE the focus is in but not on this HwndSource. // Do the once only message input filters etc and Tunnel/Bubble down // to the element that contains the child window with focus. // The Child HwndHost object will hook OnPreviewKeyDown() etc // to make the transition to its TranslateAccelerator() between the // tunnel and the bubble. else { IKeyboardInputSink focusSink = ChildSinkWithFocus; IInputElement focusElement = (IInputElement)focusSink; try { PerThreadData.TranslateAcceleratorCallDepth += 1; Keyboard.PrimaryDevice.ForceTarget = focusElement; _keyboard.Value.ProcessKeyAction(ref msg, ref handled); } finally { Keyboard.PrimaryDevice.ForceTarget = null; PerThreadData.TranslateAcceleratorCallDepth -= 1; } } } // ELSE we have seen this MSG before, we are HwndSource decendant of an // HwndSource (that ancestor presumably did the processing above). // Here we raise the tunnel/bubble events without the once only keyboard // input filtering. else { int virtualKey = HwndKeyboardInputProvider.GetVirtualKey(msg.wParam, msg.lParam); int scanCode = HwndKeyboardInputProvider.GetScanCode(msg.wParam, msg.lParam); bool isExtendedKey = HwndKeyboardInputProvider.IsExtendedKey(msg.lParam); Key key = KeyInterop.KeyFromVirtualKey(virtualKey); RoutedEvent keyPreviewEvent=null; RoutedEvent keyEvent=null; switch (msg.message) { case NativeMethods.WM_KEYUP: case NativeMethods.WM_SYSKEYUP: keyPreviewEvent = Keyboard.PreviewKeyUpEvent; keyEvent = Keyboard.KeyUpEvent; break; case NativeMethods.WM_KEYDOWN: case NativeMethods.WM_SYSKEYDOWN: keyPreviewEvent = Keyboard.PreviewKeyDownEvent; keyEvent = Keyboard.KeyDownEvent; break; } IKeyboardInputSink focusSink = HasFocus ? null : ChildSinkWithFocus; IInputElement focusElement = focusSink as IInputElement; // focusElement may be null, in which case Target is just "focus" try { Keyboard.PrimaryDevice.ForceTarget = focusElement; focusElement = Keyboard.PrimaryDevice.Target; KeyEventArgs tunnelArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key); tunnelArgs.ScanCode = scanCode; tunnelArgs.IsExtendedKey = isExtendedKey; tunnelArgs.RoutedEvent = keyPreviewEvent; focusElement.RaiseEvent(tunnelArgs); handled = tunnelArgs.Handled; if (!handled) { KeyEventArgs bubbleArgs = new KeyEventArgs(Keyboard.PrimaryDevice, this, msg.time, key); bubbleArgs.ScanCode = scanCode; bubbleArgs.IsExtendedKey = isExtendedKey; bubbleArgs.RoutedEvent=keyEvent; focusElement.RaiseEvent(bubbleArgs); handled = bubbleArgs.Handled; if (!handled) { // Raise the TranslateAccelerator event on the // InputManager to allow keyboard navigation to // happen on a descendent HwndSource InputManager.UnsecureCurrent.RaiseTranslateAccelerator(bubbleArgs); handled = bubbleArgs.Handled; } } } finally { Keyboard.PrimaryDevice.ForceTarget = null; } } return handled; } #endregion IKeyboardInputSink internal bool IsRepeatedKeyboardMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) { if (msg != _lastKeyboardMessage.message) return false; if (hwnd != _lastKeyboardMessage.hwnd) return false; if (wParam != _lastKeyboardMessage.wParam) return false; if (lParam != _lastKeyboardMessage.lParam) return false; return true; } ////// This event handler is called from HwndWrapper when it is Disposing. /// // This could happen if someone calls his Dispose before (or instead // of) our dispose. Or, more likely, the real window was killed by // something like the user clicking the close box. private void OnHwndDisposed(object sender, EventArgs args) { // This method is called from the HwndWrapper.Dispose(). // So make sure we don't call HwndWrapper.Dispose(). _inRealHwndDispose = true; Dispose(); } ////// Called after the last window message is processed. /// // HwndSource is required to continue certain operations while, // and even after, Dispose runs. HwndSource is resposible for // calling WndProcHooks with every message the window sees. // Including: WM_CLOSE, WM_DESTROY, WM_NCDESTROY. The doc says // WM_NCDESTROY is the very last message, so we can release the // Hooks after that. // This assumes the Context.Access() is held. private void OnNoMoreWindowMessages() { _hooks.Clear(); _hooks = null; } private void OnShutdownFinished(object sender, EventArgs args) { // Note: We are already in the context being disposed. Dispose(); } // // NOTE: shutdown order is very important. Review any changes // carefully. // ////// Critical: This accesses the various sites and providers /// Safe: Disposing the object is a safe operation. /// [SecurityCritical, SecurityTreatAsSafe] private void Dispose(bool disposing) { if(disposing) { // Make sure all access is synchronized. // this.VerifyAccess(); if (!_isDisposing) { // _isDisposing is a guard against re-entery into this // routine. We fire Dispose and SourceChanged (RootVisual // change) events which could cause re-entery. _isDisposing = true; // Notify listeners that we are being disposed. We do this // before we dispose our internal stuff, in case the event // listener needs to access something. if(Disposed != null) { try { Disposed(this, EventArgs.Empty); } #pragma warning disable 56500 // We can't tolerate an exception thrown by third-party code to // abort our Dispose half-way through. So we just eat it. catch { } #pragma warning restore 56500 Disposed = null; } // Remove any listeners of the ContentRendered event ClearContentRenderedListeners(); // Clear the root visual. This will raise a SourceChanged // event to registered listeners. RootVisualInternal = null; RemoveSource(); // Unregister ourselves if we are a registered KeyboardInputSink. if(_keyboardInputSite != null) { _keyboardInputSite.Unregister(); _keyboardInputSite = null; } _keyboardInputSinkChildren = null; // Dispose the HwndStylusInputProvider BEFORE we destroy the HWND. // This us because the stylus provider has an async channel and // they don't want to process data after the HWND is destroyed. if (_stylus != null) { _stylus.Value.Dispose(); _stylus = null; } // Our general shut-down principle is to destroy the window // and let the individual HwndXXX components respons to WM_DESTROY. // // (see comment above about disposing the HwndStylusInputProvider) // { if (_hwndTarget != null) { _hwndTarget.Dispose(); _hwndTarget = null; } if (_hwndWrapper != null) { // Revoke the drop target. if (_hwndWrapper.Handle != IntPtr.Zero && _registeredDropTargetCount > 0) { // This call is safe since DragDrop.RevokeDropTarget is checking the unmanged // code permission. DragDrop.RevokeDropTarget(_hwndWrapper.Handle); _registeredDropTargetCount--; } // Remove our HwndWrapper.Dispose() hander. _hwndWrapper.Disposed -= new EventHandler(OnHwndDisposed); if (!_inRealHwndDispose) _hwndWrapper.Dispose(); // Don't null out _hwndWrapper after the Dispose(). // Dispose() will start destroying the Window but we // still need to talk to it during that process while // the WM_ msgs arrive. } } if(_mouse != null) { _mouse.Value.Dispose(); _mouse = null; } if(_keyboard != null) { _keyboard.Value.Dispose(); _keyboard = null; } if (_appCommand != null) { _appCommand.Value.Dispose(); _appCommand = null; } if(null != _weakShutdownHandler) { _weakShutdownHandler.Dispose(); _weakShutdownHandler = null; } if(null != _weakPreprocessMessageHandler) { _weakPreprocessMessageHandler.Dispose(); _weakPreprocessMessageHandler = null; } // We wait to set the "_isDisposed" flag until after the // Disposed, SourceChange (RootVisual=null), etc. events // have fired. We want to remain functional should their // handlers call methods on us. // // Note: as the HwndWrapper shuts down, the final few messages // will continue to pass through our WndProc hook. _isDisposed = true; } } } private void CheckDisposed(bool verifyAccess) { if(verifyAccess) { // this.VerifyAccess(); } if(_isDisposed) { throw new ObjectDisposedException(null, SR.Get(SRID.HwndSourceDisposed)); } } ////// Critical: This code accesses hwndtarget /// TreatAsSafe: Information is ok to expose /// private bool IsUsable { [SecurityCritical,SecurityTreatAsSafe] get { return _isDisposed == false && _hwndTarget != null && _hwndTarget.IsDisposed == false; } } ////// Critical - calls a method with an elevation ( GetFocus ) /// TreatAsSafe - determining whether you have focus within the window is considered safe. /// Worst case you can know whether keyboard/keypress events will go to the current window. /// private bool HasFocus { [SecurityCritical, SecurityTreatAsSafe] get { return UnsafeNativeMethods.GetFocus() == CriticalHandle; } } private static bool IsValidSizeToContent(SizeToContent value) { return value == SizeToContent.Manual || value == SizeToContent.Width || value == SizeToContent.Height || value == SizeToContent.WidthAndHeight; } class ThreadDataBlob { public int TranslateAcceleratorCallDepth; } private static ThreadDataBlob PerThreadData { get { ThreadDataBlob data; object obj = Thread.GetData(_threadSlot); if(null == obj) { data = new ThreadDataBlob(); Thread.SetData(_threadSlot, data); } else { data = (ThreadDataBlob) obj; } return data; } } #region WeakEventHandlers private class WeakEventDispatcherShutdown: WeakReference { public WeakEventDispatcherShutdown(HwndSource source, Dispatcher that): base(source) { _that = that; _that.ShutdownFinished += new EventHandler(this.OnShutdownFinished); } public void OnShutdownFinished(object sender, EventArgs e) { HwndSource source = this.Target as HwndSource; if(null != source) { source.OnShutdownFinished(sender, e); } else { Dispose(); } } public void Dispose() { if(null != _that) { _that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished); } } private Dispatcher _that; } private class WeakEventPreprocessMessage: WeakReference { ////// Critical: This code calls attaches an arbitrary window /// to the call path for the component dispatcher call back /// [SecurityCritical] public WeakEventPreprocessMessage(HwndSource source): base(source) { ComponentDispatcher.ThreadPreprocessMessage += new ThreadMessageEventHandler(this.OnPreprocessMessage); } ////// Critical: This can be used to spoof and change input /// [SecurityCritical] public void OnPreprocessMessage(ref MSG msg, ref bool handled) { HwndSource source = this.Target as HwndSource; if(null != source) { source.OnPreprocessMessageThunk(ref msg, ref handled); } else { Dispose(); } } ////// Critical:This code calls into ComponentDispatcher /// to disconnect a listener /// TreatAsSafe: This code is ok to call /// [SecurityCritical,SecurityTreatAsSafe] public void Dispose() { ComponentDispatcher.ThreadPreprocessMessage -= new ThreadMessageEventHandler(this.OnPreprocessMessage); } } #endregion WeakEventHandlers private object _constructionParameters; // boxed HwndSourceParameters private bool _isDisposed = false; private bool _isDisposing = false; private bool _inRealHwndDispose = false; private bool _adjustSizingForNonClientArea; private bool _myOwnUpdate; private bool _isWindowInMinimizeState = false; private int _registeredDropTargetCount; private SizeToContent _sizeToContent = SizeToContent.Manual; private Size? _previousSize; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// [SecurityCritical] private HwndWrapper _hwndWrapper; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// [SecurityCritical] private HwndTarget _hwndTarget; private SecurityCriticalDataForSet_rootVisual; private ArrayList _hooks; /// /// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// private SecurityCriticalDataClass_mouse; /// /// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// private SecurityCriticalDataClass_keyboard; /// /// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// private SecurityCriticalDataClass_stylus; /// /// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data is considered critical. /// private SecurityCriticalDataClass_appCommand; WeakEventDispatcherShutdown _weakShutdownHandler; WeakEventPreprocessMessage _weakPreprocessMessageHandler; private static System.LocalDataStoreSlot _threadSlot; private MSG _lastKeyboardMessage; private List _keyboardInputSinkChildren; /// /// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data can be used to spoof input /// [SecurityCritical] private IKeyboardInputSite _keyboardInputSite = null; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data can be used to spoof input /// [SecurityCritical] private HwndWrapperHook _layoutHook; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data can be used to spoof input /// [SecurityCritical] private HwndWrapperHook _inputHook; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data can be used to spoof input /// [SecurityCritical] private HwndWrapperHook _hwndTargetHook; ////// Critical:This reference cannot be given out or assigned to outside of a verified /// elevation. This data can be used to spoof input /// [SecurityCritical] private HwndWrapperHook _publicHook; // MITIGATION: HANDLED_KEYDOWN_STILL_GENERATES_CHARS // // Avalon relies on the policy that if you handle the KeyDown // event, you will not get the TextInput events caused by // pressing the key. This is generally implemented because the // message pump calls ComponentDispatcher.RaiseThreadMessage and // we return whether or not the WM_KEYDOWN message was handled, // and the message pump will only call TranslateMessage() if the // WM_KEYDOWN was not handled. However, naive message pumps don't // call ComponentDispatcher.RaiseThreadMessage, and always call // TranslateMessage, so the WM_CHAR is generated no matter what. // The best work around we could think of was to eat the WM_CHAR // messages and not report them to Avalon. // [ThreadStatic] internal static bool _eatCharMessages; // used from HwndKeyboardInputProvider internal static int _msgEnableCharMessages; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HtmlInputText.cs
- SqlVersion.cs
- RowTypePropertyElement.cs
- MarkupCompiler.cs
- EntityContainerRelationshipSetEnd.cs
- XmlDataSource.cs
- AvTrace.cs
- IndentTextWriter.cs
- DataGridViewAdvancedBorderStyle.cs
- PageParserFilter.cs
- CodeSnippetTypeMember.cs
- FreeFormDragDropManager.cs
- DataGridViewTextBoxColumn.cs
- SqlException.cs
- ObjectStateEntryOriginalDbUpdatableDataRecord.cs
- HtmlShimManager.cs
- KoreanLunisolarCalendar.cs
- XmlSchemaComplexType.cs
- BuildProvider.cs
- LinqDataSourceDeleteEventArgs.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- HwndHostAutomationPeer.cs
- Nullable.cs
- CommonBehaviorsSection.cs
- RegexWorker.cs
- ObjectContextServiceProvider.cs
- XmlSchemaException.cs
- QueryContinueDragEvent.cs
- SmtpFailedRecipientsException.cs
- EventLogPermissionAttribute.cs
- TransportOutputChannel.cs
- ProcessHostFactoryHelper.cs
- ColorEditor.cs
- LicenseManager.cs
- FlowNode.cs
- ElementNotEnabledException.cs
- RIPEMD160.cs
- SecurityUtils.cs
- TypeResolver.cs
- LineUtil.cs
- HyperLinkField.cs
- _LocalDataStore.cs
- WebServiceClientProxyGenerator.cs
- OleDbParameter.cs
- TextRange.cs
- HttpContext.cs
- Events.cs
- BevelBitmapEffect.cs
- RelationshipConverter.cs
- QuerySafeNavigator.cs
- QuaternionValueSerializer.cs
- UTF32Encoding.cs
- ILGenerator.cs
- ManifestResourceInfo.cs
- InternalConfigHost.cs
- SynchronizingStream.cs
- DefaultAutoFieldGenerator.cs
- PropertyDescriptor.cs
- DataGridGeneralPage.cs
- StorageMappingItemLoader.cs
- StringValueConverter.cs
- WhitespaceRuleReader.cs
- AuthorizationRule.cs
- Help.cs
- StrongNamePublicKeyBlob.cs
- ThreadExceptionEvent.cs
- MimeTypePropertyAttribute.cs
- TabletDevice.cs
- SRDisplayNameAttribute.cs
- BaseAsyncResult.cs
- WebControlAdapter.cs
- LightweightCodeGenerator.cs
- PlainXmlDeserializer.cs
- Base64Encoder.cs
- CatalogPartChrome.cs
- Mappings.cs
- ProvidePropertyAttribute.cs
- PngBitmapEncoder.cs
- BaseTemplateParser.cs
- WebPartDisplayMode.cs
- XmlArrayItemAttribute.cs
- TemplateBindingExpressionConverter.cs
- XPathDocument.cs
- RemotingAttributes.cs
- ReversePositionQuery.cs
- ParenthesizePropertyNameAttribute.cs
- SystemPens.cs
- ClientUriBehavior.cs
- ErrorRuntimeConfig.cs
- GiveFeedbackEvent.cs
- DynamicControlParameter.cs
- ObjectComplexPropertyMapping.cs
- Utils.cs
- WebPartTransformer.cs
- RsaSecurityTokenAuthenticator.cs
- DbConnectionPool.cs
- SqlBulkCopyColumnMappingCollection.cs
- AppSettings.cs
- KeyValuePairs.cs
- AdjustableArrowCap.cs