Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Interop / HwndHost.cs / 1407647 / HwndHost.cs
using System;
using System.Diagnostics;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Input;
using System.Collections;
using MS.Win32;
using MS.Internal;
using MS.Internal.Interop;
using System.Security;
using System.Security.Permissions;
using Microsoft.Win32;
using System.Windows.Media;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Windows.Threading;
using System.Diagnostics.CodeAnalysis;
// Disable pragma warnings to enable PREsharp pragmas
#pragma warning disable 1634, 1691
namespace System.Windows.Interop
{
///
/// The HwndHost class hosts an HWND inside of an Avalon tree.
///
/// Subclassing requires unmanaged code permission
///
///
/// Inheritance demand put in place - as to host activeX controls you should have Unmanaged code permission.
///
///
[SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public abstract class HwndHost : FrameworkElement, IDisposable, IWin32Window, IKeyboardInputSink
{
static HwndHost()
{
FocusableProperty.OverrideMetadata(typeof(HwndHost), new FrameworkPropertyMetadata(true));
}
///
/// Constructs an instance of the HwndHost class.
///
/// Not available in Internet zone
///
/// Critical - calls critical code, sets critical _fTrusted flag.
/// PublicOk - trusted flag is set to false.
///
[ SecurityCritical ]
protected HwndHost()
{
Initialize( false ) ;
}
///
/// Critical sets fTrustedBit.
///
[SecurityCritical]
internal HwndHost(bool fTrusted )
{
Initialize( fTrusted ) ;
}
///
/// Because we own an HWND, we implement a finalizer to make sure that we destroy it.
///
~HwndHost()
{
Dispose(false);
}
///
/// Disposes this object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// The Win32 handle of the hosted window.
///
///
/// Callers must have UnmanagedCode permission to call this API.
///
///
/// Critical: This code accesses IsWindow, returns hwndHandle.
/// PublicOk: There is a demand
///
public IntPtr Handle
{
[SecurityCritical]
get
{
SecurityHelper.DemandUnmanagedCode();
return CriticalHandle;
}
}
///
/// An event that is notified of all unhandled messages received
/// by the hosted window.
///
///
/// Callers must have UnmanagedCode permission to call this API.
///
///
/// Demand put in place as a defense in depth measure.
///
public event HwndSourceHook MessageHook
{
add
{
// VerifyAccess();
SecurityHelper.DemandUnmanagedCode();
if(_hooks == null)
{
_hooks = new ArrayList(8);
}
_hooks.Add(value);
}
remove
{
// VerifyAccess();
SecurityHelper.DemandUnmanagedCode();
if(_hooks != null)
{
_hooks.Remove(value);
if(_hooks.Count == 0)
{
_hooks = null;
}
}
}
}
///
///
///
///
/// Critical - Calls ComponentDispatcher.UnsecureCurrentKeyboardMessage.
/// TreatAsSafe - Only calls for trusted controls
///
[SecurityCritical, SecurityTreatAsSafe]
protected override void OnKeyUp(KeyEventArgs e)
{
MSG msg;
if (_fTrusted.Value)
{
msg = ComponentDispatcher.UnsecureCurrentKeyboardMessage;
}
else
{
msg = ComponentDispatcher.CurrentKeyboardMessage;
}
ModifierKeys modifiers = HwndKeyboardInputProvider.GetSystemModifierKeys();
bool handled = ((IKeyboardInputSink)this).TranslateAccelerator(ref msg, modifiers);
if(handled)
e.Handled = handled;
base.OnKeyUp(e);
}
///
///
///
///
/// Critical - Calls ComponentDispatcher.UnsecureCurrentKeyboardMessage.
/// TreatAsSafe - Only calls for trusted controls
///
[SecurityCritical, SecurityTreatAsSafe]
protected override void OnKeyDown(KeyEventArgs e)
{
MSG msg;
if (_fTrusted.Value)
{
msg = ComponentDispatcher.UnsecureCurrentKeyboardMessage;
}
else
{
msg = ComponentDispatcher.CurrentKeyboardMessage;
}
ModifierKeys modifiers = HwndKeyboardInputProvider.GetSystemModifierKeys();
bool handled = ((IKeyboardInputSink)this).TranslateAccelerator(ref msg, modifiers);
if(handled)
e.Handled = handled;
base.OnKeyDown(e);
}
#region IKeyboardInputSink
/// General security note on the implementation pattern of this interface. In Dev10 it was chosen
/// to expose the interface implementation for overriding to customers. We did so by keeping the
/// explicit interface implementations (that do have the property of being hidden from the public
/// contract, which limits IntelliSense on derived types like WebBrowser) while sticking protected
/// virtuals next to them. Those virtuals contain our base implementation, while the explicit
/// interface implementation methods do call trivially into the virtuals.
///
/// This comment outlines the security rationale applied to those methods.
///
///
/// The security attributes on the virtual methods within this region mirror the corresponding
/// IKeyboardInputSink methods; customers can override those methods, so we insert a LinkDemand
/// to encourage them to have a LinkDemand too (via FxCop).
///
///
/// Registers a IKeyboardInputSink with the HwndSource in order
/// to retreive a unique IKeyboardInputSite for it.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual IKeyboardInputSite RegisterKeyboardInputSinkCore(IKeyboardInputSink sink)
{
throw new InvalidOperationException(SR.Get(SRID.HwndHostDoesNotSupportChildKeyboardSinks));
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
{
return RegisterKeyboardInputSinkCore(sink);
}
///
/// Gives the component a chance to process keyboard input.
/// Return value is true if handled, false if not. Components
/// will generally call a child component's TranslateAccelerator
/// if they can't handle the input themselves. The message must
/// either be WM_KEYDOWN or WM_SYSKEYDOWN. It is illegal to
/// modify the MSG structure, it's passed by reference only as
/// a performance optimization.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOk: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)
{
return TranslateAcceleratorCore(ref msg, modifiers);
}
///
/// Set focus to the first or last tab stop (according to the
/// TraversalRequest). If it can't, because it has no tab stops,
/// the return value is false.
///
protected virtual bool TabIntoCore(TraversalRequest request)
{
return false;
}
bool IKeyboardInputSink.TabInto(TraversalRequest request)
{
return TabIntoCore(request);
}
///
/// The property should start with a null value. The component's
/// container will set this property to a non-null value before
/// any other methods are called. It may be set multiple times,
/// and should be set to null before disposal.
///
///
/// Critical: This API can be used for input spoofing
/// PublicOK: The interface declaration for this method has a demand on it.
///
IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite { get; [SecurityCritical] set; }
///
/// This method is called whenever one of the component's
/// mnemonics is invoked. The message must either be WM_KEYDOWN
/// or WM_SYSKEYDOWN. It's illegal to modify the MSG structrure,
/// it's passed by reference only as a performance optimization.
/// If this component contains child components, the container
/// OnMnemonic will need to call the child's OnMnemonic method.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool OnMnemonicCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
{
return OnMnemonicCore(ref msg, modifiers);
}
///
/// Gives the component a chance to process keyboard input messages
/// WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic.
/// Will return true if "handled" meaning don't pass it to OnMnemonic.
/// The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR.
/// It is illegal to modify the MSG structure, it's passed by reference
/// only as a performance optimization.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool TranslateCharCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers)
{
return TranslateCharCore(ref msg, modifiers);
}
///
/// This returns true if the sink, or a child of it, has focus. And false otherwise.
///
///
/// Critical: Calls a method with a SUC - GetFocus.
/// TreatAsSafe: No critical information exposed.
/// It's ok to return whether hwndHost has focus within itself in PT.
///
[SecurityCritical, SecurityTreatAsSafe]
protected virtual bool HasFocusWithinCore()
{
HandleRef hwndFocus = new HandleRef(this, UnsafeNativeMethods.GetFocus());
if (_hwnd.Handle != IntPtr.Zero && (hwndFocus.Handle == _hwnd.Handle || UnsafeNativeMethods.IsChild(_hwnd, hwndFocus)))
{
return true;
}
return false;
}
///
/// PublicOK: It's ok to return whether hwndHost has focus within itself in PT.
///
bool IKeyboardInputSink.HasFocusWithin()
{
return HasFocusWithinCore();
}
#endregion IKeyboardInputSink
///
/// Updates the child window to reflect the state of this element.
///
///
/// This includes the size of the window, the position of the
/// window, and the visibility of the window.
///
/// Not available in Internet zone
///
/// Critical: This code accesses critical code and also calls into PresentationSource
/// PublicOk : Repositioning the activeX control is ok.
/// Net effect is to make window location consistent with what layout calculated.
///
[SecurityCritical]
public void UpdateWindowPos()
{
// Verify the thread has access to the context.
// VerifyAccess();
if (_isDisposed)
{
return;
}
// Position the child HWND where layout put it. To do this we
// have to get coordinates relative to the parent window.
PresentationSource source = null;
CompositionTarget vt = null;
if (( CriticalHandle != IntPtr.Zero) && IsVisible)
{
source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if(source != null)
{
vt = source.CompositionTarget;
}
}
if(vt != null && vt.RootVisual != null)
{
// Translate the layout information assigned to us from the co-ordinate
// space of this element, through the root visual, to the Win32 client
// co-ordinate space
NativeMethods.RECT rcClientRTLAdjusted = CalculateAssignedRC(source);
// Set the Win32 position for the child window.
//
// Note, we can't check the existing position because we use
// SWP_ASYNCWINDOWPOS, which means we could have pending position
// change requests that haven't been applied yet. If we need
// this functionality (to avoid the extra SetWindowPos calls),
// we'll have to track the last RECT we sent Win32 ourselves.
//
Rect rectClientRTLAdjusted = PointUtil.ToRect(rcClientRTLAdjusted);
OnWindowPositionChanged(rectClientRTLAdjusted);
// Show the window
// Based on Dwayne, the reason we also show/hide window in UpdateWindowPos is for the
// following kind of scenario: When applying RenderTransform to HwndHost, the hwnd
// will be left behind. Developer can workaround by hide the hwnd first using pinvoke.
// After the RenderTransform is applied to the HwndHost, call UpdateWindowPos to [....] up
// the hwnd's location, size and visibility with WPF.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_SHOW);
}
else
{
// For some reason we shouldn't be displayed: either we don't
// have a parent, or the parent no longer has a root visual,
// or we are marked as not being visible.
//
// Just hide the window to get it out of the way.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
}
}
// Translate the layout information assigned to us from the co-ordinate
// space of this element, through the root visual, to the Win32 client
// co-ordinate space
///
/// Critical: This code accesses critical code and also calls into PresentationSource
/// TAS : Calculate the new position of the activeX control is ok.
/// Net effect is to make window location consistent with what layout calculated.
///
[SecurityCritical, SecurityTreatAsSafe]
private NativeMethods.RECT CalculateAssignedRC(PresentationSource source)
{
Rect rectElement = new Rect(RenderSize);
Rect rectRoot = PointUtil.ElementToRoot(rectElement, this, source);
Rect rectClient = PointUtil.RootToClient(rectRoot, source);
// Adjust for Right-To-Left oriented windows
IntPtr hwndParent = UnsafeNativeMethods.GetParent(_hwnd);
NativeMethods.RECT rcClient = PointUtil.FromRect(rectClient);
NativeMethods.RECT rcClientRTLAdjusted = PointUtil.AdjustForRightToLeft(rcClient, new HandleRef(null, hwndParent));
return rcClientRTLAdjusted;
}
///
/// Disposes this object.
///
///
/// true if called from explisit Dispose; and we free all objects managed and un-managed.
/// false if called from the finalizer; and we free only un-managed objects.
///
///
/// Derived classes should override this if they have additional
/// cleanup to do. The base class implementation should be called.
/// Note that the calling thread must be the dispatcher thread.
/// If a window is being hosted, that window is destroyed.
///
///
/// Critical - call to RemoveSourceChangeHandler invokes critical delegate.
/// SecurityTreatAsSafe : - disposing the HwndHost is considered ok.
///
[ SecurityCritical, SecurityTreatAsSafe ]
protected virtual void Dispose(bool disposing)
{
if (_isDisposed == true)
{
return;
}
if(disposing)
{
// Verify the thread has access to the context.
#pragma warning suppress 6519
VerifyAccess();
// Remove our subclass. Even if this fails, it will be forcably removed
// when the window is destroyed.
if (_hwndSubclass != null)
{
// Check if it is trusted (WebOC and AddInHost), call CriticalDetach to avoid the Demand.
if (_fTrusted.Value == true)
{
_hwndSubclass.CriticalDetach(false);
}
else
{
_hwndSubclass.RequestDetach(false);
}
_hwndSubclass = null;
}
// Drop the hooks so that they can be garbage-collected.
_hooks = null;
// We no longer need to know about the source changing.
PresentationSource.RemoveSourceChangedHandler(this, new SourceChangedEventHandler(OnSourceChanged));
}
if (_weakEventDispatcherShutdown != null) // Can be null if the static ctor failed ... see WebBrowser.
{
_weakEventDispatcherShutdown.Dispose();
_weakEventDispatcherShutdown = null;
}
DestroyWindow();
_isDisposed = true;
}
private void OnDispatcherShutdown(object sender, EventArgs e)
{
Dispose();
}
///
/// Derived classes override this method to actually build the
/// window being hosted.
///
///
/// The parent HWND for the child window.
///
///
/// The HWND handle to the child window that was created.
///
///
/// The window that is returned must be a child window of the
/// specified parent window.
///
/// In addition, the child window will only be subclassed if
/// the window is owned by the calling thread.
///
protected abstract HandleRef BuildWindowCore(HandleRef hwndParent);
///
/// Derived classes override this method to destroy the
/// window being hosted.
///
protected abstract void DestroyWindowCore(HandleRef hwnd);
///
/// A protected override for accessing the window proc of the
/// hosted child window.
///
/// Not available in Internet zone
///
/// Critical - accesses _hwnd Critical member.
/// PublicOk - Inheritance Demand for unmanaged codepermission to buslclass.
/// any caller of the protected must have Unmanaged code permission.
/// DemandIfUntrusted is there as a defense in depth measure.
///
[ SecurityCritical ]
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
DemandIfUntrusted();
switch ((WindowMessage)msg)
{
case WindowMessage.WM_NCDESTROY:
_hwnd = new HandleRef(null, IntPtr.Zero);
break;
// When layout happens, we first calculate the right size/location then call SetWindowPos.
// We only allow the changes that are coming from Avalon layout. The hwnd is not allowed to change by itself.
// So the size of the hwnd should always be RenderSize and the position be where layout puts it.
case WindowMessage.WM_WINDOWPOSCHANGING:
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if (source != null)
{
// 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));
// Get the rect assigned by layout to us.
NativeMethods.RECT assignedRC = CalculateAssignedRC(source);
windowPos.cx = assignedRC.right - assignedRC.left;
windowPos.cy = assignedRC.bottom - assignedRC.top;
windowPos.x = assignedRC.left;
windowPos.y = assignedRC.top;
// marshal size/location back
Marshal.StructureToPtr(windowPos, lParam, true);
}
break;
case WindowMessage.WM_GETOBJECT:
handled = true;
return OnWmGetObject(wParam, lParam);
}
return IntPtr.Zero ;
}
#region Automation
///
/// Creates AutomationPeer ( )
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new HwndHostAutomationPeer(this);
}
///
/// Critical - Calls critical HwndHost.CriticalHandle.
///
[SecurityCritical]
private IntPtr OnWmGetObject(IntPtr wparam, IntPtr lparam)
{
IntPtr result = IntPtr.Zero;
AutomationPeer containerPeer = UIElementAutomationPeer.CreatePeerForElement(this);
if (containerPeer != null)
{
// get the element proxy
IRawElementProviderSimple el = containerPeer.GetInteropChild();
result = AutomationInteropProvider.ReturnRawElementProvider(CriticalHandle, wparam, lparam, el);
}
return result;
}
#endregion Automation
//
[ SecurityCritical ]
protected virtual void OnWindowPositionChanged(Rect rcBoundingBox)
{
if (_isDisposed)
{
return;
}
UnsafeNativeMethods.SetWindowPos(_hwnd,
new HandleRef(null, IntPtr.Zero),
(int)rcBoundingBox.X,
(int)rcBoundingBox.Y,
(int)rcBoundingBox.Width,
(int)rcBoundingBox.Height,
NativeMethods.SWP_ASYNCWINDOWPOS
| NativeMethods.SWP_NOZORDER
| NativeMethods.SWP_NOCOPYBITS
| NativeMethods.SWP_NOACTIVATE);
}
///
/// Return the desired size of the HWND.
///
///
/// HWNDs usually expect a very simplisitic layout model where
/// a window gets to be whatever size it wants to be. To respect
/// this we request the initial size that the window was created
/// at. A window created with a 0 dimension will adopt whatever
/// size the containing layout wants it to be. Layouts are free
/// to actually size the window to whatever they want, and the
/// child window will always be sized accordingly.
///
/// Derived classes should only override this method if they
/// have special knowlege about the size the window wants to be.
/// Examples of such may be special HWND types like combo boxes.
/// In such cases, the base class must still be called, but the
/// return value can be changed appropriately.
///
/// Not available in Internet zone
///
/// Critical - calls CriticalHandle
/// TreatAsSafe - CriticalHandle used for a null check, not leaked out.
/// Ok to Override MeasureOverride and return a size in PT.
/// Demand put in place as a defense in depth measure.
///
///
[ SecurityCritical, SecurityTreatAsSafe ]
protected override Size MeasureOverride(Size constraint)
{
DemandIfUntrusted();
Size desiredSize = new Size(0,0);
// Measure to our desired size. If we have a 0-length dimension,
// the system will assume we don't care about that dimension.
if(CriticalHandle != IntPtr.Zero)
{
desiredSize.Width = Math.Min(_desiredSize.Width, constraint.Width);
desiredSize.Height = Math.Min(_desiredSize.Height, constraint.Height);
}
return desiredSize;
}
///
/// GetDrawing - Returns the drawing content of this Visual.
///
///
/// This returns a bitmap obtained by calling the PrintWindow Win32 API.
///
internal override DrawingGroup GetDrawing()
{
return GetDrawingHelper();
}
///
/// Returns the bounding box of the content.
///
internal override Rect GetContentBounds()
{
return new Rect(RenderSize);
}
///
/// Critical - calls many native methods, accesses critical data
/// TreatAsSafe - Demands UIWindow permission before giving out a bitmap of this window.
///
[SecurityCritical, SecurityTreatAsSafe]
private DrawingGroup GetDrawingHelper()
{
// Printing an HWND requires UIPermissionWindow.AllWindows to give out its pixels.
SecurityHelper.DemandUIWindowPermission();
DrawingGroup drawingGroup = null;
if(_hwnd.Handle != IntPtr.Zero && UnsafeNativeMethods.IsWindow(_hwnd))
{
NativeMethods.RECT rc = new NativeMethods.RECT();
SafeNativeMethods.GetWindowRect(_hwnd, ref rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
HandleRef hdcScreen = new HandleRef(this, UnsafeNativeMethods.GetDC(new HandleRef(this, IntPtr.Zero)));
if(hdcScreen.Handle != IntPtr.Zero)
{
HandleRef hdcBitmap = new HandleRef(this, IntPtr.Zero);
HandleRef hBitmap = new HandleRef(this, IntPtr.Zero);
try
{
hdcBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleDC(hdcScreen));
if(hdcBitmap.Handle != IntPtr.Zero)
{
hBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleBitmap(hdcScreen, width, height));
if(hBitmap.Handle != IntPtr.Zero)
{
// Select the bitmap into the DC so that we draw to it.
IntPtr hOldBitmap = UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hBitmap.Handle);
try
{
// Clear the bitmap to white (so we don't waste toner printing a black bitmap something fails).
NativeMethods.RECT rcPaint = new NativeMethods.RECT(0,0,width, height);
IntPtr hbrWhite = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.WHITE_BRUSH);
UnsafeNativeMethods.CriticalFillRect(hdcBitmap.Handle, ref rcPaint, hbrWhite);
// First try to use the PrintWindow API.
bool result = UnsafeNativeMethods.CriticalPrintWindow(_hwnd, hdcBitmap, 0);
if(result == false)
{
// Fall back to sending a WM_PRINT message to the window.
//
// Note: there are known cases where WM_PRINT is not implemented
// to provide visual parity with WM_PAINT. However, since the
// GetDrawing method is virtual, the derived class can override
// this default implementation and provide a better implementation.
UnsafeNativeMethods.SendMessage(_hwnd.Handle, WindowMessage.WM_PRINT, hdcBitmap.Handle, (IntPtr) (NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT));
}
else
{
// There is a know issue where calling PrintWindow on a window will
// clear all dirty regions (but since it is redirected, the screen
// won't be updated). As a result we can leave unpainted pixels on
// the screen if PrintWindow is called when the window was dirty.
//
// To fix this, we just force the child window to repaint.
//
UnsafeNativeMethods.CriticalRedrawWindow(_hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RDW_INVALIDATE | NativeMethods.RDW_ALLCHILDREN);
}
// Create a DrawingGroup that only contains an ImageDrawing that wraps the bitmap.
drawingGroup = new DrawingGroup();
System.Windows.Media.Imaging.BitmapSource bitmapSource = Imaging.CriticalCreateBitmapSourceFromHBitmap(hBitmap.Handle, IntPtr.Zero, Int32Rect.Empty, null, WICBitmapAlphaChannelOption.WICBitmapIgnoreAlpha);
Rect rectElement = new Rect(RenderSize);
drawingGroup.Children.Add(new ImageDrawing(bitmapSource, rectElement));
drawingGroup.Freeze();
}
finally
{
// Put the old bitmap back into the DC.
UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hOldBitmap);
}
}
}
}
finally
{
UnsafeNativeMethods.ReleaseDC(new HandleRef(this, IntPtr.Zero), hdcScreen);
hdcScreen = new HandleRef(null, IntPtr.Zero);
if(hBitmap.Handle != IntPtr.Zero)
{
UnsafeNativeMethods.DeleteObject(hBitmap);
hBitmap = new HandleRef(this, IntPtr.Zero);
}
if(hdcBitmap.Handle != IntPtr.Zero)
{
UnsafeNativeMethods.CriticalDeleteDC(hdcBitmap);
hdcBitmap = new HandleRef(this, IntPtr.Zero);
}
}
}
}
return drawingGroup;
}
///
/// Critical - calls a method that linkdemands.
/// creates critical for set data.
///
[ SecurityCritical ]
private void Initialize( bool fTrusted )
{
_fTrusted = new SecurityCriticalDataForSet ( fTrusted ) ;
_hwndSubclassHook = new HwndWrapperHook(SubclassWndProc);
_handlerLayoutUpdated = new EventHandler(OnLayoutUpdated);
_handlerEnabledChanged = new DependencyPropertyChangedEventHandler(OnEnabledChanged);
_handlerVisibleChanged = new DependencyPropertyChangedEventHandler(OnVisibleChanged);
PresentationSource.AddSourceChangedHandler(this, new SourceChangedEventHandler(OnSourceChanged));
_weakEventDispatcherShutdown = new WeakEventDispatcherShutdown(this, this.Dispatcher);
}
///
/// Use this method as a defense-in-depth measure only.
///
///
/// Not critical - demands are ok.
///
private void DemandIfUntrusted()
{
if ( ! _fTrusted.Value )
SecurityHelper.DemandUnmanagedCode();
}
///
/// Critical - calls CriticalFromVisual.
/// TreatAsSafe - does not expose the HwndSource obtained.
///
[SecurityCritical , SecurityTreatAsSafe ]
private void OnSourceChanged(object sender, SourceChangedEventArgs e)
{
// Remove ourselves as an IKeyboardInputSinks child of our previous
// containing window.
IKeyboardInputSite keyboardInputSite = ((IKeyboardInputSink)this).KeyboardInputSite;
if (keyboardInputSite != null)
{
if (_fTrusted.Value == true)
{
new UIPermission(PermissionState.Unrestricted).Assert(); //BlessedAssert:
}
try
{
// Derived classes that implement IKeyboardInputSink should support setting it to null.
((IKeyboardInputSink)this).KeyboardInputSite = null;
keyboardInputSite.Unregister();
}
finally
{
if (_fTrusted.Value == true)
{
CodeAccessPermission.RevertAssert();
}
}
}
// Add ourselves as an IKeyboardInputSinks child of our containing window.
IKeyboardInputSink source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */) as IKeyboardInputSink;
if(source != null)
{
if (_fTrusted.Value == true)
{
new UIPermission(PermissionState.Unrestricted).Assert(); //BlessedAssert:
}
try
{
((IKeyboardInputSink)this).KeyboardInputSite = source.RegisterKeyboardInputSink(this);
}
finally
{
if (_fTrusted.Value == true)
{
CodeAccessPermission.RevertAssert();
}
}
}
BuildOrReparentWindow();
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
UpdateWindowPos();
}
///
/// Critical: This code calls into critical method EnableWindow
/// TreatAsSafe: Changing window to being enabled is safe.
///
[SecurityCritical, SecurityTreatAsSafe]
private void OnEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_isDisposed)
{
return;
}
bool boolNewValue = (bool)e.NewValue;
UnsafeNativeMethods.EnableWindow(_hwnd, boolNewValue);
}
///
/// Critical: This code calls into critical method show window
/// TreatAsSafe: Changing window visibility is safe.
/// Window is always a child window.
///
[SecurityCritical,SecurityTreatAsSafe]
private void OnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_isDisposed)
{
return;
}
bool vis = (bool)e.NewValue;
//
if(vis)
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_SHOWNA);
else
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
}
// This routine handles the following cases:
// 1) a parent window is present, build the child window
// 2) a parent is present, reparent the child window to it
// 3) a parent window is not present, hide the child window by parenting it to SystemResources.Hwnd window.
///
/// Critical - calls Critical GetParent
/// TreatAsSafe - it doesn't disclose GetParent returned information. also
/// as a defense in depth measure - we demand if not trusted. Setting trusted is critical
///
[SecurityCritical, SecurityTreatAsSafe]
private void BuildOrReparentWindow()
{
DemandIfUntrusted();
// Verify the thread has access to the context.
// VerifyAccess();
// Prevent reentry while building a child window,
// also prevent the reconstruction of Disposed objects.
if(_isBuildingWindow || _isDisposed)
{
return;
}
_isBuildingWindow = true;
// Find the source window, this must be the parent window of
// the child window.
IntPtr hwndParent = IntPtr.Zero;
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if(source != null)
{
HwndSource hwndSource = source as HwndSource ;
if(hwndSource != null)
{
hwndParent = hwndSource.CriticalHandle;
}
}
else
{
// attempt to also walk through 3D - if we get a non-null result then we know we are inside of
// a 3D scene which is not supported
PresentationSource goingThrough3DSource = PresentationSource.CriticalFromVisual(this, true /* enable2DTo3DTransition */);
if (goingThrough3DSource != null)
{
if (TraceHwndHost.IsEnabled)
{
TraceHwndHost.Trace(TraceEventType.Warning, TraceHwndHost.HwndHostIn3D);
}
}
}
try
{
if(hwndParent != IntPtr.Zero)
{
if(_hwnd.Handle == IntPtr.Zero)
{
// We now have a parent window, so we can create the child
// window.
BuildWindow(new HandleRef(null, hwndParent));
this.LayoutUpdated += _handlerLayoutUpdated;
this.IsEnabledChanged += _handlerEnabledChanged;
this.IsVisibleChanged += _handlerVisibleChanged;
}
else if(hwndParent != UnsafeNativeMethods.GetParent(_hwnd))
{
// We have a different parent window. Just reparent the
// child window under the new parent window.
UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null,hwndParent));
}
}
else
{
// Reparent the window to the SystemResources.Hwnd
// window. This keeps the child window around, but it is not
// visible. We can reparent the window later when a new
// parent is available
UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null, SystemResources.Hwnd.Handle));
// ...But we have a potential problem: If the SystemResources listener window gets
// destroyed ahead of the call to HwndHost.OnDispatcherShutdown(), the HwndHost's window
// will be destroyed too, before the "logical" Dispose has had a chance to do proper
// shutdown. This turns out to be very significant for WebBrowser/ActiveXHost, which shuts
// down the hosted control through the COM interfaces, and the control destroys its
// window internally. Evidently, the WebOC fails to do full, proper cleanup if its
// window is destroyed unexpectedly.
// To avoid this situation, we make sure SystemResources responds to the Dispatcher
// shutdown event after this HwndHost.
SystemResources.DelayHwndShutdown();
}
}
finally
{
// Be careful to clear our guard bit.
_isBuildingWindow = false;
}
}
///
/// Critical: Calls critical methods - eg. GetWindowLong, IsParent, GetParent etc.
/// TreatAsSafe: We demand if the trusted bit is not set.
/// Setting the trusted bit is criical.
///
[ SecurityCritical, SecurityTreatAsSafe ]
private void BuildWindow(HandleRef hwndParent)
{
// Demand unmanaged code to the caller. IT'S RISKY TO REMOVE THIS
DemandIfUntrusted();
// Allow the derived class to build our HWND.
_hwnd = BuildWindowCore(hwndParent);
if(_hwnd.Handle == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(_hwnd))
{
throw new InvalidOperationException(SR.Get(SRID.ChildWindowNotCreated));
}
// Make sure that the window that was created is indeed a child window.
int windowStyle = UnsafeNativeMethods.GetWindowLong(new HandleRef(this,_hwnd.Handle), NativeMethods.GWL_STYLE);
if((windowStyle & NativeMethods.WS_CHILD) == 0)
{
throw new InvalidOperationException(SR.Get(SRID.HostedWindowMustBeAChildWindow));
}
// Make sure the child window is the child of the expected parent window.
if(hwndParent.Handle != UnsafeNativeMethods.GetParent(_hwnd))
{
throw new InvalidOperationException(SR.Get(SRID.ChildWindowMustHaveCorrectParent));
}
// Only subclass the child HWND if it is owned by our thread.
int idWindowProcess;
int idWindowThread = UnsafeNativeMethods.GetWindowThreadProcessId(_hwnd, out idWindowProcess);
#if WCP_SERVER2003_OR_LATER_ENABLED
IntPtr hCurrentThread = UnsafeNativeMethods.GetCurrentThread();
if ((idWindowThread == SafeNativeMethods.GetThreadId(hCurrentThread)) &&
(idWindowProcess == UnsafeNativeMethods.GetProcessIdOfThread(hCurrentThread)))
#else
if ((idWindowThread == SafeNativeMethods.GetCurrentThreadId()) &&
(idWindowProcess == SafeNativeMethods.GetCurrentProcessId()))
#endif
{
_hwndSubclass = new HwndSubclass(_hwndSubclassHook);
_hwndSubclass.CriticalAttach(_hwnd.Handle);
}
// Initially make sure the window is hidden. We will show it later during rendering.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
// Assume the desired size is the initial size. If the window was
// created with a 0-length dimension, we assume this means we
// should fill all available space.
NativeMethods.RECT rc = new NativeMethods.RECT();
SafeNativeMethods.GetWindowRect(_hwnd, ref rc);
// Convert from pixels to measure units.
// PresentationSource can't be null if we get here.
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
Point ptUpperLeft = new Point(rc.left, rc.top);
Point ptLowerRight = new Point(rc.right, rc.bottom);
ptUpperLeft = source.CompositionTarget.TransformFromDevice.Transform(ptUpperLeft);
ptLowerRight = source.CompositionTarget.TransformFromDevice.Transform(ptLowerRight);
_desiredSize = new Size(ptLowerRight.X - ptUpperLeft.X, ptLowerRight.Y - ptUpperLeft.Y);
// We have a new desired size, so invalidate measure.
InvalidateMeasure();
}
///
/// Critical - calls CriticalHandle.
/// TreatAsSafe - destroying a window previously created considered safe.
///
[ SecurityCritical, SecurityTreatAsSafe ]
private void DestroyWindow()
{
// Destroy the window if we are hosting one.
if( CriticalHandle == IntPtr.Zero)
return;
if(!CheckAccess())
{
// I understand we can get in here on the finalizer thread. And
// touching other GC'ed objects in the finalizer is typically bad.
// But a Context object can be accessed after finalization.
// We need to touch the Context to switch to the right thread.
// If the Context has been finalized then we won't get switched
// and that is OK.
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(AsyncDestroyWindow), null);
return;
}
HandleRef hwnd = _hwnd;
_hwnd = new HandleRef(null, IntPtr.Zero);
DestroyWindowCore(hwnd);
}
private object AsyncDestroyWindow(object arg)
{
DestroyWindow();
return null;
}
///
/// Critical - returns Handle
///
internal IntPtr CriticalHandle
{
[SecurityCritical]
get
{
if(_hwnd.Handle != IntPtr.Zero)
{
if(!UnsafeNativeMethods.IsWindow(_hwnd))
{
_hwnd = new HandleRef(null, IntPtr.Zero);
}
}
return _hwnd.Handle;
}
}
///
/// Critical - can be used to spoof messages.
///
[ SecurityCritical ]
private IntPtr SubclassWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
IntPtr result = IntPtr.Zero ;
// Call the virtual first.
result = WndProc(hwnd, msg, wParam, lParam, ref handled);
// Call the handlers for the MessageHook event.
if(!handled && _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;
}
}
}
return result;
}
private DependencyPropertyChangedEventHandler _handlerEnabledChanged;
private DependencyPropertyChangedEventHandler _handlerVisibleChanged;
private EventHandler _handlerLayoutUpdated;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HwndSubclass _hwndSubclass;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HwndWrapperHook _hwndSubclassHook;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HandleRef _hwnd;
private ArrayList _hooks;
private Size _desiredSize;
private SecurityCriticalDataForSet _fTrusted ;
private bool _isBuildingWindow = false;
private bool _isDisposed = false;
private class WeakEventDispatcherShutdown: WeakReference
{
public WeakEventDispatcherShutdown(HwndHost hwndHost, Dispatcher that): base(hwndHost)
{
_that = that;
_that.ShutdownFinished += new EventHandler(this.OnShutdownFinished);
}
public void OnShutdownFinished(object sender, EventArgs e)
{
HwndHost hwndHost = this.Target as HwndHost;
if(null != hwndHost)
{
hwndHost.OnDispatcherShutdown(sender, e);
}
else
{
Dispose();
}
}
public void Dispose()
{
if(null != _that)
{
_that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished);
}
}
private Dispatcher _that;
}
WeakEventDispatcherShutdown _weakEventDispatcherShutdown;
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Diagnostics;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Input;
using System.Collections;
using MS.Win32;
using MS.Internal;
using MS.Internal.Interop;
using System.Security;
using System.Security.Permissions;
using Microsoft.Win32;
using System.Windows.Media;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Windows.Threading;
using System.Diagnostics.CodeAnalysis;
// Disable pragma warnings to enable PREsharp pragmas
#pragma warning disable 1634, 1691
namespace System.Windows.Interop
{
///
/// The HwndHost class hosts an HWND inside of an Avalon tree.
///
/// Subclassing requires unmanaged code permission
///
///
/// Inheritance demand put in place - as to host activeX controls you should have Unmanaged code permission.
///
///
[SecurityPermission(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
public abstract class HwndHost : FrameworkElement, IDisposable, IWin32Window, IKeyboardInputSink
{
static HwndHost()
{
FocusableProperty.OverrideMetadata(typeof(HwndHost), new FrameworkPropertyMetadata(true));
}
///
/// Constructs an instance of the HwndHost class.
///
/// Not available in Internet zone
///
/// Critical - calls critical code, sets critical _fTrusted flag.
/// PublicOk - trusted flag is set to false.
///
[ SecurityCritical ]
protected HwndHost()
{
Initialize( false ) ;
}
///
/// Critical sets fTrustedBit.
///
[SecurityCritical]
internal HwndHost(bool fTrusted )
{
Initialize( fTrusted ) ;
}
///
/// Because we own an HWND, we implement a finalizer to make sure that we destroy it.
///
~HwndHost()
{
Dispose(false);
}
///
/// Disposes this object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// The Win32 handle of the hosted window.
///
///
/// Callers must have UnmanagedCode permission to call this API.
///
///
/// Critical: This code accesses IsWindow, returns hwndHandle.
/// PublicOk: There is a demand
///
public IntPtr Handle
{
[SecurityCritical]
get
{
SecurityHelper.DemandUnmanagedCode();
return CriticalHandle;
}
}
///
/// An event that is notified of all unhandled messages received
/// by the hosted window.
///
///
/// Callers must have UnmanagedCode permission to call this API.
///
///
/// Demand put in place as a defense in depth measure.
///
public event HwndSourceHook MessageHook
{
add
{
// VerifyAccess();
SecurityHelper.DemandUnmanagedCode();
if(_hooks == null)
{
_hooks = new ArrayList(8);
}
_hooks.Add(value);
}
remove
{
// VerifyAccess();
SecurityHelper.DemandUnmanagedCode();
if(_hooks != null)
{
_hooks.Remove(value);
if(_hooks.Count == 0)
{
_hooks = null;
}
}
}
}
///
///
///
///
/// Critical - Calls ComponentDispatcher.UnsecureCurrentKeyboardMessage.
/// TreatAsSafe - Only calls for trusted controls
///
[SecurityCritical, SecurityTreatAsSafe]
protected override void OnKeyUp(KeyEventArgs e)
{
MSG msg;
if (_fTrusted.Value)
{
msg = ComponentDispatcher.UnsecureCurrentKeyboardMessage;
}
else
{
msg = ComponentDispatcher.CurrentKeyboardMessage;
}
ModifierKeys modifiers = HwndKeyboardInputProvider.GetSystemModifierKeys();
bool handled = ((IKeyboardInputSink)this).TranslateAccelerator(ref msg, modifiers);
if(handled)
e.Handled = handled;
base.OnKeyUp(e);
}
///
///
///
///
/// Critical - Calls ComponentDispatcher.UnsecureCurrentKeyboardMessage.
/// TreatAsSafe - Only calls for trusted controls
///
[SecurityCritical, SecurityTreatAsSafe]
protected override void OnKeyDown(KeyEventArgs e)
{
MSG msg;
if (_fTrusted.Value)
{
msg = ComponentDispatcher.UnsecureCurrentKeyboardMessage;
}
else
{
msg = ComponentDispatcher.CurrentKeyboardMessage;
}
ModifierKeys modifiers = HwndKeyboardInputProvider.GetSystemModifierKeys();
bool handled = ((IKeyboardInputSink)this).TranslateAccelerator(ref msg, modifiers);
if(handled)
e.Handled = handled;
base.OnKeyDown(e);
}
#region IKeyboardInputSink
/// General security note on the implementation pattern of this interface. In Dev10 it was chosen
/// to expose the interface implementation for overriding to customers. We did so by keeping the
/// explicit interface implementations (that do have the property of being hidden from the public
/// contract, which limits IntelliSense on derived types like WebBrowser) while sticking protected
/// virtuals next to them. Those virtuals contain our base implementation, while the explicit
/// interface implementation methods do call trivially into the virtuals.
///
/// This comment outlines the security rationale applied to those methods.
///
///
/// The security attributes on the virtual methods within this region mirror the corresponding
/// IKeyboardInputSink methods; customers can override those methods, so we insert a LinkDemand
/// to encourage them to have a LinkDemand too (via FxCop).
///
///
/// Registers a IKeyboardInputSink with the HwndSource in order
/// to retreive a unique IKeyboardInputSite for it.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual IKeyboardInputSite RegisterKeyboardInputSinkCore(IKeyboardInputSink sink)
{
throw new InvalidOperationException(SR.Get(SRID.HwndHostDoesNotSupportChildKeyboardSinks));
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
IKeyboardInputSite IKeyboardInputSink.RegisterKeyboardInputSink(IKeyboardInputSink sink)
{
return RegisterKeyboardInputSinkCore(sink);
}
///
/// Gives the component a chance to process keyboard input.
/// Return value is true if handled, false if not. Components
/// will generally call a child component's TranslateAccelerator
/// if they can't handle the input themselves. The message must
/// either be WM_KEYDOWN or WM_SYSKEYDOWN. It is illegal to
/// modify the MSG structure, it's passed by reference only as
/// a performance optimization.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOk: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.TranslateAccelerator(ref MSG msg, ModifierKeys modifiers)
{
return TranslateAcceleratorCore(ref msg, modifiers);
}
///
/// Set focus to the first or last tab stop (according to the
/// TraversalRequest). If it can't, because it has no tab stops,
/// the return value is false.
///
protected virtual bool TabIntoCore(TraversalRequest request)
{
return false;
}
bool IKeyboardInputSink.TabInto(TraversalRequest request)
{
return TabIntoCore(request);
}
///
/// The property should start with a null value. The component's
/// container will set this property to a non-null value before
/// any other methods are called. It may be set multiple times,
/// and should be set to null before disposal.
///
///
/// Critical: This API can be used for input spoofing
/// PublicOK: The interface declaration for this method has a demand on it.
///
IKeyboardInputSite IKeyboardInputSink.KeyboardInputSite { get; [SecurityCritical] set; }
///
/// This method is called whenever one of the component's
/// mnemonics is invoked. The message must either be WM_KEYDOWN
/// or WM_SYSKEYDOWN. It's illegal to modify the MSG structrure,
/// it's passed by reference only as a performance optimization.
/// If this component contains child components, the container
/// OnMnemonic will need to call the child's OnMnemonic method.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool OnMnemonicCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.OnMnemonic(ref MSG msg, ModifierKeys modifiers)
{
return OnMnemonicCore(ref msg, modifiers);
}
///
/// Gives the component a chance to process keyboard input messages
/// WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR before calling OnMnemonic.
/// Will return true if "handled" meaning don't pass it to OnMnemonic.
/// The message must be WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or WM_SYSDEADCHAR.
/// It is illegal to modify the MSG structure, it's passed by reference
/// only as a performance optimization.
///
///
/// Critical: This API can be used for input spoofing.
/// PublicOK: This method has a demand on it.
///
/// The security attributes on this method mirror the corresponding IKeyboardInputSink method;
/// customers can override this method, so we insert a LinkDemand.
///
[SecurityCritical, UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted=true)]
protected virtual bool TranslateCharCore(ref MSG msg, ModifierKeys modifiers)
{
return false;
}
///
/// Critical: Calls a method with a LinkDemand on it.
/// PublicOK: The interface declaration for this method has a demand on it.
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
[SecurityCritical]
bool IKeyboardInputSink.TranslateChar(ref MSG msg, ModifierKeys modifiers)
{
return TranslateCharCore(ref msg, modifiers);
}
///
/// This returns true if the sink, or a child of it, has focus. And false otherwise.
///
///
/// Critical: Calls a method with a SUC - GetFocus.
/// TreatAsSafe: No critical information exposed.
/// It's ok to return whether hwndHost has focus within itself in PT.
///
[SecurityCritical, SecurityTreatAsSafe]
protected virtual bool HasFocusWithinCore()
{
HandleRef hwndFocus = new HandleRef(this, UnsafeNativeMethods.GetFocus());
if (_hwnd.Handle != IntPtr.Zero && (hwndFocus.Handle == _hwnd.Handle || UnsafeNativeMethods.IsChild(_hwnd, hwndFocus)))
{
return true;
}
return false;
}
///
/// PublicOK: It's ok to return whether hwndHost has focus within itself in PT.
///
bool IKeyboardInputSink.HasFocusWithin()
{
return HasFocusWithinCore();
}
#endregion IKeyboardInputSink
///
/// Updates the child window to reflect the state of this element.
///
///
/// This includes the size of the window, the position of the
/// window, and the visibility of the window.
///
/// Not available in Internet zone
///
/// Critical: This code accesses critical code and also calls into PresentationSource
/// PublicOk : Repositioning the activeX control is ok.
/// Net effect is to make window location consistent with what layout calculated.
///
[SecurityCritical]
public void UpdateWindowPos()
{
// Verify the thread has access to the context.
// VerifyAccess();
if (_isDisposed)
{
return;
}
// Position the child HWND where layout put it. To do this we
// have to get coordinates relative to the parent window.
PresentationSource source = null;
CompositionTarget vt = null;
if (( CriticalHandle != IntPtr.Zero) && IsVisible)
{
source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if(source != null)
{
vt = source.CompositionTarget;
}
}
if(vt != null && vt.RootVisual != null)
{
// Translate the layout information assigned to us from the co-ordinate
// space of this element, through the root visual, to the Win32 client
// co-ordinate space
NativeMethods.RECT rcClientRTLAdjusted = CalculateAssignedRC(source);
// Set the Win32 position for the child window.
//
// Note, we can't check the existing position because we use
// SWP_ASYNCWINDOWPOS, which means we could have pending position
// change requests that haven't been applied yet. If we need
// this functionality (to avoid the extra SetWindowPos calls),
// we'll have to track the last RECT we sent Win32 ourselves.
//
Rect rectClientRTLAdjusted = PointUtil.ToRect(rcClientRTLAdjusted);
OnWindowPositionChanged(rectClientRTLAdjusted);
// Show the window
// Based on Dwayne, the reason we also show/hide window in UpdateWindowPos is for the
// following kind of scenario: When applying RenderTransform to HwndHost, the hwnd
// will be left behind. Developer can workaround by hide the hwnd first using pinvoke.
// After the RenderTransform is applied to the HwndHost, call UpdateWindowPos to [....] up
// the hwnd's location, size and visibility with WPF.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_SHOW);
}
else
{
// For some reason we shouldn't be displayed: either we don't
// have a parent, or the parent no longer has a root visual,
// or we are marked as not being visible.
//
// Just hide the window to get it out of the way.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
}
}
// Translate the layout information assigned to us from the co-ordinate
// space of this element, through the root visual, to the Win32 client
// co-ordinate space
///
/// Critical: This code accesses critical code and also calls into PresentationSource
/// TAS : Calculate the new position of the activeX control is ok.
/// Net effect is to make window location consistent with what layout calculated.
///
[SecurityCritical, SecurityTreatAsSafe]
private NativeMethods.RECT CalculateAssignedRC(PresentationSource source)
{
Rect rectElement = new Rect(RenderSize);
Rect rectRoot = PointUtil.ElementToRoot(rectElement, this, source);
Rect rectClient = PointUtil.RootToClient(rectRoot, source);
// Adjust for Right-To-Left oriented windows
IntPtr hwndParent = UnsafeNativeMethods.GetParent(_hwnd);
NativeMethods.RECT rcClient = PointUtil.FromRect(rectClient);
NativeMethods.RECT rcClientRTLAdjusted = PointUtil.AdjustForRightToLeft(rcClient, new HandleRef(null, hwndParent));
return rcClientRTLAdjusted;
}
///
/// Disposes this object.
///
///
/// true if called from explisit Dispose; and we free all objects managed and un-managed.
/// false if called from the finalizer; and we free only un-managed objects.
///
///
/// Derived classes should override this if they have additional
/// cleanup to do. The base class implementation should be called.
/// Note that the calling thread must be the dispatcher thread.
/// If a window is being hosted, that window is destroyed.
///
///
/// Critical - call to RemoveSourceChangeHandler invokes critical delegate.
/// SecurityTreatAsSafe : - disposing the HwndHost is considered ok.
///
[ SecurityCritical, SecurityTreatAsSafe ]
protected virtual void Dispose(bool disposing)
{
if (_isDisposed == true)
{
return;
}
if(disposing)
{
// Verify the thread has access to the context.
#pragma warning suppress 6519
VerifyAccess();
// Remove our subclass. Even if this fails, it will be forcably removed
// when the window is destroyed.
if (_hwndSubclass != null)
{
// Check if it is trusted (WebOC and AddInHost), call CriticalDetach to avoid the Demand.
if (_fTrusted.Value == true)
{
_hwndSubclass.CriticalDetach(false);
}
else
{
_hwndSubclass.RequestDetach(false);
}
_hwndSubclass = null;
}
// Drop the hooks so that they can be garbage-collected.
_hooks = null;
// We no longer need to know about the source changing.
PresentationSource.RemoveSourceChangedHandler(this, new SourceChangedEventHandler(OnSourceChanged));
}
if (_weakEventDispatcherShutdown != null) // Can be null if the static ctor failed ... see WebBrowser.
{
_weakEventDispatcherShutdown.Dispose();
_weakEventDispatcherShutdown = null;
}
DestroyWindow();
_isDisposed = true;
}
private void OnDispatcherShutdown(object sender, EventArgs e)
{
Dispose();
}
///
/// Derived classes override this method to actually build the
/// window being hosted.
///
///
/// The parent HWND for the child window.
///
///
/// The HWND handle to the child window that was created.
///
///
/// The window that is returned must be a child window of the
/// specified parent window.
///
/// In addition, the child window will only be subclassed if
/// the window is owned by the calling thread.
///
protected abstract HandleRef BuildWindowCore(HandleRef hwndParent);
///
/// Derived classes override this method to destroy the
/// window being hosted.
///
protected abstract void DestroyWindowCore(HandleRef hwnd);
///
/// A protected override for accessing the window proc of the
/// hosted child window.
///
/// Not available in Internet zone
///
/// Critical - accesses _hwnd Critical member.
/// PublicOk - Inheritance Demand for unmanaged codepermission to buslclass.
/// any caller of the protected must have Unmanaged code permission.
/// DemandIfUntrusted is there as a defense in depth measure.
///
[ SecurityCritical ]
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
DemandIfUntrusted();
switch ((WindowMessage)msg)
{
case WindowMessage.WM_NCDESTROY:
_hwnd = new HandleRef(null, IntPtr.Zero);
break;
// When layout happens, we first calculate the right size/location then call SetWindowPos.
// We only allow the changes that are coming from Avalon layout. The hwnd is not allowed to change by itself.
// So the size of the hwnd should always be RenderSize and the position be where layout puts it.
case WindowMessage.WM_WINDOWPOSCHANGING:
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if (source != null)
{
// 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));
// Get the rect assigned by layout to us.
NativeMethods.RECT assignedRC = CalculateAssignedRC(source);
windowPos.cx = assignedRC.right - assignedRC.left;
windowPos.cy = assignedRC.bottom - assignedRC.top;
windowPos.x = assignedRC.left;
windowPos.y = assignedRC.top;
// marshal size/location back
Marshal.StructureToPtr(windowPos, lParam, true);
}
break;
case WindowMessage.WM_GETOBJECT:
handled = true;
return OnWmGetObject(wParam, lParam);
}
return IntPtr.Zero ;
}
#region Automation
///
/// Creates AutomationPeer ( )
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new HwndHostAutomationPeer(this);
}
///
/// Critical - Calls critical HwndHost.CriticalHandle.
///
[SecurityCritical]
private IntPtr OnWmGetObject(IntPtr wparam, IntPtr lparam)
{
IntPtr result = IntPtr.Zero;
AutomationPeer containerPeer = UIElementAutomationPeer.CreatePeerForElement(this);
if (containerPeer != null)
{
// get the element proxy
IRawElementProviderSimple el = containerPeer.GetInteropChild();
result = AutomationInteropProvider.ReturnRawElementProvider(CriticalHandle, wparam, lparam, el);
}
return result;
}
#endregion Automation
//
[ SecurityCritical ]
protected virtual void OnWindowPositionChanged(Rect rcBoundingBox)
{
if (_isDisposed)
{
return;
}
UnsafeNativeMethods.SetWindowPos(_hwnd,
new HandleRef(null, IntPtr.Zero),
(int)rcBoundingBox.X,
(int)rcBoundingBox.Y,
(int)rcBoundingBox.Width,
(int)rcBoundingBox.Height,
NativeMethods.SWP_ASYNCWINDOWPOS
| NativeMethods.SWP_NOZORDER
| NativeMethods.SWP_NOCOPYBITS
| NativeMethods.SWP_NOACTIVATE);
}
///
/// Return the desired size of the HWND.
///
///
/// HWNDs usually expect a very simplisitic layout model where
/// a window gets to be whatever size it wants to be. To respect
/// this we request the initial size that the window was created
/// at. A window created with a 0 dimension will adopt whatever
/// size the containing layout wants it to be. Layouts are free
/// to actually size the window to whatever they want, and the
/// child window will always be sized accordingly.
///
/// Derived classes should only override this method if they
/// have special knowlege about the size the window wants to be.
/// Examples of such may be special HWND types like combo boxes.
/// In such cases, the base class must still be called, but the
/// return value can be changed appropriately.
///
/// Not available in Internet zone
///
/// Critical - calls CriticalHandle
/// TreatAsSafe - CriticalHandle used for a null check, not leaked out.
/// Ok to Override MeasureOverride and return a size in PT.
/// Demand put in place as a defense in depth measure.
///
///
[ SecurityCritical, SecurityTreatAsSafe ]
protected override Size MeasureOverride(Size constraint)
{
DemandIfUntrusted();
Size desiredSize = new Size(0,0);
// Measure to our desired size. If we have a 0-length dimension,
// the system will assume we don't care about that dimension.
if(CriticalHandle != IntPtr.Zero)
{
desiredSize.Width = Math.Min(_desiredSize.Width, constraint.Width);
desiredSize.Height = Math.Min(_desiredSize.Height, constraint.Height);
}
return desiredSize;
}
///
/// GetDrawing - Returns the drawing content of this Visual.
///
///
/// This returns a bitmap obtained by calling the PrintWindow Win32 API.
///
internal override DrawingGroup GetDrawing()
{
return GetDrawingHelper();
}
///
/// Returns the bounding box of the content.
///
internal override Rect GetContentBounds()
{
return new Rect(RenderSize);
}
///
/// Critical - calls many native methods, accesses critical data
/// TreatAsSafe - Demands UIWindow permission before giving out a bitmap of this window.
///
[SecurityCritical, SecurityTreatAsSafe]
private DrawingGroup GetDrawingHelper()
{
// Printing an HWND requires UIPermissionWindow.AllWindows to give out its pixels.
SecurityHelper.DemandUIWindowPermission();
DrawingGroup drawingGroup = null;
if(_hwnd.Handle != IntPtr.Zero && UnsafeNativeMethods.IsWindow(_hwnd))
{
NativeMethods.RECT rc = new NativeMethods.RECT();
SafeNativeMethods.GetWindowRect(_hwnd, ref rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
HandleRef hdcScreen = new HandleRef(this, UnsafeNativeMethods.GetDC(new HandleRef(this, IntPtr.Zero)));
if(hdcScreen.Handle != IntPtr.Zero)
{
HandleRef hdcBitmap = new HandleRef(this, IntPtr.Zero);
HandleRef hBitmap = new HandleRef(this, IntPtr.Zero);
try
{
hdcBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleDC(hdcScreen));
if(hdcBitmap.Handle != IntPtr.Zero)
{
hBitmap = new HandleRef(this, UnsafeNativeMethods.CriticalCreateCompatibleBitmap(hdcScreen, width, height));
if(hBitmap.Handle != IntPtr.Zero)
{
// Select the bitmap into the DC so that we draw to it.
IntPtr hOldBitmap = UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hBitmap.Handle);
try
{
// Clear the bitmap to white (so we don't waste toner printing a black bitmap something fails).
NativeMethods.RECT rcPaint = new NativeMethods.RECT(0,0,width, height);
IntPtr hbrWhite = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.WHITE_BRUSH);
UnsafeNativeMethods.CriticalFillRect(hdcBitmap.Handle, ref rcPaint, hbrWhite);
// First try to use the PrintWindow API.
bool result = UnsafeNativeMethods.CriticalPrintWindow(_hwnd, hdcBitmap, 0);
if(result == false)
{
// Fall back to sending a WM_PRINT message to the window.
//
// Note: there are known cases where WM_PRINT is not implemented
// to provide visual parity with WM_PAINT. However, since the
// GetDrawing method is virtual, the derived class can override
// this default implementation and provide a better implementation.
UnsafeNativeMethods.SendMessage(_hwnd.Handle, WindowMessage.WM_PRINT, hdcBitmap.Handle, (IntPtr) (NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT));
}
else
{
// There is a know issue where calling PrintWindow on a window will
// clear all dirty regions (but since it is redirected, the screen
// won't be updated). As a result we can leave unpainted pixels on
// the screen if PrintWindow is called when the window was dirty.
//
// To fix this, we just force the child window to repaint.
//
UnsafeNativeMethods.CriticalRedrawWindow(_hwnd, IntPtr.Zero, IntPtr.Zero, NativeMethods.RDW_INVALIDATE | NativeMethods.RDW_ALLCHILDREN);
}
// Create a DrawingGroup that only contains an ImageDrawing that wraps the bitmap.
drawingGroup = new DrawingGroup();
System.Windows.Media.Imaging.BitmapSource bitmapSource = Imaging.CriticalCreateBitmapSourceFromHBitmap(hBitmap.Handle, IntPtr.Zero, Int32Rect.Empty, null, WICBitmapAlphaChannelOption.WICBitmapIgnoreAlpha);
Rect rectElement = new Rect(RenderSize);
drawingGroup.Children.Add(new ImageDrawing(bitmapSource, rectElement));
drawingGroup.Freeze();
}
finally
{
// Put the old bitmap back into the DC.
UnsafeNativeMethods.CriticalSelectObject(hdcBitmap, hOldBitmap);
}
}
}
}
finally
{
UnsafeNativeMethods.ReleaseDC(new HandleRef(this, IntPtr.Zero), hdcScreen);
hdcScreen = new HandleRef(null, IntPtr.Zero);
if(hBitmap.Handle != IntPtr.Zero)
{
UnsafeNativeMethods.DeleteObject(hBitmap);
hBitmap = new HandleRef(this, IntPtr.Zero);
}
if(hdcBitmap.Handle != IntPtr.Zero)
{
UnsafeNativeMethods.CriticalDeleteDC(hdcBitmap);
hdcBitmap = new HandleRef(this, IntPtr.Zero);
}
}
}
}
return drawingGroup;
}
///
/// Critical - calls a method that linkdemands.
/// creates critical for set data.
///
[ SecurityCritical ]
private void Initialize( bool fTrusted )
{
_fTrusted = new SecurityCriticalDataForSet ( fTrusted ) ;
_hwndSubclassHook = new HwndWrapperHook(SubclassWndProc);
_handlerLayoutUpdated = new EventHandler(OnLayoutUpdated);
_handlerEnabledChanged = new DependencyPropertyChangedEventHandler(OnEnabledChanged);
_handlerVisibleChanged = new DependencyPropertyChangedEventHandler(OnVisibleChanged);
PresentationSource.AddSourceChangedHandler(this, new SourceChangedEventHandler(OnSourceChanged));
_weakEventDispatcherShutdown = new WeakEventDispatcherShutdown(this, this.Dispatcher);
}
///
/// Use this method as a defense-in-depth measure only.
///
///
/// Not critical - demands are ok.
///
private void DemandIfUntrusted()
{
if ( ! _fTrusted.Value )
SecurityHelper.DemandUnmanagedCode();
}
///
/// Critical - calls CriticalFromVisual.
/// TreatAsSafe - does not expose the HwndSource obtained.
///
[SecurityCritical , SecurityTreatAsSafe ]
private void OnSourceChanged(object sender, SourceChangedEventArgs e)
{
// Remove ourselves as an IKeyboardInputSinks child of our previous
// containing window.
IKeyboardInputSite keyboardInputSite = ((IKeyboardInputSink)this).KeyboardInputSite;
if (keyboardInputSite != null)
{
if (_fTrusted.Value == true)
{
new UIPermission(PermissionState.Unrestricted).Assert(); //BlessedAssert:
}
try
{
// Derived classes that implement IKeyboardInputSink should support setting it to null.
((IKeyboardInputSink)this).KeyboardInputSite = null;
keyboardInputSite.Unregister();
}
finally
{
if (_fTrusted.Value == true)
{
CodeAccessPermission.RevertAssert();
}
}
}
// Add ourselves as an IKeyboardInputSinks child of our containing window.
IKeyboardInputSink source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */) as IKeyboardInputSink;
if(source != null)
{
if (_fTrusted.Value == true)
{
new UIPermission(PermissionState.Unrestricted).Assert(); //BlessedAssert:
}
try
{
((IKeyboardInputSink)this).KeyboardInputSite = source.RegisterKeyboardInputSink(this);
}
finally
{
if (_fTrusted.Value == true)
{
CodeAccessPermission.RevertAssert();
}
}
}
BuildOrReparentWindow();
}
private void OnLayoutUpdated(object sender, EventArgs e)
{
UpdateWindowPos();
}
///
/// Critical: This code calls into critical method EnableWindow
/// TreatAsSafe: Changing window to being enabled is safe.
///
[SecurityCritical, SecurityTreatAsSafe]
private void OnEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_isDisposed)
{
return;
}
bool boolNewValue = (bool)e.NewValue;
UnsafeNativeMethods.EnableWindow(_hwnd, boolNewValue);
}
///
/// Critical: This code calls into critical method show window
/// TreatAsSafe: Changing window visibility is safe.
/// Window is always a child window.
///
[SecurityCritical,SecurityTreatAsSafe]
private void OnVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (_isDisposed)
{
return;
}
bool vis = (bool)e.NewValue;
//
if(vis)
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_SHOWNA);
else
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
}
// This routine handles the following cases:
// 1) a parent window is present, build the child window
// 2) a parent is present, reparent the child window to it
// 3) a parent window is not present, hide the child window by parenting it to SystemResources.Hwnd window.
///
/// Critical - calls Critical GetParent
/// TreatAsSafe - it doesn't disclose GetParent returned information. also
/// as a defense in depth measure - we demand if not trusted. Setting trusted is critical
///
[SecurityCritical, SecurityTreatAsSafe]
private void BuildOrReparentWindow()
{
DemandIfUntrusted();
// Verify the thread has access to the context.
// VerifyAccess();
// Prevent reentry while building a child window,
// also prevent the reconstruction of Disposed objects.
if(_isBuildingWindow || _isDisposed)
{
return;
}
_isBuildingWindow = true;
// Find the source window, this must be the parent window of
// the child window.
IntPtr hwndParent = IntPtr.Zero;
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
if(source != null)
{
HwndSource hwndSource = source as HwndSource ;
if(hwndSource != null)
{
hwndParent = hwndSource.CriticalHandle;
}
}
else
{
// attempt to also walk through 3D - if we get a non-null result then we know we are inside of
// a 3D scene which is not supported
PresentationSource goingThrough3DSource = PresentationSource.CriticalFromVisual(this, true /* enable2DTo3DTransition */);
if (goingThrough3DSource != null)
{
if (TraceHwndHost.IsEnabled)
{
TraceHwndHost.Trace(TraceEventType.Warning, TraceHwndHost.HwndHostIn3D);
}
}
}
try
{
if(hwndParent != IntPtr.Zero)
{
if(_hwnd.Handle == IntPtr.Zero)
{
// We now have a parent window, so we can create the child
// window.
BuildWindow(new HandleRef(null, hwndParent));
this.LayoutUpdated += _handlerLayoutUpdated;
this.IsEnabledChanged += _handlerEnabledChanged;
this.IsVisibleChanged += _handlerVisibleChanged;
}
else if(hwndParent != UnsafeNativeMethods.GetParent(_hwnd))
{
// We have a different parent window. Just reparent the
// child window under the new parent window.
UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null,hwndParent));
}
}
else
{
// Reparent the window to the SystemResources.Hwnd
// window. This keeps the child window around, but it is not
// visible. We can reparent the window later when a new
// parent is available
UnsafeNativeMethods.SetParent(_hwnd, new HandleRef(null, SystemResources.Hwnd.Handle));
// ...But we have a potential problem: If the SystemResources listener window gets
// destroyed ahead of the call to HwndHost.OnDispatcherShutdown(), the HwndHost's window
// will be destroyed too, before the "logical" Dispose has had a chance to do proper
// shutdown. This turns out to be very significant for WebBrowser/ActiveXHost, which shuts
// down the hosted control through the COM interfaces, and the control destroys its
// window internally. Evidently, the WebOC fails to do full, proper cleanup if its
// window is destroyed unexpectedly.
// To avoid this situation, we make sure SystemResources responds to the Dispatcher
// shutdown event after this HwndHost.
SystemResources.DelayHwndShutdown();
}
}
finally
{
// Be careful to clear our guard bit.
_isBuildingWindow = false;
}
}
///
/// Critical: Calls critical methods - eg. GetWindowLong, IsParent, GetParent etc.
/// TreatAsSafe: We demand if the trusted bit is not set.
/// Setting the trusted bit is criical.
///
[ SecurityCritical, SecurityTreatAsSafe ]
private void BuildWindow(HandleRef hwndParent)
{
// Demand unmanaged code to the caller. IT'S RISKY TO REMOVE THIS
DemandIfUntrusted();
// Allow the derived class to build our HWND.
_hwnd = BuildWindowCore(hwndParent);
if(_hwnd.Handle == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(_hwnd))
{
throw new InvalidOperationException(SR.Get(SRID.ChildWindowNotCreated));
}
// Make sure that the window that was created is indeed a child window.
int windowStyle = UnsafeNativeMethods.GetWindowLong(new HandleRef(this,_hwnd.Handle), NativeMethods.GWL_STYLE);
if((windowStyle & NativeMethods.WS_CHILD) == 0)
{
throw new InvalidOperationException(SR.Get(SRID.HostedWindowMustBeAChildWindow));
}
// Make sure the child window is the child of the expected parent window.
if(hwndParent.Handle != UnsafeNativeMethods.GetParent(_hwnd))
{
throw new InvalidOperationException(SR.Get(SRID.ChildWindowMustHaveCorrectParent));
}
// Only subclass the child HWND if it is owned by our thread.
int idWindowProcess;
int idWindowThread = UnsafeNativeMethods.GetWindowThreadProcessId(_hwnd, out idWindowProcess);
#if WCP_SERVER2003_OR_LATER_ENABLED
IntPtr hCurrentThread = UnsafeNativeMethods.GetCurrentThread();
if ((idWindowThread == SafeNativeMethods.GetThreadId(hCurrentThread)) &&
(idWindowProcess == UnsafeNativeMethods.GetProcessIdOfThread(hCurrentThread)))
#else
if ((idWindowThread == SafeNativeMethods.GetCurrentThreadId()) &&
(idWindowProcess == SafeNativeMethods.GetCurrentProcessId()))
#endif
{
_hwndSubclass = new HwndSubclass(_hwndSubclassHook);
_hwndSubclass.CriticalAttach(_hwnd.Handle);
}
// Initially make sure the window is hidden. We will show it later during rendering.
UnsafeNativeMethods.ShowWindowAsync(_hwnd, NativeMethods.SW_HIDE);
// Assume the desired size is the initial size. If the window was
// created with a 0-length dimension, we assume this means we
// should fill all available space.
NativeMethods.RECT rc = new NativeMethods.RECT();
SafeNativeMethods.GetWindowRect(_hwnd, ref rc);
// Convert from pixels to measure units.
// PresentationSource can't be null if we get here.
PresentationSource source = PresentationSource.CriticalFromVisual(this, false /* enable2DTo3DTransition */);
Point ptUpperLeft = new Point(rc.left, rc.top);
Point ptLowerRight = new Point(rc.right, rc.bottom);
ptUpperLeft = source.CompositionTarget.TransformFromDevice.Transform(ptUpperLeft);
ptLowerRight = source.CompositionTarget.TransformFromDevice.Transform(ptLowerRight);
_desiredSize = new Size(ptLowerRight.X - ptUpperLeft.X, ptLowerRight.Y - ptUpperLeft.Y);
// We have a new desired size, so invalidate measure.
InvalidateMeasure();
}
///
/// Critical - calls CriticalHandle.
/// TreatAsSafe - destroying a window previously created considered safe.
///
[ SecurityCritical, SecurityTreatAsSafe ]
private void DestroyWindow()
{
// Destroy the window if we are hosting one.
if( CriticalHandle == IntPtr.Zero)
return;
if(!CheckAccess())
{
// I understand we can get in here on the finalizer thread. And
// touching other GC'ed objects in the finalizer is typically bad.
// But a Context object can be accessed after finalization.
// We need to touch the Context to switch to the right thread.
// If the Context has been finalized then we won't get switched
// and that is OK.
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(AsyncDestroyWindow), null);
return;
}
HandleRef hwnd = _hwnd;
_hwnd = new HandleRef(null, IntPtr.Zero);
DestroyWindowCore(hwnd);
}
private object AsyncDestroyWindow(object arg)
{
DestroyWindow();
return null;
}
///
/// Critical - returns Handle
///
internal IntPtr CriticalHandle
{
[SecurityCritical]
get
{
if(_hwnd.Handle != IntPtr.Zero)
{
if(!UnsafeNativeMethods.IsWindow(_hwnd))
{
_hwnd = new HandleRef(null, IntPtr.Zero);
}
}
return _hwnd.Handle;
}
}
///
/// Critical - can be used to spoof messages.
///
[ SecurityCritical ]
private IntPtr SubclassWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
IntPtr result = IntPtr.Zero ;
// Call the virtual first.
result = WndProc(hwnd, msg, wParam, lParam, ref handled);
// Call the handlers for the MessageHook event.
if(!handled && _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;
}
}
}
return result;
}
private DependencyPropertyChangedEventHandler _handlerEnabledChanged;
private DependencyPropertyChangedEventHandler _handlerVisibleChanged;
private EventHandler _handlerLayoutUpdated;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HwndSubclass _hwndSubclass;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HwndWrapperHook _hwndSubclassHook;
///
/// Critical - ctor was critical. Manipulating/Handing this out to PT would be unsafe.
///
[ SecurityCritical ]
private HandleRef _hwnd;
private ArrayList _hooks;
private Size _desiredSize;
private SecurityCriticalDataForSet _fTrusted ;
private bool _isBuildingWindow = false;
private bool _isDisposed = false;
private class WeakEventDispatcherShutdown: WeakReference
{
public WeakEventDispatcherShutdown(HwndHost hwndHost, Dispatcher that): base(hwndHost)
{
_that = that;
_that.ShutdownFinished += new EventHandler(this.OnShutdownFinished);
}
public void OnShutdownFinished(object sender, EventArgs e)
{
HwndHost hwndHost = this.Target as HwndHost;
if(null != hwndHost)
{
hwndHost.OnDispatcherShutdown(sender, e);
}
else
{
Dispose();
}
}
public void Dispose()
{
if(null != _that)
{
_that.ShutdownFinished-= new EventHandler(this.OnShutdownFinished);
}
}
private Dispatcher _that;
}
WeakEventDispatcherShutdown _weakEventDispatcherShutdown;
}
}
// 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
- SqlUserDefinedAggregateAttribute.cs
- cryptoapiTransform.cs
- FrugalList.cs
- ManagementScope.cs
- DesignerVerbCollection.cs
- ValidatedControlConverter.cs
- CalendarDateRange.cs
- Button.cs
- TypeSystemProvider.cs
- InvariantComparer.cs
- UrlMappingsModule.cs
- TreeNodeConverter.cs
- EncodingInfo.cs
- Int32CollectionConverter.cs
- ModelUtilities.cs
- RawMouseInputReport.cs
- DataGridViewSelectedCellCollection.cs
- PrintDialog.cs
- RuleSettingsCollection.cs
- HttpBindingExtension.cs
- XmlSchemaDatatype.cs
- AccessViolationException.cs
- SafeJobHandle.cs
- TextRunProperties.cs
- Nullable.cs
- HttpContext.cs
- MethodMessage.cs
- CompareInfo.cs
- dtdvalidator.cs
- WebPartDisplayModeCancelEventArgs.cs
- Symbol.cs
- FileAuthorizationModule.cs
- StreamResourceInfo.cs
- PropertyConverter.cs
- TypeSystemHelpers.cs
- SafeRightsManagementPubHandle.cs
- ellipse.cs
- WebPartDisplayModeEventArgs.cs
- Point.cs
- TraceSwitch.cs
- GuidelineCollection.cs
- SecurityTokenInclusionMode.cs
- HtmlTableCell.cs
- MachinePropertyVariants.cs
- Codec.cs
- CustomGrammar.cs
- ToolboxComponentsCreatedEventArgs.cs
- XmlSerializableServices.cs
- MessageBox.cs
- Shared.cs
- RelationshipDetailsCollection.cs
- SamlConstants.cs
- httpserverutility.cs
- WorkflowItemPresenter.cs
- RSAOAEPKeyExchangeDeformatter.cs
- CharacterBuffer.cs
- Array.cs
- LineSegment.cs
- TextTreeRootTextBlock.cs
- FormatControl.cs
- VSWCFServiceContractGenerator.cs
- ObjectTokenCategory.cs
- EncodingInfo.cs
- SqlSelectStatement.cs
- RulePatternOps.cs
- MsmqAuthenticationMode.cs
- DataMisalignedException.cs
- SafeProcessHandle.cs
- SplineKeyFrames.cs
- EntityDataSourceSelectedEventArgs.cs
- InProcStateClientManager.cs
- MachineKeySection.cs
- KnownBoxes.cs
- ResourceDisplayNameAttribute.cs
- DataMemberConverter.cs
- SQLSingle.cs
- HostSecurityManager.cs
- ListViewEditEventArgs.cs
- SpellCheck.cs
- ToolStripPanelRenderEventArgs.cs
- DocumentPageTextView.cs
- Line.cs
- TokenFactoryFactory.cs
- Geometry.cs
- PermissionSetEnumerator.cs
- ItemCollection.cs
- FixedPageAutomationPeer.cs
- ReferencedType.cs
- DateTimeFormatInfoScanner.cs
- WindowsSspiNegotiation.cs
- MailSettingsSection.cs
- _TransmitFileOverlappedAsyncResult.cs
- _ShellExpression.cs
- ObjectDataSourceChooseTypePanel.cs
- serverconfig.cs
- ClientType.cs
- RewritingPass.cs
- SqlFileStream.cs
- SchemaImporter.cs
- ScriptingScriptResourceHandlerSection.cs