File: System\DirectoryServices\Protocols\Interop\SafeHandles.Linux.cs
Web Access
Project: src\src\libraries\System.DirectoryServices.Protocols\src\System.DirectoryServices.Protocols.csproj (System.DirectoryServices.Protocols)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.Win32.SafeHandles;
 
namespace System.DirectoryServices.Protocols
{
    internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        internal bool _needDispose;
 
        public ConnectionHandle()
            : base(true)
        {
            Interop.Ldap.ldap_initialize(out handle, null);
            _needDispose = true;
        }
 
        internal ConnectionHandle(string uri)
            : base(true)
        {
            Interop.Ldap.ldap_initialize(out handle, uri);
            _needDispose = true;
        }
 
        internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true)
        {
            _needDispose = disposeHandle;
            if (value == IntPtr.Zero)
            {
                throw new LdapException(SR.LDAP_CONNECT_ERROR);
            }
            else
            {
                SetHandle(value);
            }
        }
 
        protected override bool ReleaseHandle()
        {
            if (_needDispose)
            {
                IntPtr nullPointer = IntPtr.Zero;
                Interop.Ldap.ldap_unbind_ext_s(handle, ref nullPointer, ref nullPointer);
            }
 
            handle = IntPtr.Zero;
            return true;
        }
    }
 
    internal sealed class SafeBerHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public SafeBerHandle() : base(true)
        {
            SetHandle(Interop.Ldap.ber_alloc(1));
            if (handle == IntPtr.Zero)
            {
                throw new OutOfMemoryException();
            }
        }
 
        internal SafeBerHandle(BerVal value) : base(true)
        {
            // In Linux if bv_val is null ber_init will segFault instead of returning IntPtr.Zero.
            // In Linux if bv_len is 0 ber_init returns a valid pointer which will then fail when trying to use it,
            // so we fail early by throwing exception if this is the case.
            if (value.bv_val == IntPtr.Zero || value.bv_len.Value == 0)
            {
                throw new BerConversionException();
            }
            SetHandle(Interop.Ldap.ber_init(value));
            if (handle == IntPtr.Zero)
            {
                throw new BerConversionException();
            }
        }
 
        protected override bool ReleaseHandle()
        {
            Interop.Ldap.ber_free(handle, 1);
            return true;
        }
    }
}