Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mcs / class / corlib / System.Runtime.InteropServices / SafeHandle.cs
index c706ceed6184073e2a374ed306b1eaf70d0d5c16..5a8f5ce05fda7356dc79ee4831ea5847e6069329 100644 (file)
@@ -61,50 +61,8 @@ using System.Threading;
 namespace System.Runtime.InteropServices
 {
        [StructLayout (LayoutKind.Sequential)]
-       public abstract class SafeHandle : CriticalFinalizerObject, IDisposable
+       public abstract partial class SafeHandle
        {
-               /* Warning: the offset of handle is mapped inside the runtime
-                * if you move this, you must updated the runtime definition of
-                * MonoSafeHandle */
-               protected IntPtr handle;
-
-               /*
-                * To prevent handle recycling security attacks we must enforce the
-                * following invariant: we cannot successfully AddRef a handle on which
-                * we've committed to the process of releasing.
-                *
-                * We ensure this by never AddRef'ing a handle that is marked closed and
-                * never marking a handle as closed while the ref count is non-zero. For
-                * this to be thread safe we must perform inspection/updates of the two
-                * values as a single atomic operation. We achieve this by storing them both
-                * in a single aligned DWORD and modifying the entire state via interlocked
-                * compare exchange operations.
-                *
-                * Additionally we have to deal with the problem of the Dispose operation.
-                * We must assume that this operation is directly exposed to untrusted
-                * callers and that malicious callers will try and use what is basically a
-                * Release call to decrement the ref count to zero and free the handle while
-                * it's still in use (the other way a handle recycling attack can be
-                * mounted). We combat this by allowing only one Dispose to operate against
-                * a given safe handle (which balances the creation operation given that
-                * Dispose suppresses finalization). We record the fact that a Dispose has
-                * been requested in the same state field as the ref count and closed state.
-                *
-                * So the state field ends up looking like this:
-                *
-                *  31                                                        2  1   0
-                * +-----------------------------------------------------------+---+---+
-                * |                           Ref count                       | D | C |
-                * +-----------------------------------------------------------+---+---+
-                *
-                * Where D = 1 means a Dispose has been performed and C = 1 means the
-                * underlying handle has (or will be shortly) released.
-                */
-               int state;
-
-               bool owns_handle;
-               bool fully_initialized;
-
                const int RefCount_Mask = 0x7ffffffc;
                const int RefCount_One = 0x4;
 
@@ -113,49 +71,6 @@ namespace System.Runtime.InteropServices
                        Disposed = 0x00000002,
                }
 
-#if NET_2_1
-               protected SafeHandle ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
-               protected SafeHandle (IntPtr invalidHandleValue, bool ownsHandle)
-               {
-                       handle = invalidHandleValue;
-                       state = RefCount_One;
-                       owns_handle = ownsHandle;
-
-                       if (!owns_handle)
-                               GC.SuppressFinalize (this);
-
-                       fully_initialized = true;
-               }
-
-               ~SafeHandle ()
-               {
-                       Dispose (false);
-               }
-
-               public bool IsClosed {
-                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-                       get {
-                               return (state & (int) State.Closed) != 0;
-                       }
-               }
-
-               public abstract bool IsInvalid {
-                       [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-                       get;
-               }
-
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-               protected void SetHandle (IntPtr handle)
-               {
-                       this.handle = handle;
-               }
-
                /*
                 * This should only be called for cases when you know for a fact that
                 * your handle is invalid and you want to record that information.
@@ -168,35 +83,13 @@ namespace System.Runtime.InteropServices
                        int old_state, new_state;
 
                        do {
-                               old_state = state;
+                               old_state = _state;
                                new_state = old_state | (int) State.Closed;
-                       } while (Interlocked.CompareExchange (ref state, new_state, old_state) != old_state);
+                       } while (Interlocked.CompareExchange (ref _state, new_state, old_state) != old_state);
 
                        GC.SuppressFinalize (this);
                }
 
-               /*
-                * This method is necessary for getting an IntPtr out of a SafeHandle.
-                * Used to tell whether a call to create the handle succeeded by comparing
-                * the handle against a known invalid value, and for backwards
-                * compatibility to support the handle properties returning IntPtrs on
-                * many of our Framework classes.
-                * Note that this method is dangerous for two reasons:
-                *  1) If the handle has been marked invalid with SetHandleasInvalid,
-                *     DangerousGetHandle will still return the original handle value.
-                *  2) The handle returned may be recycled at any point. At best this means
-                *     the handle might stop working suddenly. At worst, if the handle or
-                *     the resource the handle represents is exposed to untrusted code in
-                *     any way, this can lead to a handle recycling security attack (i.e. an
-                *     untrusted caller can query data on the handle you've just returned
-                *     and get back information for an entirely unrelated resource).
-                */
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-               public IntPtr DangerousGetHandle ()
-               {
-                       return handle;
-               }
-
                /*
                 * Add a reason why this handle should not be relinquished (i.e. have
                 * ReleaseHandle called on it). This method has dangerous in the name since
@@ -215,19 +108,19 @@ namespace System.Runtime.InteropServices
                [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                public void DangerousAddRef (ref bool success)
                {
-                       if (!fully_initialized)
+                       if (!_fullyInitialized)
                                throw new InvalidOperationException ();
 
                        int old_state, new_state;
 
                        do {
-                               old_state = state;
+                               old_state = _state;
 
                                if ((old_state & (int) State.Closed) != 0)
                                        throw new ObjectDisposedException ("handle");
 
                                new_state = old_state + RefCount_One;
-                       } while (Interlocked.CompareExchange (ref state, new_state, old_state) != old_state);
+                       } while (Interlocked.CompareExchange (ref _state, new_state, old_state) != old_state);
 
                        success = true;
                }
@@ -249,30 +142,17 @@ namespace System.Runtime.InteropServices
                        DangerousReleaseInternal (false);
                }
 
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-               public void Close ()
+               void InternalDispose ()
                {
-                       Dispose (true);
-               }
-
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-               public void Dispose ()
-               {
-                       Dispose (true);
-                       GC.SuppressFinalize (this);
+                       if (!_fullyInitialized)
+                               throw new InvalidOperationException ();
+                       DisposeInternal ();
                }
 
-               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
-               protected virtual void Dispose (bool disposing)
+               void InternalFinalize ()
                {
-                       if (disposing) {
-                               if (!fully_initialized)
-                                       throw new InvalidOperationException ();
+                       if (_fullyInitialized)
                                DisposeInternal ();
-                       } else {
-                               if (fully_initialized)
-                                       DisposeInternal ();
-                       }
                }
 
                void DisposeInternal ()
@@ -283,7 +163,7 @@ namespace System.Runtime.InteropServices
 
                void DangerousReleaseInternal (bool dispose)
                {
-                       if (!fully_initialized)
+                       if (!_fullyInitialized)
                                throw new InvalidOperationException ();
 
                        int old_state, new_state;
@@ -294,7 +174,7 @@ namespace System.Runtime.InteropServices
                        bool perform_release = false;
 
                        do {
-                               old_state = state;
+                               old_state = _state;
 
                                /* If this is a Dispose operation we have additional requirements (to
                                 * ensure that Dispose happens at most once as the comments in AddRef
@@ -315,7 +195,7 @@ namespace System.Runtime.InteropServices
                                perform_release =
                                        (old_state & RefCount_Mask) == RefCount_One
                                         && (old_state & (int) State.Closed) == 0
-                                        && owns_handle;
+                                        && _ownsHandle;
 
                                if (perform_release && IsInvalid)
                                        perform_release = false;
@@ -329,7 +209,7 @@ namespace System.Runtime.InteropServices
                                        (old_state - RefCount_One)
                                         | ((old_state & RefCount_Mask) == RefCount_One ? (int) State.Closed : 0)
                                         | (dispose ? (int) State.Disposed : 0);
-                       } while (Interlocked.CompareExchange (ref state, new_state, old_state) != old_state);
+                       } while (Interlocked.CompareExchange (ref _state, new_state, old_state) != old_state);
 
                        if (perform_release)
                                ReleaseHandle ();