Adding Linux support to System.DirectoryServices.Protocols (#35380)
authorJose Perez Rodriguez <joperezr@microsoft.com>
Thu, 7 May 2020 20:37:38 +0000 (13:37 -0700)
committerGitHub <noreply@github.com>
Thu, 7 May 2020 20:37:38 +0000 (13:37 -0700)
44 files changed:
src/libraries/Common/src/Interop/Interop.Ldap.cs [new file with mode: 0644]
src/libraries/Common/src/Interop/Linux/Interop.Libraries.cs
src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs [new file with mode: 0644]
src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs [new file with mode: 0644]
src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs
src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs [new file with mode: 0644]
src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/DirectoryControl.cs
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.cs
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapPartialResultsProcessor.cs
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs [deleted file]
src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs [deleted file]
src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs [new file with mode: 0644]
src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/LdapSessionOptionsTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/SortRequestControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/System.DirectoryServices.Protocols.Tests.csproj
src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs
src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs

diff --git a/src/libraries/Common/src/Interop/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Interop.Ldap.cs
new file mode 100644 (file)
index 0000000..121fae5
--- /dev/null
@@ -0,0 +1,176 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    public const int SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2;
+    public const int SEC_WINNT_AUTH_IDENTITY_VERSION = 0x200;
+    public const string MICROSOFT_KERBEROS_NAME_W = "Kerberos";
+}
+
+namespace System.DirectoryServices.Protocols
+{
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal class Luid
+    {
+        private readonly int _lowPart;
+        private readonly int _highPart;
+
+        public int LowPart => _lowPart;
+        public int HighPart => _highPart;
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal sealed class SEC_WINNT_AUTH_IDENTITY_EX
+    {
+        public int version;
+        public int length;
+        public string user;
+        public int userLength;
+        public string domain;
+        public int domainLength;
+        public string password;
+        public int passwordLength;
+        public int flags;
+        public string packageList;
+        public int packageListLength;
+    }
+
+    internal enum BindMethod : uint // Not Supported in Linux
+    {
+        LDAP_AUTH_OTHERKIND = 0x86,
+        LDAP_AUTH_SICILY = LDAP_AUTH_OTHERKIND | 0x0200,
+        LDAP_AUTH_MSN = LDAP_AUTH_OTHERKIND | 0x0800,
+        LDAP_AUTH_NTLM = LDAP_AUTH_OTHERKIND | 0x1000,
+        LDAP_AUTH_DPA = LDAP_AUTH_OTHERKIND | 0x2000,
+        LDAP_AUTH_NEGOTIATE = LDAP_AUTH_OTHERKIND | 0x0400,
+        LDAP_AUTH_SSPI = LDAP_AUTH_NEGOTIATE,
+        LDAP_AUTH_DIGEST = LDAP_AUTH_OTHERKIND | 0x4000,
+        LDAP_AUTH_EXTERNAL = LDAP_AUTH_OTHERKIND | 0x0020,
+        LDAP_AUTH_KRBV4 = 0xFF,
+        LDAP_AUTH_SIMPLE = 0x80
+    }
+
+    internal enum LdapOption
+    {
+        LDAP_OPT_DESC = 0x01,
+        LDAP_OPT_DEREF = 0x02,
+        LDAP_OPT_SIZELIMIT = 0x03,
+        LDAP_OPT_TIMELIMIT = 0x04,
+        LDAP_OPT_REFERRALS = 0x08,
+        LDAP_OPT_RESTART = 0x09,
+        LDAP_OPT_SSL = 0x0a, // Not Supported in Linux
+        LDAP_OPT_REFERRAL_HOP_LIMIT = 0x10, // Not Supported in Linux
+        LDAP_OPT_VERSION = 0x11,
+        LDAP_OPT_SERVER_CONTROLS = 0x12, // Not Supported in Windows
+        LDAP_OPT_CLIENT_CONTROLS = 0x13, // Not Supported in Windows
+        LDAP_OPT_API_FEATURE_INFO = 0x15,
+        LDAP_OPT_HOST_NAME = 0x30,
+        LDAP_OPT_ERROR_NUMBER = 0x31,
+        LDAP_OPT_ERROR_STRING = 0x32,
+        LDAP_OPT_SERVER_ERROR = 0x33,
+        LDAP_OPT_SERVER_EXT_ERROR = 0x34, // Not Supported in Linux
+        LDAP_OPT_HOST_REACHABLE = 0x3E, // Not Supported in Linux
+        LDAP_OPT_PING_KEEP_ALIVE = 0x36, // Not Supported in Linux
+        LDAP_OPT_PING_WAIT_TIME = 0x37, // Not Supported in Linux
+        LDAP_OPT_PING_LIMIT = 0x38, // Not Supported in Linux
+        LDAP_OPT_DNSDOMAIN_NAME = 0x3B, // Not Supported in Linux
+        LDAP_OPT_GETDSNAME_FLAGS = 0x3D, // Not Supported in Linux
+        LDAP_OPT_PROMPT_CREDENTIALS = 0x3F, // Not Supported in Linux
+        LDAP_OPT_TCP_KEEPALIVE = 0x40, // Not Supported in Linux
+        LDAP_OPT_FAST_CONCURRENT_BIND = 0x41, // Not Supported in Linux
+        LDAP_OPT_SEND_TIMEOUT = 0x42, // Not Supported in Linux
+        LDAP_OPT_REFERRAL_CALLBACK = 0x70, // Not Supported in Linux
+        LDAP_OPT_CLIENT_CERTIFICATE = 0x80, // Not Supported in Linux
+        LDAP_OPT_SERVER_CERTIFICATE = 0x81, // Not Supported in Linux
+        LDAP_OPT_AUTO_RECONNECT = 0x91, // Not Supported in Linux
+        LDAP_OPT_SSPI_FLAGS = 0x92,
+        LDAP_OPT_SSL_INFO = 0x93, // Not Supported in Linux
+        LDAP_OPT_SIGN = 0x95,
+        LDAP_OPT_ENCRYPT = 0x96,
+        LDAP_OPT_SASL_METHOD = 0x97,
+        LDAP_OPT_AREC_EXCLUSIVE = 0x98, // Not Supported in Linux
+        LDAP_OPT_SECURITY_CONTEXT = 0x99,
+        LDAP_OPT_ROOTDSE_CACHE = 0x9a // Not Supported in Linux
+    }
+
+    internal enum ResultAll
+    {
+        LDAP_MSG_ALL = 1,
+        LDAP_MSG_RECEIVED = 2,
+        LDAP_MSG_POLLINGALL = 3 // Not Supported in Linux
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal sealed class LDAP_TIMEVAL
+    {
+        public int tv_sec;
+        public int tv_usec;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    internal sealed class berval
+    {
+        public int bv_len = 0;
+        public IntPtr bv_val = IntPtr.Zero;
+
+        public berval() { }
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal sealed class LdapControl
+    {
+        public IntPtr ldctl_oid = IntPtr.Zero;
+        public berval ldctl_value = null;
+        public bool ldctl_iscritical = false;
+
+        public LdapControl() { }
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal struct LdapReferralCallback
+    {
+        public int sizeofcallback;
+        public QUERYFORCONNECTIONInternal query;
+        public NOTIFYOFNEWCONNECTIONInternal notify;
+        public DEREFERENCECONNECTIONInternal dereference;
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal struct CRYPTOAPI_BLOB
+    {
+        public int cbData;
+        public IntPtr pbData;
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal struct SecPkgContext_IssuerListInfoEx
+    {
+        public IntPtr aIssuers;
+        public int cIssuers;
+    }
+
+    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+    internal sealed class LdapMod
+    {
+        public int type = 0;
+        public IntPtr attribute = IntPtr.Zero;
+        public IntPtr values = IntPtr.Zero;
+
+        ~LdapMod()
+        {
+            if (attribute != IntPtr.Zero)
+            {
+                Marshal.FreeHGlobal(attribute);
+            }
+
+            if (values != IntPtr.Zero)
+            {
+                Marshal.FreeHGlobal(values);
+            }
+        }
+    }
+}
index 25f0ce0a445e922594d7703ed04879455ddc3393..e7bc0d31f0d8642dfc2d3cfcab22e2471f161235 100644 (file)
@@ -7,6 +7,7 @@ internal static partial class Interop
     internal static partial class Libraries
     {
         internal const string Odbc32 = "libodbc.so.2";
+        internal const string OpenLdap = "libldap-2.4.so.2";
         internal const string MsQuic = "msquic";
     }
 }
diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs
new file mode 100644 (file)
index 0000000..4a059e3
--- /dev/null
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.DirectoryServices.Protocols;
+
+internal static partial class Interop
+{
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_alloc_t", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ber_alloc(int option);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_init", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ber_init(berval value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_free", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ber_free([In] IntPtr berelement, int option);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
+    public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
+    public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
+    public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)]
+    public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_flatten", CharSet = CharSet.Ansi)]
+    public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_bvfree", CharSet = CharSet.Ansi)]
+    public static extern int ber_bvfree(IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_bvecfree", CharSet = CharSet.Ansi)]
+    public static extern int ber_bvecfree(IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
+    public static extern int ber_scanf(SafeBerHandle berElement, string format);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
+    public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
+    public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)]
+    public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value);
+}
diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs
new file mode 100644 (file)
index 0000000..7925e24
--- /dev/null
@@ -0,0 +1,145 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.DirectoryServices.Protocols;
+
+internal static partial class Interop
+{
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_initialize", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern int ldap_initialize(out IntPtr ld, string hostname);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_init", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern IntPtr ldap_init(string hostName, int portNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_unbind_ext_s", CharSet = CharSet.Ansi)]
+    public static extern int ldap_unbind_ext_s(IntPtr ld, ref IntPtr serverctrls, ref IntPtr clientctrls);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_dn", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_get_values_len", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Ansi)]
+    public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_result2error", CharSet = CharSet.Ansi)]
+    public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_search_ext", CharSet = CharSet.Ansi)]
+    public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern int ldap_set_option_int([In] ConnectionHandle ld, [In] LdapOption option, ref int inValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)]
+    public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_start_tls_s", CharSet = CharSet.Ansi)]
+    public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)]
+    public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)]
+    public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_extended_result", CharSet = CharSet.Ansi)]
+    public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_reference", CharSet = CharSet.Ansi)]
+    public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals, IntPtr ServerControls, byte freeIt);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_sasl_bind_s", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern int ldap_sasl_bind_s([In] ConnectionHandle ld, string dn, string mechanism, berval cred, IntPtr servercontrol, IntPtr clientcontrol, ref berval servercredp);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_simple_bind_s", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern int ldap_simple_bind([In] ConnectionHandle ld, string who, string passwd);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_bind_s", CharSet = CharSet.Ansi, SetLastError = true)]
+    public static extern int ldap_bind_s([In] ConnectionHandle ld, string who, string passwd, int method);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_err2string", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_err2string(int err);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_extended_operation", CharSet = CharSet.Ansi)]
+    public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_attribute", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_entry", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_first_reference", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_create_sort_control", CharSet = CharSet.Ansi)]
+    public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_control_free", CharSet = CharSet.Ansi)]
+    public static extern int ldap_control_free(IntPtr control);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_controls_free", CharSet = CharSet.Ansi)]
+    public static extern int ldap_controls_free([In] IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_value_free", CharSet = CharSet.Ansi)]
+    public static extern int ldap_value_free([In] IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_value_free_len([In] IntPtr berelement);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_memfree", CharSet = CharSet.Ansi)]
+    public static extern void ldap_memfree([In] IntPtr value);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_modify_ext", CharSet = CharSet.Ansi)]
+    public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_attribute", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_entry", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_next_reference", CharSet = CharSet.Ansi)]
+    public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_abandon", CharSet = CharSet.Ansi)]
+    public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_add_ext", CharSet = CharSet.Ansi)]
+    public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_delete_ext", CharSet = CharSet.Ansi)]
+    public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_rename", CharSet = CharSet.Ansi)]
+    public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_compare_ext", CharSet = CharSet.Ansi)]
+    public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+}
index 1c1b3db6a0b762c30f4020baec035983556bc6ec..2672c4cc489e52360015c6be0e188a5e03492dc1 100644 (file)
@@ -34,6 +34,7 @@ internal static partial class Interop
         internal const string WebSocket = "websocket.dll";
         internal const string WinHttp = "winhttp.dll";
         internal const string WinMM = "winmm.dll";
+        internal const string Wldap32 = "wldap32.dll";
         internal const string Ws2_32 = "ws2_32.dll";
         internal const string Wtsapi32 = "wtsapi32.dll";
         internal const string CompressionNative = "clrcompression.dll";
diff --git a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs
new file mode 100644 (file)
index 0000000..5f87ea5
--- /dev/null
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.DirectoryServices.Protocols;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_free", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ber_free([In] IntPtr berelement, int option);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_alloc_t", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ber_alloc(int option);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+    public static extern int ber_printf_emptyarg(SafeBerHandle berElement, string format);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+    public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+    public static extern int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
+    public static extern int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)]
+    public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_init", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ber_init(berval value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+    public static extern int ber_scanf(SafeBerHandle berElement, string format);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+    public static extern int ber_scanf_int(SafeBerHandle berElement, string format, ref int value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+    public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
+    public static extern int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref int bitLength);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)]
+    public static extern int ber_bvfree(IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvecfree", CharSet = CharSet.Unicode)]
+    public static extern int ber_bvecfree(IntPtr value);
+}
diff --git a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ldap.cs
new file mode 100644 (file)
index 0000000..a73cd89
--- /dev/null
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.DirectoryServices.Protocols;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_bind_sW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_bind_s([In]ConnectionHandle ldapHandle, string dn, SEC_WINNT_AUTH_IDENTITY_EX credentials, BindMethod method);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_initW", SetLastError = true, CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_init(string hostName, int portNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_connect", CharSet = CharSet.Unicode)]
+    public static extern int ldap_connect([In] ConnectionHandle ldapHandle, LDAP_TIMEVAL timeout);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_unbind", CharSet = CharSet.Unicode)]
+    public static extern int ldap_unbind([In] IntPtr ldapHandle);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_set_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int inValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LdapGetLastError")]
+    public static extern int LdapGetLastError();
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "cldap_openW", SetLastError = true, CharSet = CharSet.Unicode)]
+    public static extern IntPtr cldap_open(string hostName, int portNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_simple_bind_sW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_simple_bind_s([In] ConnectionHandle ldapHandle, string distinguishedName, string password);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_delete_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Unicode)]
+    public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_memfreeW", CharSet = CharSet.Unicode)]
+    public static extern void ldap_memfree([In] IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_freeW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_value_free([In] IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_controls_freeW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_controls_free([In] IntPtr value);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_abandon", CharSet = CharSet.Unicode)]
+    public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_start_tls_sW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_stop_tls_s", CharSet = CharSet.Unicode)]
+    public static extern byte ldap_stop_tls(ConnectionHandle ldapHandle);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_rename_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_compare_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_add_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_modify_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_extended_operationW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_extended_resultW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_msgfree", CharSet = CharSet.Unicode)]
+    public static extern int ldap_msgfree([In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_search_extW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_entry", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_entry", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_reference", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_reference", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_attributeW", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_values_lenW", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Unicode)]
+    public static extern IntPtr ldap_value_free_len([In] IntPtr berelement);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_referenceW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_create_sort_controlW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_control_freeW", CharSet = CharSet.Unicode)]
+    public static extern int ldap_control_free(IntPtr control);
+
+    [DllImport("Crypt32.dll", EntryPoint = "CertFreeCRLContext", CharSet = CharSet.Unicode)]
+    public static extern int CertFreeCRLContext(IntPtr certContext);
+
+    [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result2error", CharSet = CharSet.Unicode)]
+    public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt);
+}
index a1fa96ae4019b4c1ecfd93b9bab256871b58691e..09328b9fb21591f171868f0ce765f598bc8cb967 100644 (file)
@@ -4,7 +4,7 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <NoWarn>$(NoWarn);0649;CA1810</NoWarn>
     <IncludeDllSafeSearchPathAttribute>true</IncludeDllSafeSearchPathAttribute>
-    <TargetFrameworks>$(NetCoreAppCurrent)-Windows_NT;netstandard2.0;netcoreapp2.0-Windows_NT;_$(NetFrameworkCurrent)</TargetFrameworks>
+    <TargetFrameworks>$(NetCoreAppCurrent)-Linux;netcoreapp2.0-Linux;$(NetCoreAppCurrent)-Windows_NT;netstandard2.0;netcoreapp2.0-Windows_NT;_$(NetFrameworkCurrent)</TargetFrameworks>
     <ExcludeCurrentNetCoreAppFromPackage>true</ExcludeCurrentNetCoreAppFromPackage>
   </PropertyGroup>
   <!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
     <Compile Include="System\DirectoryServices\Protocols\ldap\LdapException.cs" />
     <Compile Include="System\DirectoryServices\Protocols\ldap\LdapPartialResultsProcessor.cs" />
     <Compile Include="System\DirectoryServices\Protocols\ldap\LdapSessionOptions.cs" />
-    <Compile Include="System\DirectoryServices\Protocols\ldap\SafeHandles.cs" />
-    <Compile Include="System\DirectoryServices\Protocols\ldap\Wldap32UnsafeMethods.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\SafeHandles.cs" />
+    <Compile Include="$(CommonPath)Interop\Interop.Ldap.cs">
+      <Link>Common\Interop\Interop.Ldap.cs</Link>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
+    <Compile Include="System\DirectoryServices\Protocols\common\BerConverter.Windows.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\LdapPal.Windows.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\BerPal.Windows.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\ldap\LdapConnection.Windows.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\ldap\LdapSessionOptions.Windows.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\SafeHandles.Windows.cs" />
+    <Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs">
+      <Link>Common\Interop\Windows\Interop.Libraries.cs</Link>
+    </Compile>
+    <Compile Include="$(CommonPath)Interop\Windows\Wldap32\Interop.Ldap.cs">
+      <Link>Common\Interop\Windows\Wldap32\Interop.Ldap.cs</Link>
+    </Compile>
+    <Compile Include="$(CommonPath)Interop\Windows\Wldap32\Interop.Ber.cs">
+      <Link>Common\Interop\Windows\Wldap32\Interop.Ber.cs</Link>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup Condition="'$(TargetsLinux)' == 'true'">
+    <Compile Include="System\DirectoryServices\Protocols\common\BerConverter.Linux.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\LdapPal.Linux.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\BerPal.Linux.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\ldap\LdapConnection.Linux.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\ldap\LdapSessionOptions.Linux.cs" />
+    <Compile Include="System\DirectoryServices\Protocols\Interop\SafeHandles.Linux.cs" />
+    <Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs">
+      <Link>Common\Interop\Linux\Interop.Libraries.cs</Link>
+    </Compile>
+    <Compile Include="$(CommonPath)Interop\Linux\OpenLdap\Interop.Ldap.cs">
+      <Link>Common\Interop\Linux\OpenLdap\Interop.Ldap.cs</Link>
+    </Compile>
+    <Compile Include="$(CommonPath)Interop\Linux\OpenLdap\Interop.Ber.cs">
+      <Link>Common\Interop\Linux\OpenLdap\Interop.Ber.cs</Link>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System.Security.AccessControl" />
@@ -63,4 +99,4 @@
   <ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
     <Reference Include="System.ComponentModel.Primitives" />
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Linux.cs
new file mode 100644 (file)
index 0000000..f58a94d
--- /dev/null
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.DirectoryServices.Protocols
+{
+    internal static class BerPal
+    {
+        internal static void FreeBervalArray(IntPtr ptrResult) => Interop.ber_bvecfree(ptrResult);
+
+        internal static void FreeBerval(IntPtr flattenptr) => Interop.ber_bvfree(flattenptr);
+
+        internal static void FreeBerElement(IntPtr berelement, int option) => Interop.ber_free(berelement, option);
+
+        internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.ber_flatten(berElement, ref flattenptr);
+
+        internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.ber_printf_berarray(berElement, format, value);
+
+        internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.ber_printf_bytearray(berElement, format, value, length);
+
+        internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.ber_printf_emptyarg(berElement, format);
+
+        internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.ber_printf_int(berElement, format, value);
+
+        internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.ber_scanf(berElement, format);
+
+        internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength);
+
+        internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.ber_scanf_int(berElement, format, ref result);
+
+        internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.ber_scanf_ptr(berElement, format, ref value);
+
+        internal static bool IsBerDecodeError(int errorCode) => errorCode == -1;
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/BerPal.Windows.cs
new file mode 100644 (file)
index 0000000..bec5b5a
--- /dev/null
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal static class BerPal
+    {
+        internal static void FreeBervalArray(IntPtr ptrResult) => Interop.ber_bvecfree(ptrResult);
+
+        internal static void FreeBerval(IntPtr flattenptr) => Interop.ber_bvfree(flattenptr);
+
+        internal static void FreeBerElement(IntPtr berelement, int option) => Interop.ber_free(berelement, option);
+
+        internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.ber_flatten(berElement, ref flattenptr);
+
+        internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.ber_printf_berarray(berElement, format, value);
+
+        internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.ber_printf_bytearray(berElement, format, value, length);
+
+        internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.ber_printf_emptyarg(berElement, format);
+
+        internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.ber_printf_int(berElement, format, value);
+
+        internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.ber_scanf(berElement, format);
+
+        internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength);
+
+        internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.ber_scanf_int(berElement, format, ref result);
+
+        internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.ber_scanf_ptr(berElement, format, ref value);
+
+        internal static bool IsBerDecodeError(int errorCode) => errorCode != 0;
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs
new file mode 100644 (file)
index 0000000..09ae9c5
--- /dev/null
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal static class LdapPal
+    {
+        internal static void CancelDirectoryAsyncOperation(ConnectionHandle ldapHandle, int messagId) => Interop.ldap_abandon(ldapHandle, messagId);
+
+        internal static int AddDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_add(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int CompareDirectoryEntries(ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_compare(ldapHandle, dn, attributeName, binaryValue, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static void FreeDirectoryControl(IntPtr control) => Interop.ldap_control_free(control);
+
+        internal static void FreeDirectoryControls(IntPtr value) => Interop.ldap_controls_free(value);
+
+        internal static int CreateDirectorySortControl(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control) => Interop.ldap_create_sort_control(handle, keys, critical, ref control);
+
+        internal static int DeleteDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => Interop.ldap_delete_ext(ldapHandle, dn, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int ExtendedDirectoryOperation(ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_extended_operation(ldapHandle, oid, data, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static IntPtr GetFirstAttributeFromEntry(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr address) => Interop.ldap_first_attribute(ldapHandle, result, ref address);
+
+        internal static IntPtr GetFirstEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_entry(ldapHandle, result);
+
+        internal static IntPtr GetFirstReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_reference(ldapHandle, result);
+
+        internal static IntPtr GetDistinguishedName(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_get_dn(ldapHandle, result);
+
+        internal static int GetLastErrorFromConnection(ConnectionHandle ldapHandle)
+        {
+            int result = 0;
+            Interop.ldap_get_option_int(ldapHandle, LdapOption.LDAP_OPT_ERROR_NUMBER, ref result);
+            return result;
+        }
+
+        internal static int GetIntOption(ConnectionHandle ldapHandle, LdapOption option, ref int outValue) => Interop.ldap_get_option_int(ldapHandle, option, ref outValue);
+
+        internal static int GetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr outValue) => Interop.ldap_get_option_ptr(ldapHandle, option, ref outValue);
+
+        internal static int GetSecurityHandleOption(ConnectionHandle ldapHandle, LdapOption option, ref SecurityHandle outValue) => Interop.ldap_get_option_sechandle(ldapHandle, option, ref outValue);
+
+        // This option is not supported on Linux, so it would most likely throw.
+        internal static int GetSecInfoOption(ConnectionHandle ldapHandle, LdapOption option, SecurityPackageContextConnectionInformation outValue) => Interop.ldap_get_option_secInfo(ldapHandle, option, outValue);
+
+        internal static IntPtr GetValuesFromAttribute(ConnectionHandle ldapHandle, IntPtr result, string name) => Interop.ldap_get_values_len(ldapHandle, result, name);
+
+        internal static void FreeMemory(IntPtr outValue) => Interop.ldap_memfree(outValue);
+
+        internal static int ModifyDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_modify(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static IntPtr GetNextAttributeFromResult(ConnectionHandle ldapHandle, IntPtr result, IntPtr address) => Interop.ldap_next_attribute(ldapHandle, result, address);
+
+        internal static IntPtr GetNextEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_entry(ldapHandle, result);
+
+        internal static IntPtr GetNextReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_reference(ldapHandle, result);
+
+        internal static int ParseExtendedResult(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt) => Interop.ldap_parse_extended_result(ldapHandle, result, ref oid, ref data, freeIt);
+
+        internal static int ParseReference(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr referrals) => Interop.ldap_parse_reference(ldapHandle, result, ref referrals, IntPtr.Zero, 0);
+
+        internal static int ParseResult(ConnectionHandle ldapHandle, IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt) =>
+                                Interop.ldap_parse_result(ldapHandle, result, ref serverError, ref dn, ref message, ref referral, ref control, freeIt);
+
+        internal static int ParseResultReferral(ConnectionHandle ldapHandle, IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt)
+            => Interop.ldap_parse_result_referral(ldapHandle, result, serverError, dn, message, ref referral, control, freeIt);
+
+        internal static int RenameDirectoryEntry(ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_rename(ldapHandle, dn, newRdn, newParentDn, deleteOldRdn, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int GetResultFromAsyncOperation(ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Message) => Interop.ldap_result(ldapHandle, messageId, all, timeout, ref Message);
+
+        internal static int ResultToErrorCode(ConnectionHandle ldapHandle, IntPtr result, int freeIt) => Interop.ldap_result2error(ldapHandle, result, freeIt);
+
+        internal static int SearchDirectory(ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber) =>
+                                Interop.ldap_search(ldapHandle, dn, scope, filter, attributes, attributeOnly, servercontrol, clientcontrol, timelimit, sizelimit, ref messageNumber);
+
+        // This option is not supported in Linux, so it would most likely throw.
+        internal static int SetClientCertOption(ConnectionHandle ldapHandle, LdapOption option, QUERYCLIENTCERT outValue) => Interop.ldap_set_option_clientcert(ldapHandle, option, outValue);
+
+        internal static int SetIntOption(ConnectionHandle ld, LdapOption option, ref int inValue) => Interop.ldap_set_option_int(ld, option, ref inValue);
+
+        internal static int SetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr inValue) => Interop.ldap_set_option_ptr(ldapHandle, option, ref inValue);
+
+        internal static int SetReferralOption(ConnectionHandle ldapHandle, LdapOption option, ref LdapReferralCallback outValue) => Interop.ldap_set_option_referral(ldapHandle, option, ref outValue);
+
+        // This option is not supported in Linux, so it would most likely throw.
+        internal static int SetServerCertOption(ConnectionHandle ldapHandle, LdapOption option, VERIFYSERVERCERT outValue) => Interop.ldap_set_option_servercert(ldapHandle, option, outValue);
+
+        internal static int BindToDirectory(ConnectionHandle ld, string who, string passwd) => Interop.ldap_simple_bind(ld, who, passwd);
+
+        internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls);
+
+        // openldap doesn't have a ldap_stop_tls function. Returning true as no-op for Linux.
+        internal static byte StopTls(ConnectionHandle ldapHandle) => 1;
+
+        internal static void FreeValue(IntPtr referral) => Interop.ldap_value_free(referral);
+
+        internal static void FreeAttributes(IntPtr berelement) => Interop.ldap_value_free_len(berelement);
+
+        internal static string PtrToString(IntPtr requestName) => Marshal.PtrToStringAnsi(requestName);
+
+        internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalAnsi(s);
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Windows.cs
new file mode 100644 (file)
index 0000000..8a70be9
--- /dev/null
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal static class LdapPal
+    {
+        internal static void CancelDirectoryAsyncOperation(ConnectionHandle ldapHandle, int messagId) => Interop.ldap_abandon(ldapHandle, messagId);
+
+        internal static int AddDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_add(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int CompareDirectoryEntries(ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_compare(ldapHandle, dn, attributeName, strValue, binaryValue, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static void FreeDirectoryControl(IntPtr control) => Interop.ldap_control_free(control);
+
+        internal static void FreeDirectoryControls(IntPtr value) => Interop.ldap_controls_free(value);
+
+        internal static int CreateDirectorySortControl(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control) => Interop.ldap_create_sort_control(handle, keys, critical, ref control);
+
+        internal static int DeleteDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) => Interop.ldap_delete_ext(ldapHandle, dn, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int ExtendedDirectoryOperation(ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_extended_operation(ldapHandle, oid, data, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static IntPtr GetFirstAttributeFromEntry(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr address) => Interop.ldap_first_attribute(ldapHandle, result, ref address);
+
+        internal static IntPtr GetFirstEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_entry(ldapHandle, result);
+
+        internal static IntPtr GetFirstReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_first_reference(ldapHandle, result);
+
+        internal static IntPtr GetDistinguishedName(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_get_dn(ldapHandle, result);
+
+        internal static int GetLastErrorFromConnection(ConnectionHandle ldapHandle) => Interop.LdapGetLastError();
+
+        internal static int GetIntOption(ConnectionHandle ldapHandle, LdapOption option, ref int outValue) => Interop.ldap_get_option_int(ldapHandle, option, ref outValue);
+
+        internal static int GetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr outValue) => Interop.ldap_get_option_ptr(ldapHandle, option, ref outValue);
+
+        internal static int GetSecurityHandleOption(ConnectionHandle ldapHandle, LdapOption option, ref SecurityHandle outValue) => Interop.ldap_get_option_sechandle(ldapHandle, option, ref outValue);
+
+        internal static int GetSecInfoOption(ConnectionHandle ldapHandle, LdapOption option, SecurityPackageContextConnectionInformation outValue) => Interop.ldap_get_option_secInfo(ldapHandle, option, outValue);
+
+        internal static IntPtr GetValuesFromAttribute(ConnectionHandle ldapHandle, IntPtr result, string name) => Interop.ldap_get_values_len(ldapHandle, result, name);
+
+        internal static void FreeMemory(IntPtr outValue) => Interop.ldap_memfree(outValue);
+
+        internal static int ModifyDirectoryEntry(ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_modify(ldapHandle, dn, attrs, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static IntPtr GetNextAttributeFromResult(ConnectionHandle ldapHandle, IntPtr result, IntPtr address) => Interop.ldap_next_attribute(ldapHandle, result, address);
+
+        internal static IntPtr GetNextEntryFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_entry(ldapHandle, result);
+
+        internal static IntPtr GetNextReferenceFromResult(ConnectionHandle ldapHandle, IntPtr result) => Interop.ldap_next_reference(ldapHandle, result);
+
+        internal static int ParseExtendedResult(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt) => Interop.ldap_parse_extended_result(ldapHandle, result, ref oid, ref data, freeIt);
+
+        internal static int ParseReference(ConnectionHandle ldapHandle, IntPtr result, ref IntPtr referrals) => Interop.ldap_parse_reference(ldapHandle, result, ref referrals);
+
+        internal static int ParseResult(ConnectionHandle ldapHandle, IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt) =>
+                               Interop.ldap_parse_result(ldapHandle, result, ref serverError, ref dn, ref message, ref referral, ref control, freeIt);
+
+        internal static int ParseResultReferral(ConnectionHandle ldapHandle, IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt)
+            => Interop.ldap_parse_result_referral(ldapHandle, result, serverError, dn, message, ref referral, control, freeIt);
+
+        internal static int RenameDirectoryEntry(ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber) =>
+                                Interop.ldap_rename(ldapHandle, dn, newRdn, newParentDn, deleteOldRdn, servercontrol, clientcontrol, ref messageNumber);
+
+        internal static int GetResultFromAsyncOperation(ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Message) => Interop.ldap_result(ldapHandle, messageId, all, timeout, ref Message);
+
+        internal static int ResultToErrorCode(ConnectionHandle ldapHandle, IntPtr result, int freeIt) => Interop.ldap_result2error(ldapHandle, result, freeIt);
+
+        internal static int SearchDirectory(ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber) =>
+                                Interop.ldap_search(ldapHandle, dn, scope, filter, attributes, attributeOnly, servercontrol, clientcontrol, timelimit, sizelimit, ref messageNumber);
+
+        internal static int SetClientCertOption(ConnectionHandle ldapHandle, LdapOption option, QUERYCLIENTCERT outValue) => Interop.ldap_set_option_clientcert(ldapHandle, option, outValue);
+
+        internal static int SetIntOption(ConnectionHandle ld, LdapOption option, ref int inValue) => Interop.ldap_set_option_int(ld, option, ref inValue);
+
+        internal static int SetPtrOption(ConnectionHandle ldapHandle, LdapOption option, ref IntPtr inValue) => Interop.ldap_set_option_ptr(ldapHandle, option, ref inValue);
+
+        internal static int SetReferralOption(ConnectionHandle ldapHandle, LdapOption option, ref LdapReferralCallback outValue) => Interop.ldap_set_option_referral(ldapHandle, option, ref outValue);
+
+        internal static int SetServerCertOption(ConnectionHandle ldapHandle, LdapOption option, VERIFYSERVERCERT outValue) => Interop.ldap_set_option_servercert(ldapHandle, option, outValue);
+
+        internal static int BindToDirectory(ConnectionHandle ld, string who, string passwd) => Interop.ldap_simple_bind_s(ld, who, passwd);
+
+        internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls);
+
+        internal static byte StopTls(ConnectionHandle ldapHandle) => Interop.ldap_stop_tls(ldapHandle);
+
+        internal static void FreeValue(IntPtr referral) => Interop.ldap_value_free(referral);
+
+        internal static void FreeAttributes(IntPtr berelement) => Interop.ldap_value_free_len(berelement);
+
+        internal static string PtrToString(IntPtr requestName) => Marshal.PtrToStringUni(requestName);
+
+        internal static IntPtr StringToPtr(string s) => Marshal.StringToHGlobalUni(s);
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs
new file mode 100644 (file)
index 0000000..8478b4b
--- /dev/null
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid
+    {
+        internal bool _needDispose = false;
+
+        internal ConnectionHandle()
+            :base(true)
+        {
+            Interop.ldap_initialize(out handle, null);
+            _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_unbind_ext_s(handle, ref nullPointer, ref nullPointer);
+            }
+
+            handle = IntPtr.Zero;
+            return true;
+        }
+    }
+
+    internal sealed class SafeBerHandle : SafeHandleZeroOrMinusOneIsInvalid
+    {
+        internal SafeBerHandle() : base(true)
+        {
+            SetHandle(Interop.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 == 0)
+            {
+                throw new BerConversionException();
+            }
+            SetHandle(Interop.ber_init(value));
+            if (handle == IntPtr.Zero)
+            {
+                throw new BerConversionException();
+            }
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            Interop.ber_free(handle, 1);
+            return true;
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Windows.cs
new file mode 100644 (file)
index 0000000..26d3b49
--- /dev/null
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal sealed class SafeBerHandle : SafeHandleZeroOrMinusOneIsInvalid
+    {
+        internal SafeBerHandle() : base(true)
+        {
+            SetHandle(Interop.ber_alloc(1));
+            if (handle == IntPtr.Zero)
+            {
+                throw new OutOfMemoryException();
+            }
+        }
+
+        internal SafeBerHandle(berval value) : base(true)
+        {
+            SetHandle(Interop.ber_init(value));
+            if (handle == IntPtr.Zero)
+            {
+                throw new BerConversionException();
+            }
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            Interop.ber_free(handle, 1);
+            return true;
+        }
+    }
+
+    internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid
+    {
+        internal bool _needDispose = false;
+
+        internal ConnectionHandle() : base(true)
+        {
+            SetHandle(Interop.ldap_init(null, 389));
+
+            if (handle == IntPtr.Zero)
+            {
+                int error = Interop.LdapGetLastError();
+                if (Utility.IsLdapError((LdapError)error))
+                {
+                    string errorMessage = LdapErrorMappings.MapResultCode(error);
+                    throw new LdapException(error, errorMessage);
+                }
+                else
+                {
+                    throw new LdapException(error);
+                }
+            }
+        }
+
+        internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true)
+        {
+            _needDispose = disposeHandle;
+            if (value == IntPtr.Zero)
+            {
+                int error = Interop.LdapGetLastError();
+                if (Utility.IsLdapError((LdapError)error))
+                {
+                    string errorMessage = LdapErrorMappings.MapResultCode(error);
+                    throw new LdapException(error, errorMessage);
+                }
+                else
+                {
+                    throw new LdapException(error);
+                }
+            }
+            else
+            {
+                SetHandle(value);
+            }
+        }
+        protected override bool ReleaseHandle()
+        {
+            if (handle != IntPtr.Zero)
+            {
+                if (_needDispose)
+                {
+                    Interop.ldap_unbind(handle);
+                }
+
+                handle = IntPtr.Zero;
+            }
+            return true;
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.cs
new file mode 100644 (file)
index 0000000..0904f64
--- /dev/null
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.DirectoryServices.Protocols
+{
+    internal sealed class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
+    {
+        internal static IntPtr _dummyPointer = new IntPtr(1);
+
+        internal HGlobalMemHandle(IntPtr value) : base(true)
+        {
+            SetHandle(value);
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            if (handle != _dummyPointer)
+            {
+                Marshal.FreeHGlobal(handle);
+            }
+            return true;
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Linux.cs
new file mode 100644 (file)
index 0000000..2d1b850
--- /dev/null
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections;
+
+namespace System.DirectoryServices.Protocols
+{
+    public static partial class BerConverter
+    {
+        private static unsafe int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle berElement)
+        {
+            // Windows doesn't really decode BitStrings correctly, and wldap32 will internally treat it as 'O' Octet string.
+            // In order to match behavior, in Linux we will interpret 'B' as 'O' when passing the call to libldap.
+
+            int error = 0;
+            // return berval
+            byte[] byteArray = DecodingByteArrayHelper(berElement, 'O', ref error);
+            if (!BerPal.IsBerDecodeError(error))
+            {
+                // add result to the list
+                resultList.Add(byteArray);
+            }
+
+            return error;
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.Windows.cs
new file mode 100644 (file)
index 0000000..88e4f25
--- /dev/null
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace System.DirectoryServices.Protocols
+{
+    public static partial class BerConverter
+    {
+        private static unsafe int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle berElement)
+        {
+            int error;
+            // return a bitstring and its length
+            IntPtr ptrResult = IntPtr.Zero;
+            int length = 0;
+            error = BerPal.ScanNextBitString(berElement, "B", ref ptrResult, ref length);
+
+            if (!BerPal.IsBerDecodeError(error))
+            {
+                byte[] byteArray = null;
+                if (ptrResult != IntPtr.Zero)
+                {
+                    byteArray = new byte[length];
+                    Marshal.Copy(ptrResult, byteArray, 0, length);
+                }
+                resultList.Add(byteArray);
+            }
+            else
+            {
+                Debug.WriteLine("ber_scanf for format character 'B' failed");
+            }
+
+            // no need to free memory as wldap32 returns the original pointer instead of a duplicating memory pointer that
+            // needs to be freed
+            return error;
+        }
+    }
+}
index 65599433b1a7fc2547cd0f64720aa8ade325632f..dde428136c77e06a915d9117af6a8415daee0ab2 100644 (file)
@@ -2,15 +2,14 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections;
 using System.Diagnostics;
-using System.Globalization;
 using System.Runtime.InteropServices;
-using System.Collections;
 using System.Text;
 
 namespace System.DirectoryServices.Protocols
 {
-    public static class BerConverter
+    public static partial class BerConverter
     {
         public static byte[] Encode(string format, params object[] value)
         {
@@ -27,7 +26,7 @@ namespace System.DirectoryServices.Protocols
             Debug.WriteLine("Begin encoding\n");
 
             // allocate the berelement
-            BerSafeHandle berElement = new BerSafeHandle();
+            SafeBerHandle berElement = new SafeBerHandle();
 
             int valueCount = 0;
             int error = 0;
@@ -37,7 +36,7 @@ namespace System.DirectoryServices.Protocols
                 if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n')
                 {
                     // no argument needed
-                    error = Wldap32.ber_printf_emptyarg(berElement, new string(fmt, 1));
+                    error = BerPal.PrintEmptyArgument(berElement, new string(fmt, 1));
                 }
                 else if (fmt == 't' || fmt == 'i' || fmt == 'e')
                 {
@@ -56,7 +55,7 @@ namespace System.DirectoryServices.Protocols
                     }
 
                     // one int argument
-                    error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (int)value[valueCount]);
+                    error = BerPal.PrintInt(berElement, new string(fmt, 1), (int)value[valueCount]);
 
                     // increase the value count
                     valueCount++;
@@ -78,7 +77,7 @@ namespace System.DirectoryServices.Protocols
                     }
 
                     // one int argument
-                    error = Wldap32.ber_printf_int(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0);
+                    error = BerPal.PrintInt(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0);
 
                     // increase the value count
                     valueCount++;
@@ -220,7 +219,7 @@ namespace System.DirectoryServices.Protocols
             {
                 // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory
                 // deallocation, wldap has special check. So have to use IntPtr directly here.
-                error = Wldap32.ber_flatten(berElement, ref flattenptr);
+                error = BerPal.FlattenBerElement(berElement, ref flattenptr);
 
                 if (error == -1)
                 {
@@ -247,7 +246,7 @@ namespace System.DirectoryServices.Protocols
             finally
             {
                 if (flattenptr != IntPtr.Zero)
-                    Wldap32.ber_bvfree(flattenptr);
+                    BerPal.FreeBerval(flattenptr);
             }
 
             return encodingResult;
@@ -273,7 +272,7 @@ namespace System.DirectoryServices.Protocols
             UTF8Encoding utf8Encoder = new UTF8Encoding(false, true);
             berval berValue = new berval();
             ArrayList resultList = new ArrayList();
-            BerSafeHandle berElement = null;
+            SafeBerHandle berElement = null;
 
             object[] decodeResult = null;
             decodeSucceeded = false;
@@ -292,7 +291,7 @@ namespace System.DirectoryServices.Protocols
 
             try
             {
-                berElement = new BerSafeHandle(berValue);
+                berElement = new SafeBerHandle(berValue);
             }
             finally
             {
@@ -307,17 +306,17 @@ namespace System.DirectoryServices.Protocols
                 char fmt = format[formatCount];
                 if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n' || fmt == 'x')
                 {
-                    error = Wldap32.ber_scanf(berElement, new string(fmt, 1));
+                    error = BerPal.ScanNext(berElement, new string(fmt, 1));
 
-                    if (error != 0)
+                    if (BerPal.IsBerDecodeError(error))
                         Debug.WriteLine("ber_scanf for {, }, [, ], n or x failed");
                 }
                 else if (fmt == 'i' || fmt == 'e' || fmt == 'b')
                 {
                     int result = 0;
-                    error = Wldap32.ber_scanf_int(berElement, new string(fmt, 1), ref result);
+                    error = BerPal.ScanNextInt(berElement, new string(fmt, 1), ref result);
 
-                    if (error == 0)
+                    if (!BerPal.IsBerDecodeError(error))
                     {
                         if (fmt == 'b')
                         {
@@ -341,7 +340,7 @@ namespace System.DirectoryServices.Protocols
                 {
                     // return a string
                     byte[] byteArray = DecodingByteArrayHelper(berElement, 'O', ref error);
-                    if (error == 0)
+                    if (!BerPal.IsBerDecodeError(error))
                     {
                         string s = null;
                         if (byteArray != null)
@@ -354,7 +353,7 @@ namespace System.DirectoryServices.Protocols
                 {
                     // return berval
                     byte[] byteArray = DecodingByteArrayHelper(berElement, fmt, ref error);
-                    if (error == 0)
+                    if (!BerPal.IsBerDecodeError(error))
                     {
                         // add result to the list
                         resultList.Add(byteArray);
@@ -362,26 +361,7 @@ namespace System.DirectoryServices.Protocols
                 }
                 else if (fmt == 'B')
                 {
-                    // return a bitstring and its length
-                    IntPtr ptrResult = IntPtr.Zero;
-                    int length = 0;
-                    error = Wldap32.ber_scanf_bitstring(berElement, "B", ref ptrResult, ref length);
-
-                    if (error == 0)
-                    {
-                        byte[] byteArray = null;
-                        if (ptrResult != IntPtr.Zero)
-                        {
-                            byteArray = new byte[length];
-                            Marshal.Copy(ptrResult, byteArray, 0, length);
-                        }
-                        resultList.Add(byteArray);
-                    }
-                    else
-                        Debug.WriteLine("ber_scanf for format character 'B' failed");
-
-                    // no need to free memory as wldap32 returns the original pointer instead of a duplicating memory pointer that
-                    // needs to be freed
+                    error = DecodeBitStringHelper(resultList, berElement);
                 }
                 else if (fmt == 'v')
                 {
@@ -390,7 +370,7 @@ namespace System.DirectoryServices.Protocols
                     string[] stringArray = null;
 
                     byteArrayresult = DecodingMultiByteArrayHelper(berElement, 'V', ref error);
-                    if (error == 0)
+                    if (!BerPal.IsBerDecodeError(error))
                     {
                         if (byteArrayresult != null)
                         {
@@ -416,7 +396,7 @@ namespace System.DirectoryServices.Protocols
                     byte[][] result = null;
 
                     result = DecodingMultiByteArrayHelper(berElement, fmt, ref error);
-                    if (error == 0)
+                    if (!BerPal.IsBerDecodeError(error))
                     {
                         resultList.Add(result);
                     }
@@ -427,7 +407,7 @@ namespace System.DirectoryServices.Protocols
                     throw new ArgumentException(SR.BerConverterUndefineChar);
                 }
 
-                if (error != 0)
+                if (BerPal.IsBerDecodeError(error))
                 {
                     // decode failed, just return
                     return decodeResult;
@@ -444,7 +424,7 @@ namespace System.DirectoryServices.Protocols
             return decodeResult;
         }
 
-        private static int EncodingByteArrayHelper(BerSafeHandle berElement, byte[] tempValue, char fmt)
+        private static int EncodingByteArrayHelper(SafeBerHandle berElement, byte[] tempValue, char fmt)
         {
             int error = 0;
 
@@ -454,18 +434,18 @@ namespace System.DirectoryServices.Protocols
                 IntPtr tmp = Marshal.AllocHGlobal(tempValue.Length);
                 Marshal.Copy(tempValue, 0, tmp, tempValue.Length);
                 HGlobalMemHandle memHandle = new HGlobalMemHandle(tmp);
-
-                error = Wldap32.ber_printf_bytearray(berElement, new string(fmt, 1), memHandle, tempValue.Length);
+                error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, tempValue.Length);
             }
             else
             {
-                error = Wldap32.ber_printf_bytearray(berElement, new string(fmt, 1), new HGlobalMemHandle(IntPtr.Zero), 0);
+                HGlobalMemHandle memHandle = new HGlobalMemHandle(HGlobalMemHandle._dummyPointer);
+                error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, 0);
             }
 
             return error;
         }
 
-        private static byte[] DecodingByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error)
+        private static byte[] DecodingByteArrayHelper(SafeBerHandle berElement, char fmt, ref int error)
         {
             error = 0;
             IntPtr result = IntPtr.Zero;
@@ -474,11 +454,11 @@ namespace System.DirectoryServices.Protocols
 
             // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory
             // deallocation, wldap has special check. So have to use IntPtr directly here.
-            error = Wldap32.ber_scanf_ptr(berElement, new string(fmt, 1), ref result);
+            error = BerPal.ScanNextPtr(berElement, new string(fmt, 1), ref result);
 
             try
             {
-                if (error == 0)
+                if (!BerPal.IsBerDecodeError(error))
                 {
                     if (result != IntPtr.Zero)
                     {
@@ -494,17 +474,17 @@ namespace System.DirectoryServices.Protocols
             finally
             {
                 if (result != IntPtr.Zero)
-                    Wldap32.ber_bvfree(result);
+                    BerPal.FreeBerval(result);
             }
 
             return byteArray;
         }
 
-        private static int EncodingMultiByteArrayHelper(BerSafeHandle berElement, byte[][] tempValue, char fmt)
+        private static int EncodingMultiByteArrayHelper(SafeBerHandle berElement, byte[][] tempValue, char fmt)
         {
             IntPtr berValArray = IntPtr.Zero;
             IntPtr tempPtr = IntPtr.Zero;
-            SafeBerval[] managedBerVal = null;
+            berval[] managedBervalArray = null;
             int error = 0;
 
             try
@@ -513,31 +493,26 @@ namespace System.DirectoryServices.Protocols
                 {
                     int i = 0;
                     berValArray = Utility.AllocHGlobalIntPtrArray(tempValue.Length + 1);
-                    int structSize = Marshal.SizeOf(typeof(SafeBerval));
-                    managedBerVal = new SafeBerval[tempValue.Length];
+                    int structSize = Marshal.SizeOf(typeof(berval));
+                    managedBervalArray = new berval[tempValue.Length];
 
                     for (i = 0; i < tempValue.Length; i++)
                     {
                         byte[] byteArray = tempValue[i];
 
                         // construct the managed berval
-                        managedBerVal[i] = new SafeBerval();
+                        managedBervalArray[i] = new berval();
 
-                        if (byteArray == null)
-                        {
-                            managedBerVal[i].bv_len = 0;
-                            managedBerVal[i].bv_val = IntPtr.Zero;
-                        }
-                        else
+                        if (byteArray != null)
                         {
-                            managedBerVal[i].bv_len = byteArray.Length;
-                            managedBerVal[i].bv_val = Marshal.AllocHGlobal(byteArray.Length);
-                            Marshal.Copy(byteArray, 0, managedBerVal[i].bv_val, byteArray.Length);
+                            managedBervalArray[i].bv_len = byteArray.Length;
+                            managedBervalArray[i].bv_val = Marshal.AllocHGlobal(byteArray.Length);
+                            Marshal.Copy(byteArray, 0, managedBervalArray[i].bv_val, byteArray.Length);
                         }
 
                         // allocate memory for the unmanaged structure
                         IntPtr valPtr = Marshal.AllocHGlobal(structSize);
-                        Marshal.StructureToPtr(managedBerVal[i], valPtr, false);
+                        Marshal.StructureToPtr(managedBervalArray[i], valPtr, false);
 
                         tempPtr = (IntPtr)((long)berValArray + IntPtr.Size * i);
                         Marshal.WriteIntPtr(tempPtr, valPtr);
@@ -547,9 +522,7 @@ namespace System.DirectoryServices.Protocols
                     Marshal.WriteIntPtr(tempPtr, IntPtr.Zero);
                 }
 
-                error = Wldap32.ber_printf_berarray(berElement, new string(fmt, 1), berValArray);
-
-                GC.KeepAlive(managedBerVal);
+                error = BerPal.PrintBerArray(berElement, new string(fmt, 1), berValArray);
             }
             finally
             {
@@ -563,12 +536,22 @@ namespace System.DirectoryServices.Protocols
                     }
                     Marshal.FreeHGlobal(berValArray);
                 }
+                if (managedBervalArray != null)
+                {
+                    foreach (berval managedBerval in managedBervalArray)
+                    {
+                        if (managedBerval.bv_val != IntPtr.Zero)
+                        {
+                            Marshal.FreeHGlobal(managedBerval.bv_val);
+                        }
+                    }
+                }
             }
 
             return error;
         }
 
-        private static byte[][] DecodingMultiByteArrayHelper(BerSafeHandle berElement, char fmt, ref int error)
+        private static byte[][] DecodingMultiByteArrayHelper(SafeBerHandle berElement, char fmt, ref int error)
         {
             error = 0;
             // several berval
@@ -580,9 +563,9 @@ namespace System.DirectoryServices.Protocols
 
             try
             {
-                error = Wldap32.ber_scanf_ptr(berElement, new string(fmt, 1), ref ptrResult);
+                error = BerPal.ScanNextPtr(berElement, new string(fmt, 1), ref ptrResult);
 
-                if (error == 0)
+                if (!BerPal.IsBerDecodeError(error))
                 {
                     if (ptrResult != IntPtr.Zero)
                     {
@@ -615,7 +598,7 @@ namespace System.DirectoryServices.Protocols
             {
                 if (ptrResult != IntPtr.Zero)
                 {
-                    Wldap32.ber_bvecfree(ptrResult);
+                    BerPal.FreeBervalArray(ptrResult);
                 }
             }
 
index 8a9efa373315df480c660f3a555990fafdfd9f8b..ca22f76d9d0be389a5d447c913392e5203553174 100644 (file)
@@ -729,7 +729,7 @@ namespace System.DirectoryServices.Protocols
                 Marshal.WriteIntPtr(tempPtr, IntPtr.Zero);
 
                 bool critical = IsCritical;
-                int error = Wldap32.ldap_create_sort_control(UtilityHandle.GetHandle(), memHandle, critical ? (byte)1 : (byte)0, ref control);
+                int error = LdapPal.CreateDirectorySortControl(UtilityHandle.GetHandle(), memHandle, critical ? (byte)1 : (byte)0, ref control);
 
                 if (error != 0)
                 {
@@ -759,7 +759,7 @@ namespace System.DirectoryServices.Protocols
             {
                 if (control != IntPtr.Zero)
                 {
-                    Wldap32.ldap_control_free(control);
+                    LdapPal.FreeDirectoryControl(control);
                 }
 
                 if (memHandle != IntPtr.Zero)
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs
new file mode 100644 (file)
index 0000000..405d4f9
--- /dev/null
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Net;
+
+namespace System.DirectoryServices.Protocols
+{
+    public partial class LdapConnection
+    {
+        // Linux doesn't support setting FQDN so we mark the flag as if it is already set so we don't make a call to set it again.
+        private bool _setFQDNDone = true;
+
+        private void InternalInitConnectionHandle(string hostname) => _ldapHandle = new ConnectionHandle(Interop.ldap_init(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose);
+
+        private int InternalConnectToServer()
+        {
+            Debug.Assert(!_ldapHandle.IsInvalid);
+            // In Linux you don't have to call Connect after calling init. You directly call bind.
+            return 0;
+        }
+
+        private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method)
+        {
+            int error;
+            if (tempCredential == null && AuthType == AuthType.External)
+            {
+                error = Interop.ldap_simple_bind(_ldapHandle, null, null);
+            }
+            else
+            {
+                error = Interop.ldap_simple_bind(_ldapHandle, cred.user, cred.password);
+            }
+
+            return error;
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Windows.cs
new file mode 100644 (file)
index 0000000..6ae5eb9
--- /dev/null
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Net;
+
+namespace System.DirectoryServices.Protocols
+{
+    public partial class LdapConnection
+    {
+        private bool _setFQDNDone = false;
+
+        private void InternalInitConnectionHandle(string hostname)
+        {
+            LdapDirectoryIdentifier directoryIdentifier = _directoryIdentifier as LdapDirectoryIdentifier;
+
+            // User wants to setup a connectionless session with server.
+            if (directoryIdentifier.Connectionless)
+            {
+                _ldapHandle = new ConnectionHandle(Interop.cldap_open(hostname, directoryIdentifier.PortNumber), _needDispose);
+            }
+            else
+            {
+                _ldapHandle = new ConnectionHandle(Interop.ldap_init(hostname, directoryIdentifier.PortNumber), _needDispose);
+            }
+        }
+
+        private int InternalConnectToServer()
+        {
+            // Connect explicitly to the server.
+            var timeout = new LDAP_TIMEVAL()
+            {
+                tv_sec = (int)(_connectionTimeOut.Ticks / TimeSpan.TicksPerSecond)
+            };
+            Debug.Assert(!_ldapHandle.IsInvalid);
+            return Interop.ldap_connect(_ldapHandle, timeout);
+        }
+
+        private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method)
+            => tempCredential == null && AuthType == AuthType.External ? Interop.ldap_bind_s(_ldapHandle, null, null, method) : Interop.ldap_bind_s(_ldapHandle, null, cred, method);
+    }
+}
index eef1bd29f821077989f3c91d469844bc565b3098..c66383e6d8a97f005c8e282a6580180fe473bc20 100644 (file)
@@ -12,6 +12,7 @@ using System.Runtime.InteropServices;
 using System.Xml;
 using System.Threading;
 using System.Security.Cryptography.X509Certificates;
+using System.Diagnostics.CodeAnalysis;
 
 namespace System.DirectoryServices.Protocols
 {
@@ -20,7 +21,7 @@ namespace System.DirectoryServices.Protocols
     [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
     internal delegate bool QUERYCLIENTCERT(IntPtr Connection, IntPtr trusted_CAs, ref IntPtr certificateHandle);
 
-    public class LdapConnection : DirectoryConnection, IDisposable
+    public partial class LdapConnection : DirectoryConnection, IDisposable
     {
         internal enum LdapResult
         {
@@ -48,7 +49,6 @@ namespace System.DirectoryServices.Protocols
         private static readonly LdapPartialResultsProcessor s_partialResultsProcessor = null;
         private static readonly ManualResetEvent s_waitHandle = null;
         private static readonly PartialResultsRetriever s_retriever = null;
-        private bool _setFQDNDone = false;
         internal bool _needDispose = true;
         private bool _connected = false;
         internal QUERYCLIENTCERT _clientCertificateRoutine = null;
@@ -216,15 +216,7 @@ namespace System.DirectoryServices.Protocols
                 }
             }
 
-            // User wants to setup a connectionless session with server.
-            if (((LdapDirectoryIdentifier)_directoryIdentifier).Connectionless == true)
-            {
-                _ldapHandle = new ConnectionHandle(Wldap32.cldap_open(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose);
-            }
-            else
-            {
-                _ldapHandle = new ConnectionHandle(Wldap32.ldap_init(hostname, ((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber), _needDispose);
-            }
+            InternalInitConnectionHandle(hostname);
 
             // Create a WeakReference object with the target of ldapHandle and put it into our handle table.
             lock (s_objectLock)
@@ -303,7 +295,7 @@ namespace System.DirectoryServices.Protocols
                 if (error == 0)
                 {
                     // Success code but message is -1, unexpected.
-                    error = Wldap32.LdapGetLastError();
+                    error = LdapPal.GetLastErrorFromConnection(_ldapHandle);
                 }
 
                 throw ConstructException(error, operation);
@@ -406,7 +398,7 @@ namespace System.DirectoryServices.Protocols
             if (error == 0)
             {
                 // Success code but message is -1, unexpected.
-                error = Wldap32.LdapGetLastError();
+                error = LdapPal.GetLastErrorFromConnection(_ldapHandle);
             }
 
             throw ConstructException(error, operation);
@@ -476,7 +468,7 @@ namespace System.DirectoryServices.Protocols
             }
 
             // Cancel the request.
-            Wldap32.ldap_abandon(_ldapHandle, messageId);
+            LdapPal.CancelDirectoryAsyncOperation(_ldapHandle, messageId);
 
             LdapRequestState resultObject = result._resultObject;
             if (resultObject != null)
@@ -634,17 +626,18 @@ namespace System.DirectoryServices.Protocols
                 if (request is DeleteRequest)
                 {
                     // It is an delete operation.
-                    error = Wldap32.ldap_delete_ext(_ldapHandle, ((DeleteRequest)request).DistinguishedName, serverControlArray, clientControlArray, ref messageID);
+                    error = LdapPal.DeleteDirectoryEntry(_ldapHandle, ((DeleteRequest)request).DistinguishedName, serverControlArray, clientControlArray, ref messageID);
                 }
                 else if (request is ModifyDNRequest)
                 {
                     // It is a modify dn operation
-                    error = Wldap32.ldap_rename(_ldapHandle,
-                                                 ((ModifyDNRequest)request).DistinguishedName,
-                                                 ((ModifyDNRequest)request).NewName,
-                                                 ((ModifyDNRequest)request).NewParentDistinguishedName,
-                                                 ((ModifyDNRequest)request).DeleteOldRdn ? 1 : 0,
-                                                 serverControlArray, clientControlArray, ref messageID);
+                    error = LdapPal.RenameDirectoryEntry(
+                        _ldapHandle,
+                        ((ModifyDNRequest)request).DistinguishedName,
+                        ((ModifyDNRequest)request).NewName,
+                        ((ModifyDNRequest)request).NewParentDistinguishedName,
+                        ((ModifyDNRequest)request).DeleteOldRdn ? 1 : 0,
+                        serverControlArray, clientControlArray, ref messageID);
                 }
                 else if (request is CompareRequest compareRequest)
                 {
@@ -680,12 +673,13 @@ namespace System.DirectoryServices.Protocols
                     }
 
                     // It is a compare request.
-                    error = Wldap32.ldap_compare(_ldapHandle,
-                                                  ((CompareRequest)request).DistinguishedName,
-                                                  assertion.Name,
-                                                  stringValue,
-                                                  berValuePtr,
-                                                  serverControlArray, clientControlArray, ref messageID);
+                    error = LdapPal.CompareDirectoryEntries(
+                        _ldapHandle,
+                        ((CompareRequest)request).DistinguishedName,
+                        assertion.Name,
+                        stringValue,
+                        berValuePtr,
+                        serverControlArray, clientControlArray, ref messageID);
                 }
                 else if (request is AddRequest || request is ModifyRequest)
                 {
@@ -715,17 +709,19 @@ namespace System.DirectoryServices.Protocols
 
                     if (request is AddRequest)
                     {
-                        error = Wldap32.ldap_add(_ldapHandle,
-                                                  ((AddRequest)request).DistinguishedName,
-                                                  modArray,
-                                                  serverControlArray, clientControlArray, ref messageID);
+                        error = LdapPal.AddDirectoryEntry(
+                            _ldapHandle,
+                            ((AddRequest)request).DistinguishedName,
+                            modArray,
+                            serverControlArray, clientControlArray, ref messageID);
                     }
                     else
                     {
-                        error = Wldap32.ldap_modify(_ldapHandle,
-                                                     ((ModifyRequest)request).DistinguishedName,
-                                                     modArray,
-                                                     serverControlArray, clientControlArray, ref messageID);
+                        error = LdapPal.ModifyDirectoryEntry(
+                            _ldapHandle,
+                            ((ModifyRequest)request).DistinguishedName,
+                            modArray,
+                            serverControlArray, clientControlArray, ref messageID);
                     }
                 }
                 else if (request is ExtendedRequest extendedRequest)
@@ -744,10 +740,11 @@ namespace System.DirectoryServices.Protocols
                         Marshal.Copy(val, 0, berValuePtr.bv_val, val.Length);
                     }
 
-                    error = Wldap32.ldap_extended_operation(_ldapHandle,
-                                                            name,
-                                                            berValuePtr,
-                                                            serverControlArray, clientControlArray, ref messageID);
+                    error = LdapPal.ExtendedDirectoryOperation(
+                        _ldapHandle,
+                        name,
+                        berValuePtr,
+                        serverControlArray, clientControlArray, ref messageID);
                 }
                 else if (request is SearchRequest searchRequest)
                 {
@@ -772,7 +769,7 @@ namespace System.DirectoryServices.Protocols
                         int i = 0;
                         for (i = 0; i < attributeCount; i++)
                         {
-                            IntPtr controlPtr = Marshal.StringToHGlobalUni(searchRequest.Attributes[i]);
+                            IntPtr controlPtr = LdapPal.StringToPtr(searchRequest.Attributes[i]);
                             tempPtr = (IntPtr)((long)searchAttributes + IntPtr.Size * i);
                             Marshal.WriteIntPtr(tempPtr, controlPtr);
                         }
@@ -793,17 +790,18 @@ namespace System.DirectoryServices.Protocols
 
                     try
                     {
-                        error = Wldap32.ldap_search(_ldapHandle,
-                                                     searchRequest.DistinguishedName,
-                                                     searchScope,
-                                                     searchRequestFilter,
-                                                     searchAttributes,
-                                                     searchRequest.TypesOnly,
-                                                     serverControlArray,
-                                                     clientControlArray,
-                                                     searchTimeLimit,
-                                                     searchRequest.SizeLimit,
-                                                     ref messageID);
+                        error = LdapPal.SearchDirectory(
+                            _ldapHandle,
+                            searchRequest.DistinguishedName,
+                            searchScope,
+                            searchRequestFilter,
+                            searchAttributes,
+                            searchRequest.TypesOnly,
+                            serverControlArray,
+                            clientControlArray,
+                            searchTimeLimit,
+                            searchRequest.SizeLimit,
+                            ref messageID);
                     }
                     finally
                     {
@@ -1006,7 +1004,7 @@ namespace System.DirectoryServices.Protocols
             // Set the certificate callback routine here if user adds the certifcate to the certificate collection.
             if (ClientCertificates.Count != 0)
             {
-                int certError = Wldap32.ldap_set_option_clientcert(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine);
+                int certError = LdapPal.SetClientCertOption(_ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _clientCertificateRoutine);
                 if (certError != (int)ResultCode.Success)
                 {
                     if (Utility.IsLdapError((LdapError)certError))
@@ -1025,19 +1023,13 @@ namespace System.DirectoryServices.Protocols
             // Set the LDAP_OPT_AREC_EXCLUSIVE flag if necessary.
             if (((LdapDirectoryIdentifier)Directory).FullyQualifiedDnsHostName && !_setFQDNDone)
             {
-                SessionOptions.FQDN = true;
+                SessionOptions.SetFqdnRequired();
                 _setFQDNDone = true;
             }
 
-            // Connect explicitly to the server.
-            var timeout = new LDAP_TIMEVAL()
-            {
-                tv_sec = (int)(_connectionTimeOut.Ticks / TimeSpan.TicksPerSecond)
-            };
-            Debug.Assert(!_ldapHandle.IsInvalid);
-            int error = Wldap32.ldap_connect(_ldapHandle, timeout);
+            int error = InternalConnectToServer();
 
-            // Filed, throw an exception.
+            // Failed, throw an exception.
             if (error != (int)ResultCode.Success)
             {
                 if (Utility.IsLdapError((LdapError)error))
@@ -1106,7 +1098,7 @@ namespace System.DirectoryServices.Protocols
             int error;
             if (AuthType == AuthType.Anonymous)
             {
-                error = Wldap32.ldap_simple_bind_s(_ldapHandle, null, null);
+                error = LdapPal.BindToDirectory(_ldapHandle, null, null);
             }
             else if (AuthType == AuthType.Basic)
             {
@@ -1118,19 +1110,19 @@ namespace System.DirectoryServices.Protocols
                 }
 
                 tempDomainName.Append(username);
-                error = Wldap32.ldap_simple_bind_s(_ldapHandle, tempDomainName.ToString(), password);
+                error = LdapPal.BindToDirectory(_ldapHandle, tempDomainName.ToString(), password);
             }
             else
             {
                 var cred = new SEC_WINNT_AUTH_IDENTITY_EX()
                 {
-                    version = Wldap32.SEC_WINNT_AUTH_IDENTITY_VERSION,
+                    version = Interop.SEC_WINNT_AUTH_IDENTITY_VERSION,
                     length = Marshal.SizeOf(typeof(SEC_WINNT_AUTH_IDENTITY_EX)),
-                    flags = Wldap32.SEC_WINNT_AUTH_IDENTITY_UNICODE
+                    flags = Interop.SEC_WINNT_AUTH_IDENTITY_UNICODE
                 };
                 if (AuthType == AuthType.Kerberos)
                 {
-                    cred.packageList = Wldap32.MICROSOFT_KERBEROS_NAME_W;
+                    cred.packageList = Interop.MICROSOFT_KERBEROS_NAME_W;
                     cred.packageListLength = cred.packageList.Length;
                 }
 
@@ -1173,14 +1165,7 @@ namespace System.DirectoryServices.Protocols
                         break;
                 }
 
-                if (tempCredential == null && AuthType == AuthType.External)
-                {
-                    error = Wldap32.ldap_bind_s(_ldapHandle, null, null, method);
-                }
-                else
-                {
-                    error = Wldap32.ldap_bind_s(_ldapHandle, null, cred, method);
-                }
+                error = InternalBind(tempCredential, cred, method);
             }
 
             // Failed, throw exception.
@@ -1275,7 +1260,7 @@ namespace System.DirectoryServices.Protocols
                         managedControls[i] = new LdapControl()
                         {
                             // Get the control type.
-                            ldctl_oid = Marshal.StringToHGlobalUni(((DirectoryControl)controlList[i]).Type),
+                            ldctl_oid = LdapPal.StringToPtr(((DirectoryControl)controlList[i]).Type),
 
                             // Get the control cricality.
                             ldctl_iscritical = ((DirectoryControl)controlList[i]).IsCritical
@@ -1358,7 +1343,7 @@ namespace System.DirectoryServices.Protocols
                     attributes[i].type |= LDAP_MOD_BVALUES;
 
                     // Write the attribute name.
-                    attributes[i].attribute = Marshal.StringToHGlobalUni(modAttribute.Name);
+                    attributes[i].attribute = LdapPal.StringToPtr(modAttribute.Name);
 
                     // Write the values.
                     int valuesCount = 0;
@@ -1451,7 +1436,7 @@ namespace System.DirectoryServices.Protocols
                 needAbandon = false;
             }
 
-            int error = Wldap32.ldap_result(_ldapHandle, messageId, (int)resultType, timeout, ref ldapResult);
+            int error = LdapPal.GetResultFromAsyncOperation(_ldapHandle, messageId, (int)resultType, timeout, ref ldapResult);
             if (error != -1 && error != 0)
             {
                 // parsing the result
@@ -1499,13 +1484,13 @@ namespace System.DirectoryServices.Protocols
                             response = new ExtendedResponse(responseDn, responseControl, (ResultCode)resultError, responseMessage, responseReferral);
                             if (resultError == (int)ResultCode.Success)
                             {
-                                resultError = Wldap32.ldap_parse_extended_result(_ldapHandle, ldapResult, ref requestName, ref requestValue, 0 /*not free it*/);
+                                resultError = LdapPal.ParseExtendedResult(_ldapHandle, ldapResult, ref requestName, ref requestValue, 0 /*not free it*/);
                                 if (resultError == 0)
                                 {
                                     string name = null;
                                     if (requestName != IntPtr.Zero)
                                     {
-                                        name = Marshal.PtrToStringUni(requestName);
+                                        name = LdapPal.PtrToString(requestName);
                                     }
 
                                     berval val = null;
@@ -1542,7 +1527,7 @@ namespace System.DirectoryServices.Protocols
                             SearchResultReferenceCollection searchResultReferences = new SearchResultReferenceCollection();
 
                             // parsing the resultentry
-                            entryMessage = Wldap32.ldap_first_entry(_ldapHandle, ldapResult);
+                            entryMessage = LdapPal.GetFirstEntryFromResult(_ldapHandle, ldapResult);
 
                             int entrycount = 0;
                             while (entryMessage != IntPtr.Zero)
@@ -1554,11 +1539,11 @@ namespace System.DirectoryServices.Protocols
                                 }
 
                                 entrycount++;
-                                entryMessage = Wldap32.ldap_next_entry(_ldapHandle, entryMessage);
+                                entryMessage = LdapPal.GetNextEntryFromResult(_ldapHandle, entryMessage);
                             }
 
                             // Parse the reference.
-                            IntPtr referenceMessage = Wldap32.ldap_first_reference(_ldapHandle, ldapResult);
+                            IntPtr referenceMessage = LdapPal.GetFirstReferenceFromResult(_ldapHandle, ldapResult);
 
                             while (referenceMessage != IntPtr.Zero)
                             {
@@ -1568,7 +1553,7 @@ namespace System.DirectoryServices.Protocols
                                     searchResultReferences.Add(reference);
                                 }
 
-                                referenceMessage = Wldap32.ldap_next_reference(_ldapHandle, referenceMessage);
+                                referenceMessage = LdapPal.GetNextReferenceFromResult(_ldapHandle, referenceMessage);
                             }
 
                             ((SearchResponse)response).Entries = searchResultEntries;
@@ -1601,17 +1586,17 @@ namespace System.DirectoryServices.Protocols
                 {
                     if (requestName != IntPtr.Zero)
                     {
-                        Wldap32.ldap_memfree(requestName);
+                        LdapPal.FreeMemory(requestName);
                     }
 
                     if (requestValue != IntPtr.Zero)
                     {
-                        Wldap32.ldap_memfree(requestValue);
+                        LdapPal.FreeMemory(requestValue);
                     }
 
                     if (ldapResult != IntPtr.Zero)
                     {
-                        Wldap32.ldap_msgfree(ldapResult);
+                        LdapPal.FreeMemory(ldapResult);
                     }
                 }
             }
@@ -1634,13 +1619,13 @@ namespace System.DirectoryServices.Protocols
                 }
                 else
                 {
-                    error = Wldap32.LdapGetLastError();
+                    error = LdapPal.GetLastErrorFromConnection(_ldapHandle);
                 }
 
                 // Abandon the request.
                 if (needAbandon)
                 {
-                    Wldap32.ldap_abandon(_ldapHandle, messageId);
+                    LdapPal.CancelDirectoryAsyncOperation(_ldapHandle, messageId);
                 }
             }
 
@@ -1657,15 +1642,15 @@ namespace System.DirectoryServices.Protocols
 
             try
             {
-                int resultError = Wldap32.ldap_parse_result(_ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */);
+                int resultError = LdapPal.ParseResult(_ldapHandle, ldapResult, ref serverError, ref dn, ref message, ref referral, ref control, 0 /* not free it */);
 
                 if (resultError == 0)
                 {
                     // Parse the dn.
-                    responseDn = Marshal.PtrToStringUni(dn);
+                    responseDn = LdapPal.PtrToString(dn);
 
                     // Parse the message.
-                    responseMessage = Marshal.PtrToStringUni(message);
+                    responseMessage = LdapPal.PtrToString(message);
 
                     // Parse the referral.
                     if (referral != IntPtr.Zero)
@@ -1676,7 +1661,7 @@ namespace System.DirectoryServices.Protocols
                         var referralList = new ArrayList();
                         while (singleReferral != null)
                         {
-                            string s = Marshal.PtrToStringUni((IntPtr)singleReferral);
+                            string s = LdapPal.PtrToString((IntPtr)singleReferral);
                             referralList.Add(s);
 
                             i++;
@@ -1718,7 +1703,7 @@ namespace System.DirectoryServices.Protocols
                     // we need to take care of one special case, when can't connect to the server, ldap_parse_result fails with local error
                     if (resultError == (int)LdapError.LocalError)
                     {
-                        int tmpResult = Wldap32.ldap_result2error(_ldapHandle, ldapResult, 0 /* not free it */);
+                        int tmpResult = LdapPal.ResultToErrorCode(_ldapHandle, ldapResult, 0 /* not free it */);
                         if (tmpResult != 0)
                         {
                             resultError = tmpResult;
@@ -1732,22 +1717,22 @@ namespace System.DirectoryServices.Protocols
             {
                 if (dn != IntPtr.Zero)
                 {
-                    Wldap32.ldap_memfree(dn);
+                    LdapPal.FreeMemory(dn);
                 }
 
                 if (message != IntPtr.Zero)
                 {
-                    Wldap32.ldap_memfree(message);
+                    LdapPal.FreeMemory(message);
                 }
 
                 if (referral != IntPtr.Zero)
                 {
-                    Wldap32.ldap_value_free(referral);
+                    LdapPal.FreeValue(referral);
                 }
 
                 if (control != IntPtr.Zero)
                 {
-                    Wldap32.ldap_controls_free(control);
+                    LdapPal.FreeDirectoryControls(control);
                 }
             }
         }
@@ -1762,11 +1747,11 @@ namespace System.DirectoryServices.Protocols
             {
                 // Get the dn.
                 string entryDn = null;
-                dn = Wldap32.ldap_get_dn(_ldapHandle, entryMessage);
+                dn = LdapPal.GetDistinguishedName(_ldapHandle, entryMessage);
                 if (dn != IntPtr.Zero)
                 {
-                    entryDn = Marshal.PtrToStringUni(dn);
-                    Wldap32.ldap_memfree(dn);
+                    entryDn = LdapPal.PtrToString(dn);
+                    LdapPal.FreeMemory(dn);
                     dn = IntPtr.Zero;
                 }
 
@@ -1774,7 +1759,7 @@ namespace System.DirectoryServices.Protocols
                 SearchResultAttributeCollection attributes = resultEntry.Attributes;
 
                 // Get attributes.
-                attribute = Wldap32.ldap_first_attribute(_ldapHandle, entryMessage, ref address);
+                attribute = LdapPal.GetFirstAttributeFromEntry(_ldapHandle, entryMessage, ref address);
 
                 int tempcount = 0;
                 while (attribute != IntPtr.Zero)
@@ -1782,14 +1767,14 @@ namespace System.DirectoryServices.Protocols
                     DirectoryAttribute attr = ConstructAttribute(entryMessage, attribute);
                     attributes.Add(attr.Name, attr);
 
-                    Wldap32.ldap_memfree(attribute);
+                    LdapPal.FreeMemory(attribute);
                     tempcount++;
-                    attribute = Wldap32.ldap_next_attribute(_ldapHandle, entryMessage, address);
+                    attribute = LdapPal.GetNextAttributeFromResult(_ldapHandle, entryMessage, address);
                 }
 
                 if (address != IntPtr.Zero)
                 {
-                    Wldap32.ber_free(address, 0);
+                    BerPal.FreeBerElement(address, 0);
                     address = IntPtr.Zero;
                 }
 
@@ -1799,17 +1784,17 @@ namespace System.DirectoryServices.Protocols
             {
                 if (dn != IntPtr.Zero)
                 {
-                    Wldap32.ldap_memfree(dn);
+                    LdapPal.FreeMemory(dn);
                 }
 
                 if (attribute != IntPtr.Zero)
                 {
-                    Wldap32.ldap_memfree(attribute);
+                    LdapPal.FreeMemory(attribute);
                 }
 
                 if (address != IntPtr.Zero)
                 {
-                    Wldap32.ber_free(address, 0);
+                    BerPal.FreeBerElement(address, 0);
                 }
             }
         }
@@ -1821,10 +1806,9 @@ namespace System.DirectoryServices.Protocols
                 _isSearchResult = true
             };
 
-            string name = Marshal.PtrToStringUni(attributeName);
+            string name = LdapPal.PtrToString(attributeName);
             attribute.Name = name;
-
-            IntPtr valuesArray = Wldap32.ldap_get_values_len(_ldapHandle, entryMessage, name);
+            IntPtr valuesArray = LdapPal.GetValuesFromAttribute(_ldapHandle, entryMessage, name);
             try
             {
                 if (valuesArray != IntPtr.Zero)
@@ -1852,7 +1836,7 @@ namespace System.DirectoryServices.Protocols
             {
                 if (valuesArray != IntPtr.Zero)
                 {
-                    Wldap32.ldap_value_free_len(valuesArray);
+                    LdapPal.FreeAttributes(valuesArray);
                 }
             }
 
@@ -1862,8 +1846,7 @@ namespace System.DirectoryServices.Protocols
         internal SearchResultReference ConstructReference(IntPtr referenceMessage)
         {
             IntPtr referenceArray = IntPtr.Zero;
-
-            int error = Wldap32.ldap_parse_reference(_ldapHandle, referenceMessage, ref referenceArray);
+            int error = LdapPal.ParseReference(_ldapHandle, referenceMessage, ref referenceArray);
 
             try
             {
@@ -1877,14 +1860,14 @@ namespace System.DirectoryServices.Protocols
                         tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count);
                         while (tempPtr != IntPtr.Zero)
                         {
-                            string s = Marshal.PtrToStringUni(tempPtr);
+                            string s = LdapPal.PtrToString(tempPtr);
                             referralList.Add(s);
 
                             count++;
                             tempPtr = Marshal.ReadIntPtr(referenceArray, IntPtr.Size * count);
                         }
 
-                        Wldap32.ldap_value_free(referenceArray);
+                        LdapPal.FreeValue(referenceArray);
                         referenceArray = IntPtr.Zero;
                     }
 
@@ -1904,7 +1887,7 @@ namespace System.DirectoryServices.Protocols
             {
                 if (referenceArray != IntPtr.Zero)
                 {
-                    Wldap32.ldap_value_free(referenceArray);
+                    LdapPal.FreeValue(referenceArray);
                 }
             }
 
@@ -1973,7 +1956,7 @@ namespace System.DirectoryServices.Protocols
             Marshal.PtrToStructure(controlPtr, control);
 
             Debug.Assert(control.ldctl_oid != IntPtr.Zero);
-            string controlType = Marshal.PtrToStringUni(control.ldctl_oid);
+            string controlType = LdapPal.PtrToString(control.ldctl_oid);
 
             byte[] bytes = new byte[control.ldctl_value.bv_len];
             Marshal.Copy(control.ldctl_value.bv_val, bytes, 0, control.ldctl_value.bv_len);
index 0477e494f9f2de871c9db19e9fbff18f206d9898..3d6b85838ca013d18d8aa7361cc13de465bec418 100644 (file)
@@ -214,7 +214,7 @@ namespace System.DirectoryServices.Protocols
                 asyncResult._resultStatus = ResultsStatus.Done;
 
                 // Need to abandon this request.
-                Wldap32.ldap_abandon(connection._ldapHandle, asyncResult._messageID);
+                LdapPal.CancelDirectoryAsyncOperation(connection._ldapHandle, asyncResult._messageID);
             }
         }
 
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Linux.cs
new file mode 100644 (file)
index 0000000..209aa74
--- /dev/null
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.DirectoryServices.Protocols
+{
+    public partial class LdapSessionOptions
+    {
+        private static void PALCertFreeCRLContext(IntPtr certPtr) { /* No op */ }
+
+        public bool SecureSocketLayer
+        {
+            get => throw new PlatformNotSupportedException();
+            set => throw new PlatformNotSupportedException();
+        }
+    }
+}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.Windows.cs
new file mode 100644 (file)
index 0000000..e781549
--- /dev/null
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.DirectoryServices.Protocols
+{
+    public partial class LdapSessionOptions
+    {
+        private static void PALCertFreeCRLContext(IntPtr certPtr) => Interop.CertFreeCRLContext(certPtr);
+
+        public bool SecureSocketLayer
+        {
+            get
+            {
+                int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SSL);
+                return outValue == 1;
+            }
+            set
+            {
+                int temp = value ? 1 : 0;
+                SetIntValueHelper(LdapOption.LDAP_OPT_SSL, temp);
+            }
+        }
+    }
+}
index 2ff8d02bc4eb22ee21248a839f73ac30baeaae55..e59d8352ab68ef1e119ef15a9c2f6b8305b6ed1e 100644 (file)
@@ -116,7 +116,7 @@ namespace System.DirectoryServices.Protocols
         public IntPtr Upper;
     }
 
-    public class LdapSessionOptions
+    public partial class LdapSessionOptions
     {
         private readonly LdapConnection _connection = null;
         private ReferralCallback _callbackRoutine = new ReferralCallback();
@@ -155,20 +155,6 @@ namespace System.DirectoryServices.Protocols
             }
         }
 
-        public bool SecureSocketLayer
-        {
-            get
-            {
-                int outValue = GetIntValueHelper(LdapOption.LDAP_OPT_SSL);
-                return outValue == 1;
-            }
-            set
-            {
-                int temp = value ? 1 : 0;
-                SetIntValueHelper(LdapOption.LDAP_OPT_SSL, temp);
-            }
-        }
-
         public int ReferralHopLimit
         {
             get => GetIntValueHelper(LdapOption.LDAP_OPT_REFERRAL_HOP_LIMIT);
@@ -319,7 +305,7 @@ namespace System.DirectoryServices.Protocols
                 }
 
                 var secInfo = new SecurityPackageContextConnectionInformation();
-                int error = Wldap32.ldap_get_option_secInfo(_connection._ldapHandle, LdapOption.LDAP_OPT_SSL_INFO, secInfo);
+                int error = LdapPal.GetSecInfoOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SSL_INFO, secInfo);
                 ErrorChecking.CheckAndSetLdapError(error);
 
                 return secInfo;
@@ -337,7 +323,7 @@ namespace System.DirectoryServices.Protocols
 
                 SecurityHandle tempHandle = default;
 
-                int error = Wldap32.ldap_get_option_sechandle(_connection._ldapHandle, LdapOption.LDAP_OPT_SECURITY_CONTEXT, ref tempHandle);
+                int error = LdapPal.GetSecurityHandleOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SECURITY_CONTEXT, ref tempHandle);
                 ErrorChecking.CheckAndSetLdapError(error);
 
                 return tempHandle;
@@ -489,7 +475,7 @@ namespace System.DirectoryServices.Protocols
 
                 if (value != null)
                 {
-                    int certError = Wldap32.ldap_set_option_clientcert(_connection._ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _connection._clientCertificateRoutine);
+                    int certError = LdapPal.SetClientCertOption(_connection._ldapHandle, LdapOption.LDAP_OPT_CLIENT_CERTIFICATE, _connection._clientCertificateRoutine);
                     if (certError != (int)ResultCode.Success)
                     {
                         if (Utility.IsLdapError((LdapError)certError))
@@ -531,7 +517,7 @@ namespace System.DirectoryServices.Protocols
 
                 if (value != null)
                 {
-                    int error = Wldap32.ldap_set_option_servercert(_connection._ldapHandle, LdapOption.LDAP_OPT_SERVER_CERTIFICATE, _serverCertificateRoutine);
+                    int error = LdapPal.SetServerCertOption(_connection._ldapHandle, LdapOption.LDAP_OPT_SERVER_CERTIFICATE, _serverCertificateRoutine);
                     ErrorChecking.CheckAndSetLdapError(error);
                 }
 
@@ -547,13 +533,9 @@ namespace System.DirectoryServices.Protocols
             set => SetIntValueHelper(LdapOption.LDAP_OPT_DEREF, (int)value);
         }
 
-        internal bool FQDN
+        internal void SetFqdnRequired()
         {
-            set
-            {
-                // set the value to true
-                SetIntValueHelper(LdapOption.LDAP_OPT_AREC_EXCLUSIVE, 1);
-            }
+            SetIntValueHelper(LdapOption.LDAP_OPT_AREC_EXCLUSIVE, 1);
         }
 
         public void FastConcurrentBind()
@@ -569,7 +551,7 @@ namespace System.DirectoryServices.Protocols
 
             // Do the fast concurrent bind.
             int inValue = 1;
-            int error = Wldap32.ldap_set_option_int(_connection._ldapHandle, LdapOption.LDAP_OPT_FAST_CONCURRENT_BIND, ref inValue);
+            int error = LdapPal.SetIntOption(_connection._ldapHandle, LdapOption.LDAP_OPT_FAST_CONCURRENT_BIND, ref inValue);
             ErrorChecking.CheckAndSetLdapError(error);
         }
 
@@ -629,11 +611,11 @@ namespace System.DirectoryServices.Protocols
                     Marshal.WriteIntPtr(tempPtr, IntPtr.Zero);
                 }
 
-                int error = Wldap32.ldap_start_tls(_connection._ldapHandle, ref serverError, ref ldapResult, serverControlArray, clientControlArray);
+                int error = LdapPal.StartTls(_connection._ldapHandle, ref serverError, ref ldapResult, serverControlArray, clientControlArray);
                 if (ldapResult != IntPtr.Zero)
                 {
                     // Parse the referral.
-                    int resultError = Wldap32.ldap_parse_result_referral(_connection._ldapHandle, ldapResult, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref referral, IntPtr.Zero, 0 /* not free it */);
+                    int resultError = LdapPal.ParseResultReferral(_connection._ldapHandle, ldapResult, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref referral, IntPtr.Zero, 0 /* not free it */);
                     if (resultError == 0 && referral != IntPtr.Zero)
                     {
                         char** referralPtr = (char**)referral;
@@ -642,7 +624,7 @@ namespace System.DirectoryServices.Protocols
                         ArrayList referralList = new ArrayList();
                         while (singleReferral != null)
                         {
-                            string s = Marshal.PtrToStringUni((IntPtr)singleReferral);
+                            string s = LdapPal.PtrToString((IntPtr)singleReferral);
                             referralList.Add(s);
 
                             i++;
@@ -652,7 +634,7 @@ namespace System.DirectoryServices.Protocols
                         // Free heap memory.
                         if (referral != IntPtr.Zero)
                         {
-                            Wldap32.ldap_value_free(referral);
+                            LdapPal.FreeValue(referral);
                             referral = IntPtr.Zero;
                         }
 
@@ -759,7 +741,7 @@ namespace System.DirectoryServices.Protocols
 
                 if (referral != IntPtr.Zero)
                 {
-                    Wldap32.ldap_value_free(referral);
+                    LdapPal.FreeValue(referral);
                 }
             }
         }
@@ -771,7 +753,7 @@ namespace System.DirectoryServices.Protocols
                 throw new ObjectDisposedException(GetType().Name);
             }
 
-            byte result = Wldap32.ldap_stop_tls(_connection._ldapHandle);
+            byte result = LdapPal.StopTls(_connection._ldapHandle);
             if (result == 0)
             {
                 throw new TlsOperationException(null, SR.TLSStopFailure);
@@ -786,7 +768,7 @@ namespace System.DirectoryServices.Protocols
             }
 
             int outValue = 0;
-            int error = Wldap32.ldap_get_option_int(_connection._ldapHandle, option, ref outValue);
+            int error = LdapPal.GetIntOption(_connection._ldapHandle, option, ref outValue);
             ErrorChecking.CheckAndSetLdapError(error);
 
             return outValue;
@@ -800,7 +782,7 @@ namespace System.DirectoryServices.Protocols
             }
 
             int temp = value;
-            int error = Wldap32.ldap_set_option_int(_connection._ldapHandle, option, ref temp);
+            int error = LdapPal.SetIntOption(_connection._ldapHandle, option, ref temp);
 
             ErrorChecking.CheckAndSetLdapError(error);
         }
@@ -813,18 +795,18 @@ namespace System.DirectoryServices.Protocols
             }
 
             IntPtr outValue = new IntPtr(0);
-            int error = Wldap32.ldap_get_option_ptr(_connection._ldapHandle, option, ref outValue);
+            int error = LdapPal.GetPtrOption(_connection._ldapHandle, option, ref outValue);
             ErrorChecking.CheckAndSetLdapError(error);
 
             string stringValue = null;
             if (outValue != IntPtr.Zero)
             {
-                stringValue = Marshal.PtrToStringUni(outValue);
+                stringValue = LdapPal.PtrToString(outValue);
             }
 
             if (releasePtr)
             {
-                Wldap32.ldap_memfree(outValue);
+                LdapPal.FreeMemory(outValue);
             }
 
             return stringValue;
@@ -840,12 +822,12 @@ namespace System.DirectoryServices.Protocols
             IntPtr inValue = IntPtr.Zero;
             if (value != null)
             {
-                inValue = Marshal.StringToHGlobalUni(value);
+                inValue = LdapPal.StringToPtr(value);
             }
 
             try
             {
-                int error = Wldap32.ldap_set_option_ptr(_connection._ldapHandle, option, ref inValue);
+                int error = LdapPal.SetPtrOption(_connection._ldapHandle, option, ref inValue);
                 ErrorChecking.CheckAndSetLdapError(error);
             }
             finally
@@ -866,8 +848,7 @@ namespace System.DirectoryServices.Protocols
                 notify = tempCallback.NotifyNewConnection == null ? null : _notifiyDelegate,
                 dereference = tempCallback.DereferenceConnection == null ? null : _dereferenceDelegate
             };
-
-            int error = Wldap32.ldap_set_option_referral(_connection._ldapHandle, LdapOption.LDAP_OPT_REFERRAL_CALLBACK, ref value);
+            int error = LdapPal.SetReferralOption(_connection._ldapHandle, LdapOption.LDAP_OPT_REFERRAL_CALLBACK, ref value);
             ErrorChecking.CheckAndSetLdapError(error);
         }
 
@@ -884,7 +865,7 @@ namespace System.DirectoryServices.Protocols
             {
                 if (NewDNPtr != IntPtr.Zero)
                 {
-                    NewDN = Marshal.PtrToStringUni(NewDNPtr);
+                    NewDN = LdapPal.PtrToString(NewDNPtr);
                 }
 
                 var target = new StringBuilder();
@@ -951,7 +932,7 @@ namespace System.DirectoryServices.Protocols
                 string newDN = null;
                 if (newDNPtr != IntPtr.Zero)
                 {
-                    newDN = Marshal.PtrToStringUni(newDNPtr);
+                    newDN = LdapPal.PtrToString(newDNPtr);
                 }
 
                 var target = new StringBuilder();
@@ -1099,7 +1080,7 @@ namespace System.DirectoryServices.Protocols
                 }
                 finally
                 {
-                    Wldap32.CertFreeCRLContext(certPtr);
+                    PALCertFreeCRLContext(certPtr);
                 }
 
                 value = _serverCertificateDelegate(_connection, certificate);
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/SafeHandles.cs
deleted file mode 100644 (file)
index 50a4966..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Win32.SafeHandles;
-using System.Runtime.InteropServices;
-using System.Security;
-
-namespace System.DirectoryServices.Protocols
-{
-    internal sealed class BerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
-    {
-        internal BerSafeHandle() : base(true)
-        {
-            SetHandle(Wldap32.ber_alloc(1));
-            if (handle == IntPtr.Zero)
-            {
-                throw new OutOfMemoryException();
-            }
-        }
-
-        internal BerSafeHandle(berval value) : base(true)
-        {
-            SetHandle(Wldap32.ber_init(value));
-            if (handle == IntPtr.Zero)
-            {
-                throw new BerConversionException();
-            }
-        }
-
-        protected override bool ReleaseHandle()
-        {
-            Wldap32.ber_free(handle, 1);
-            return true;
-        }
-    }
-
-    internal sealed class HGlobalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
-    {
-        internal HGlobalMemHandle(IntPtr value) : base(true)
-        {
-            SetHandle(value);
-        }
-
-        protected override bool ReleaseHandle()
-        {
-            Marshal.FreeHGlobal(handle);
-            return true;
-        }
-    }
-
-    internal sealed class ConnectionHandle : SafeHandleZeroOrMinusOneIsInvalid
-    {
-        internal bool _needDispose = false;
-
-        internal ConnectionHandle() : base(true)
-        {
-            SetHandle(Wldap32.ldap_init(null, 389));
-
-            if (handle == IntPtr.Zero)
-            {
-                int error = Wldap32.LdapGetLastError();
-                if (Utility.IsLdapError((LdapError)error))
-                {
-                    string errorMessage = LdapErrorMappings.MapResultCode(error);
-                    throw new LdapException(error, errorMessage);
-                }
-                else
-                {
-                    throw new LdapException(error);
-                }
-            }
-        }
-
-        internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true)
-        {
-            _needDispose = disposeHandle;
-            if (value == IntPtr.Zero)
-            {
-                int error = Wldap32.LdapGetLastError();
-                if (Utility.IsLdapError((LdapError)error))
-                {
-                    string errorMessage = LdapErrorMappings.MapResultCode(error);
-                    throw new LdapException(error, errorMessage);
-                }
-                else
-                {
-                    throw new LdapException(error);
-                }
-            }
-            else
-            {
-                SetHandle(value);
-            }
-        }
-        protected override bool ReleaseHandle()
-        {
-            if (handle != IntPtr.Zero)
-            {
-                if (_needDispose)
-                {
-                    Wldap32.ldap_unbind(handle);
-                }
-
-                handle = IntPtr.Zero;
-            }
-            return true;
-        }
-    }
-}
diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/Wldap32UnsafeMethods.cs
deleted file mode 100644 (file)
index 34605a4..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.InteropServices;
-using System.Security;
-
-namespace System.DirectoryServices.Protocols
-{
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal class Luid
-    {
-        private readonly int _lowPart;
-        private readonly int _highPart;
-
-        public int LowPart => _lowPart;
-        public int HighPart => _highPart;
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal sealed class SEC_WINNT_AUTH_IDENTITY_EX
-    {
-        public int version;
-        public int length;
-        public string user;
-        public int userLength;
-        public string domain;
-        public int domainLength;
-        public string password;
-        public int passwordLength;
-        public int flags;
-        public string packageList;
-        public int packageListLength;
-    }
-
-    internal enum BindMethod : uint
-    {
-        LDAP_AUTH_OTHERKIND = 0x86,
-        LDAP_AUTH_SICILY = LDAP_AUTH_OTHERKIND | 0x0200,
-        LDAP_AUTH_MSN = LDAP_AUTH_OTHERKIND | 0x0800,
-        LDAP_AUTH_NTLM = LDAP_AUTH_OTHERKIND | 0x1000,
-        LDAP_AUTH_DPA = LDAP_AUTH_OTHERKIND | 0x2000,
-        LDAP_AUTH_NEGOTIATE = LDAP_AUTH_OTHERKIND | 0x0400,
-        LDAP_AUTH_SSPI = LDAP_AUTH_NEGOTIATE,
-        LDAP_AUTH_DIGEST = LDAP_AUTH_OTHERKIND | 0x4000,
-        LDAP_AUTH_EXTERNAL = LDAP_AUTH_OTHERKIND | 0x0020
-    }
-
-    internal enum LdapOption
-    {
-        LDAP_OPT_DESC = 0x01,
-        LDAP_OPT_DEREF = 0x02,
-        LDAP_OPT_SIZELIMIT = 0x03,
-        LDAP_OPT_TIMELIMIT = 0x04,
-        LDAP_OPT_REFERRALS = 0x08,
-        LDAP_OPT_RESTART = 0x09,
-        LDAP_OPT_SSL = 0x0a,
-        LDAP_OPT_REFERRAL_HOP_LIMIT = 0x10,
-        LDAP_OPT_VERSION = 0x11,
-        LDAP_OPT_API_FEATURE_INFO = 0x15,
-        LDAP_OPT_HOST_NAME = 0x30,
-        LDAP_OPT_ERROR_NUMBER = 0x31,
-        LDAP_OPT_ERROR_STRING = 0x32,
-        LDAP_OPT_SERVER_ERROR = 0x33,
-        LDAP_OPT_SERVER_EXT_ERROR = 0x34,
-        LDAP_OPT_HOST_REACHABLE = 0x3E,
-        LDAP_OPT_PING_KEEP_ALIVE = 0x36,
-        LDAP_OPT_PING_WAIT_TIME = 0x37,
-        LDAP_OPT_PING_LIMIT = 0x38,
-        LDAP_OPT_DNSDOMAIN_NAME = 0x3B,
-        LDAP_OPT_GETDSNAME_FLAGS = 0x3D,
-        LDAP_OPT_PROMPT_CREDENTIALS = 0x3F,
-        LDAP_OPT_TCP_KEEPALIVE = 0x40,
-        LDAP_OPT_FAST_CONCURRENT_BIND = 0x41,
-        LDAP_OPT_SEND_TIMEOUT = 0x42,
-        LDAP_OPT_REFERRAL_CALLBACK = 0x70,
-        LDAP_OPT_CLIENT_CERTIFICATE = 0x80,
-        LDAP_OPT_SERVER_CERTIFICATE = 0x81,
-        LDAP_OPT_AUTO_RECONNECT = 0x91,
-        LDAP_OPT_SSPI_FLAGS = 0x92,
-        LDAP_OPT_SSL_INFO = 0x93,
-        LDAP_OPT_SIGN = 0x95,
-        LDAP_OPT_ENCRYPT = 0x96,
-        LDAP_OPT_SASL_METHOD = 0x97,
-        LDAP_OPT_AREC_EXCLUSIVE = 0x98,
-        LDAP_OPT_SECURITY_CONTEXT = 0x99,
-        LDAP_OPT_ROOTDSE_CACHE = 0x9a
-    }
-
-    internal enum ResultAll
-    {
-        LDAP_MSG_ALL = 1,
-        LDAP_MSG_RECEIVED = 2,
-        LDAP_MSG_POLLINGALL = 3
-    }
-
-    [StructLayout(LayoutKind.Sequential)]
-    internal sealed class LDAP_TIMEVAL
-    {
-        public int tv_sec;
-        public int tv_usec;
-    }
-
-    [StructLayout(LayoutKind.Sequential)]
-    internal sealed class berval
-    {
-        public int bv_len = 0;
-        public IntPtr bv_val = IntPtr.Zero;
-
-        public berval() { }
-    }
-
-    [StructLayout(LayoutKind.Sequential)]
-    internal sealed class SafeBerval
-    {
-        public int bv_len = 0;
-        public IntPtr bv_val = IntPtr.Zero;
-
-        ~SafeBerval()
-        {
-            if (bv_val != IntPtr.Zero)
-            {
-                Marshal.FreeHGlobal(bv_val);
-            }
-        }
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal sealed class LdapControl
-    {
-        public IntPtr ldctl_oid = IntPtr.Zero;
-        public berval ldctl_value = null;
-        public bool ldctl_iscritical = false;
-
-        public LdapControl() { }
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal struct LdapReferralCallback
-    {
-        public int sizeofcallback;
-        public QUERYFORCONNECTIONInternal query;
-        public NOTIFYOFNEWCONNECTIONInternal notify;
-        public DEREFERENCECONNECTIONInternal dereference;
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal struct CRYPTOAPI_BLOB
-    {
-        public int cbData;
-        public IntPtr pbData;
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal struct SecPkgContext_IssuerListInfoEx
-    {
-        public IntPtr aIssuers;
-        public int cIssuers;
-    }
-
-    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
-    internal sealed class LdapMod
-    {
-        public int type = 0;
-        public IntPtr attribute = IntPtr.Zero;
-        public IntPtr values = IntPtr.Zero;
-
-        ~LdapMod()
-        {
-            if (attribute != IntPtr.Zero)
-            {
-                Marshal.FreeHGlobal(attribute);
-            }
-
-            if (values != IntPtr.Zero)
-            {
-                Marshal.FreeHGlobal(values);
-            }
-        }
-    }
-
-    internal class Wldap32
-    {
-        private const string Wldap32dll = "wldap32.dll";
-
-        public const int SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2;
-        public const int SEC_WINNT_AUTH_IDENTITY_VERSION = 0x200;
-        public const string MICROSOFT_KERBEROS_NAME_W = "Kerberos";
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_bind_sW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_bind_s([In]ConnectionHandle ldapHandle, string dn, SEC_WINNT_AUTH_IDENTITY_EX credentials, BindMethod method);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_initW", SetLastError = true, CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_init(string hostName, int portNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_connect", CharSet = CharSet.Unicode)]
-        public static extern int ldap_connect([In] ConnectionHandle ldapHandle, LDAP_TIMEVAL timeout);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, EntryPoint = "ldap_unbind", CharSet = CharSet.Unicode)]
-        public static extern int ldap_unbind([In] IntPtr ldapHandle);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_get_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_set_option_int([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref int inValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_get_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_set_option_ptr([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref IntPtr inValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_get_option_sechandle([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref SecurityHandle outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_get_option_secInfo([In] ConnectionHandle ldapHandle, [In] LdapOption option, [In, Out] SecurityPackageContextConnectionInformation outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_set_option_clientcert([In] ConnectionHandle ldapHandle, [In] LdapOption option, QUERYCLIENTCERT outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_set_optionW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_set_option_servercert([In] ConnectionHandle ldapHandle, [In] LdapOption option, VERIFYSERVERCERT outValue);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "LdapGetLastError")]
-        public static extern int LdapGetLastError();
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "cldap_openW", SetLastError = true, CharSet = CharSet.Unicode)]
-        public static extern IntPtr cldap_open(string hostName, int portNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_simple_bind_sW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_simple_bind_s([In] ConnectionHandle ldapHandle, string distinguishedName, string password);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_delete_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_delete_ext([In] ConnectionHandle ldapHandle, string dn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result", SetLastError = true, CharSet = CharSet.Unicode)]
-        public static extern int ldap_result([In] ConnectionHandle ldapHandle, int messageId, int all, LDAP_TIMEVAL timeout, ref IntPtr Mesage);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_resultW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_parse_result_referral([In] ConnectionHandle ldapHandle, [In] IntPtr result, IntPtr serverError, IntPtr dn, IntPtr message, ref IntPtr referral, IntPtr control, byte freeIt);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_memfreeW", CharSet = CharSet.Unicode)]
-        public static extern void ldap_memfree([In] IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_freeW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_value_free([In] IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_controls_freeW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_controls_free([In] IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_abandon", CharSet = CharSet.Unicode)]
-        public static extern int ldap_abandon([In] ConnectionHandle ldapHandle, [In] int messagId);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_start_tls_sW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_stop_tls_s", CharSet = CharSet.Unicode)]
-        public static extern byte ldap_stop_tls(ConnectionHandle ldapHandle);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_rename_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_rename([In] ConnectionHandle ldapHandle, string dn, string newRdn, string newParentDn, int deleteOldRdn, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_compare_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_compare([In] ConnectionHandle ldapHandle, string dn, string attributeName, string strValue, berval binaryValue, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_add_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_add([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_modify_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_modify([In] ConnectionHandle ldapHandle, string dn, IntPtr attrs, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_extended_operationW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_extended_operation([In] ConnectionHandle ldapHandle, string oid, berval data, IntPtr servercontrol, IntPtr clientcontrol, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_extended_resultW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_parse_extended_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr oid, ref IntPtr data, byte freeIt);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_msgfree", CharSet = CharSet.Unicode)]
-        public static extern int ldap_msgfree([In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_search_extW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_search([In] ConnectionHandle ldapHandle, string dn, int scope, string filter, IntPtr attributes, bool attributeOnly, IntPtr servercontrol, IntPtr clientcontrol, int timelimit, int sizelimit, ref int messageNumber);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_entry", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_first_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_entry", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_next_entry([In] ConnectionHandle ldapHandle, [In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_reference", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_first_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_reference", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_next_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_dnW", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_get_dn([In] ConnectionHandle ldapHandle, [In] IntPtr result);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_first_attributeW", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_first_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr address);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_next_attributeW", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_next_attribute([In] ConnectionHandle ldapHandle, [In] IntPtr result, [In, Out] IntPtr address);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_free", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ber_free([In] IntPtr berelement, int option);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_get_values_lenW", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_get_values_len([In] ConnectionHandle ldapHandle, [In] IntPtr result, string name);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_value_free_len", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ldap_value_free_len([In] IntPtr berelement);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_parse_referenceW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_parse_reference([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref IntPtr referrals);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_alloc_t", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ber_alloc(int option);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
-        public static extern int ber_printf_emptyarg(BerSafeHandle berElement, string format);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
-        public static extern int ber_printf_int(BerSafeHandle berElement, string format, int value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
-        public static extern int ber_printf_bytearray(BerSafeHandle berElement, string format, HGlobalMemHandle value, int length);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_printf", CharSet = CharSet.Unicode)]
-        public static extern int ber_printf_berarray(BerSafeHandle berElement, string format, IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)]
-        public static extern int ber_flatten(BerSafeHandle berElement, ref IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_init", CharSet = CharSet.Unicode)]
-        public static extern IntPtr ber_init(berval value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
-        public static extern int ber_scanf(BerSafeHandle berElement, string format);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
-        public static extern int ber_scanf_int(BerSafeHandle berElement, string format, ref int value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
-        public static extern int ber_scanf_ptr(BerSafeHandle berElement, string format, ref IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_scanf", CharSet = CharSet.Unicode)]
-        public static extern int ber_scanf_bitstring(BerSafeHandle berElement, string format, ref IntPtr value, ref int length);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)]
-        public static extern int ber_bvfree(IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvecfree", CharSet = CharSet.Unicode)]
-        public static extern int ber_bvecfree(IntPtr value);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_create_sort_controlW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_create_sort_control(ConnectionHandle handle, IntPtr keys, byte critical, ref IntPtr control);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_control_freeW", CharSet = CharSet.Unicode)]
-        public static extern int ldap_control_free(IntPtr control);
-
-        [DllImport("Crypt32.dll", EntryPoint = "CertFreeCRLContext", CharSet = CharSet.Unicode)]
-        public static extern int CertFreeCRLContext(IntPtr certContext);
-
-        [DllImport(Wldap32dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ldap_result2error", CharSet = CharSet.Unicode)]
-        public static extern int ldap_result2error([In] ConnectionHandle ldapHandle, [In] IntPtr result, int freeIt);
-    }
-}
index 4c4f335a7933fc054bfd19a1a1b52107363231f1..97c70bf4c081c7976b2790038fe720882480e3b3 100644 (file)
@@ -2,10 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class AsqRequestControlTests
     {
         [Fact]
@@ -17,13 +20,29 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.1504", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } : new byte[] { 48, 2, 4, 0 };
+
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_String_Test_data()
+        {
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                yield return new object[] { null, new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } };
+                yield return new object[] { "", new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } };
+                yield return new object[] { "A", new byte[] { 48, 132, 0, 0, 0, 3, 4, 1, 65 } };
+            }
+            else
+            {
+                yield return new object[] { null, new byte[] { 48, 2, 4, 0 } };
+                yield return new object[] { "", new byte[] { 48, 2, 4, 0 } };
+                yield return new object[] { "A", new byte[] { 48, 3, 4, 1, 65 } };
+            }
         }
 
         [Theory]
-        [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 })]
-        [InlineData("", new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 })]
-        [InlineData("A", new byte[] { 48, 132, 0, 0, 0, 3, 4, 1, 65 })]
+        [MemberData(nameof(Ctor_String_Test_data))]
         public void Ctor_String(string attributeName, byte[] expectedValue)
         {
             var control = new AsqRequestControl(attributeName);
index 54f85a9e9783aafefc5da573f0457449da0160eb..a6b301da3829ce88568cf02ab14c68b436e9d7c2 100644 (file)
@@ -3,10 +3,12 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class BerConverterTests
     {
         public static IEnumerable<object[]> Encode_TestData()
@@ -15,22 +17,28 @@ namespace System.DirectoryServices.Protocols.Tests
             yield return new object[] { "", new object[10], new byte[0] };
             yield return new object[] { "b", new object[] { true, false, true, false }, new byte[] { 1, 1, 255 } };
 
-            yield return new object[] { "{", new object[] { "a" }, new byte[] { 48, 0, 0, 0, 0, 0 } };
-            yield return new object[] { "{}", new object[] { "a" }, new byte[] { 48, 132, 0, 0, 0, 0 } };
-            yield return new object[] { "[", new object[] { "a" }, new byte[] { 49, 0, 0, 0, 0, 0 } };
-            yield return new object[] { "[]", new object[] { "a" }, new byte[] { 49, 132, 0, 0, 0, 0 } };
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                yield return new object[] { "{", new object[] { "a" }, new byte[] { 48, 0, 0, 0, 0, 0 } }; // This format is not supported by Linux OpenLDAP
+            }
+            yield return new object[] { "{}", new object[] { "a" }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 0 } : new byte[] { 48, 0 } };
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                yield return new object[] { "[", new object[] { "a" }, new byte[] { 49, 0, 0, 0, 0, 0 } }; // This format is not supported by Linux OpenLDAP
+            }
+            yield return new object[] { "[]", new object[] { "a" }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 49, 132, 0, 0, 0, 0 } : new byte[] { 49, 0 } };
             yield return new object[] { "n", new object[] { "a" }, new byte[] { 5, 0 } };
 
-            yield return new object[] { "tetie", new object[] { -1, 0, 1, 2, 3 }, new byte[] { 255, 1, 0, 1, 1, 2, 10, 1, 3 } };
-            yield return new object[] { "{tetie}", new object[] { -1, 0, 1, 2, 3 }, new byte[] { 48, 132, 0, 0, 0, 9, 255, 1, 0, 1, 1, 2, 10, 1, 3 } };
+            yield return new object[] { "tetie", new object[] { -1, 0, 1, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 255, 1, 0, 1, 1, 2, 10, 1, 3 } : new byte[] { 10, 1, 0, 1, 1, 2, 10, 1, 3 } };
+            yield return new object[] { "{tetie}", new object[] { -1, 0, 1, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 255, 1, 0, 1, 1, 2, 10, 1, 3 } : new byte[] { 48, 9, 10, 1, 0, 1, 1, 2, 10, 1, 3 } };
 
             yield return new object[] { "bb", new object[] { true, false }, new byte[] { 1, 1, 255, 1, 1, 0 } };
-            yield return new object[] { "{bb}", new object[] { true, false }, new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            yield return new object[] { "{bb}", new object[] { true, false }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } : new byte[] { 48, 6, 1, 1, 255, 1, 1, 0 } };
 
             yield return new object[] { "ssss", new object[] { null, "", "abc", "\0" }, new byte[] { 4, 0, 4, 0, 4, 3, 97, 98, 99, 4, 1, 0 } };
-            yield return new object[] { "oXo", new object[] { null, new byte[] { 0, 1, 2, 255 }, new byte[0] }, new byte[] { 4, 0, 3, 4, 0, 1, 2, 255, 4, 0 } };
+            yield return new object[] { "oXo", new object[] { null, new byte[] { 0, 1, 2, 255 }, new byte[0] }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 4, 0, 3, 4, 0, 1, 2, 255, 4, 0 } : new byte[] { 4, 0, 3, 2, 4, 0, 4, 0 } };
             yield return new object[] { "vv", new object[] { null, new string[] { "abc", "", null } }, new byte[] { 4, 3, 97, 98, 99, 4, 0, 4, 0 } };
-            yield return new object[] { "{vv}", new object[] { null, new string[] { "abc", "", null } }, new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } };
+            yield return new object[] { "{vv}", new object[] { null, new string[] { "abc", "", null } }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } : new byte[] { 48, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 } };
             yield return new object[] { "VVVV", new object[] { null, new byte[][] { new byte[] { 0, 1, 2, 3 }, null }, new byte[][] { new byte[0] }, new byte[0][] }, new byte[] { 4, 4, 0, 1, 2, 3, 4, 0, 4, 0 } };
         }
 
@@ -112,10 +120,13 @@ namespace System.DirectoryServices.Protocols.Tests
             yield return new object[] { "{bb}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { true, false } };
             yield return new object[] { "{OO}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[] { 255 }, new byte[] { 0 } } };
             yield return new object[] { "{BB}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[] { 255 }, new byte[] { 0 } } };
-            yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } };
-            yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new string[] { "\x01" }, null } };
-            yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } };
-            yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[][] { new byte[] { 1 } }, null } };
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // vv and VV formats are not supported yet in Linux
+            {
+                yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } };
+                yield return new object[] { "{vv}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new string[] { "\x01" }, null } };
+                yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 9, 4, 3, 97, 98, 99, 4, 0, 4, 0 }, new object[] { null, null } };
+                yield return new object[] { "{VV}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { new byte[][] { new byte[] { 1 } }, null } };
+            }
         }
 
         [Theory]
@@ -139,18 +150,29 @@ namespace System.DirectoryServices.Protocols.Tests
             AssertExtensions.Throws<ArgumentException>(null, () => BerConverter.Decode(format, values));
         }
 
+        public static IEnumerable<object[]> Decode_Invalid_ThrowsBerConversionException_Data()
+        {
+            yield return new object[] { "n", null };
+            yield return new object[] { "n", new byte[0] };
+            yield return new object[] { "{", new byte[] { 1 } };
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                yield return new object[] { "}", new byte[] { 1 } }; // This is considered a valid case in Linux
+            }
+            yield return new object[] { "{}{}{}{}{}{}{}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                yield return new object[] { "aaa", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            } 
+            yield return new object[] { "iii", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            yield return new object[] { "eee", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            yield return new object[] { "bbb", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            yield return new object[] { "OOO", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+            yield return new object[] { "BBB", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 } };
+        }
+
         [Theory]
-        [InlineData("n", null)]
-        [InlineData("n", new byte[0])]
-        [InlineData("{", new byte[] { 1 })]
-        [InlineData("}", new byte[] { 1 })]
-        [InlineData("{}{}{}{}{}{}{}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("aaa", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("iii", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("eee", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("bbb", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("OOO", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
-        [InlineData("BBB", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 })]
+        [MemberData(nameof(Decode_Invalid_ThrowsBerConversionException_Data))]
         public void Decode_Invalid_ThrowsBerConversionException(string format, byte[] values)
         {
             Assert.Throws<BerConversionException>(() => BerConverter.Decode(format, values));
index 09f212987f652e76aa24cb3a214ae59b246984a8..8a494282e67f16a580e4d23496bb3d7b20d9a963 100644 (file)
@@ -2,10 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class DirSyncRequestControlTests
     {
         [Fact]
@@ -20,13 +23,19 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.841", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 };
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_Cookie_Data()
+        {
+            yield return new object[] { null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } };
+            yield return new object[] { new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } };
+            yield return new object[] { new byte[] { 97, 98, 99 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } : new byte[] { 48, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } };
         }
 
         [Theory]
-        [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })]
-        [InlineData(new byte[0], new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })]
-        [InlineData(new byte[] { 97, 98, 99 }, new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 0, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 })]
+        [MemberData(nameof(Ctor_Cookie_Data))]
         public void Ctor_Cookie(byte[] cookie, byte[] expectedValue)
         {
             var control = new DirSyncRequestControl(cookie);
@@ -41,10 +50,15 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(expectedValue, control.GetValue());
         }
 
+        public static IEnumerable<object[]> Ctor_Cookie_Options_Data()
+        {
+            yield return new object[] { null, DirectorySynchronizationOptions.None, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } };
+            yield return new object[] { new byte[0], DirectorySynchronizationOptions.None - 1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 4, 255, 255, 255, 255, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 255, 2, 3, 16, 0, 0, 4, 0 } };
+            yield return new object[] { new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } : new byte[] { 48, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 } };
+        }
+
         [Theory]
-        [InlineData(null, DirectorySynchronizationOptions.None, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })]
-        [InlineData(new byte[0], DirectorySynchronizationOptions.None - 1, new byte[] { 48, 132, 0, 0, 0, 13, 2, 4, 255, 255, 255, 255, 2, 3, 16, 0, 0, 4, 0 })]
-        [InlineData(new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, new byte[] { 48, 132, 0, 0, 0, 13, 2, 1, 1, 2, 3, 16, 0, 0, 4, 3, 97, 98, 99 })]
+        [MemberData(nameof(Ctor_Cookie_Options_Data))]
         public void Ctor_Cookie_Options(byte[] cookie, DirectorySynchronizationOptions option, byte[] expectedValue)
         {
             var control = new DirSyncRequestControl(cookie, option);
@@ -59,10 +73,15 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(expectedValue, control.GetValue());
         }
 
+        public static IEnumerable<object[]> Ctor_Cookie_Options_AttributeCount_Data()
+        {
+            yield return new object[] { null, DirectorySynchronizationOptions.None, 1048576, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } : new byte[] { 48, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 } };
+            yield return new object[] { new byte[0], DirectorySynchronizationOptions.None - 1, 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 4, 255, 255, 255, 255, 2, 1, 0, 4, 0 } : new byte[] { 48, 8, 2, 1, 255, 2, 1, 0, 4, 0 } };
+            yield return new object[] { new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 } : new byte[] { 48, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 } };
+        }
+
         [Theory]
-        [InlineData(null, DirectorySynchronizationOptions.None, 1048576, new byte[] { 48, 132, 0, 0, 0, 10, 2, 1, 0, 2, 3, 16, 0, 0, 4, 0 })]
-        [InlineData(new byte[0], DirectorySynchronizationOptions.None - 1, 0, new byte[] { 48, 132, 0, 0, 0, 11, 2, 4, 255, 255, 255, 255, 2, 1, 0, 4, 0 })]
-        [InlineData(new byte[] { 97, 98, 99 }, DirectorySynchronizationOptions.ObjectSecurity, 10, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 1, 2, 1, 10, 4, 3, 97, 98, 99 })]
+        [MemberData(nameof(Ctor_Cookie_Options_AttributeCount_Data))]
         public void Ctor_Cookie_Options_AttributeCount(byte[] cookie, DirectorySynchronizationOptions option, int attributeCount , byte[] expectedValue)
         {
             var control = new DirSyncRequestControl(cookie, option, attributeCount);
index f520df26b2b4dc2a05606eed259d40ea26ab7d61..af065dfd6a393db44e0dca218bdd9fce3932f81c 100644 (file)
@@ -2,17 +2,12 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System.Runtime.InteropServices;
-using System.Collections.Generic;
-using System.Collections;
+using System.DirectoryServices.Tests;
 using System.Globalization;
 using System.Net;
 using Xunit;
-using System.Threading;
-using System.DirectoryServices.Tests;
-using System.DirectoryServices.Protocols;
 
-namespace System.DirectoryServicesProtocols.Tests
+namespace System.DirectoryServices.Protocols.Tests
 {
     public partial class DirectoryServicesProtocolsTests
     {
diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesTestHelpers.cs
new file mode 100644 (file)
index 0000000..80ac7ec
--- /dev/null
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using Xunit;
+
+[assembly: ActiveIssue("https://github.com/dotnet/runtime/issues/35912", TestRuntimes.Mono)]
+
+namespace System.DirectoryServices.Protocols.Tests
+{
+    public static class DirectoryServicesTestHelpers
+    {
+        public static bool IsWindowsOrLibLdapIsInstalled => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || IsLibLdapInstalled;
+
+        // Cache the check once we have performed it once
+        private static bool? _isLibLdapInstalled = null;
+
+        public static bool IsLibLdapInstalled
+        {
+            get
+            {
+                if (!_isLibLdapInstalled.HasValue)
+                {
+                    try
+                    {
+                        // Attempt PInvoking into libldap
+                        IntPtr handle = ber_alloc(1);
+                        ber_free(handle, 1);
+                        _isLibLdapInstalled = true;
+                    }
+                    catch (Exception)
+                    {
+                        _isLibLdapInstalled = false;
+                    }
+                }
+                return _isLibLdapInstalled.Value;
+            }
+        }
+
+        internal const string OpenLdap = "libldap-2.4.so.2";
+
+        [DllImport(OpenLdap, EntryPoint = "ber_alloc_t", CharSet = CharSet.Ansi)]
+        internal static extern IntPtr ber_alloc(int option);
+
+        [DllImport(OpenLdap, EntryPoint = "ber_free", CharSet = CharSet.Ansi)]
+        public static extern IntPtr ber_free([In] IntPtr berelement, int option);
+    }
+}
index 7a759afeb07ba60571ec787c22e896747f2f2589..ade556afd0d9f9269ce2ab7d73992c95dce99b37 100644 (file)
@@ -3,10 +3,12 @@
 // See the LICENSE file in the project root for more information.
 
 using System.ComponentModel;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class ExtendedDNControlTests
     {
         [Fact]
@@ -18,7 +20,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.529", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 } : new byte[] { 48, 3, 2, 1, 0 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         [Fact]
@@ -30,7 +33,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.529", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 } : new byte[] { 48, 3, 2, 1, 1 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         [Theory]
index ee262ec1a03c17703de03f6044171dc6755c9110..c8b8fb0a5be95de885600929e305b514d2b3b2e5 100644 (file)
@@ -5,13 +5,12 @@
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Net;
-using System.Net.Sockets;
 using System.Threading;
-using System.Threading.Tasks;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class LdapConnectionTests
     {
         [Theory]
index f8ea1cceea2e435eba080b363e3ad84486756fc3..30abf231c19420a487488c7586aa813b12e63697 100644 (file)
@@ -8,9 +8,11 @@ using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class LdapSessionOptionsTests
     {
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(ReferralChasingOptions.None)]
         [InlineData(ReferralChasingOptions.External)]
         public void ReferralChasing_Set_GetReturnsExpected(ReferralChasingOptions value)
@@ -47,6 +49,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void SecureSocketLayer_Set_GetReturnsExpected(bool value)
@@ -62,6 +65,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void SecureSocketLayer_GetSetWhenDisposed_ThrowsObjectDisposedException()
         {
             var connection = new LdapConnection("server");
@@ -72,6 +76,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void ReferralHopLimit_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -142,6 +147,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void HostName_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -168,6 +174,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void DomainName_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -194,6 +201,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(LocatorFlags.AvoidSelf)]
         [InlineData(LocatorFlags.None - 1)]
         public void LocatorFlag_Set_GetReturnsExpected(LocatorFlags value)
@@ -219,6 +227,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void HostReachable_Get_ReturnsTrue()
         {
             using (var connection = new LdapConnection("server"))
@@ -238,6 +247,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void PingKeepAliveTimeout_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -272,6 +282,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void PingLimit_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -304,6 +315,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void PingWaitTimeout_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -338,6 +350,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void AutoReconnect_Set_GetReturnsExpected(bool value)
@@ -363,6 +376,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(-1)]
         [InlineData(10)]
         public void SspiFlag_Set_GetReturnsExpected(int value)
@@ -388,6 +402,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void SslInformation_GetNotStarted_ThrowsDirectoryOperationException()
         {
             using (var connection = new LdapConnection("server"))
@@ -407,6 +422,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void SecurityContext_GetNotStarted_ThrowsDirectoryOperationException()
         {
             using (var connection = new LdapConnection("server"))
@@ -426,6 +442,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void Signing_Set_GetReturnsExpected(bool value)
@@ -451,6 +468,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void Sealing_Set_GetReturnsExpected(bool value)
@@ -476,6 +494,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void SaslMethod_Set_ThrowsLdapException()
         {
             using (var connection = new LdapConnection("server"))
@@ -498,6 +517,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void RootDseCache_Set_GetReturnsExpected(bool value)
@@ -523,6 +543,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)]
         [InlineData(true)]
         [InlineData(false)]
         public void TcpKeepAlive_Set_GetReturnsExpected(bool value)
@@ -548,6 +569,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void SendTimeout_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -595,6 +617,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void ReferralCallback_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -625,6 +648,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void QueryClientCertificate_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -653,6 +677,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void VerifyServerCertificate_Set_GetReturnsExpected()
         {
             using (var connection = new LdapConnection("server"))
@@ -699,6 +724,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Fact]
+        [PlatformSpecific(TestPlatforms.Windows)]
         public void StopTransportLayerSecurity_NotStarted_ThrowsTlsOperationException()
         {
             using (var connection = new LdapConnection("server"))
index 6ce552719fb7816c1cb96aa0b8077c6585eceaa9..e629b5327b636cc1bf2bcb9440ba52dcde3ac2d3 100644 (file)
@@ -3,12 +3,12 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Collections.Generic;
-using System.ComponentModel;
-using System.Security.Principal;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class PageResultRequestControlTests
     {
         [Fact]
@@ -21,12 +21,18 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(512, control.PageSize);
             Assert.Equal("1.2.840.113556.1.4.319", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 };
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_PageSize_Data()
+        {
+            yield return new object[] { 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 } };
+            yield return new object[] { 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 10, 4, 0 } : new byte[] { 48, 5, 2, 1, 10, 4, 0 } };
         }
 
         [Theory]
-        [InlineData(0, new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 })]
-        [InlineData(10, new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 10, 4, 0 })]
+        [MemberData(nameof(Ctor_PageSize_Data))]
         public void Ctor_PageSize(int pageSize, byte[] expectedValue)
         {
             var control = new PageResultRequestControl(pageSize);
@@ -45,10 +51,15 @@ namespace System.DirectoryServices.Protocols.Tests
             AssertExtensions.Throws<ArgumentException>("value", () => new PageResultRequestControl(-1));
         }
 
+        public static IEnumerable<object[]> Ctor_Cookie_Data()
+        {
+            yield return new object[] { null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 } };
+            yield return new object[] { new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 } : new byte[] { 48, 6, 2, 2, 2, 0, 4, 0 } };
+            yield return new object[] { new byte[] { 1, 2, 3, }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 } : new byte[] { 48, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 } };
+        }
+
         [Theory]
-        [InlineData(null, new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 })]
-        [InlineData(new byte[0], new byte[] { 48, 132, 0, 0, 0, 6, 2, 2, 2, 0, 4, 0 })]
-        [InlineData(new byte[] { 1, 2, 3, }, new byte[] { 48, 132, 0, 0, 0, 9, 2, 2, 2, 0, 4, 3, 1, 2, 3 })]
+        [MemberData(nameof(Ctor_Cookie_Data))]
         public void Ctor_Cookie(byte[] cookie, byte[] expectedValue)
         {
             var control = new PageResultRequestControl(cookie);
index 590da560d8383f95d7d851614e9f4e77c72cc119..300bf8c4874f1a88c2da3e8a40ee7ef4a242374e 100644 (file)
@@ -3,12 +3,13 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Collections.Generic;
-using System.ComponentModel;
+using System.Runtime.InteropServices;
 using System.Security.Principal;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class QuotaControlTests
     {
         [Fact]
@@ -20,7 +21,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.1852", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 2, 4, 0 } : new byte[] { 48, 2, 4, 0 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         public static IEnumerable<object[]> Ctor_QuerySid_TestData()
@@ -30,6 +32,7 @@ namespace System.DirectoryServices.Protocols.Tests
         }
 
         [Theory]
+        [PlatformSpecific(TestPlatforms.Windows)] //Security Identifiers only work on Windows
         [MemberData(nameof(Ctor_QuerySid_TestData))]
         public void Ctor_QuerySid_Test(SecurityIdentifier querySid, byte[] expectedValue)
         {
index fbf5fc0dc87dc3ea8d8a97b8319701e6ab5708c0..7fd2878537bb803512ad5a29ddd55899ea60e072 100644 (file)
@@ -3,10 +3,12 @@
 // See the LICENSE file in the project root for more information.
 
 using System.ComponentModel;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class SearchOptionsControlTests
     {
         [Fact]
@@ -18,7 +20,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.1340", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 1 } : new byte[] { 48, 3, 2, 1, 1 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         [Fact]
@@ -30,7 +33,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.1340", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 } : new byte[] { 48, 3, 2, 1, 2 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         [Theory]
index 3d0fc4e6d5024c052467ce7772e7c58347c623bb..8c7fabf0ed8bb31d62eecafdbb0f79f7db85ddb9 100644 (file)
@@ -2,11 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System.ComponentModel;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class SecurityDescriptorFlagControlTests
     {
         [Fact]
@@ -18,12 +20,18 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.801", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 0 } : new byte[] { 48, 3, 2, 1, 0 };
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_Flags_Data()
+        {
+            yield return new object[] { SecurityMasks.Group, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 } : new byte[] { 48, 3, 2, 1, 2 } };
+            yield return new object[] { SecurityMasks.None - 1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 6, 2, 4, 255, 255, 255, 255 } : new byte[] { 48, 3, 2, 1, 255 } };
         }
 
         [Theory]
-        [InlineData(SecurityMasks.Group, new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 2 })]
-        [InlineData(SecurityMasks.None - 1, new byte[] { 48, 132, 0, 0, 0, 6, 2, 4, 255, 255, 255, 255 })]
+        [MemberData(nameof(Ctor_Flags_Data))]
         public void Ctor_Flags(SecurityMasks masks, byte[] expectedValue)
         {
             var control = new SecurityDescriptorFlagControl(masks);
@@ -31,7 +39,6 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(masks, control.SecurityMasks);
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.801", control.Type);
-
             Assert.Equal(expectedValue, control.GetValue());
         }
     }
index 24c57e840cf5278373eedf373daeeb8b5da8dd69..197a8f91c9b9cf8d8aa42cb644e43776f636f99c 100644 (file)
@@ -3,10 +3,12 @@
 // See the LICENSE file in the project root for more information.
 
 using System.Reflection;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class SortRequestControlTests
     {
         [Theory]
@@ -30,13 +32,13 @@ namespace System.DirectoryServices.Protocols.Tests
             }
 
             control.IsCritical = critical;
-            Assert.Equal(new byte[]
-            {
-                48, 132, 0, 0, 0, 43, 48, 132, 0, 0, 0, 17, 4, 5,110,
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ?
+                new byte[] { 48, 132, 0, 0, 0, 43, 48, 132, 0, 0, 0, 17, 4, 5,110,
                 97, 109, 101, 49, 128, 5, 114, 117, 108, 101, 49, 129,
                 1, 255, 48, 132, 0, 0, 0, 14, 4, 5, 110, 97, 109, 101,
-                50, 128, 5, 114, 117, 108, 101, 50
-            }, control.GetValue());
+                50, 128, 5, 114, 117, 108, 101, 50} :
+                new byte[] { 48, 19, 48, 9, 4, 1, 110, 128, 1, 114, 129, 1, 255, 48, 6, 4, 1, 110, 128, 1, 114 };
+            Assert.Equal(expected, control.GetValue());
         }
 
         [Fact]
index 7cf3cdc3988f9e247065fb19e990296f8d3ac13e..164327720e33026060e7ca0a430139292e5da964 100644 (file)
@@ -1,6 +1,6 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFrameworks>$(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent)</TargetFrameworks>
+    <TargetFrameworks>$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Windows_NT;$(NetFrameworkCurrent)</TargetFrameworks>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="BerConverterTests.cs" />
@@ -47,6 +47,7 @@
     <Compile Include="AsqRequestControlTests.cs" />
     <Compile Include="AddRequestTests.cs" />
     <Compile Include="DirectoryServicesProtocolsTests.cs" />
+    <Compile Include="DirectoryServicesTestHelpers.cs" />
     <Compile Include="$(CommonTestPath)System\DirectoryServices\LdapConfiguration.cs"
              Link="Common\DirectoryServices\LdapConfiguration.cs" />
   </ItemGroup>
index 73db25a57175990aa5d9fcdcbbc98cd55dc488f8..93b790224c9509723ab5582bd3673686b8f03041 100644 (file)
@@ -2,10 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class VerifyNameControlTests
     {
         [Fact]
@@ -18,12 +21,18 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("1.2.840.113556.1.4.1338", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 };
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_ServerName_Data()
+        {
+            yield return new object[] { "", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 } : new byte[] { 48, 5, 2, 1, 0, 4, 0 } };
+            yield return new object[] { "S", (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 0, 4, 2, 83, 0 } : new byte[] { 48, 7, 2, 1, 0, 4, 2, 83, 0 } };
         }
 
         [Theory]
-        [InlineData("", new byte[] { 48, 132, 0, 0, 0, 5, 2, 1, 0, 4, 0 })]
-        [InlineData("S", new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 0, 4, 2, 83, 0 })]
+        [MemberData(nameof(Ctor_ServerName_Data))]
         public void Ctor_ServerName(string serverName, byte[] expectedValue)
         {
             var control = new VerifyNameControl(serverName);
@@ -36,9 +45,14 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(expectedValue, control.GetValue());
         }
 
+        public static IEnumerable<object[]> Ctor_ServerName_Flag_Data()
+        {
+            yield return new object[] { "", -1, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ?  new byte[] { 48, 132, 0, 0, 0, 8, 2, 4, 255, 255, 255, 255, 4, 0 } : new byte[] { 48, 5, 2, 1, 255, 4, 0 } };
+            yield return new object[] { "S", 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 10, 4, 2, 83, 0 } : new byte[] { 48, 7, 2, 1, 10, 4, 2, 83, 0 } };
+        }
+
         [Theory]
-        [InlineData("", -1, new byte[] { 48, 132, 0, 0, 0, 8, 2, 4, 255, 255, 255, 255, 4, 0 })]
-        [InlineData("S", 10, new byte[] { 48, 132, 0, 0, 0, 7, 2, 1, 10, 4, 2, 83, 0 })]
+        [MemberData(nameof(Ctor_ServerName_Flag_Data))]
         public void Ctor_ServerName_Flag(string serverName, int flag, byte[] expectedValue)
         {
             var control = new VerifyNameControl(serverName, flag);
index d2f42a65fd6cec8510f48e2f94f1fd6bfd965818..7d1844b601e058b60703037eaf67a541934ad306 100644 (file)
@@ -2,10 +2,13 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
 using Xunit;
 
 namespace System.DirectoryServices.Protocols.Tests
 {
+    [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))]
     public class VlvRequestControlTests
     {
         [Fact]
@@ -22,12 +25,18 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.True(control.ServerSide);
             Assert.Equal("2.16.840.1.113730.3.4.9", control.Type);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 };
+            Assert.Equal(expected, control.GetValue());
+        }
+
+        public static IEnumerable<object[]> Ctor_BeforeCount_AfterCount_Offset_Data()
+        {
+            yield return new object[] { 0, 0, 0, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } };
+            yield return new object[] { 10, 10, 10, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 10, 2, 1, 10, 160, 132, 0, 0, 0, 6, 2, 1, 10, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 10, 2, 1, 10, 160, 6, 2, 1, 10, 2, 1, 0 } };
         }
 
         [Theory]
-        [InlineData(0, 0, 0, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })]
-        [InlineData(10, 10, 10, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 10, 2, 1, 10, 160, 132, 0, 0, 0, 6, 2, 1, 10, 2, 1, 0 })]
+        [MemberData(nameof(Ctor_BeforeCount_AfterCount_Offset_Data))]
         public void Ctor_BeforeCount_AfterCount_Offset(int beforeCount, int afterCount, int offset, byte[] expectedValue)
         {
             var control = new VlvRequestControl(beforeCount, afterCount, offset);
@@ -44,9 +53,14 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(expectedValue, control.GetValue());
         }
 
+        public static IEnumerable<object[]> Ctor_BeforeCount_AfterCount_StringTarget_Data()
+        {
+            yield return new object[] { 0, 0, null, new byte[0], (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } };
+            yield return new object[] { 10, 10, "abc", new byte[] { 97, 98, 99 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 } : new byte[] { 48, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 } };
+        }
+
         [Theory]
-        [InlineData(0, 0, null, new byte[0], new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })]
-        [InlineData(10, 10, "abc", new byte[] { 97, 98, 99 }, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 97, 98, 99 })]
+        [MemberData(nameof(Ctor_BeforeCount_AfterCount_StringTarget_Data))]
         public void Ctor_BeforeCount_AfterCount_StringTarget(int beforeCount, int afterCount, string target, byte[] expectedTarget, byte[] expectedValue)
         {
             var control = new VlvRequestControl(beforeCount, afterCount, target);
@@ -64,9 +78,14 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.Equal(expectedValue, control.GetValue());
         }
 
+        public static IEnumerable<object[]> Ctor_BeforeCount_AfterCount_ByteArrayTarget_Data()
+        {
+            yield return new object[] { 0, 0, null, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 } : new byte[] { 48, 14, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0 } };
+            yield return new object[] { 10, 10, new byte[] { 1, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 } : new byte[] { 48, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 } };
+        }
+
         [Theory]
-        [InlineData(0, 0, null, new byte[] { 48, 132, 0, 0, 0, 18, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0 })]
-        [InlineData(10, 10, new byte[] { 1, 2, 3 }, new byte[] { 48, 132, 0, 0, 0, 11, 2, 1, 10, 2, 1, 10, 129, 3, 1, 2, 3 })]
+        [MemberData(nameof(Ctor_BeforeCount_AfterCount_ByteArrayTarget_Data))]
         public void Ctor_BeforeCount_AfterCount_ByteArrayTarget(int beforeCount, int afterCount, byte[] target, byte[] expectedValue)
         {
             var control = new VlvRequestControl(beforeCount, afterCount, target);
@@ -128,7 +147,8 @@ namespace System.DirectoryServices.Protocols.Tests
             Assert.NotSame(contextId, control.ContextId);
             Assert.Equal(contextId, control.ContextId);
 
-            Assert.Equal(new byte[] { 48, 132, 0, 0, 0, 23, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 }, control.GetValue());
+            var expected = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 23, 2, 1, 0, 2, 1, 0, 160, 132, 0, 0, 0, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 } : new byte[] { 48, 19, 2, 1, 0, 2, 1, 0, 160, 6, 2, 1, 0, 2, 1, 0, 4, 3, 1, 2, 3 };
+            Assert.Equal(expected, control.GetValue());
         }
     }
 }