Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Shared / MS / Win32 / hwndwrapper.cs / 1 / hwndwrapper.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2004 // // File: HwndWrapper.cs //----------------------------------------------------------------------------- using System; using System.Security; using System.Security.Permissions; using System.Collections.Generic; using System.Threading; using System.Windows.Threading; using System.Runtime.InteropServices; using System.Diagnostics; using MS.Internal; using System.Globalization; // CultureInfo.InvariantCulture #if WINDOWS_BASE using MS.Internal.WindowsBase; #elif PRESENTATION_CORE using MS.Internal.PresentationCore; #elif PRESENTATIONFRAMEWORK using MS.Internal.PresentationFramework; #elif DRT using MS.Internal.Drt; #else #error Attempt to use FriendAccessAllowedAttribute from an unknown assembly. using MS.Internal.YourAssemblyName; #endif // Disable pragma warnings to enable PREsharp pragmas #pragma warning disable 1634, 1691 namespace MS.Win32 { [FriendAccessAllowed] internal class HwndWrapper : DispatcherObject, IDisposable { ////// SecurityCritical: uses UnsafeNativeMethods RegisterWindowMessage /// SecurityTreatAsSafe: This is safe to call /// [SecurityCritical, SecurityTreatAsSafe] static HwndWrapper() { s_msgGCMemory = UnsafeNativeMethods.RegisterWindowMessage("HwndWrapper.GetGCMemMessage"); } ////// SecurityCritical: uses UnsafeNativeMethods GetModuleHandle /// [SecurityCritical] public HwndWrapper( int classStyle, int style, int exStyle, int x, int y, int width, int height, string name, IntPtr parent, HwndWrapperHook[] hooks) { _ownerThreadID = new SecurityCriticalDataForSet(Thread.CurrentThread.ManagedThreadId); // First, add the set of hooks. This allows the hooks to receive the // messages sent to the window very early in the process. if(hooks != null) { for(int i = 0, iEnd = hooks.Length; i < iEnd; i++) { if(null != hooks[i]) AddHook(hooks[i]); } } _wndProc = new SecurityCriticalData (new HwndWrapperHook(WndProc)); // We create the HwndSubclass object so that we can use its // window proc directly. We will not be "subclassing" the // window we create. HwndSubclass hwndSubclass = new HwndSubclass(_wndProc.Value); // Register a unique window class for this instance. NativeMethods.WNDCLASSEX_D wc_d = new NativeMethods.WNDCLASSEX_D(); IntPtr hNullBrush = UnsafeNativeMethods.CriticalGetStockObject(NativeMethods.NULL_BRUSH); if (hNullBrush == IntPtr.Zero) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle( null ); // We need to keep the Delegate object alive through the call to CreateWindowEx(). // Subclass.WndProc will install a better delegate (to the same function) when it // processes the first message. // But this first delegate needs be held alive until then. NativeMethods.WndProc initialWndProc = new NativeMethods.WndProc(hwndSubclass.SubclassWndProc); // The class name is a concat of AppName, ThreadName, and RandomNumber. // Register will fail if the string gets over 255 in length. // So limit each part to a reasonable amount. string appName; if(null != AppDomain.CurrentDomain.FriendlyName && 128 <= AppDomain.CurrentDomain.FriendlyName.Length) appName = AppDomain.CurrentDomain.FriendlyName.Substring(0, 128); else appName = AppDomain.CurrentDomain.FriendlyName; string threadName; if(null != Thread.CurrentThread.Name && 64 <= Thread.CurrentThread.Name.Length) threadName = Thread.CurrentThread.Name.Substring(0, 64); else threadName = Thread.CurrentThread.Name; // Create a suitable unique class name. _classAtom = 0; string randomName = Guid.NewGuid().ToString(); string className = String.Format(CultureInfo.InvariantCulture, "HwndWrapper[{0};{1};{2}]", appName, threadName, randomName); wc_d.cbSize = Marshal.SizeOf(typeof(NativeMethods.WNDCLASSEX_D)); wc_d.style = classStyle; wc_d.lpfnWndProc = initialWndProc; wc_d.cbClsExtra = 0; wc_d.cbWndExtra = 0; wc_d.hInstance = hInstance; wc_d.hIcon = IntPtr.Zero; wc_d.hCursor = IntPtr.Zero; wc_d.hbrBackground = hNullBrush; wc_d.lpszMenuName = ""; wc_d.lpszClassName = className; wc_d.hIconSm = IntPtr.Zero; // Register the unique class for this instance. // Note we use a GUID in the name so we are confident that // the class name should be unique. And RegisterClassEx won't // fail (for that reason). _classAtom = UnsafeNativeMethods.RegisterClassEx(wc_d); // call CreateWindow _isInCreateWindow = true; try { _handle = new SecurityCriticalDataClass (UnsafeNativeMethods.CreateWindowEx(exStyle, className, name, style, x, y, width, height, new HandleRef(null,parent), new HandleRef(null,IntPtr.Zero), new HandleRef(null,IntPtr.Zero), null)); } finally { _isInCreateWindow = false; if(_handle == null || _handle.Value == IntPtr.Zero) { // Because the HwndSubclass is pinned, but the HWND creation failed, // we need to manually clean it up. hwndSubclass.Dispose(); } } GC.KeepAlive(initialWndProc); } ~HwndWrapper() { Dispose(/*disposing = */ false, /*isHwndBeingDestroyed = */ false); } public virtual void Dispose() { // VerifyAccess(); Dispose(/*disposing = */ true, /*isHwndBeingDestroyed = */ false); GC.SuppressFinalize(this); } // internal Dispose(bool, bool) /// /// TreatAsSafe: we demand when constructed, disposing considered safe /// Critical: Elevates by calling an UnsafeNativeMethod /// [SecurityTreatAsSafe, SecurityCritical] private void Dispose(bool disposing, bool isHwndBeingDestroyed) { if (_isDisposed) { // protect against re-entrancy: Calling DestroyWindow here will send // a WM_NCDESTROY -- WndProc may catch this and call Dispose again. return; } if(disposing) { // diposing == false means we're being called from the finalizer // and can't follow any reference types that may themselves be // finalizable - thus don't call the Disposed callback. // Notify listeners that we are being disposed. if(Disposed != null) { Disposed(this, EventArgs.Empty); } } // We are now considered disposed. _isDisposed = true; if (isHwndBeingDestroyed) { // The window is in the process of being destroyed. We can't call UnregisterClass yet // so we'll ask the Dispatcher to do it later when the window is gone. Dispatcher.BeginInvoke(DispatcherPriority.Normal, (DispatcherOperationCallback)UnregisterClass, _classAtom); } else if (_handle != null && _handle.Value != IntPtr.Zero) { // The window isn't in the process of being destroyed and it hasn't been destroyed yet // (we know this since we're listening for WM_NCDESTROY). Since we're being disposed // we destroy it now. if(Thread.CurrentThread.ManagedThreadId == _ownerThreadID.Value) { // We are the owner thread, we can safely destroy the window and unregister // the class DestroyWindow(new DestroyWindowArgs(_handle, _classAtom)); } else { // Post a DispatcherOperation to ask the owner thread to destroy the window for us. Dispatcher.BeginInvoke( DispatcherPriority.Normal, (DispatcherOperationCallback)DestroyWindow, new DestroyWindowArgs(_handle, _classAtom)); } } _classAtom = 0; _handle = null; } ////// Critical: Returns the handle of the window /// public IntPtr Handle { [SecurityCritical] get { // This could be called from other threads, so snap the member. SecurityCriticalDataClasshandle = _handle; if (handle != null) { return handle.Value; } else { return IntPtr.Zero; } } } public event EventHandler Disposed; /// /// Critical: Used to add hooks to the system which can be used to listen to window messages /// [SecurityCritical] public void AddHook(HwndWrapperHook hook) { //VerifyAccess(); if(_hooks == null) { _hooks = new SecurityCriticalDataClass(new WeakReferenceList()); } _hooks.Value.Insert(0, hook); } /// /// Critical: Used to add hooks to the system which can be used to listen to window messages /// [SecurityCritical] internal void AddHookLast(HwndWrapperHook hook) { if(_hooks == null) { _hooks = new SecurityCriticalDataClass(new WeakReferenceList()); } _hooks.Value.Add(hook); } /// /// Critical: This code acceses critical value hooks /// [SecurityCritical] public void RemoveHook(HwndWrapperHook hook) { //VerifyAccess(); if (_hooks != null) { _hooks.Value.Remove(hook); } } ////// Critical: Calls the hooks and can be used to send spurious input to the system /// [SecurityCritical] private IntPtr WndProc(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 hooks if(_hooks != null) { foreach(HwndWrapperHook hook in _hooks.Value) { result = hook(hwnd, msg, wParam, lParam, ref handled); CheckForCreateWindowFailure(result, handled); if(handled) { break; } } } if (msg == NativeMethods.WM_NCDESTROY) { Dispose(/*disposing = */ true, /*isHwndBeingDestroyed = */ true); GC.SuppressFinalize(this); // We want the default window proc to process this message as // well, so we mark it as unhandled. handled = false; } else if (msg == s_msgGCMemory) { // This is a special message we respond to by forcing a GC Collect. This // is used by test apps and such. IntPtr lHeap = (IntPtr)GC.GetTotalMemory((wParam == new IntPtr(1) )? true : false); result = lHeap; handled = true; } CheckForCreateWindowFailure(result, true); // return our result return result; } private void CheckForCreateWindowFailure( IntPtr result, bool handled ) { if( ! _isInCreateWindow ) return; if( IntPtr.Zero != result ) { System.Diagnostics.Debug.WriteLine("Non-zero WndProc result=" + result); if( handled ) { if( System.Diagnostics.Debugger.IsAttached ) System.Diagnostics.Debugger.Break(); else throw new InvalidOperationException(); } } } ////// Destroys the window with the given handle and class atom and unregisters its window class /// /// A DestrowWindowParams instance ////// Critical: Destroys a Window and calls a critical method /// Partial Trust scenarios can execute this method. It takes an object so that it /// can be called by a DispatcherOperationCallback and avoid a DynamicInvoke, which /// requires ReflectionPermission. /// [SecurityCritical] internal static object DestroyWindow(object args) { SecurityCriticalDataClasshandle = ((DestroyWindowArgs)args).Handle; ushort classAtom = ((DestroyWindowArgs)args).ClassAtom; Invariant.Assert(handle != null && handle.Value != IntPtr.Zero, "Attempting to destroy an invalid hwnd"); UnsafeNativeMethods.DestroyWindow(new HandleRef(null, handle.Value)); UnregisterClass((object)classAtom); return null; } /// /// Unregisters the window class represented by classAtom /// /// A ushort representing the class atom ////// Critical: Unregisters the window class and calls a critical method /// Partial Trust scenarios can execute this method. It takes an object so that it /// can be called by a DispatcherOperationCallback and avoid a DynamicInvoke, which /// requires ReflectionPermission. /// [SecurityCritical] internal static object UnregisterClass(object arg) { ushort classAtom = (ushort)arg; if (classAtom != 0) { IntPtr hInstance = UnsafeNativeMethods.GetModuleHandle(null); UnsafeNativeMethods.UnregisterClass( new IntPtr(classAtom), //* this function is defined as taking a type lpClassName - but this can be an atom. 2 Low Bytes are the atom*/ hInstance); } return null; } // This is used only so that DestroyWindow can take a single object parameter // in order for it to be called by a DispatcherOperationCallback internal class DestroyWindowArgs { public DestroyWindowArgs(SecurityCriticalDataClasshandle, ushort classAtom) { _handle = handle; _classAtom = classAtom; } public SecurityCriticalDataClass Handle { get { return _handle; } } public ushort ClassAtom { get { return _classAtom; } } private SecurityCriticalDataClass _handle; private ushort _classAtom; } private SecurityCriticalDataClass _handle; private UInt16 _classAtom; private SecurityCriticalDataClass _hooks; private SecurityCriticalDataForSet _ownerThreadID; private SecurityCriticalData _wndProc; private bool _isDisposed; private bool _isInCreateWindow = false; // debugging variable (temporary) // Message to cause a dispose. We need this to ensure we destroy the window on the right thread. /// /// Critical: This is initialized under an elevation /// [SecurityCritical] private static int s_msgGCMemory; } // class RawWindow } // 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
- CrossSiteScriptingValidation.cs
- SqlLiftIndependentRowExpressions.cs
- LogConverter.cs
- Matrix3D.cs
- WebScriptMetadataMessageEncoderFactory.cs
- InternalConfigSettingsFactory.cs
- BufferedReadStream.cs
- XmlMembersMapping.cs
- SpellCheck.cs
- CellQuery.cs
- SqlInfoMessageEvent.cs
- FormViewPagerRow.cs
- ImageAttributes.cs
- DrawingAttributeSerializer.cs
- MarshalByRefObject.cs
- SqlCacheDependencyDatabaseCollection.cs
- bindurihelper.cs
- _ConnectionGroup.cs
- CommandConverter.cs
- EdgeProfileValidation.cs
- InvokeProviderWrapper.cs
- UrlPropertyAttribute.cs
- PipeSecurity.cs
- ComplexPropertyEntry.cs
- SqlVersion.cs
- WorkerRequest.cs
- Rectangle.cs
- DataGrid.cs
- TableLayoutRowStyleCollection.cs
- SourceFileInfo.cs
- DesignerTransactionCloseEvent.cs
- Properties.cs
- KnownBoxes.cs
- Assert.cs
- CodeTypeReference.cs
- SpecularMaterial.cs
- MaskedTextProvider.cs
- BinaryFormatterWriter.cs
- ToolboxDataAttribute.cs
- MessageBox.cs
- UpdatePanelTriggerCollection.cs
- DataPagerFieldCollection.cs
- ListManagerBindingsCollection.cs
- SqlErrorCollection.cs
- EntityContainerEmitter.cs
- StringArrayConverter.cs
- OutputCacheProfileCollection.cs
- QueueException.cs
- BigInt.cs
- TimeSpanConverter.cs
- SqlGenericUtil.cs
- OdbcEnvironment.cs
- PackUriHelper.cs
- BmpBitmapEncoder.cs
- XmlUnspecifiedAttribute.cs
- ImageMap.cs
- HttpClientCredentialType.cs
- CorePropertiesFilter.cs
- TransformGroup.cs
- Material.cs
- PasswordPropertyTextAttribute.cs
- CalendarDay.cs
- AnnotationService.cs
- GridToolTip.cs
- WindowsFormsHelpers.cs
- SurrogateSelector.cs
- ToolStripOverflow.cs
- ActivityWithResult.cs
- EdmMember.cs
- PropertyCondition.cs
- FieldMetadata.cs
- xdrvalidator.cs
- Label.cs
- ResXBuildProvider.cs
- InkCollectionBehavior.cs
- BrowsableAttribute.cs
- CommonBehaviorsSection.cs
- FrameworkTextComposition.cs
- RelatedView.cs
- EventProvider.cs
- Expressions.cs
- TableNameAttribute.cs
- SamlAuthenticationStatement.cs
- Knowncolors.cs
- XamlTemplateSerializer.cs
- PriorityBinding.cs
- PrintSystemException.cs
- _ConnectOverlappedAsyncResult.cs
- PromptEventArgs.cs
- ExceptionUtil.cs
- MenuItemBinding.cs
- SchemaObjectWriter.cs
- SyncOperationState.cs
- ScriptIgnoreAttribute.cs
- ServiceTimeoutsBehavior.cs
- NameSpaceExtractor.cs
- TextBoxAutoCompleteSourceConverter.cs
- ConfigurationSectionGroupCollection.cs
- ObjectStateEntryBaseUpdatableDataRecord.cs
- CodePageUtils.cs