diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs index 9dc20b7f4eb062..4ee4bc8bab9432 100644 --- a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs +++ b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ber.cs @@ -4,11 +4,14 @@ using System; using System.Runtime.InteropServices; using System.DirectoryServices.Protocols; +using System.Diagnostics; internal static partial class Interop { internal static partial class Ldap { + public const int ber_default_successful_return_code = 0; + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_alloc_t", CharSet = CharSet.Ansi)] public static extern IntPtr ber_alloc(int option); @@ -18,17 +21,97 @@ internal static partial class Ldap [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); + public static int ber_printf_emptyarg(SafeBerHandle berElement, string format, nuint tag) + { + if (format == "{") + { + return ber_start_seq(berElement, tag); + } + else if (format == "}") + { + return ber_put_seq(berElement, tag); + } + else if (format == "[") + { + return ber_start_set(berElement, tag); + } + else if (format == "]") + { + return ber_put_set(berElement, tag); + } + else + { + Debug.Assert(format == "n"); + return ber_put_null(berElement, tag); + } + } + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_start_seq", CharSet = CharSet.Ansi)] + public static extern int ber_start_seq(SafeBerHandle berElement, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_start_set", CharSet = CharSet.Ansi)] + public static extern int ber_start_set(SafeBerHandle berElement, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_seq", CharSet = CharSet.Ansi)] + public static extern int ber_put_seq(SafeBerHandle berElement, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_set", CharSet = CharSet.Ansi)] + public static extern int ber_put_set(SafeBerHandle berElement, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_null", CharSet = CharSet.Ansi)] + public static extern int ber_put_null(SafeBerHandle berElement, nuint tag); + + public static int ber_printf_int(SafeBerHandle berElement, string format, int value, nuint tag) + { + if (format == "i") + { + return ber_put_int(berElement, value, tag); + } + else if (format == "e") + { + return ber_put_enum(berElement, value, tag); + } + else + { + Debug.Assert(format == "b"); + return ber_put_boolean(berElement, value, tag); + } + } + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_int", CharSet = CharSet.Ansi)] + public static extern int ber_put_int(SafeBerHandle berElement, int value, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_enum", CharSet = CharSet.Ansi)] + public static extern int ber_put_enum(SafeBerHandle berElement, int value, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_boolean", CharSet = CharSet.Ansi)] + public static extern int ber_put_boolean(SafeBerHandle berElement, int value, nuint tag); - [DllImport(Libraries.OpenLdap, EntryPoint = "ber_printf", CharSet = CharSet.Ansi)] - public static extern int ber_printf_int(SafeBerHandle berElement, string format, int value); + public static int ber_printf_bytearray(SafeBerHandle berElement, string format, HGlobalMemHandle value, nuint length, nuint tag) + { + if (format == "o") + { + return ber_put_ostring(berElement, value, length, tag); + } + else if (format == "s") + { + return ber_put_string(berElement, value, tag); + } + else + { + Debug.Assert(format == "X"); + return ber_put_bitstring(berElement, value, length, tag); + } + } - [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_put_ostring", CharSet = CharSet.Ansi)] + private static extern int ber_put_ostring(SafeBerHandle berElement, HGlobalMemHandle value, nuint length, nuint tag); - [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_put_string", CharSet = CharSet.Ansi)] + private static extern int ber_put_string(SafeBerHandle berElement, HGlobalMemHandle value, nuint tag); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_put_bitstring", CharSet = CharSet.Ansi)] + private static extern int ber_put_bitstring(SafeBerHandle berElement, HGlobalMemHandle value, nuint length, nuint tag); [DllImport(Libraries.OpenLdap, EntryPoint = "ber_flatten", CharSet = CharSet.Ansi)] public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value); @@ -39,16 +122,90 @@ internal static partial class Ldap [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); + public static int ber_scanf_emptyarg(SafeBerHandle berElement, string format) + { + Debug.Assert(format == "{" || format == "}" || format == "[" || format == "]" || format == "n" || format == "x"); + if (format == "{" || format == "[") + { + nuint len = 0; + return ber_skip_tag(berElement, ref len); + } + else if (format == "]" || format == "}") + { + return ber_default_successful_return_code; + } + else + { + Debug.Assert(format == "n" || format == "x"); + return ber_get_null(berElement); + } + } + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_skip_tag", CharSet = CharSet.Ansi)] + private static extern int ber_skip_tag(SafeBerHandle berElement, ref nuint len); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_null", CharSet = CharSet.Ansi)] + private static extern int ber_get_null(SafeBerHandle berElement); + + public static int ber_scanf_int(SafeBerHandle berElement, string format, ref int value) + { + if (format == "i") + { + return ber_get_int(berElement, ref value); + } + else if (format == "e") + { + return ber_get_enum(berElement, ref value); + } + else + { + Debug.Assert(format == "b"); + return ber_get_boolean(berElement, ref value); + } + } + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_int", CharSet = CharSet.Ansi)] + private static extern int ber_get_int(SafeBerHandle berElement, ref int value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_enum", CharSet = CharSet.Ansi)] + private static extern int ber_get_enum(SafeBerHandle berElement, ref int value); + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_boolean", CharSet = CharSet.Ansi)] + private static extern int ber_get_boolean(SafeBerHandle berElement, ref int value); + + public static int ber_scanf_bitstring(SafeBerHandle berElement, string format, ref IntPtr value, ref uint bitLength) + { + Debug.Assert(format == "B"); + nuint bitLengthAsNuint = 0; + int res = ber_get_stringb(berElement, ref value, ref bitLengthAsNuint); + bitLength = (uint)bitLengthAsNuint; + return res; + } + + [DllImport(Libraries.OpenLdap, EntryPoint = "ber_get_stringb", CharSet = CharSet.Ansi)] + private static extern int ber_get_stringb(SafeBerHandle berElement, ref IntPtr value, ref nuint bitLength); + + public static int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value) + { + Debug.Assert(format == "O"); + return ber_get_stringal(berElement, ref value); + } - [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_get_stringal", CharSet = CharSet.Ansi)] + private static extern int ber_get_stringal(SafeBerHandle berElement, ref IntPtr 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); + public static int ber_printf_berarray(SafeBerHandle berElement, string format, IntPtr value, nuint tag) + { + Debug.Assert(format == "v" || format == "V"); + // V and v are not supported on Unix yet. + return -1; + } - [DllImport(Libraries.OpenLdap, EntryPoint = "ber_scanf", CharSet = CharSet.Ansi)] - public static extern int ber_scanf_ptr(SafeBerHandle berElement, string format, ref IntPtr value); + public static int ber_scanf_multibytearray(SafeBerHandle berElement, string format, ref IntPtr value) + { + Debug.Assert(format == "v" || format == "V"); + // V and v are not supported on Unix yet. + return -1; + } } } diff --git a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs index 99fec68cbcc733..0ba2c96ecf7575 100644 --- a/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs +++ b/src/libraries/Common/src/Interop/Windows/Wldap32/Interop.Ber.cs @@ -16,16 +16,7 @@ internal static partial class Ldap 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); + public static extern int ber_printf(SafeBerHandle berElement, string format, __arglist); [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_flatten", CharSet = CharSet.Unicode)] public static extern int ber_flatten(SafeBerHandle berElement, ref IntPtr value); @@ -34,16 +25,7 @@ internal static partial class Ldap 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); + public static extern int ber_scanf(SafeBerHandle berElement, string format, __arglist); [DllImport(Libraries.Wldap32, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ber_bvfree", CharSet = CharSet.Unicode)] public static extern int ber_bvfree(IntPtr value); 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 index b8856cf2d2bda2..319bdba629bc43 100644 --- 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 @@ -13,22 +13,31 @@ internal static class BerPal internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.Ldap.ber_flatten(berElement, ref flattenptr); - internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.Ldap.ber_printf_berarray(berElement, format, value); + internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value, nuint tag) => Interop.Ldap.ber_printf_berarray(berElement, format, value, tag); - internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length); + internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, nuint length, nuint tag) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length, tag); - internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.Ldap.ber_printf_emptyarg(berElement, format); + internal static int PrintEmptyArgument(SafeBerHandle berElement, string format, nuint tag) => Interop.Ldap.ber_printf_emptyarg(berElement, format, tag); - internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.Ldap.ber_printf_int(berElement, format, value); + internal static int PrintInt(SafeBerHandle berElement, string format, int value, nuint tag) => Interop.Ldap.ber_printf_int(berElement, format, value, tag); - internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format); + internal static int PrintTag(SafeBerHandle _1, string _2, nuint _3) + { + // Ber Linux tags are passed with the values that they affect, like `ber_printf_int(.., tag)`. + // So this function does nothing on Linux. + return Interop.Ldap.ber_default_successful_return_code; + } - internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.Ldap.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength); + internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf_emptyarg(berElement, format); + + internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref uint bitLength) => Interop.Ldap.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength); internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf_int(berElement, format, ref result); internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_ptr(berElement, format, ref value); + internal static int ScanNextMultiByteArray(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_multibytearray(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 index 202737f2cb2815..586bcd7d39a2cf 100644 --- 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 @@ -15,21 +15,25 @@ internal static class BerPal internal static int FlattenBerElement(SafeBerHandle berElement, ref IntPtr flattenptr) => Interop.Ldap.ber_flatten(berElement, ref flattenptr); - internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value) => Interop.Ldap.ber_printf_berarray(berElement, format, value); + internal static int PrintBerArray(SafeBerHandle berElement, string format, IntPtr value, nuint _) => Interop.Ldap.ber_printf(berElement, format, __arglist(value)); - internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, int length) => Interop.Ldap.ber_printf_bytearray(berElement, format, value, length); + internal static int PrintByteArray(SafeBerHandle berElement, string format, HGlobalMemHandle value, uint length, nuint _) => Interop.Ldap.ber_printf(berElement, format, __arglist(value, length)); - internal static int PrintEmptyArgument(SafeBerHandle berElement, string format) => Interop.Ldap.ber_printf_emptyarg(berElement, format); + internal static int PrintEmptyArgument(SafeBerHandle berElement, string format, nuint _) => Interop.Ldap.ber_printf(berElement, format, __arglist()); - internal static int PrintInt(SafeBerHandle berElement, string format, int value) => Interop.Ldap.ber_printf_int(berElement, format, value); + internal static int PrintInt(SafeBerHandle berElement, string format, int value, nuint _) => Interop.Ldap.ber_printf(berElement, format, __arglist(value)); - internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format); + internal static int PrintTag(SafeBerHandle berElement, string format, nuint tag) => Interop.Ldap.ber_printf(berElement, format, __arglist((uint)tag)); - internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref int bitLength) => Interop.Ldap.ber_scanf_bitstring(berElement, format, ref ptrResult, ref bitLength); + internal static int ScanNext(SafeBerHandle berElement, string format) => Interop.Ldap.ber_scanf(berElement, format, __arglist()); - internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf_int(berElement, format, ref result); + internal static int ScanNextBitString(SafeBerHandle berElement, string format, ref IntPtr ptrResult, ref uint bitLength) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref ptrResult, ref bitLength)); - internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf_ptr(berElement, format, ref value); + internal static int ScanNextInt(SafeBerHandle berElement, string format, ref int result) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref result)); + + internal static int ScanNextPtr(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref value)); + + internal static int ScanNextMultiByteArray(SafeBerHandle berElement, string format, ref IntPtr value) => Interop.Ldap.ber_scanf(berElement, format, __arglist(ref value)); internal static bool IsBerDecodeError(int errorCode) => errorCode != 0; } 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 index e4bd5d14c474ed..3bef316a506b96 100644 --- 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 @@ -14,7 +14,7 @@ private static int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle ber int error; // return a bitstring and its length IntPtr ptrResult = IntPtr.Zero; - int length = 0; + uint length = 0; error = BerPal.ScanNextBitString(berElement, "B", ref ptrResult, ref length); if (!BerPal.IsBerDecodeError(error)) @@ -23,7 +23,7 @@ private static int DecodeBitStringHelper(ArrayList resultList, SafeBerHandle ber if (ptrResult != IntPtr.Zero) { byteArray = new byte[length]; - Marshal.Copy(ptrResult, byteArray, 0, length); + Marshal.Copy(ptrResult, byteArray, 0, (int)length); } resultList.Add(byteArray); } diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs index 058024fad909b9..8833ae73e31dc3 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/common/BerConverter.cs @@ -29,15 +29,30 @@ public static byte[] Encode(string format, params object[] value) int valueCount = 0; int error = 0; + + // We can't use vararg on Unix and can't do ber_printf(tag), so we use ber_put_int(val, tag) + // and this local keeps tag value for the next element. + nuint tag = 0; + bool tagIsSet = false; for (int formatCount = 0; formatCount < format.Length; formatCount++) { + if (tagIsSet) + { + tagIsSet = false; + } + else + { + int lberTagDefaultInt = -1; + nuint lberTagDefaultNuint = (nuint)lberTagDefaultInt; + tag = lberTagDefaultNuint; + } char fmt = format[formatCount]; if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n') { // no argument needed - error = BerPal.PrintEmptyArgument(berElement, new string(fmt, 1)); + error = BerPal.PrintEmptyArgument(berElement, new string(fmt, 1), tag); } - else if (fmt == 't' || fmt == 'i' || fmt == 'e') + else if (fmt == 'i' || fmt == 'e') { if (valueCount >= value.Length) { @@ -54,7 +69,7 @@ public static byte[] Encode(string format, params object[] value) } // one int argument - error = BerPal.PrintInt(berElement, new string(fmt, 1), (int)value[valueCount]); + error = BerPal.PrintInt(berElement, new string(fmt, 1), (int)value[valueCount], tag); // increase the value count valueCount++; @@ -76,7 +91,7 @@ public static byte[] Encode(string format, params object[] value) } // one int argument - error = BerPal.PrintInt(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0); + error = BerPal.PrintInt(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0, tag); // increase the value count valueCount++; @@ -104,7 +119,7 @@ public static byte[] Encode(string format, params object[] value) { tempValue = utf8Encoder.GetBytes((string)value[valueCount]); } - error = EncodingByteArrayHelper(berElement, tempValue, 'o'); + error = EncodingByteArrayHelper(berElement, tempValue, 'o', tag); // increase the value count valueCount++; @@ -128,7 +143,7 @@ public static byte[] Encode(string format, params object[] value) } byte[] tempValue = (byte[])value[valueCount]; - error = EncodingByteArrayHelper(berElement, tempValue, fmt); + error = EncodingByteArrayHelper(berElement, tempValue, fmt, tag); valueCount++; } @@ -164,11 +179,13 @@ public static byte[] Encode(string format, params object[] value) { tempValues[i] = utf8Encoder.GetBytes(s); } + error = EncodingByteArrayHelper(berElement, tempValues[i], 'o', tag); + if (error == -1) + { + break; + } } } - - error = EncodingMultiByteArrayHelper(berElement, tempValues, 'V'); - valueCount++; } else if (fmt == 'V') @@ -191,8 +208,31 @@ public static byte[] Encode(string format, params object[] value) byte[][] tempValue = (byte[][])value[valueCount]; - error = EncodingMultiByteArrayHelper(berElement, tempValue, fmt); + error = EncodingMultiByteArrayHelper(berElement, tempValue, fmt, tag); + + valueCount++; + } + else if (fmt == 't') + { + if (valueCount >= value.Length) + { + // we don't have enough argument for the format string + Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); + throw new ArgumentException(SR.BerConverterNotMatch); + } + + if (!(value[valueCount] is int)) + { + // argument is wrong + Debug.WriteLine("type should be int\n"); + throw new ArgumentException(SR.BerConverterNotMatch); + } + tag = (uint)(int)value[valueCount]; + tagIsSet = true; + // It will set the tag on Windows and only check the tag on Unix. + error = BerPal.PrintTag(berElement, new string(fmt, 1), tag); + // increase the value count valueCount++; } else @@ -423,7 +463,7 @@ internal static object[] TryDecode(string format, byte[] value, out bool decodeS return decodeResult; } - private static int EncodingByteArrayHelper(SafeBerHandle berElement, byte[] tempValue, char fmt) + private static int EncodingByteArrayHelper(SafeBerHandle berElement, byte[] tempValue, char fmt, nuint tag) { int error = 0; @@ -433,12 +473,12 @@ private static int EncodingByteArrayHelper(SafeBerHandle berElement, byte[] temp IntPtr tmp = Marshal.AllocHGlobal(tempValue.Length); Marshal.Copy(tempValue, 0, tmp, tempValue.Length); HGlobalMemHandle memHandle = new HGlobalMemHandle(tmp); - error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, tempValue.Length); + error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, (uint)tempValue.Length, tag); } else { HGlobalMemHandle memHandle = new HGlobalMemHandle(HGlobalMemHandle._dummyPointer); - error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, 0); + error = BerPal.PrintByteArray(berElement, new string(fmt, 1), memHandle, 0, tag); } return error; @@ -479,7 +519,7 @@ private static byte[] DecodingByteArrayHelper(SafeBerHandle berElement, char fmt return byteArray; } - private static int EncodingMultiByteArrayHelper(SafeBerHandle berElement, byte[][] tempValue, char fmt) + private static int EncodingMultiByteArrayHelper(SafeBerHandle berElement, byte[][] tempValue, char fmt, nuint tag) { IntPtr berValArray = IntPtr.Zero; IntPtr tempPtr = IntPtr.Zero; @@ -521,7 +561,7 @@ private static int EncodingMultiByteArrayHelper(SafeBerHandle berElement, byte[] Marshal.WriteIntPtr(tempPtr, IntPtr.Zero); } - error = BerPal.PrintBerArray(berElement, new string(fmt, 1), berValArray); + error = BerPal.PrintBerArray(berElement, new string(fmt, 1), berValArray, tag); } finally { diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs index 6391870ef11aac..d2704307152d5a 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/AsqRequestControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class AsqRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs index 4a474ec57eae18..b0a47bad6fe645 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/BerConversionExceptionTests.cs @@ -9,7 +9,6 @@ namespace System.DirectoryServices.Protocols.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class BerConversionExceptionTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs index d636a889898813..ba92d33c2a7b61 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/BerConverterTests.cs @@ -9,7 +9,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class BerConverterTests { public static IEnumerable Encode_TestData() @@ -30,6 +29,10 @@ public static IEnumerable Encode_TestData() 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[] { "e", new object[] { 128 }, new byte[] { 10, 2, 0, 128 } }; + yield return new object[] { "te", new object[] { 128, 0 }, new byte[] { 128, 1, 0 } }; + yield return new object[] { "tet", new object[] { 128, 0, 133 }, new byte[] { 128, 1, 0 } }; + yield return new object[] { "tetie", new object[] { 128, 0, 133, 2, 3 }, new byte[] { 128, 1, 0, 133, 1, 2, 10, 1, 3 } }; yield return new object[] { "{tetie}", new object[] { 128, 0, 133, 2, 3 }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 48, 132, 0, 0, 0, 9, 128, 1, 0, 133, 1, 2, 10, 1, 3 } : new byte[] { 48, 9, 128, 1, 0, 133, 1, 2, 10, 1, 3 } }; @@ -37,10 +40,16 @@ public static IEnumerable Encode_TestData() 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[] { "o", new object[] { null }, new byte[] { 4, 0} }; + yield return new object[] { "X", new object[] { new byte[] { 0, 1, 2, 255 } }, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ? new byte[] { 3, 4, 0, 1, 2, 255 } : new byte[] { 3, 2, 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 } }, (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 } }; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + 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 } }; + } } [Theory] @@ -117,6 +126,7 @@ public static IEnumerable Decode_TestData() { yield return new object[] { "{}", new byte[] { 48, 0, 0, 0, 0, 0 }, new object[0] }; yield return new object[] { "{a}", new byte[] { 48, 132, 0, 0, 0, 5, 4, 3, 97, 98, 99 }, new object[] { "abc" } }; + yield return new object[] { "{i}", new byte[] { 48, 132, 0, 0, 0, 3, 2, 1, 10 }, new object[] { 10 } }; yield return new object[] { "{ie}", new byte[] { 48, 132, 0, 0, 0, 6, 1, 1, 255, 1, 1, 0 }, new object[] { -1, 0 } }; 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 } } }; diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs index 847f482176d7db..da6bcfbdf5b691 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirSyncRequestControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class DirSyncRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs index 4f79e81c83ec1f..32d2b36f062493 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryControlTests.cs @@ -5,7 +5,6 @@ namespace System.DirectoryServices.Protocols.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class DirectoryControlTests { [Theory] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs index 1329fa83a6cfff..00d56e12bc8d19 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/DirectoryServicesProtocolsTests.cs @@ -10,7 +10,6 @@ namespace System.DirectoryServices.Protocols.Tests { - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public partial class DirectoryServicesProtocolsTests { internal static bool IsLdapConfigurationExist => LdapConfiguration.Configuration != null; diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs index a7c571598d7c29..284d916613b238 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/ExtendedDNControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class ExtendedDNControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs index e6f10e4bddc7ec..537874c7f4fbd7 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/PageResultRequestControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class PageResultRequestControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs index 033865e1353d95..b1ddaa9efa8e88 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/QuotaControlTests.cs @@ -9,7 +9,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class QuotaControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs index c173904caaaef5..2a30d7dc3a522a 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SearchOptionsControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class SearchOptionsControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs index 47ceca06e70a51..6ec7955faa782b 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/SecurityDescriptorFlagControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class SecurityDescriptorFlagControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs index c6edf3487253d5..5e7469d27ed01c 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VerifyNameControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class VerifyNameControlTests { [Fact] diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs index 4ea87e1a5f6ec8..a259bd11c7e8aa 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/VlvRequestControlTests.cs @@ -8,7 +8,6 @@ namespace System.DirectoryServices.Protocols.Tests { [ConditionalClass(typeof(DirectoryServicesTestHelpers), nameof(DirectoryServicesTestHelpers.IsWindowsOrLibLdapIsInstalled))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49105", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class VlvRequestControlTests { [Fact]