SafeHandle.cs source code in C# .NET

Source code for the .NET framework in C#



/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Runtime / InteropServices / SafeHandle.cs / 2 / SafeHandle.cs

                            // ==++== 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// ==--== 
** Class:  SafeHandle 
** A specially designed handle wrapper to ensure we never leak
** an OS handle.  The runtime treats this class specially during
** P/Invoke marshaling and finalization.  Users should write
** subclasses of SafeHandle for each distinct handle type. 

using System; 
using System.Reflection;
using System.Threading;
using System.Security.Permissions;
using System.Runtime.CompilerServices; 
using System.IO;
using System.Runtime.ConstrainedExecution; 
using System.Runtime.Versioning; 

  Problems addressed by the SafeHandle class:
  1) Critical finalization - ensure we never leak OS resources in SQL.  Done
     without running truly arbitrary & unbounded amounts of managed code.
  2) Reduced graph promotion - during finalization, keep object graph small 
  3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race (HandleRef)
  4) Elimination of security races w/ explicit calls to Close (HandleProtector) 
  5) Enforcement of the above via the type system - Don't use IntPtr anymore. 
  6) Allows the handle lifetime to be controlled externally via a boolean.
  Subclasses of SafeHandle will implement the ReleaseHandle abstract method
  used to execute any code required to free the handle. This method will be
  prepared as a constrained execution region at instance construction time
  (along with all the methods in its statically determinable call graph). This 
  implies that we won't get any inconvenient jit allocation errors or rude
  thread abort interrupts while releasing the handle but the user must still 
  write careful code to avoid injecting fault paths of their own (see the CER 
  spec for more details). In particular, any sub-methods you call should be
  decorated with a reliability contract of the appropriate level. In most cases 
  this should be:
    ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)
  Also, any P/Invoke methods should use the SuppressUnmanagedCodeSecurity
  attribute to avoid a runtime security 

























namespace System.Runtime.InteropServices {
// This class should not be serializable - it's a handle.  We require unmanaged
// code permission to subclass SafeHandle to prevent people from writing a
// subclass and suddenly being able to run arbitrary native code with the
// same signature as CloseHandle.  This is technically a little redundant, but 
// we'll do this to ensure we've cut off all attack vectors.  Similarly, all
// methods have a link demand to ensure untrusted code cannot directly edit 
// or alter a handle. 
[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)] 

public abstract class SafeHandle : CriticalFinalizerObject, IDisposable
    // ! Do not add or rearrange fields as the EE depends on this layout. 
#if DEBUG 
    private String _stackTrace;  // Where we allocated this SafeHandle. 
    protected IntPtr handle;   // this must be protected so derived classes can use out params. 
    private int _state;   // Combined ref count and closed/disposed flags (so we can atomically modify them).
    private bool _ownsHandle;  // Whether we can release this handle.
#pragma warning disable 414
    private bool _fullyInitialized;  // Whether constructor completed. 
#pragma warning restore 414
    // Creates a SafeHandle class.  Users must then set the Handle property. 
    // To prevent the SafeHandle from being freed, write a subclass that
    // doesn't define a finalizer. 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    protected SafeHandle(IntPtr invalidHandleValue, bool ownsHandle)
        handle = invalidHandleValue; 
        _state = 4; // Ref count 1 and not closed or disposed.
        _ownsHandle = ownsHandle; 
        if (!ownsHandle)

        if (BCLDebug.SafeHandleStackTracesEnabled)
            _stackTrace = Environment.GetStackTrace(null, false); 
            _stackTrace = "For a stack trace showing who allocated this SafeHandle, set SafeHandleStackTraces to 1 and rerun your app."; 

        // Set this last to prevent SafeHandle's finalizer from freeing an 
        // invalid handle.  This means we don't have to worry about
        // ThreadAbortExceptions interrupting this constructor or the managed
        // constructors on subclasses that call this constructor.
        _fullyInitialized = true; 

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    extern void InternalFinalize();
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    protected void SetHandle(IntPtr handle) {
        this.handle = handle; 

    // 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;

    public bool IsClosed { 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
        get { return (_state & 1) == 1; }

    public abstract bool IsInvalid {
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    public void Close() {

    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public void Dispose() { 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    protected virtual void Dispose(bool disposing) 
        if (disposing)
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    private extern void InternalDispose();

    // 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. 
    // An example is calling a syscall and getting back ERROR_INVALID_HANDLE.
    // This method will normally leak handles! 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
    public extern void SetHandleAsInvalid(); 

    // Implement this abstract method in your derived class to specify how to
    // free the handle. Be careful not write any code that's subject to faults
    // in this method (the runtime will prepare the infrastructure for you so 
    // that no jit allocations etc. will occur, but don't allocate memory unless
    // you can deal with the failure and still free the handle). 
    // The boolean returned should be true for success and false if the runtime 
    // should fire a SafeHandleCriticalFailure MDA (CustomerDebugProbe) if that
    // MDA is enabled. 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    protected abstract bool ReleaseHandle();

    // 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
    // it must always be used carefully (e.g. called within a CER) to avoid 
    // leakage of the handle. It returns a boolean indicating whether the 
    // increment was actually performed to make it easy for program logic to
    // back out in failure cases (i.e. is a call to DangerousRelease needed). 
    // It is passed back via a ref parameter rather than as a direct return so
    // that callers need not worry about the atomicity of calling the routine
    // and assigning the return value to a variable (the variable should be
    // explicitly set to false prior to the call). The only failure cases are 
    // when the method is interrupted prior to processing by a thread abort or
    // when the handle has already been (or is in the process of being) 
    // released. 
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    public extern void DangerousAddRef(ref bool success);

    // Partner to DangerousAddRef. This should always be successful when used in
    // a correct manner (i.e. matching a successful DangerousAddRef and called 
    // from a region such as a CER where a thread abort cannot interrupt
    // processing). In the same way that unbalanced DangerousAddRef calls can 
    // cause resource leakage, unbalanced DangerousRelease calls may cause 
    // invalid handle states to become visible to other threads. This
    // constitutes a potential security hole (via handle recycling) as well as a 
    // correctness problem -- so don't ever expose Dangerous* calls out to
    // untrusted code.
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
    public extern void DangerousRelease();

// 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