HwndSubclass.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Shared / MS / Win32 / HwndSubclass.cs / 4 / HwndSubclass.cs

                            using System; 
using System.Runtime.InteropServices;
using System.Security.Permissions;
using MS.Internal;
using MS.Utility; 
using System.Windows;
using System.Windows.Threading; 
using System.Security;                       // CAS 
using System.Threading;                      // Thread
 
// The SecurityHelper class differs between assemblies and could not actually be
//  shared, so it is duplicated across namespaces to prevent name collision.
#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 a class (duplicated across multiple namespaces) from an unknown assembly.
#endif 

namespace MS.Win32 
{ 
    /// 
    ///     The HwndSubclass class provides a managed way to subclass an existing 
    ///     HWND.  This class inserts itself into the WNDPROC chain for the
    ///     window, and will call a specified delegate to process the window
    ///     messages that arrive.  The delegate has a slightly different
    ///     signature than a WNDPROC to be more specific about whether the 
    ///     message was handled or not.  If the message was not handled by the
    ///     delegate, this class passes the message on down the WNDPROC chain. 
    /// 
    ///     To use this class properly, simply:
    ///     1) Create an instance of the HwndSubclass class and pass the delegate 
    ///        to the constructor.
    ///     2) Call Attach(HWND) to subclass an existing window.
    ///     3) Call Detach(false) to unsubclass the window when you are done.
    /// 
    ///     You can also just call RequestDetach() to send a message to the
    ///     window that will cause the HwndSubclass to detach itself.  This is 
    ///     important if you are on a different thread, as the HwndSubclass class 
    ///     is not thread safe and will be operated on by the thread that owns
    ///     the window. 
    /// 
    ///  Not available to partial trust callers
    [FriendAccessAllowed] // Built into Base, also used by Framework
    internal class HwndSubclass : IDisposable 
    {
        ///  
        ///  Critical: Elevates by calling an UnsafeNativeMethod 
        ///
        [SecurityCritical] 
        static HwndSubclass()
        {
            DetachMessage = UnsafeNativeMethods.RegisterWindowMessage("HwndSubclass.DetachMessage");
            if (DetachMessage == 0) 
            {
                throw new System.ComponentModel.Win32Exception(); 
            } 

            // Go find the address of DefWindowProc. 
            IntPtr hModuleUser32 = UnsafeNativeMethods.GetModuleHandle(ExternDll.User32);
            IntPtr address = UnsafeNativeMethods.GetProcAddress(new HandleRef(null,hModuleUser32), "DefWindowProcW");

            DefWndProc = address; 
        }
 
        ///  
        ///     This HwndSubclass constructor binds the HwndSubclass object to the
        ///     specified delegate.  This delegate will be called to process 
        ///     the messages that are sent or posted to the window.
        /// 
        /// 
        ///     The delegate that will be called to process the messages that 
        ///     are sent or posted to the window.
        ///  
        ///  
        ///     Nothing.
        ///  
        /// 
        ///  Critical: This code creates an object that is not allowed in partial trust
        /// 
        [SecurityCritical] 
        public HwndSubclass(HwndWrapperHook hook)
        { 
            if(hook == null) 
            {
                throw new ArgumentNullException("hook"); 
            }

            _bond = Bond.Unattached;
            _hook = new WeakReference(hook); 

            // Allocate a GC handle so that we won't be collected, even if all 
            // references to us get released.  This is because a component outside 
            // of the managed code (ie. the window we are subclassing) still holds
            // a reference to us - just not a reference that the GC recognizes. 
            _gcHandle = GCHandle.Alloc(this);
        }

        ~HwndSubclass() 
        {
            // In Shutdown, the finalizer is called on LIVE OBJECTS. 
            // 
            // So this method can be called.  (even though we are pinned)
            // If it is, we're shutting down so it's OK to force unhooking 
            // the subclass.
            Dispose(true);
        }
 
        public virtual void Dispose()
        { 
            Dispose(false); 
        }
 
        /// 
        ///  Critical: It accesses the hooks
        ///  TreatAsSafe: setting them to null and not exposing them is safe
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private bool Dispose(bool forceUnhook) 
        { 
            _hook = null;
 
            return UnhookWindowProc(forceUnhook);
        }

        ///  
        ///     This method subclasses the specified window, such that the
        ///     delegate specified to the constructor will be called to process 
        ///     the messages that are sent or posted to this window. 
        /// 
        ///  
        ///     The window to subclass.
        /// 
        /// 
        ///     An identifier that can be used to reference this instance of 
        ///     the HwndSubclass class in the static RequestDetach method.
        ///  
        ///  
        ///  Critical: it calls CriticalAttach
        ///  TreatAsSafe: Demands for all windows 
        ///
        [SecurityCritical, SecurityTreatAsSafe]
        public IntPtr Attach(IntPtr hwnd)
        { 
            SecurityHelper.DemandUIWindowPermission();
 
            if (_bond != Bond.Unattached) 
                throw new InvalidOperationException(SR.Get(SRID.HwndSubclassMultipleAttach));
 
            return CriticalAttach( hwnd ) ;
        }

 
        /// 
        ///     This method unsubclasses this HwndSubclass object from the window 
        ///     it previously subclassed. The HwndSubclass object is not thread 
        ///     safe, and should thus be called only by the thread that owns
        ///     the window being unsubclassed. 
        /// 
        /// 
        ///     Whether or not the unsubclassing should be forced.  Due to the
        ///     way that Win32 implements window subclassing, it is not always 
        ///     possible to safely remove a window proc from the WNDPROC chain.
        ///     However, the delegate will not be called again after this 
        ///     method returns. 
        /// 
        ///  
        ///     Whether or not this HwndSubclass object was actually removed from
        ///     the WNDPROC chain.
        /// 
        ///  
        ///  TreatAsSafe:  Demands for all windows
        ///  Critical: Elevates by calling an UnsafeNativeMethod 
        /// 
        [SecurityCritical]
        public bool Detach(bool force) 
        {
            SecurityHelper.DemandUIWindowPermission();

            return CriticalDetach(force); 
        }
 
        ///  
        ///  Critical: Elevates by calling an UnsafeNativeMethod
        /// 
        [SecurityCritical]
        internal bool CriticalDetach(bool force)
        {
            bool detached; 

            // If we have already detached, return immediately. 
            if(_bond == Bond.Detached || _bond == Bond.Unattached) 
            {
                detached = true; 
            }
            else
            {
                // When we detach, we simply make a note of it. 
                _bond = Bond.Orphaned;
 
                // try to unhook the subclass 
                detached = Dispose(force);
            } 

            return detached;
        }
 
        /// 
        ///     This method sends a message to the window that is currently 
        ///     subclassed by this instance of the HwndSubclass class, in order 
        ///     to unsubclass the window.  This is important if a different
        ///     thread than the thread that owns the window wants to initiate 
        ///     the unsubclassing.
        /// 
        /// 
        ///     Whether or not the unsubclassing should be forced.  Due to the 
        ///     way that Win32 implements window subclassing, it is not always
        ///     possible to safely remove a window proc from the WNDPROC chain. 
        ///     However, the delegate will not be called again after this 
        ///     method returns.
        ///  
        /// 
        ///     Nothing.
        /// 
        ///  
        ///  TreatAsSafe:  Does not expose the hwnd
        ///  Critical: Probes _hwndAttached for value 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public void RequestDetach(bool force) 
        {
            // Let the static version do the work.
            if(_hwndAttached != IntPtr.Zero)
            { 
                RequestDetach(_hwndAttached, (IntPtr) _gcHandle, force);
            } 
        } 

        ///  
        ///     This method sends a message to the specified window in order to
        ///     cause the specified bridge to unsubclass the window.  This is
        ///     important if a different thread than the thread that owns the
        ///     window wants to initiate the unsubclassing.  The HwndSubclass 
        ///     object must be identified by the value returned from Attach().
        ///  
        ///  
        ///     The window to unsubclass.
        ///  
        /// 
        ///     The identifier of the subclass to unsubclass.
        /// 
        ///  
        ///     Whether or not the unsubclassing should be forced.  Due to the
        ///     way that Win32 implements window subclassing, it is not always 
        ///     possible to safely remove a window proc from the WNDPROC chain. 
        ///     However, the delegate will not be called again after this
        ///     method returns. 
        /// 
        /// 
        ///     Nothing.
        ///  
        /// 
        ///  TreatAsSafe:  Demands for all windows code 
        ///  Critical: Elevates by calling an UnsafeNativeMethod 
        ///
        [SecurityCritical, SecurityTreatAsSafe ] 
        public static void RequestDetach(IntPtr hwnd, IntPtr subclass, bool force)
        {
            SecurityHelper.DemandUIWindowPermission();
            if(hwnd == IntPtr.Zero) 
            {
                throw new ArgumentNullException("hwnd"); 
            } 
            if(subclass == IntPtr.Zero)
            { 
                throw new ArgumentNullException("subclass");
            }

            int iForce = force ? 1 : 0; 
            UnsafeNativeMethods.SendMessage(hwnd, DetachMessage, subclass, (IntPtr) iForce);
        } 
 
        /// 
        ///     This is the WNDPROC that gets inserted into the window's 
        ///     WNDPROC chain.  It responds to various conditions that
        ///     would cause this HwndSubclass object to unsubclass the window,
        ///     and then calls the delegate specified to the HwndSubclass
        ///     constructor to process the message.  If the delegate does not 
        ///     handle the message, the message is then passed on down the
        ///     WNDPROC chain for further processing. 
        ///  
        /// 
        ///     The window that this message was sent or posted to. 
        /// 
        /// 
        ///     The message that was sent or posted.
        ///  
        /// 
        ///     A parameter for the message that was sent or posted. 
        ///  
        /// 
        ///     A parameter for the message that was sent or posted. 
        /// 
        /// 
        ///     The value that is the result of processing the message.
        ///  
        ///
        ///  Critical: this function elevates via unsafe native method calls 
        /// 
        [SecurityCritical]
        public IntPtr SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) 
        {
            IntPtr retval = IntPtr.Zero;
            bool handled = false;
 
            // If we are unattached and we receive a message, then we must have
            // been used as the original window proc.  In this case, we insert 
            // ourselves as if the original window proc had been DefWindowProc. 
            // We pass in DefWndProcStub as a workaround for a bug in UxTheme on
            // Windows XP. For details see the comment on the DefWndProcWrapper method. 
            if(_bond == Bond.Unattached)
            {
                HookWindowProc(hwnd, new NativeMethods.WndProc(SubclassWndProc),
                    Marshal.GetFunctionPointerForDelegate(DefWndProcStub)); 
            }
            else if(_bond == Bond.Detached) 
            { 
                throw new InvalidOperationException();
            } 

            IntPtr oldWndProc = _oldWndProc;    // in case we get detached during this method

            if(msg == DetachMessage) 
            {
                // We received our special message to detach.  Make sure it is intended 
                // for us by matching the bridge. 
                if(wParam == IntPtr.Zero || wParam == (IntPtr)_gcHandle)
                { 
                    int param = (int)lParam;    // 0 - normal, 1 - force, 2 - force and forward
                    bool force = (param > 0);

                    retval = CriticalDetach(force) ? new IntPtr(1) : IntPtr.Zero ; 
                    handled = (param < 2);
                } 
            } 
            else
            { 
                // Pass this message to our delegate function.  Do this under
                // the exception filter/handlers of the dispatcher for this thread.
                Dispatcher dispatcher = Dispatcher.FromThread(Thread.CurrentThread);
                if(dispatcher != null && !dispatcher.HasShutdownFinished) 
                {
                    if (_dispatcherOperationCallback == null) 
                        _dispatcherOperationCallback = new DispatcherOperationCallback(this.DispatcherCallbackOperation); 

                    // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid 
                    // creating a new data structure every time we call DispatcherCallbackOperation
                    // Cache the param locally in case of reentrance and set _paramDispatcherCallbackOperation to null so reentrancy calls will create a new param
                    if (_paramDispatcherCallbackOperation == null)
                        _paramDispatcherCallbackOperation = new DispatcherOperationCallbackParameter(); 

                    DispatcherOperationCallbackParameter param = _paramDispatcherCallbackOperation; 
                    _paramDispatcherCallbackOperation = null; 
                    param.hwnd = hwnd;
                    param.msg = msg; 
                    param.wParam = wParam;
                    param.lParam = lParam;
                    //synchronous call
                    object result = dispatcher.Invoke( 
                             DispatcherPriority.Send,
                             _dispatcherOperationCallback, 
                             param); 

 
                    if (result != null)
                    {
                        handled = param.handled;
                        retval = param.retVal; 
                    }
 
                    // Restore _paramDispatcherCallbackOperation to the previous value so we will reuse it on the next call 
                    _paramDispatcherCallbackOperation = param;
                } 

                // Handle WM_NCDESTROY explicitly to forcibly clean up.
                if(msg == NativeMethods.WM_NCDESTROY)
                { 
                    // The fact that we received this message means that we are
                    // still in the call chain.  This is our last chance to clean 
                    // up, and no other message should be received by this window 
                    // proc again. It is OK to force a cleanup now.
                    CriticalDetach(true); 

                    // Always pass the WM_NCDESTROY message down the chain!
                    handled = false;
                } 
            }
 
            // If our window proc didn't handle this message, pass it on down the 
            // chain.
            if(!handled) 
            {
                retval = CallOldWindowProc(oldWndProc, hwnd, msg, wParam, lParam);
            }
 
            return retval;
        } 
 
        // Perf bug: 1963989
        // _paramDispatcherCallbackOperation is a thread static member which should be reused to avoid 
        // creating a new data structure every time we DispatcherCallbackOperation is called
        // It also contains the return results (handled and retValue) from DispatcherCallbackOperation call
        /// 
        ///  Critical: DispatcherOperationCallbackParameter contains hwnd, which is critical 
        ///
        [SecurityCritical] 
        [ThreadStatic] 
        private static DispatcherOperationCallbackParameter _paramDispatcherCallbackOperation;
 
        // This class is used as a parameter and return result for DispatcherCallbackOperation call
        private class DispatcherOperationCallbackParameter
        {
            public IntPtr hwnd, wParam, lParam, retVal; 
            public int msg;
            public bool handled; 
        } 

        private DispatcherOperationCallback _dispatcherOperationCallback = null; 

        /// 
        ///  Critical: it calls GetWindowLongPtr(), which is Critical
        /// 
        [ SecurityCritical ]
        internal IntPtr CriticalAttach( IntPtr hwnd ) 
        { 
            if(hwnd == IntPtr.Zero)
            { 
                throw new ArgumentNullException("hwnd");
            }
            if(_bond != Bond.Unattached)
            { 
                throw new InvalidOperationException();
            } 
 
            NativeMethods.WndProc newWndProc = new NativeMethods.WndProc(SubclassWndProc);
            IntPtr oldWndProc = UnsafeNativeMethods.GetWindowLongPtr(new HandleRef(this,hwnd), NativeMethods.GWL_WNDPROC); 
            HookWindowProc(hwnd, newWndProc, oldWndProc);

            // Return the GC handle as a unique identifier of this
            return (IntPtr) _gcHandle; 
        }
 
        ///  
        ///     Critical: This code is a callback into the dispatcher. It is present
        ///      because under enforcements anonymous delagates throw a demand since 
        ///      it becomes a transparent calling critical for this particular call
        /// 
        [SecurityCritical]
        private object DispatcherCallbackOperation(object o) 
        {
            DispatcherOperationCallbackParameter param = (DispatcherOperationCallbackParameter)o; 
            param.handled = false; 
            param.retVal = IntPtr.Zero;
            if (_bond == Bond.Attached) 
            {
                HwndWrapperHook hook= _hook.Target as HwndWrapperHook;

                if (hook != null) 
                {
                    // make the call 
                    param.retVal = hook(param.hwnd, param.msg, param.wParam, param.lParam, ref param.handled); 
                }
            } 

            return param;
        }
 
        /// 
        ///     This method lets the user call the old WNDPROC, i.e 
        ///     the next WNDPROC in the chain directly. 
        /// 
        ///  
        ///     The WndProc to call.
        /// 
        /// 
        ///     The window that this message was sent or posted to. 
        /// 
        ///  
        ///     The message that was sent or posted. 
        /// 
        ///  
        ///     A parameter for the message that was sent or posted.
        /// 
        /// 
        ///     A parameter for the message that was sent or posted. 
        /// 
        ///  
        ///     The value that is the result of processing the message. 
        /// 
        ///  
        ///  Critical: Elevates by calling an UnsafeNativeMethod
        ///
        [SecurityCritical]
        IntPtr CallOldWindowProc(IntPtr oldWndProc, IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) 
        {
            return UnsafeNativeMethods.CallWindowProc(oldWndProc, hwnd, msg, wParam, lParam); 
        } 

        /// 
        /// Critical - it calls CriticalSetWindowLong()
        ///
        [SecurityCritical]
        private void HookWindowProc(IntPtr hwnd, NativeMethods.WndProc newWndProc, IntPtr oldWndProc) 
        {
            _hwndAttached = hwnd; 
            _hwndHandleRef = new HandleRef(null,_hwndAttached); 
            _bond = Bond.Attached;
 
            _attachedWndProc = newWndProc;
            _oldWndProc = oldWndProc;
            IntPtr oldWndProc2 = (IntPtr)UnsafeNativeMethods.CriticalSetWindowLong(_hwndHandleRef, NativeMethods.GWL_WNDPROC, _attachedWndProc);
 
            // Track this window so that we can rip out the managed window proc
            // when the CLR shuts down. 
            ManagedWndProcTracker.TrackHwndSubclass(this, _hwndAttached); 
        }
 
        // This method should only be called from Dispose. Otherwise assumptions about the disposing/finalize state could be violated.
        // force - when true, remove this subclass from the WndProc chain regardless of
        //          its current position.  When false, remove this subclass only
        //          if it is possible to do so without damaging other WndProcs 
        //          (i.e. only if this is at the head of the chain).
        // 
        // Removing this subclass from the WndProc chain when it is not at the head 
        // also removes all other WndProcs that appear before this one on the chain,
        // so is generally not appropriate. It is OK in the following situations: 
        //  a) in response to the WM_NCDESTROY message
        //  b) in response to the AppDomainProcessExit event
        //  c) in response to the AppDomainExit event
        // In cases (a) and (b) the HWND is being destroyed, so the earlier 
        // WndProcs are no longer useful anyway.  In case (c), we have to remove
        // all managed code from the chain lest it be called after it has been 
        // removed from memory;  removing earlier WndProcs is unfortunate, but 
        // necessary.  [Note that at AppDomainExit we remove all managed WndProcs,
        // regardless of which AppDomain they came from.  There is room for 
        // improvement here - we could remove only the ones belong to the AppDomain
        // that is exiting.  This situation seems too unlikely to worry about in V1.]
        //
        // This method returns true if the subclass is no longer in the WndProc chain. 
        //
        /// 
        /// Critical - it calls CriticalSetWindowLong() and GetWindowLongWndProc() 
        /// TreatAsSafe - no input params, no exposed data, just removing ourselves from window proc chain
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private bool UnhookWindowProc(bool force)
        {
            // if we're not in the WndProc chain, there's nothing to do 
            if (_bond == Bond.Unattached || _bond == Bond.Detached)
            { 
                return true; 
            }
 
            // we'll remove ourselves from the chain if we're at the head, or if
            // the 'force' parameter was true.
            if (!force)
            { 
                NativeMethods.WndProc currentWndProc = UnsafeNativeMethods.GetWindowLongWndProc(new HandleRef(this,_hwndAttached));
                force = (currentWndProc == _attachedWndProc); 
            } 

            // if we're not unhooking, return and report 
            if (!force)
            {
                return false;
            } 

            // unhook from the tracker 
            _bond = Bond.Orphaned;  // ignore messages while we're unhooking 
            ManagedWndProcTracker.UnhookHwndSubclass(this);
 
            // unhook, the Win32 way
            try
            {
                UnsafeNativeMethods.CriticalSetWindowLong(_hwndHandleRef, NativeMethods.GWL_WNDPROC, _oldWndProc); 
            }
            catch (System.ComponentModel.Win32Exception e) 
            { 
                if (e.NativeErrorCode != 1400) // ERROR_INVALID_WINDOW_HANDLE
                { 
                    throw;
                }
            }
 

            // clear our state 
            _bond = Bond.Detached; 

            _oldWndProc = IntPtr.Zero; 
            _attachedWndProc = null;
            _hwndAttached = IntPtr.Zero;
            _hwndHandleRef = new HandleRef(null,IntPtr.Zero);
 
            // un-Pin this object.
            // Note: the GC is free to collect this object at anytime 
            // after we have freed this handle - that is, once all 
            // other managed references go away.
 
            //AvDebug.Assert(_gcHandle.IsAllocated, "External GC handle has not been allocated.");

            if(null != _gcHandle)
                _gcHandle.Free(); 

            return true; 
        } 

 


        /// 
        /// DefWndProcWrapper is a wrapper around DefWndProc.  This is a workaround 
        /// for WindowsSE bugs 124461 and 124455, which affect Windows XP SP2, Luna theme.
        /// 
        /// HwndSubclass.SubclassWndProc is sometimes directly set as the window proc of a 
        /// Window (HwndWrapper's constructor does this).  When this happens it subclasses
        /// itself on the first message it receives. Since the old window proc is itself, 
        /// it saves off DefWndProc as the old window proc instead.
        ///
        /// As described by the bugs and and KB article 319740, if we set DefWndProc
        /// as the window proc of the window, we'll leak 6 GDI region objects 
        /// corresponding to the Luna-themed non-client area.
        /// 
        /// The reason for this is that the kernel will flag that window as a server-side 
        /// window. If the WndProc replacement happens in response to a WM_NCDESTROY message
        /// (as it does in the case where Avalon is creating and closing windows), the Shell 
        /// won't clean up the regions.
        ///
        /// The fix is slated for XP SP3, so for now WPF is implementing a workaround:
        /// if we set the window proc to be a stub that calls into DefWndProc, the kernel 
        /// won't set us as a server-side window.
        ///  
        ///  
        ///  Critical: Elevates by calling an UnsafeNativeMethod
        /// 
        [SecurityCritical]
        private static IntPtr DefWndProcWrapper(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
        {
            return UnsafeNativeMethods.CallWindowProc(DefWndProc, hwnd, msg, wParam, lParam); 
        }
 
 

        // Message to cause a detach. 
        //      WPARAM=IntPtr returned from Attach(), or 0 to match all subclasses.
        //      LPARAM= 0 - normal (unhook subclass if it is first on the chain)
        //              1 - force unhooking subclass from the chain
        //              2 - force, and forward message to next WndProc 
        internal static readonly int DetachMessage;
 
        private enum Bond 
        {
            Unattached, 
            Attached,
            Detached,
            Orphaned
        } 

 
        ///  
        /// This is a delegate that points to DefWndProcWrapper.  It is set into
        /// a Window's WndProc instead of DefWndProc in order to work around a bug. 
        /// See the comment on DefWndProcWrapper.
        ///
        /// By instantiating this delegate as a static variable we ensure that
        /// it will remain alive long enough to process messages. 
        /// 
        ///  
        ///     Critical: This will expose DefWndProc 
        /// 
        [SecurityCritical] 
        private static NativeMethods.WndProc DefWndProcStub = new NativeMethods.WndProc(DefWndProcWrapper);

        /// 
        ///     Critical: This will expose wndproc 
        /// 
        [SecurityCritical] 
        private static IntPtr DefWndProc; 

        ///  
        ///     Critical: This will expose the intptr of the window
        /// 
        [SecurityCritical]
        private IntPtr _hwndAttached; 
        /// 
        ///     Critical: This will expose window handle 
        ///  
        [SecurityCritical]
        private HandleRef _hwndHandleRef; 
        /// 
        ///     Critical: This will expose wndproc
        /// 
        [SecurityCritical] 
        private NativeMethods.WndProc _attachedWndProc;
        ///  
        ///     Critical: This will expose wndproc 
        /// 
        [SecurityCritical] 
        private IntPtr                _oldWndProc;
        private Bond                  _bond;
        private GCHandle              _gcHandle;
        ///  
        ///     Critical: This will expose hook
        ///  
        [SecurityCritical] 
        private WeakReference _hook;
    }; 
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK